Compare commits

...
Author SHA1 Message Date
Fabian 42e618e330 - Fixed mix of friendly vs. non-friendly.
- Added testwise coward mode, so that friendly AI fighters and bombers do depart when taking too much hits. ;-)
2008-08-15 01:10:23 +00:00
Fabian 3e1b9c173b Added ai/newai/newai.cpp to Windows projects. 2008-08-05 17:28:23 +00:00
Fabian 3e61b43b31 Moved newai to below ai/. 2008-08-05 17:25:14 +00:00
Fabian 918a805080 Added defined compilation to distiguish between call from module and call from static library. 2008-08-05 17:23:32 +00:00
Fabian 75f5273c0e Oops, forgot to remove debugging code. 2008-08-02 12:25:46 +00:00
Fabian e130b74231 - Added newai.cpp to Makefile.am.
- Changed ai_module_init to newai_ai_module_init due to new naming scheme.
2008-08-02 12:16:12 +00:00
Fabian 3a6f03a984 - Added possibility to fallback to program image if library or symbol in library cannot be found.
- Added doxygen documentation.
- Added dummy function for included AI implementations.
2008-08-02 12:13:56 +00:00
Fabian 0287e166df Added an example AI implementation.
Under linux the following works to build it:

g++ -I. -I /usr/include/SDL newai/newai.cpp -shared -o newai.so

Then you need to use:

LD_LIBRARY_PATH=$(pwd) ./fs2_open_r

And add a newai-aip.tbm file:

#AI Profiles

$Profile Name: FS2 RETAIL
+nocreate
$AI Module: newai
#End
2008-08-02 00:23:37 +00:00
Fabian 1fb5f9cd9b Added aimodular.cpp aimodular.h also to MSVC++ project files. 2008-07-29 18:27:31 +00:00
Fabian 92d8507c12 - Added modular files to Makefile.am.
- Added -rdynamic to be able to use global variables from the main program in the NewAI DLL file.
2008-07-29 18:16:43 +00:00
Fabian 914ed7a2f5 Added modular system to load a new AI on the fly via a DLL or SO file:
The DLL file needs to do:

extern "C" {
	void ai_module_init(void);
}

and override the table functions it wants to override.
2008-07-29 18:13:15 +00:00
Fabian 9dca3f22db - Added global references to the default tables.
- Fixed missing includes for aiinternal.h.
2008-07-29 17:12:18 +00:00
Fabian 42ad6cba7c Added optional string $AI Module to AI Profiles. 2008-07-29 17:09:56 +00:00
Fabian 12b153fd73 Oops, I completely forgot the call table for aicode as I was using the wrong diff ...
Anyway, now aicode_ is calltabled also and can be used in modularized form.
2008-06-21 01:47:18 +00:00
Fabian 7a7eb3b711 Added calltables for most ai_* functions so the AI can be replaced without breaking compatibility with retail. 2008-06-20 18:35:31 +00:00
taylor d18277e2ba make copy of trunk for AI work 2008-05-25 13:59:05 +00:00
WMCoolmon f035cd2b6e Fix a null vec_normalize bug from additive weapons 2008-05-25 06:29:59 +00:00
Backslash 245aefcb44 More end_string_at_first_hash_symbol stuff -- targetbox orders, docked ships, message senders 2008-05-25 02:55:56 +00:00
Backslash 3fb37e85b0 Whoops, wrong repository. Quick correction. 2008-05-24 06:55:19 +00:00
Backslash 1086be9eba bump MAX_ALT_TYPE_NAMES 2008-05-24 06:44:29 +00:00
karajorma 41bbd6cc16 Fix bug where wings with only one ship would ignore orders 2008-05-23 20:24:47 +00:00
phreak 1dda11f9ec remove references to cloaking code. 2008-05-17 17:35:55 +00:00
phreak 0ca63f3c96 Mantis #1462
non-local SSMs home in on objects instead of points to they can track moving targets.

ship_apply_tag and ssm_create take "team" arguments now to indicate which team fired the ssm strike.

ship-tag sexp also has an optional team argument added.  Team 0 is used if the team is not defined.

missiles that are fired without a parent and are locked will travel at their max velocity and not 1/4 of their max.

bugfixes where sometimes an animation may sometimes have a duration of zero and cause an infinite loop.
2008-05-16 01:29:19 +00:00
karajorma cefb883d55 Fix a crash when using <argument> with a numeric variable (Mantis 1656) 2008-05-15 22:42:38 +00:00
karajorma a711c256b4 Fix various crashes, assertions and Int3s caused by SEXPs unable to find subsystems after the player changes class during loadout. 2008-05-14 19:36:17 +00:00
taylor 82561d3b27 hopefully fix order issue from future wing waves (Mantis #1683) 2008-05-06 00:13:52 +00:00
30 changed files with 3007 additions and 489 deletions

No files matched your search

+5
View File
@@ -211,6 +211,9 @@ FS2_SOURCES = \
ai/aiturret.cpp \
ai/ai_profiles.cpp \
ai/ai_profiles.h \
ai/aimodular.h \
ai/aimodular.cpp \
ai/newai/newai.cpp \
anim/animplay.cpp \
anim/animplay.h \
anim/packunpack.cpp \
@@ -822,6 +825,8 @@ fs2_open_r_SOURCES = \
fs2_open_d_LDADD = libcode.a ../libjpeg/libjpeg.a ../lua/liblua.a
fs2_open_r_LDADD = libcode.a ../libjpeg/libjpeg.a ../lua/liblua.a
fs2_open_d_LDFLAGS = -rdynamic
fs2_open_r_LDFLAGS = -rdynamic
##
## End MAIN binary
+4
View File
@@ -235,6 +235,10 @@ void parse_ai_profiles_tbl(char *filename)
// fill in any and all settings; they're all optional and can be in any order
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
{
strcpy(profile->ai_module, "retail");
if (optional_string("$AI Module:"))
stuff_string(profile->ai_module, F_NAME, NAME_LENGTH);
if (optional_string("$Player Afterburner Recharge Scale:"))
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
+2
View File
@@ -80,6 +80,8 @@
typedef struct ai_profile_t {
char profile_name[NAME_LENGTH];
char ai_module[NAME_LENGTH];
int flags;
+179 -24
View File
@@ -482,13 +482,141 @@ extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *mo
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
// FF 14-06-07
// AI Big Table Wrapper
struct aibig_call_table *aibig_table = &AIBigDefaultTable;
void ai_big_evade_ship ()
{
aibig_table->ai_big_evade_ship();
}
void ai_big_chase_attack (ai_info *aip, ship_info *sip, vec3d *enemy_pos, float dist_to_enemy, int modelnum)
{
aibig_table->ai_big_chase_attack(aip, sip, enemy_pos, dist_to_enemy, modelnum);
}
void ai_big_avoid_ship ()
{
aibig_table->ai_big_avoid_ship();
}
int ai_big_maybe_follow_subsys_path (int do_dot_check)
{
return aibig_table->ai_big_maybe_follow_subsys_path(do_dot_check);
}
void ai_bpap (object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal)
{
aibig_table->ai_bpap(objp, attacker_objp_pos, attacker_objp_fvec, attack_point, local_attack_point, fov, weapon_travel_dist, surface_normal);
}
void ai_big_pick_attack_point_turret (object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
{
aibig_table->ai_big_pick_attack_point_turret(objp, ssp, gpos, gvec, attack_point, fov, weapon_travel_dist);
}
void ai_big_pick_attack_point (object *objp, object *attacker_objp, vec3d *attack_point, float fov)
{
aibig_table->ai_big_pick_attack_point(objp, attacker_objp, attack_point, fov);
}
void ai_big_subsys_path_cleanup (ai_info *aip)
{
aibig_table->ai_big_subsys_path_cleanup(aip);
}
int ai_big_maybe_start_strafe (ai_info *aip, ship_info *sip)
{
return aibig_table->ai_big_maybe_start_strafe(aip, sip);
}
void ai_big_chase_ct ()
{
aibig_table->ai_big_chase_ct();
}
void ai_big_maybe_fire_weapons (float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
{
aibig_table->ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy, firing_pos, enemy_pos, enemy_vel);
}
void ai_big_switch_to_chase_mode (ai_info *aip)
{
aibig_table->ai_big_switch_to_chase_mode(aip);
}
int ai_big_strafe_maybe_retreat (float dist, vec3d *target_pos)
{
return aibig_table->ai_big_strafe_maybe_retreat(dist, target_pos);
}
void ai_big_chase ()
{
aibig_table->ai_big_chase();
}
void ai_big_ship (object *objp)
{
aibig_table->ai_big_ship(objp);
}
void ai_big_attack_get_data (vec3d *enemy_pos, float *dist_to_enemy, float *dot_to_enemy)
{
aibig_table->ai_big_attack_get_data(enemy_pos, dist_to_enemy, dot_to_enemy);
}
void ai_big_strafe_attack ()
{
aibig_table->ai_big_strafe_attack();
}
void ai_big_strafe_avoid ()
{
aibig_table->ai_big_strafe_avoid();
}
void ai_big_strafe_retreat1 ()
{
aibig_table->ai_big_strafe_retreat1();
}
void ai_big_strafe_retreat2 ()
{
aibig_table->ai_big_strafe_retreat2();
}
void ai_big_strafe_position ()
{
aibig_table->ai_big_strafe_position();
}
void ai_big_strafe ()
{
aibig_table->ai_big_strafe();
}
int ai_big_maybe_enter_strafe_mode (object *pl_objp, int weapon_objnum, int consider_target_only)
{
return aibig_table->ai_big_maybe_enter_strafe_mode(pl_objp, weapon_objnum, consider_target_only);
}
void ai_big_strafe_maybe_attack_turret (object *ship_objp, object *weapon_objp)
{
aibig_table->ai_big_strafe_maybe_attack_turret(ship_objp, weapon_objp);
}
// AI Big Default implementation
// Called by ai_big_pick_attack_point.
// Generates a random attack point.
// If truly_random flag set (haha), then generate a pretty random number. Otherwise, generate a static rand which
// tends to not change from frame to frame.
// Try four times and choose nearest point to increase chance of getting a good point.
void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal)
void aibig_ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal)
{
float nearest_dist;
vec3d result_point, best_point;
@@ -607,7 +735,7 @@ done_1:
//
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
void aibig_ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
{
if (!timestamp_elapsed(ssp->turret_pick_big_attack_point_timestamp)) {
vec3d result_point;
@@ -627,7 +755,7 @@ void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
// Note, attacker_objp can be a ship or a weapon.
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov)
void aibig_ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov)
{
Assert(objp->instance > -1);
Assert(objp->type == OBJ_SHIP);
@@ -696,7 +824,7 @@ void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack
}
// Handler for SM_EVADE submode ( called from ai_big_chase() )
void ai_big_evade_ship()
void aibig_ai_big_evade_ship()
{
vec3d player_pos, enemy_pos;
float dist;
@@ -744,13 +872,13 @@ void ai_big_evade_ship()
}
// Handler for SM_AVOID submode ( called from ai_big_chase() )
void ai_big_avoid_ship()
void aibig_ai_big_avoid_ship()
{
ai_big_evade_ship();
}
// reset path following information
void ai_big_subsys_path_cleanup(ai_info *aip)
void aibig_ai_big_subsys_path_cleanup(ai_info *aip)
{
if ( aip->ai_flags & AIF_ON_SUBSYS_PATH ) {
aip->ai_flags &= ~AIF_ON_SUBSYS_PATH;
@@ -765,7 +893,7 @@ void ai_big_subsys_path_cleanup(ai_info *aip)
// input: do_dot_check => default value 0, flag to indicate whether check should be done to ensure
// subsystem is within certain field of view. We don't want to check fov when
// strafing, since ship is weaving to avoid turret fire
int ai_big_maybe_follow_subsys_path(int do_dot_check)
int aibig_ai_big_maybe_follow_subsys_path(int do_dot_check)
{
ai_info *aip;
float dot = 1.0f, min_dot;
@@ -899,7 +1027,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
// 0 => ship should not change ai mode, no fighter/bomber threats are near
//
// NOTE: uses SCAN_FIGHTERS_INTERVAL and ENTER_STRAFE_THREAT_DIST_SQUARED which are defined in AiBig.h
int ai_big_maybe_start_strafe(ai_info *aip, ship_info *sip)
int aibig_ai_big_maybe_start_strafe(ai_info *aip, ship_info *sip)
{
// if moving slowly (or stopped), and SIF_SMALL_SHIP, then enter STRAFE mode if enemy fighter/bombers
// are near
@@ -934,7 +1062,7 @@ int ai_big_maybe_start_strafe(ai_info *aip, ship_info *sip)
}
// ATTACK submode handler for chase mode.
void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float dist_to_enemy, int modelnum)
void aibig_ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float dist_to_enemy, int modelnum)
{
int start_bank;
float dot_to_enemy, time_to_hit;
@@ -1051,7 +1179,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
}
// Handler for submode SM_CONTINUOUS_TURN
void ai_big_chase_ct()
void aibig_ai_big_chase_ct()
{
ai_chase_ct();
}
@@ -1068,7 +1196,7 @@ extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
// dist_to_enemy => distance (in m) to attack point on current target
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
//
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
void aibig_ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
{
ai_info *aip;
ship_weapon *swp;
@@ -1173,7 +1301,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
}
// switch ai ship into chase mode
void ai_big_switch_to_chase_mode(ai_info *aip)
void aibig_ai_big_switch_to_chase_mode(ai_info *aip)
{
aip->previous_mode = aip->mode;
aip->mode = AIM_CHASE;
@@ -1184,7 +1312,7 @@ void ai_big_switch_to_chase_mode(ai_info *aip)
extern int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos);
// Make object Pl_objp chase object En_objp, which is a big ship, not a small ship.
void ai_big_chase()
void aibig_ai_big_chase()
{
float dist_to_enemy, dot_to_enemy;
vec3d player_pos, enemy_pos, vec_to_enemy;
@@ -1474,7 +1602,7 @@ void ai_big_chase()
aip->time_enemy_in_range *= (1.0f - flFrametime);
}
void ai_big_ship(object *objp)
void aibig_ai_big_ship(object *objp)
{
// do nothing
}
@@ -1485,7 +1613,7 @@ void ai_big_ship(object *objp)
// dist => distance from Pl_objp front to attack point
// dot => dot of Pl_objp fvec and vector to attack point
// fire_pos => world pos from which firing
void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_to_enemy)
void aibig_ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_to_enemy)
{
vec3d player_pos, vec_to_enemy, predicted_enemy_pos;
ship *shipp = &Ships[Pl_objp->instance];
@@ -1544,7 +1672,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
// AIS_STRAFE_RETREAT
int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
int aibig_ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1601,7 +1729,7 @@ int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
}
// attack directly to the turret and fire weapons
void ai_big_strafe_attack()
void aibig_ai_big_strafe_attack()
{
ai_info *aip;
vec3d target_pos;
@@ -1704,7 +1832,7 @@ void ai_big_strafe_attack()
}
// pick a new attack point when entering this state, and keep using it
void ai_big_strafe_avoid()
void aibig_ai_big_strafe_avoid()
{
ai_info *aip;
vec3d target_pos;
@@ -1730,7 +1858,7 @@ void ai_big_strafe_avoid()
}
// move towards aip->goal_point in an evasive manner
void ai_big_strafe_retreat1()
void aibig_ai_big_strafe_retreat1()
{
float dist;
ai_info *aip;
@@ -1776,7 +1904,7 @@ void ai_big_strafe_retreat1()
accelerate_ship(aip, 1.0f);
}
void ai_big_strafe_retreat2()
void aibig_ai_big_strafe_retreat2()
{
float dist;
ai_info *aip;
@@ -1815,7 +1943,7 @@ void ai_big_strafe_retreat2()
}
// reposition self to begin another strafing run
void ai_big_strafe_position()
void aibig_ai_big_strafe_position()
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1833,7 +1961,7 @@ void ai_big_strafe_position()
// #define AIS_STRAFE_RETREAT1 204 // fly away from attack point (on an avoid vector)
// #define AIS_STRAFE_POSITION 205 // re-position to resume strafing attack
//
void ai_big_strafe()
void aibig_ai_big_strafe()
{
ai_info *aip;
@@ -1883,7 +2011,7 @@ void ai_big_strafe()
//
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
// so, enter AIM_STRAFE
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consider_target_only)
int aibig_ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consider_target_only)
{
ai_info *aip;
ship_info *sip;
@@ -1957,7 +2085,7 @@ int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consi
// Consider attacking a turret, if a turret actually fired the weapon
// input: ship_objp => ship that will attack the turret
// weapon_objp =>
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
void aibig_ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
{
ai_info *aip;
object *parent_objp;
@@ -2006,3 +2134,30 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
// attack the turret
set_targeted_subsys(aip, Weapons[weapon_objp->instance].turret_subsys, OBJ_INDEX(parent_objp));
}
struct aibig_call_table AIBigDefaultTable = {
aibig_ai_big_evade_ship,
aibig_ai_big_chase_attack,
aibig_ai_big_avoid_ship,
aibig_ai_big_maybe_follow_subsys_path,
aibig_ai_bpap,
aibig_ai_big_pick_attack_point_turret,
aibig_ai_big_pick_attack_point,
aibig_ai_big_subsys_path_cleanup,
aibig_ai_big_maybe_start_strafe,
aibig_ai_big_chase_ct,
aibig_ai_big_maybe_fire_weapons,
aibig_ai_big_switch_to_chase_mode,
aibig_ai_big_strafe_maybe_retreat,
aibig_ai_big_chase,
aibig_ai_big_ship,
aibig_ai_big_attack_get_data,
aibig_ai_big_strafe_attack,
aibig_ai_big_strafe_avoid,
aibig_ai_big_strafe_retreat1,
aibig_ai_big_strafe_retreat2,
aibig_ai_big_strafe_position,
aibig_ai_big_strafe,
aibig_ai_big_maybe_enter_strafe_mode,
aibig_ai_big_strafe_maybe_attack_turret
};
+38 -1
View File
@@ -102,6 +102,43 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
// AI Big Table Wrapper
#include "ship/ship.h"
struct aibig_call_table
{
void (*ai_big_evade_ship) ();
void (*ai_big_chase_attack) (ai_info *aip, ship_info *sip, vec3d *enemy_pos, float dist_to_enemy, int modelnum);
void (*ai_big_avoid_ship) ();
int (*ai_big_maybe_follow_subsys_path) (int do_dot_check=1);
void (*ai_bpap) (object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal);
void (*ai_big_pick_attack_point_turret) (object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist);
void (*ai_big_pick_attack_point) (object *objp, object *attacker_objp, vec3d *attack_point, float fov);
void (*ai_big_subsys_path_cleanup) (ai_info *aip);
int (*ai_big_maybe_start_strafe) (ai_info *aip, ship_info *sip);
void (*ai_big_chase_ct) ();
void (*ai_big_maybe_fire_weapons) (float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel);
void (*ai_big_switch_to_chase_mode) (ai_info *aip);
int (*ai_big_strafe_maybe_retreat) (float dist, vec3d *target_pos);
void (*ai_big_chase) ();
void (*ai_big_ship) (object *objp);
void (*ai_big_attack_get_data) (vec3d *enemy_pos, float *dist_to_enemy, float *dot_to_enemy);
void (*ai_big_strafe_attack) ();
void (*ai_big_strafe_avoid) ();
void (*ai_big_strafe_retreat1) ();
void (*ai_big_strafe_retreat2) ();
void (*ai_big_strafe_position) ();
void (*ai_big_strafe) ();
int (*ai_big_maybe_enter_strafe_mode) (object *pl_objp, int weapon_objnum, int consider_target_only);
void (*ai_big_strafe_maybe_attack_turret) (object *ship_objp, object *weapon_objp);
};
// Set new pointer to override ai_big* function calls
// possibly copying the old function calls first
extern struct aibig_call_table *aibig_table;
extern struct aibig_call_table AIBigDefaultTable;
#endif
+1414 -212
View File
File diff suppressed because it is too large. Load diff
+233 -32
View File
@@ -772,11 +772,176 @@ ai_goal_list Ai_goal_names[] =
int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
// FF 04-06-07
// AI Goal Table Wrapper
struct aigoal_call_table *aigoal_table = &AIGoalDefaultTable;
char* Ai_goal_text (int goal)
{
return aigoal_table->Ai_goal_text(goal);
}
void ai_maybe_add_form_goal (wing *wingp)
{
aigoal_table->ai_maybe_add_form_goal(wingp);
}
void ai_post_process_mission ()
{
aigoal_table->ai_post_process_mission();
}
int ai_query_goal_valid (int ship, int ai_goal)
{
return aigoal_table->ai_query_goal_valid(ship, ai_goal);
}
void ai_remove_ship_goal (ai_info *aip, int index)
{
aigoal_table->ai_remove_ship_goal(aip, index);
}
void ai_clear_ship_goals (ai_info *aip)
{
aigoal_table->ai_clear_ship_goals(aip);
}
void ai_clear_wing_goals (int wingnum)
{
aigoal_table->ai_clear_wing_goals(wingnum);
}
void ai_mission_wing_goal_complete (int wingnum, ai_goal *remove_goalp)
{
aigoal_table->ai_mission_wing_goal_complete(wingnum, remove_goalp);
}
void ai_mission_goal_complete (ai_info *aip)
{
aigoal_table->ai_mission_goal_complete(aip);
}
int ai_get_subsystem_type (char *subsystem)
{
return aigoal_table->ai_get_subsystem_type(subsystem);
}
void ai_goal_purge_invalid_goals (ai_goal *aigp, ai_goal *goal_list)
{
aigoal_table->ai_goal_purge_invalid_goals(aigp, goal_list);
}
void ai_goal_purge_all_invalid_goals (ai_goal *aigp)
{
aigoal_table->ai_goal_purge_all_invalid_goals(aigp);
}
int ai_goal_find_dockpoint (int shipnum, int dock_type)
{
return aigoal_table->ai_goal_find_dockpoint(shipnum, dock_type);
}
void ai_goal_fixup_dockpoints (ai_info *aip, ai_goal *aigp)
{
aigoal_table->ai_goal_fixup_dockpoints(aip, aigp);
}
void ai_add_goal_sub_player (int type, int mode, int submode, char *shipname, ai_goal *aigp)
{
aigoal_table->ai_add_goal_sub_player(type, mode, submode, shipname, aigp);
}
int ai_goal_find_empty_slot (ai_goal *goals, int active_goal)
{
return aigoal_table->ai_goal_find_empty_slot(goals, active_goal);
}
void ai_add_ship_goal_player (int type, int mode, int submode, char *shipname, ai_info *aip)
{
aigoal_table->ai_add_ship_goal_player(type, mode, submode, shipname, aip);
}
void ai_add_wing_goal_player (int type, int mode, int submode, char *shipname, int wingnum)
{
aigoal_table->ai_add_wing_goal_player(type, mode, submode, shipname, wingnum);
}
void ai_add_goal_sub_sexp (int sexp, int type, ai_goal *aigp, char *actor_name)
{
aigoal_table->ai_add_goal_sub_sexp(sexp, type, aigp, actor_name);
}
void ai_add_ship_goal_sexp (int sexp, int type, ai_info *aip)
{
aigoal_table->ai_add_ship_goal_sexp(sexp, type, aip);
}
void ai_add_wing_goal_sexp (int sexp, int type, int wingnum)
{
aigoal_table->ai_add_wing_goal_sexp(sexp, type, wingnum);
}
void ai_add_goal_ship_internal (ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate)
{
aigoal_table->ai_add_goal_ship_internal(aip, goal_type, name, docker_point, dockee_point, immediate);
}
void ai_add_goal_wing_internal (wing *wingp, int goal_type, char *name, int immediate)
{
aigoal_table->ai_add_goal_wing_internal(wingp, goal_type, name, immediate);
}
void ai_copy_mission_wing_goal (ai_goal *aigp, ai_info *aip)
{
aigoal_table->ai_copy_mission_wing_goal(aigp, aip);
}
int ai_mission_goal_achievable (int objnum, ai_goal *aigp)
{
return aigoal_table->ai_mission_goal_achievable(objnum, aigp);
}
int ai_goal_priority_compare (const void *a, const void *b)
{
return aigoal_table->ai_goal_priority_compare(a, b);
}
void prioritize_goals (int objnum, ai_info *aip)
{
aigoal_table->prioritize_goals(objnum, aip);
}
void validate_mission_goals (int objnum, ai_info *aip)
{
aigoal_table->validate_mission_goals(objnum, aip);
}
void ai_process_mission_orders (int objnum, ai_info *aip)
{
aigoal_table->ai_process_mission_orders(objnum, aip);
}
void ai_update_goal_references (ai_goal *goals, int type, char *old_name, char *new_name)
{
aigoal_table->ai_update_goal_references(goals, type, old_name, new_name);
}
int query_referenced_in_ai_goals (ai_goal *goals, int type, char *name)
{
return aigoal_table->query_referenced_in_ai_goals(goals, type, name);
}
char* ai_add_dock_name (char *str)
{
return aigoal_table->ai_add_dock_name(str);
}
// AL 11-17-97: A text description of the AI goals. This is used for printing out on the
// HUD what a ship's current orders are. If the AI goal doesn't correspond to something that
// ought to be printable, then NULL is used.
// JAS: Converted to a function in order to externalize the strings
char *Ai_goal_text(int goal)
char *aigoal_Ai_goal_text(int goal)
{
switch(goal) {
case 1:
@@ -815,7 +980,7 @@ char *Ai_goal_text(int goal)
// function to maybe add the form on my wing goal for a player's starting wing. Called when a player wing arrives.
// Goober5000 - made more generic
void ai_maybe_add_form_goal( wing *wingp )
void aigoal_ai_maybe_add_form_goal( wing *wingp )
{
int j;
char *wing_leader;
@@ -853,7 +1018,7 @@ void ai_maybe_add_form_goal( wing *wingp )
}
}
void ai_post_process_mission()
void aigoal_ai_post_process_mission()
{
object *objp;
@@ -907,7 +1072,7 @@ void ai_post_process_mission()
}
// function which determines is a goal is valid for a particular type of ship
int ai_query_goal_valid( int ship, int ai_goal )
int aigoal_ai_query_goal_valid( int ship, int ai_goal )
{
int accepted;
@@ -930,7 +1095,7 @@ int ai_query_goal_valid( int ship, int ai_goal )
}
// remove an ai goal from it's list. Uses the active_goal member as the goal to remove
void ai_remove_ship_goal( ai_info *aip, int index )
void aigoal_ai_remove_ship_goal( ai_info *aip, int index )
{
// only need to set the ai_mode for the particular goal to AI_GOAL_NONE
// reset ai mode to default behavior. Might get changed next time through
@@ -950,7 +1115,7 @@ void ai_remove_ship_goal( ai_info *aip, int index )
//ai_do_default_behavior( &Objects[Ships[aip->shipnum].objnum] );
}
void ai_clear_ship_goals( ai_info *aip )
void aigoal_ai_clear_ship_goals( ai_info *aip )
{
int i;
@@ -969,7 +1134,7 @@ void ai_clear_ship_goals( ai_info *aip )
}
}
void ai_clear_wing_goals( int wingnum )
void aigoal_ai_clear_wing_goals( int wingnum )
{
int i;
wing *wingp = &Wings[wingnum];
@@ -999,7 +1164,7 @@ void ai_clear_wing_goals( int wingnum )
// structure of the goal to be removed. This process is slightly tricky since some member of the wing
// might be pursuing a different goal. We will have to compare based on mode, submode, priority,
// and name.. This routine is only currently called from waypoint code!!!
void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
void aigoal_ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
{
int mode, submode, priority, i;
char *name;
@@ -1059,7 +1224,7 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
// routine which is called with an ai object complete it's goal. Do some action
// based on the goal what was just completed
void ai_mission_goal_complete( ai_info *aip )
void aigoal_ai_mission_goal_complete( ai_info *aip )
{
// if the active goal is dynamic or none, just return. (AI_GOAL_NONE is probably an error, but
// I don't think that this is a problem)
@@ -1071,7 +1236,7 @@ void ai_mission_goal_complete( ai_info *aip )
}
int ai_get_subsystem_type( char *subsystem )
int aigoal_ai_get_subsystem_type( char *subsystem )
{
if ( strstr(subsystem, "engine") ) {
return SUBSYSTEM_ENGINE;
@@ -1107,7 +1272,7 @@ int ai_get_subsystem_type( char *subsystem )
// which are destroy, etc, should get removed. goal list is the list of goals to purge. It is
// always MAX_AI_GOALS in length. This function will only get called when the goal which causes
// purging becomes valid.
void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list )
void aigoal_ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list )
{
int i;
ai_goal *purge_goal;
@@ -1173,7 +1338,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list )
}
// function to purge the goals of *all* ships in the game based on the incoming goal structure
void ai_goal_purge_all_invalid_goals(ai_goal *aigp)
void aigoal_ai_goal_purge_all_invalid_goals(ai_goal *aigp)
{
int i;
ship_obj *sop;
@@ -1196,7 +1361,7 @@ void ai_goal_purge_all_invalid_goals(ai_goal *aigp)
}
// Goober5000
int ai_goal_find_dockpoint(int shipnum, int dock_type)
int aigoal_ai_goal_find_dockpoint(int shipnum, int dock_type)
{
int dock_index = -1;
int loop_count = 0;
@@ -1247,7 +1412,7 @@ int ai_goal_find_dockpoint(int shipnum, int dock_type)
// passed are the pointer to goal we are working with. aip if the ai_info pointer
// of the ship with the order. aigp is a pointer to the goal (of aip) of which we are
// fixing up the docking points
void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
void aigoal_ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
{
int shipnum, docker_index, dockee_index;
@@ -1318,7 +1483,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
// from the mission goals (i.e. those goals which come from events) in that we don't
// use sexpressions for goals from the player...so we enumerate all the parameters
void ai_add_goal_sub_player(int type, int mode, int submode, char *shipname, ai_goal *aigp )
void aigoal_ai_add_goal_sub_player(int type, int mode, int submode, char *shipname, ai_goal *aigp )
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
@@ -1359,7 +1524,7 @@ void ai_add_goal_sub_player(int type, int mode, int submode, char *shipname, ai_
// friendlies want to rearm at the same time. The support ship forgets what it's doing and flies
// off to repair somebody while still docked. I reproduced this with retail, so it's not a bug in
// my new docking code. :)
int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
int aigoal_ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
{
int gindex, oldest_index;
@@ -1389,7 +1554,7 @@ int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
// is issued to ship or wing (from player), mode is AI_GOAL_*. submode is the submode the
// ship should go into. shipname is the object of the action. aip is the ai_info pointer
// of the ship receiving the order
void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip )
void aigoal_ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip )
{
int empty_index;
ai_goal *aigp;
@@ -1415,7 +1580,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, a
// adds a goal from the player to the given wing (which in turn will add it to the proper
// ships in the wing
void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum )
void aigoal_ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum )
{
int i, empty_index;
wing *wingp = &Wings[wingnum];
@@ -1439,7 +1604,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
// common routine to add a sexpression mission goal to the appropriate goal structure.
void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
void aigoal_ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
{
int node, dummy, op;
char *text;
@@ -1630,7 +1795,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
// adds an ai goal for an individual ship
// type determines who has issues this ship a goal (i.e. the player/mission event/etc)
void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
void aigoal_ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
{
int gindex;
@@ -1639,7 +1804,7 @@ void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
}
// code to add ai goals to wings.
void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
void aigoal_ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
{
int i;
wing *wingp = &Wings[wingnum];
@@ -1673,7 +1838,7 @@ void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
// this name can be a shipname or a wingname)
// docker_point and dockee_point are used for the AI_GOAL_DOCK command to tell two ships where to dock
// immediate means to process this order right away
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate )
void aigoal_ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate )
{
int gindex;
ai_goal *aigp;
@@ -1753,7 +1918,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int doc
// across waves of the wing so we merely need to add the goal to each ship in the wing. Certain
// goal are simply not valid for wings (like dock, undock). Immediate parameter gets passed to add_ship_goal
// to say whether or not we should process this goal right away
void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate )
void aigoal_ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate )
{
int i;
@@ -1769,7 +1934,7 @@ void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int imme
}
// this function copies goals from a wing to an ai_info * from a ship.
void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
void aigoal_ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
{
int j;
@@ -1790,7 +1955,7 @@ void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
// function to determine if an ai goal is achieveable or not. Will return
// one of the AI_GOAL_* values. Also determines is a goal was successful.
int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
int aigoal_ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
int status;
char *ai_shipname;
@@ -2269,7 +2434,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// Compare function for sorting ai_goals based on priority.
// Return values set to sort array in _decreasing_ order.
int ai_goal_priority_compare(const void *a, const void *b)
int aigoal_ai_goal_priority_compare(const void *a, const void *b)
{
ai_goal *ga, *gb;
@@ -2318,7 +2483,7 @@ int ai_goal_priority_compare(const void *a, const void *b)
// Then sort on time for goals of equivalent priority.
// objnum The object number to act upon. Redundant with *aip.
// *aip The AI info to act upon. Goals are stored at aip->goals
void prioritize_goals(int objnum, ai_info *aip)
void aigoal_prioritize_goals(int objnum, ai_info *aip)
{
// First sort based on priority field.
insertion_sort(aip->goals, MAX_AI_GOALS, sizeof(ai_goal), ai_goal_priority_compare);
@@ -2328,7 +2493,7 @@ void prioritize_goals(int objnum, ai_info *aip)
// Remove obsolete goals.
// objnum Object of interest. Redundant with *aip.
// *aip contains goals at aip->goals.
void validate_mission_goals(int objnum, ai_info *aip)
void aigoal_validate_mission_goals(int objnum, ai_info *aip)
{
int i;
@@ -2403,7 +2568,7 @@ extern char *Mode_text[MAX_AI_BEHAVIORS];
// code to process ai "orders". Orders include those determined from the mission file and those
// given by the player to a ship that is under his control. This function gets called for every
// AI object every N seconds through the ai loop.
void ai_process_mission_orders( int objnum, ai_info *aip )
void aigoal_ai_process_mission_orders( int objnum, ai_info *aip )
{
object *objp = &Objects[objnum];
object *other_obj;
@@ -2724,7 +2889,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
}
void ai_update_goal_references(ai_goal *goals, int type, char *old_name, char *new_name)
void aigoal_ai_update_goal_references(ai_goal *goals, int type, char *old_name, char *new_name)
{
int i, mode, flag, dummy;
@@ -2791,7 +2956,7 @@ void ai_update_goal_references(ai_goal *goals, int type, char *old_name, char *n
}
}
int query_referenced_in_ai_goals(ai_goal *goals, int type, char *name)
int aigoal_query_referenced_in_ai_goals(ai_goal *goals, int type, char *name)
{
int i, mode, flag;
@@ -2856,7 +3021,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, char *name)
return 0;
}
char *ai_add_dock_name(char *str)
char *aigoal_ai_add_dock_name(char *str)
{
char *ptr;
int i;
@@ -2871,3 +3036,39 @@ char *ai_add_dock_name(char *str)
strcpy(ptr, str);
return ptr;
}
struct aigoal_call_table AIGoalDefaultTable = {
aigoal_Ai_goal_text,
aigoal_ai_maybe_add_form_goal,
aigoal_ai_post_process_mission,
aigoal_ai_query_goal_valid,
aigoal_ai_remove_ship_goal,
aigoal_ai_clear_ship_goals,
aigoal_ai_clear_wing_goals,
aigoal_ai_mission_wing_goal_complete,
aigoal_ai_mission_goal_complete,
aigoal_ai_get_subsystem_type,
aigoal_ai_goal_purge_invalid_goals,
aigoal_ai_goal_purge_all_invalid_goals,
aigoal_ai_goal_find_dockpoint,
aigoal_ai_goal_fixup_dockpoints,
aigoal_ai_add_goal_sub_player,
aigoal_ai_goal_find_empty_slot,
aigoal_ai_add_ship_goal_player,
aigoal_ai_add_wing_goal_player,
aigoal_ai_add_goal_sub_sexp,
aigoal_ai_add_ship_goal_sexp,
aigoal_ai_add_wing_goal_sexp,
aigoal_ai_add_goal_ship_internal,
aigoal_ai_add_goal_wing_internal,
aigoal_ai_copy_mission_wing_goal,
aigoal_ai_mission_goal_achievable,
aigoal_ai_goal_priority_compare,
aigoal_prioritize_goals,
aigoal_validate_mission_goals,
aigoal_ai_process_mission_orders,
aigoal_ai_update_goal_references,
aigoal_query_referenced_in_ai_goals,
aigoal_ai_add_dock_name
};
+44
View File
@@ -292,4 +292,48 @@ extern int ai_query_goal_valid( int ship, int ai_goal );
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
extern void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate = 1 );
// AI Goal Table Wrapper
struct aigoal_call_table
{
char* (*Ai_goal_text) (int goal);
void (*ai_maybe_add_form_goal) (wing *wingp);
void (*ai_post_process_mission) ();
int (*ai_query_goal_valid) (int ship, int ai_goal);
void (*ai_remove_ship_goal) (ai_info *aip, int index);
void (*ai_clear_ship_goals) (ai_info *aip);
void (*ai_clear_wing_goals) (int wingnum);
void (*ai_mission_wing_goal_complete) (int wingnum, ai_goal *remove_goalp);
void (*ai_mission_goal_complete) (ai_info *aip);
int (*ai_get_subsystem_type) (char *subsystem);
void (*ai_goal_purge_invalid_goals) (ai_goal *aigp, ai_goal *goal_list);
void (*ai_goal_purge_all_invalid_goals) (ai_goal *aigp);
int (*ai_goal_find_dockpoint) (int shipnum, int dock_type);
void (*ai_goal_fixup_dockpoints) (ai_info *aip, ai_goal *aigp);
void (*ai_add_goal_sub_player) (int type, int mode, int submode, char *shipname, ai_goal *aigp);
int (*ai_goal_find_empty_slot) (ai_goal *goals, int active_goal);
void (*ai_add_ship_goal_player) (int type, int mode, int submode, char *shipname, ai_info *aip);
void (*ai_add_wing_goal_player) (int type, int mode, int submode, char *shipname, int wingnum);
void (*ai_add_goal_sub_sexp) (int sexp, int type, ai_goal *aigp, char *actor_name);
void (*ai_add_ship_goal_sexp) (int sexp, int type, ai_info *aip);
void (*ai_add_wing_goal_sexp) (int sexp, int type, int wingnum);
void (*ai_add_goal_ship_internal) (ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate);
void (*ai_add_goal_wing_internal) (wing *wingp, int goal_type, char *name, int immediate);
void (*ai_copy_mission_wing_goal) (ai_goal *aigp, ai_info *aip);
int (*ai_mission_goal_achievable) (int objnum, ai_goal *aigp);
int (*ai_goal_priority_compare) (const void *a, const void *b);
void (*prioritize_goals) (int objnum, ai_info *aip);
void (*validate_mission_goals) (int objnum, ai_info *aip);
void (*ai_process_mission_orders) (int objnum, ai_info *aip);
void (*ai_update_goal_references) (ai_goal *goals, int type, char *old_name, char *new_name);
int (*query_referenced_in_ai_goals) (ai_goal *goals, int type, char *name);
char* (*ai_add_dock_name) (char *str);
};
// Set new pointer to override ai_goal* function calls
// possibly copying the old function calls first
extern struct aigoal_call_table *aigoal_table;
extern struct aigoal_call_table AIGoalDefaultTable;
#endif
+255
View File
@@ -10,6 +10,22 @@
#ifndef _AIINTERNAL_H
#define _AIINTERNAL_H
#include "weapon/weapon.h"
#include "weapon/swarm.h"
#include "object/objectdock.h"
typedef struct eval_nearest_objnum {
int objnum;
object *trial_objp;
int enemy_team_mask;
int enemy_wing;
float range;
int max_attackers;
int nearest_objnum;
float nearest_dist;
int check_danger_weapon_objnum;
} eval_nearest_objnum;
//Returns true if the specified object is a stealth ship, false if not
bool is_object_stealth_ship(object* objp);
@@ -28,4 +44,243 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip);
//Does all the stuff needed to aim and fire a turret.
void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum);
// AI Turret Table Wrapper
struct eval_enemy_obj_struct;
struct aiturret_call_table
{
int (*turret_select_best_weapon) (ship_subsys *turret, object *target);
int (*valid_turret_enemy) (object *objp, object *turret_parent);
void (*evaluate_obj_as_target) (object *objp, eval_enemy_obj_struct *eeo);
int (*get_nearest_turret_objnum) (int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag);
int (*find_turret_enemy) (ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy, float fov);
int (*turret_should_pick_new_target) (ship_subsys *turret);
void (*turret_set_next_fire_timestamp) (int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip);
int (*turret_should_fire_aspect) (ship_subsys *turret, float dot, weapon_info *wip);
bool (*turret_fire_weapon) (int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos, float flak_range_override);
void (*turret_swarm_fire_from_turret) (turret_swarm_info *tsi);
void (*ai_fire_from_turret) (ship *shipp, ship_subsys *ss, int parent_objnum);
};
// Set new pointer to override ai_goal* function calls
// possibly copying the old function calls first
extern struct aiturret_call_table *aiturret_table;
extern struct aiturret_call_table AITurretDefaultTable;
// AI Code Table Wrapper
struct aicode_call_table
{
void (*ai_set_rearm_status) (int team, int time);
int (*ai_good_time_to_rearm) (object *objp);
void (*ai_good_secondary_time) (int team, int weapon_index, int max_fire_count, char *shipname);
int (*is_preferred_weapon) (int weapon_num, object *firer_objp, object *target_objp);
void (*ai_init_secondary_info) ();
void (*free_ai_stuff) ();
void (*parse_ai_class) ();
void (*reset_ai_class_names) ();
void (*parse_aitbl) ();
void (*ai_init) ();
void (*ai_level_init) ();
int (*ai_is_stealth_visible) (object *viewer_objp, object *stealth_objp);
void (*update_ai_stealth_info_with_error) (ai_info *aip);
void (*ai_update_danger_weapon) (int attacked_objnum, int weapon_objnum);
void (*ai_turn_towards_vector) (vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags);
void (*init_ship_info) ();
int (*set_target_objnum) (ai_info *aip, int objnum);
ship_subsys* (*set_targeted_subsys) (ai_info *aip, ship_subsys *new_subsys, int parent_objnum);
void (*ai_object_init) (object *obj, int ai_index);
void (*adjust_accel_for_docking) (ai_info *aip);
void (*accelerate_ship) (ai_info *aip, float accel);
void (*change_acceleration) (ai_info *aip, float delta_accel);
void (*set_accel_for_target_speed) (object *objp, float tspeed);
void (*turn_towards_point) (object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
void (*turn_away_from_point) (object *objp, vec3d *point, float bank_override);
float (*turn_towards_tangent) (object *objp, vec3d *point, float radius);
float (*turn_toward_tangent_with_axis) (object *objp, object *center_objp, float radius);
int (*object_is_targetable) (object *target, ship *viewer);
int (*num_enemies_attacking) (int objnum);
float (*get_wing_lowest_max_speed) (object *objp);
int (*is_ignore_object_sub) (int *ignore_objnum, int *ignore_signature, int objnum);
int (*find_ignore_new_object_index) (ai_info *aip, int objnum);
int (*is_ignore_object) (ai_info *aip, int objnum, int just_the_original=0);
int (*get_nearest_bbox_point) (object *ship_obj, vec3d *start, vec3d *box_pt);
void (*evaluate_object_as_nearest_objnum) (eval_nearest_objnum *eno);
int (*get_nearest_objnum) (int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers);
int (*find_nearby_threat) (int objnum, int enemy_team_mask, float range, int *count);
int (*num_turrets_attacking) (object *turret_parent, int target_objnum);
int (*get_enemy_timestamp) ();
int (*find_enemy) (int objnum, float range, int max_attackers);
void (*ai_set_goal_maybe_abort_dock) (object *objp, ai_info *aip);
void (*force_avoid_player_check) (object *objp, ai_info *aip);
void (*ai_attack_object) (object *attacker, object *attacked, int priority, ship_subsys *ssp);
void (*ai_attack_wing) (object *attacker, int wingnum, int priority);
void (*ai_evade_object) (object *evader, object *evaded, int priority);
int (*compact_ignore_new_objects) (ai_info *aip, int force=0);
void (*ai_ignore_object) (object *ignorer, object *ignored, int priority, int ignore_new);
void (*ai_ignore_wing) (object *ignorer, int wingnum, int priority);
void (*create_model_path) (object *pl_objp, object *mobjp, int path_num, int subsys_path);
void (*create_model_exit_path) (object *pl_objp, object *mobjp, int path_num, int count);
void (*ai_find_path) (object *pl_objp, int objnum, int path_num, int exit_flag, int subsys_path);
int (*maybe_avoid_player) (object *objp, vec3d *goal_pos);
void (*ai_stay_still) (object *still_objp, vec3d *view_pos);
void (*ai_do_objects_docked_stuff) (object *docker, int docker_point, object *dockee, int dockee_point);
void (*ai_do_objects_undocked_stuff) (object *docker, object *dockee);
void (*ai_dock_with_object) (object *docker, int docker_index, object *dockee, int dockee_index, int priority, int dock_type);
void (*ai_start_fly_to_ship) (object *objp, int shipnum);
void (*ai_start_waypoints) (object *objp, int waypoint_list_index, int wp_flags);
void (*ai_do_stay_near) (object *objp, object *other_objp, float dist);
void (*ai_do_safety) (object *objp);
void (*ai_form_on_wing) (object *objp, object *goal_objp);
int (*ai_formation_object_get_slotnum) (int objnum, object *objp);
float (*compute_time_to_enemy) (float dist_to_enemy, object *pobjp, object *eobjp);
void (*ai_set_positions) (object *pl_objp, object *en_objp, ai_info *aip, vec3d *player_pos, vec3d *enemy_pos);
float (*maybe_recreate_path) (object *objp, ai_info *aip, int force_recreate_flag, int override_hash=0);
void (*set_accel_for_docking) (object *objp, ai_info *aip, float dot, float dot_to_next, float dist_to_next, float dist_to_goal, ship_info *sip);
float (*ai_path) ();
void (*ai_safety_pick_spot) (object *objp);
float (*ai_safety_goto_spot) (object *objp);
void (*ai_safety_circle_spot) (object *objp);
void (*ai_safety) ();
void (*ai_fly_to_ship) ();
void (*ai_waypoints) ();
void (*avoid_ship) ();
int (*maybe_resume_previous_mode) (object *objp, ai_info *aip);
int (*ai_maybe_fire_afterburner) (object *objp, ai_info *aip);
void (*maybe_afterburner_after_ship_hit) (object *objp, ai_info *aip, object *en_objp);
int (*is_instructor) (object *objp);
void (*evade_weapon) ();
void (*slide_face_ship) ();
void (*evade_ship) ();
void (*ai_evade) ();
int (*ai_select_primary_weapon_OLD) (object *objp, object *other_objp, int flags);
int (*ai_select_primary_weapon) (object *objp, object *other_objp, int flags);
void (*set_primary_weapon_linkage) (object *objp);
int (*ai_fire_primary_weapon) (object *objp);
void (*ai_select_secondary_weapon) (object *objp, ship_weapon *swp, int priority1=-1, int priority2=-1);
void (*ai_maybe_announce_shockwave_weapon) (object *firing_objp, int weapon_index);
int (*check_ok_to_fire) (int objnum, int target_objnum, weapon_info *wip);
int (*ai_fire_secondary_weapon) (object *objp, int priority1, int priority2);
void (*set_predicted_enemy_pos_turret) (vec3d *predicted_enemy_pos, vec3d *gun_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
void (*set_predicted_enemy_pos) (vec3d *predicted_enemy_pos, object *pobjp, object *eobjp, ai_info *aip);
void (*ai_chase_ct) ();
void (*ai_chase_eb) (ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float dist_to_enemy);
float (*ai_endangered_time) (object *ship_objp, object *weapon_objp);
float (*ai_endangered_by_weapon) (ai_info *aip);
int (*ai_near_full_strength) (object *objp);
void (*attack_set_accel) (ai_info *aip, float dist_to_enemy, float dot_to_enemy, float dot_from_enemy);
void (*get_behind_ship) (ai_info *aip, ship_info *sip, float dist_to_enemy);
int (*avoid_player) (object *objp, vec3d *goal_pos);
int (*maybe_avoid_big_ship) (object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
void (*ai_stealth_find) ();
void (*ai_stealth_sweep) ();
void (*ai_chase_attack) (ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float dist_to_enemy, int modelnum);
void (*ai_chase_es) (ai_info *aip, ship_info *sip);
void (*ai_chase_ga) (ai_info *aip, ship_info *sip);
int (*ai_set_attack_subsystem) (object *objp, int subnum);
void (*ai_set_guard_vec) (object *objp, object *guard_objp);
void (*ai_set_guard_wing) (object *objp, int wingnum);
void (*ai_set_evade_object) (object *objp, object *other_objp);
void (*ai_set_guard_object) (object *objp, object *other_objp);
void (*update_aspect_lock_information) (ai_info *aip, vec3d *vec_to_enemy, float dist_to_enemy, float enemy_radius);
void (*ai_chase_fly_away) (object *objp, ai_info *aip);
int (*has_preferred_secondary) (object *objp, object *en_objp, ship_weapon *swp);
void (*ai_choose_secondary_weapon) (object *objp, ai_info *aip, object *en_objp);
float (*set_secondary_fire_delay) (ai_info *aip, ship *shipp, weapon_info *swip);
void (*ai_chase_big_approach_set_goal) (vec3d *goal_pos, object *attack_objp, object *target_objp, float *accel);
void (*ai_chase_big_circle_set_goal) (vec3d *goal_pos, object *attack_objp, object *target_objp, float *accel);
void (*ai_chase_big_get_separations) (object *attack_objp, object *target_objp, vec3d *horz_vec_to_target, float *desired_separation, float *cur_separation);
void (*ai_chase_big_parallel_set_goal) (vec3d *goal_pos, object *attack_objp, object *target_objp, float *accel);
void (*ai_cruiser_chase_set_goal_pos) (vec3d *goal_pos, object *pl_objp, object *en_objp);
int (*maybe_hack_cruiser_chase_abort) ();
void (*ai_cruiser_chase) ();
void (*ai_chase) ();
int (*num_ships_attacking) (int target_objnum);
void (*remove_farthest_attacker) (int objnum);
int (*ai_maybe_limit_attackers) (int attacked_objnum);
void (*guard_object_was_hit) (object *guard_objp, object *hitter_objp);
void (*maybe_update_guard_object) (object *hit_objp, object *hitter_objp);
int (*ai_guard_find_nearby_bomb) (object *guarding_objp, object *guarded_objp);
void (*ai_guard_find_nearby_ship) (object *guarding_objp, object *guarded_objp);
void (*ai_guard_find_nearby_asteroid) (object *guarding_objp, object *guarded_objp);
void (*ai_guard_find_nearby_object) ();
void (*ai_big_guard) ();
void (*ai_guard) ();
void (*ai_do_objects_repairing_stuff) (object *repaired_objp, object *repair_objp, int how);
void (*ai_cleanup_dock_mode_subjective) (object *objp);
void (*ai_cleanup_dock_mode_objective) (object *objp);
void (*ai_cleanup_rearm_mode) (object *objp);
void (*ai_still) ();
void (*ai_stay_near) ();
int (*maybe_dock_obstructed) (object *cur_objp, object *goal_objp, int big_only_flag);
void (*ai_dock) ();
void (*process_subobjects) (int objnum);
void (*ai_fly_in_formation) (int wingnum);
void (*ai_disband_formation) (int wingnum);
int (*formation_is_leader_chaotic) (object *objp);
void (*ai_most_massive_object_of_its_wing_of_all_docked_objects_helper) (object *objp, dock_function_info *infop);
int (*ai_formation) ();
void (*ai_do_repair_frame) (object *objp, ai_info *aip, float frametime);
void (*call_doa) (object *child, object *parent);
void (*ai_maybe_launch_cmeasure) (object *objp, ai_info *aip);
void (*ai_preprocess_ignore_objnum) (object *objp, ai_info *aip);
void (*ai_chase_circle) (object *objp);
void (*ai_transfer_shield) (object *objp, int quadrant_num);
void (*ai_balance_shield) (object *objp);
void (*ai_manage_shield) (object *objp, ai_info *aip);
void (*ai_maybe_evade_locked_missile) (object *objp, ai_info *aip);
void (*maybe_evade_dumbfire_weapon) (ai_info *aip);
int (*ai_acquire_emerge_path) (object *pl_objp, int parent_objnum, int allowed_path_mask, vec3d *pos, vec3d *fvec);
void (*ai_emerge_bay_path_cleanup) (ai_info *aip);
void (*ai_bay_emerge) ();
int (*ai_find_closest_depart_path) (ai_info *aip, polymodel *pm, int allowed_path_mask);
int (*ai_acquire_depart_path) (object *pl_objp, int parent_objnum, int allowed_path_mask);
void (*ai_bay_depart) ();
void (*ai_sentrygun) ();
void (*ai_execute_behavior) (ai_info *aip);
int (*maybe_request_support) (object *objp);
void (*ai_set_mode_warp_out) (object *objp, ai_info *aip);
void (*ai_maybe_depart) (object *objp);
void (*ai_warp_out) (object *objp);
void (*ai_announce_ship_dying) (object *dying_objp);
int (*aas_1) (object *objp, ai_info *aip, vec3d *safe_pos);
int (*ai_avoid_shockwave) (object *objp, ai_info *aip);
int (*ai_await_repair_frame) (object *objp, ai_info *aip);
void (*ai_maybe_self_destruct) (object *objp, ai_info *aip);
int (*ai_need_new_target) (object *pl_objp, int target_objnum);
int (*maybe_big_ship_collide_recover_frame) (object *objp, ai_info *aip);
void (*validate_mode_submode) (ai_info *aip);
void (*ai_frame) (int objnum);
void (*ai_process) (object *obj, int ai_index, float frametime);
void (*init_ai_object) (int objnum);
void (*init_ai_objects) ();
void (*init_ai_system) ();
void (*ai_set_default_behavior) (object *obj, int classnum);
void (*ai_do_default_behavior) (object *obj);
void (*process_friendly_hit_message) (int message, object *objp);
void (*maybe_process_friendly_hit) (object *objp_hitter, object *objp_hit, object *objp_weapon);
void (*maybe_set_dynamic_chase) (ai_info *aip, int hitter_objnum);
void (*big_ship_collide_recover_start) (object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
void (*ai_update_lethality) (object *ship_obj, object *other_obj, float damage);
void (*ai_ship_hit) (object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
void (*ai_ship_destroy) (int shipnum, int method);
void (*ai_deathroll_start) (object *dying_objp);
int (*ai_abort_rearm_request) (object *requester_objp);
void (*ai_add_rearm_goal) (object *requester_objp, object *support_objp);
int (*ai_issue_rearm_request) (object *requester_objp);
void (*ai_rearm_repair) (object *objp, int docker_index, object *goal_objp, int dockee_index, int priority);
void (*cheat_fire_synaptic) (object *objp, ship *shipp, ai_info *aip);
void (*maybe_cheat_fire_synaptic) (object *objp, ai_info *aip);
};
// Set new pointer to override ai_code* function calls
// possibly copying the old function calls first
extern struct aicode_call_table *aicode_table;
extern struct aicode_call_table AICodeDefaultTable;
#endif
+185
View File
@@ -0,0 +1,185 @@
/**
* @file aimodular.cpp
* @brief Modular loading of new AI code based on name in AI Profile.
*
* The ai_module_init function should be called by ai_init.
*
* @author Fabian Franz <[email protected]>
*
*/
#include "ai/aibig.h"
#include "ai/aigoals.h"
#include "ai/aiinternal.h"
#ifdef _WIN32
#include <Windows.h>
/** @brief Wrapper for the dlopen functions for Windows */
#define dlopen(x,y) ((x==NULL)?GetModuleHandle(x):LoadLibrary(x))
#define dlsym GetProcAddress
#define dlclose FreeLibrary
static HINSTANCE handle = NULL; /**< @brief Handle for the loaded library */
#else
#include <dlfcn.h>
static void* handle = NULL; /**< @brief Handle for the loaded library */
#endif
/** @brief ai_module_init_function prototype */
typedef void (*ai_module_init_function)(void);
void ai_module_dlclose(void);
/**
* @brief Fallback function to load new AI from same process image.
*
* This function is used if no dynamic library with the name can be found
* or it does not contain the correct symbol.
*
* @param func_name The symbol to look for in handle
* @return Returns 0 on success and -1,-2 on errors
*
*/
int ai_module_dlopen_process(char* func_name)
{
ai_module_init_function ai_module_init_func;
// Maybe close handle first
ai_module_dlclose();
handle = dlopen(NULL, RTLD_NOW);
if (handle == NULL)
return -1;
ai_module_init_func=(ai_module_init_function)dlsym(handle, func_name);
#ifdef _WIN32
// Under WIN32 GetModuleHandle is not
// incrementing the reference counter
// so we need to "free" the handle directly
handle=NULL;
#endif
if (ai_module_init_func == NULL)
return -2;
ai_module_init_func();
return 0;
}
/**
* @brief Loads new AI from dynamic library
*
* This function looks for dllname.dll or dllname.so
* tries to load it into memory and if it finds the
* dllname_ai_module_init function it starts it.
*
* If it does not find the library or symbol it falls
* back to ai_module_dlopen_process.
*
* @param dllname The name of the library to load
* @return Returns 0 on success and -1,-2 on errors
*
*/
int ai_module_dlopen(char* dllname)
{
char buf[PATH_MAX+1];
char init_func_name[PATH_MAX+1];
ai_module_init_function ai_module_init_func;
#ifdef _WIN32
snprintf(buf, PATH_MAX, "%s.dll", dllname);
#else
snprintf(buf, PATH_MAX, "%s.so", dllname);
#endif
snprintf(init_func_name, PATH_MAX, "%s_ai_module_init", dllname);
handle = dlopen(buf, RTLD_NOW);
if (handle == NULL)
return ai_module_dlopen_process(init_func_name);
ai_module_init_func=(ai_module_init_function)dlsym(handle, init_func_name);
if (ai_module_init_func == NULL)
return ai_module_dlopen_process(init_func_name);
ai_module_init_func();
return 0;
}
/**
* @brief Closes the library handle
*
* This function closes the library handle.
*
*/
void ai_module_dlclose(void)
{
if (handle != NULL)
{
dlclose(handle);
handle=NULL;
}
}
/**
* @brief Inits or resets the AI code tables
*
* This function first resets the AI code tables,
* then closes any open libraries from before.
*
* Then it ooks if the ai_module is not "retail"
* and if that is the case it loads a library with this name.
*
*/
void ai_module_init(void)
{
// First Reset values
aibig_table = &AIBigDefaultTable;
aicode_table = &AICodeDefaultTable;
aigoal_table = &AIGoalDefaultTable;
aiturret_table = &AITurretDefaultTable;
ai_module_dlclose();
if (The_mission.ai_profile == NULL)
return;
if (strncmp(The_mission.ai_profile->ai_module, "retail", 6) != 0)
{
if (ai_module_dlopen(The_mission.ai_profile->ai_module) != 0)
{
char err[1024];
snprintf(err, sizeof(err), "AI_module_init(%s) failed: %s\n", The_mission.ai_profile->ai_module, dlerror());
mprintf(err);
}
}
}
extern "C" {
void newai_ai_module_init(void);
}
/**
* @brief Dummy function
*
* This dummy functions calls all AI implementations
* that should be statically included.
*
*/
void ai_module_dummy()
{
newai_ai_module_init();
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef _AIMODULAR_H
#define _AIMODULAR_H
void ai_module_init(void);
#endif
+89 -22
View File
@@ -233,6 +233,69 @@ typedef struct eval_enemy_obj_struct {
int nearest_objnum;
} eval_enemy_obj_struct;
// FF 17-06-07
// AI Turret Table Wrapper
struct aiturret_call_table *aiturret_table = &AITurretDefaultTable;
int turret_select_best_weapon (ship_subsys *turret, object *target)
{
return aiturret_table->turret_select_best_weapon(turret, target);
}
int valid_turret_enemy (object *objp, object *turret_parent)
{
return aiturret_table->valid_turret_enemy(objp, turret_parent);
}
void evaluate_obj_as_target (object *objp, eval_enemy_obj_struct *eeo)
{
aiturret_table->evaluate_obj_as_target(objp, eeo);
}
int get_nearest_turret_objnum (int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag)
{
return aiturret_table->get_nearest_turret_objnum(turret_parent_objnum, turret_subsys, enemy_team_mask, tpos, tvec, current_enemy, big_only_flag, small_only_flag, tagged_only_flag, beam_flag);
}
int find_turret_enemy (ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy, float fov)
{
return aiturret_table->find_turret_enemy(turret_subsys, objnum, tpos, tvec, current_enemy, fov);
}
int turret_should_pick_new_target (ship_subsys *turret)
{
return aiturret_table->turret_should_pick_new_target(turret);
}
void turret_set_next_fire_timestamp (int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip)
{
aiturret_table->turret_set_next_fire_timestamp(weapon_num, wip, turret, aip);
}
int turret_should_fire_aspect (ship_subsys *turret, float dot, weapon_info *wip)
{
return aiturret_table->turret_should_fire_aspect(turret, dot, wip);
}
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos = NULL, float flak_range_override = 100.0f)
{
return aiturret_table->turret_fire_weapon(weapon_num, turret, parent_objnum, turret_pos, turret_fvec, predicted_pos, flak_range_override);
}
void turret_swarm_fire_from_turret (turret_swarm_info *tsi)
{
aiturret_table->turret_swarm_fire_from_turret(tsi);
}
void ai_fire_from_turret (ship *shipp, ship_subsys *ss, int parent_objnum)
{
aiturret_table->ai_fire_from_turret(shipp, ss, parent_objnum);
}
// AI Turret default implementation
// return 1 if objp is in fov of the specified turret, tp. Otherwise return 0.
// dist = distance from turret to center point of object
int object_in_turret_fov(object *objp, model_subsystem *tp, vec3d *tvec, vec3d *tpos, float dist)
@@ -274,7 +337,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
//Note that all non-negative return values are expressed in
//what I like to call "widx"s.
//Returns -1 if unable to find a weapon for the target at all.
int turret_select_best_weapon(ship_subsys *turret, object *target)
int aiturret_turret_select_best_weapon(ship_subsys *turret, object *target)
{
//TODO: Fill this out with extraodinary gun-picking algorithms
if(turret->weapons.num_primary_banks > 0)
@@ -441,7 +504,7 @@ float longest_turret_weapon_range(ship_weapon *swp)
// input: objp => object that turret is considering as an enemy
// turret_parent => object index for ship that turret sits on
// turret => turret pointer
int valid_turret_enemy(object *objp, object *turret_parent)
int aiturret_valid_turret_enemy(object *objp, object *turret_parent)
{
if ( objp == turret_parent ) {
return 0;
@@ -505,7 +568,7 @@ int valid_turret_enemy(object *objp, object *turret_parent)
}
extern int Player_attacking_enabled;
void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
void aiturret_evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
{
object *turret_parent_obj = &Objects[eeo->turret_parent_objnum];
ship *shipp;
@@ -716,7 +779,7 @@ int is_target_beam_valid(ship_weapon *swp, object *objp)
// tpos => position of turret (world coords)
// tvec => forward vector of turret (world coords)
// current_enemy => objnum of current turret target
int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag)
int aiturret_get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag)
{
//float weapon_travel_dist;
int weapon_system_ok;
@@ -857,7 +920,7 @@ DCF_BOOL(use_parent_target, Use_parent_target)
// tpos => position of turret (world coords)
// tvec => forward vector of turret (world coords)
// current_enemy => objnum of current turret target
int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy, float fov)
int aiturret_find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy, float fov)
{
int enemy_team_mask, enemy_objnum;
model_subsystem *tp;
@@ -1201,7 +1264,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
}
// return !0 if the specified target should scan for a new target, otherwise return 0
int turret_should_pick_new_target(ship_subsys *turret)
int aiturret_turret_should_pick_new_target(ship_subsys *turret)
{
// int target_type;
@@ -1224,7 +1287,7 @@ int turret_should_pick_new_target(ship_subsys *turret)
}
// Set the next fire timestamp for a turret, based on weapon type and ai class
void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip)
void aiturret_turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
float wait = wip->fire_wait * 1000.0f;
@@ -1280,7 +1343,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
}
// Decide if a turret should launch an aspect seeking missile
int turret_should_fire_aspect(ship_subsys *turret, float dot, weapon_info *wip)
int aiturret_turret_should_fire_aspect(ship_subsys *turret, float dot, weapon_info *wip)
{
if ( (dot > AICODE_TURRET_DUMBFIRE_ANGLE) && (turret->turret_time_enemy_in_range >= MIN(wip->min_lock_time,AICODE_TURRET_MAX_TIME_IN_RANGE)) ) {
return 1;
@@ -1304,7 +1367,7 @@ void turret_update_enemy_in_range(ship_subsys *turret, float seconds)
}
// Fire a weapon from a turret
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos = NULL, float flak_range_override = 100.0f)
bool aiturret_turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *turret_fvec, vec3d *predicted_pos = NULL, float flak_range_override = 100.0f)
{
matrix turret_orient;
int weapon_objnum;
@@ -1355,11 +1418,6 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
// fire a beam weapon
beam_fire(&fire_info);
if (parent_ship->cloak_stage == 2) {
beam_weapon_info *bip=&wip->b_info;
shipfx_start_cloak(parent_ship,bip->beam_warmup + bip->beam_warmdown + (int)(bip->beam_life*1000.0f) + 1000);
}
return true;
}
// don't fire swam, but set up swarm info instead
@@ -1426,11 +1484,6 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
}
if ((parent_ship->cloak_stage > 0) && (parent_ship->cloak_stage < 3))
{
shipfx_start_cloak(parent_ship,500);
}
}
// reset any animations if we need to
@@ -1449,8 +1502,8 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
return true;
}
//void turret_swarm_fire_from_turret(ship_subsys *turret, int parent_objnum, int target_objnum, ship_subsys *target_subsys)
void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
//void aiturret_turret_swarm_fire_from_turret(ship_subsys *turret, int parent_objnum, int target_objnum, ship_subsys *target_subsys)
void aiturret_turret_swarm_fire_from_turret(turret_swarm_info *tsi)
{
int weapon_objnum;
matrix turret_orient;
@@ -1514,7 +1567,7 @@ int Num_find_turret_enemy = 0;
int Num_turrets_fired = 0;
// Given a turret tp and its parent parent_objnum, fire from the turret at its enemy.
extern int Nebula_sec_range;
void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
void aiturret_ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
{
float weapon_firing_range;
@@ -1985,3 +2038,17 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ss->turret_time_enemy_in_range = 0.0f;
}
}
struct aiturret_call_table AITurretDefaultTable = {
aiturret_turret_select_best_weapon,
aiturret_valid_turret_enemy,
aiturret_evaluate_obj_as_target,
aiturret_get_nearest_turret_objnum,
aiturret_find_turret_enemy,
aiturret_turret_should_pick_new_target,
aiturret_turret_set_next_fire_timestamp,
aiturret_turret_should_fire_aspect,
aiturret_turret_fire_weapon,
aiturret_turret_swarm_fire_from_turret,
aiturret_ai_fire_from_turret
};
+122
View File
@@ -0,0 +1,122 @@
#include "ai/aibig.h"
#include "ai/aigoals.h"
#include "ai/aiinternal.h"
struct aicode_call_table AICodeNewAITable;
#include "iff_defs/iff_defs.h"
#define DEPARTURE_HULL_PERCENT 0.3 // Departure if 15% to 30% hull strength left
void newai_ai_maybe_depart(object* objp_ship)
{
ship *shipp = &Ships[objp_ship->instance];
// Coward mode:
//
// Depart if:
// * not player and
// * same team as player and player not traitor and
// * fighter or bomber
// * hull multiplied with random value below critical
if (objp_ship->flags & OF_PLAYER_SHIP)
return;
// make sure player is on their team and not a traitor
if ((Player_ship->team != shipp->team) || (Player_ship->team == Iff_traitor))
return;
if ((Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER|SIF_BOMBER)) == 0)
return;
if (objp_ship->hull_strength*(frand()+1) < DEPARTURE_HULL_PERCENT * shipp->ship_max_hull_strength)
mission_do_departure(objp_ship);
}
// Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
void newai_aicode_ai_ship_hit (object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal)
{
// Call the default implementation
AICodeDefaultTable.ai_ship_hit(objp_ship, hit_objp, hitpos, shield_quadrant, hit_normal);
if (hit_objp->parent >= 0)
{
object *objp_hitter = &Objects[hit_objp->parent];
if ( objp_hitter->type == OBJ_SHIP )
{
ship *shipp_hitter = &Ships[objp_hitter->instance];
ship *shipp_hit = &Ships[objp_ship->instance];
fprintf(stderr, "Ship %s hit %s\n", shipp_hitter->ship_name, shipp_hit->ship_name);
}
}
newai_ai_maybe_depart(objp_ship);
}
void newai_aicode_maybe_process_friendly_hit(object *objp_hitter, object *objp_hit, object *objp_weapon)
{
AICodeDefaultTable.maybe_process_friendly_hit(objp_hitter, objp_hit, objp_weapon);
if (obj_team(objp_hitter) == obj_team(objp_hit))
{
if ( objp_hitter->type != OBJ_SHIP )
return;
ship *shipp_hitter = &Ships[objp_hitter->instance];
ship *shipp_hit = &Ships[objp_hit->instance];
fprintf(stderr, "Ship %s friendly hit %s\n", shipp_hitter->ship_name, shipp_hit->ship_name);
}
}
int newai_aicode_ai_fire_primary_weapon(object *objp)
{
int fired = AICodeDefaultTable.ai_fire_primary_weapon(objp);
if (fired)
{
ship *shipp = &Ships[objp->instance];
fprintf(stderr, "Ship %s fired primary weapon\n", shipp->ship_name);
}
}
void newai_aicode_init_ship_info()
{
static int called=0;
if (called == 0)
{
fprintf(stderr, "Init ship info was called\n");
called=1;
}
AICodeDefaultTable.init_ship_info();
}
extern "C" {
void newai_ai_module_init();
}
void newai_ai_module_init()
{
#ifdef PACKAGE_NAME
fprintf(stderr, "ai_module_init() called\n");
#else
fprintf(stderr, "ai_module_init() modular called\n");
#endif
// First make a copy
memcpy(&AICodeNewAITable, &AICodeDefaultTable, sizeof(AICodeNewAITable));
// Now set up our overridden functions
aicode_table = &AICodeNewAITable;
aicode_table->init_ship_info=newai_aicode_init_ship_info;
aicode_table->ai_ship_hit=newai_aicode_ai_ship_hit;
//aicode_table->ai_fire_primary_weapon=newai_aicode_ai_fire_primary_weapon;
//aicode_table->maybe_process_friendly_hit=newai_aicode_maybe_process_friendly_hit;
}
+3 -6
View File
@@ -4892,15 +4892,12 @@ sexp_list_item *sexp_tree::get_listing_opf(int opf, int parent_node, int arg_ind
// every-time-argument... meaning if either w_arg or e_arg is >= 1, we can continue
w_arg = find_ancestral_argument_number(OP_WHEN_ARGUMENT, current_node);
e_arg = find_ancestral_argument_number(OP_EVERY_TIME_ARGUMENT, current_node);
if (w_arg < 1 && e_arg < 1 /* && the same for any future _ARGUMENT sexps */ )
{
if (w_arg < 1 && e_arg < 1 /* && the same for any future _ARGUMENT sexps */ ) {
return list;
}
// also skip if the list is empty, and *also* skip for OPF_NULL, because
// it takes no data (though it can take plenty of operators)
if (list == NULL || opf == OPF_NULL)
{
// also skip for OPF_NULL, because it takes no data (though it can take plenty of operators)
if (opf == OPF_NULL) {
return list;
}
+16 -7
View File
@@ -231,7 +231,7 @@ void ssm_level_init()
}
// start a subspace missile effect
void ssm_create(vec3d *target, vec3d *start, int ssm_index, ssm_firing_info *override)
void ssm_create(object *target, vec3d *start, int ssm_index, ssm_firing_info *override, int team)
{
ssm_strike *ssm;
matrix dir;
@@ -280,13 +280,17 @@ void ssm_create(vec3d *target, vec3d *start, int ssm_index, ssm_firing_info *ove
else {
// forward orientation
vec3d temp;
vm_vec_sub(&temp, target, start);
vm_vec_normalize(&temp);
vm_vec_sub(&temp, &target->pos, start);
vm_vec_normalize(&temp);
vm_vector_2_matrix(&dir, &temp, NULL, NULL);
// stuff info
ssm->sinfo.ssm_index = ssm_index;
ssm->sinfo.target = *target;
ssm->sinfo.target = target;
ssm->sinfo.ssm_team = team;
for(idx=0; idx<Ssm_info[ssm_index].count; idx++){
ssm->sinfo.delay_stamp[idx] = timestamp(200 + (int)frand_range(-199.0f, 1000.0f));
ssm_get_random_start_pos(&ssm->sinfo.start_pos[idx], start, &dir, ssm_index);
@@ -326,6 +330,7 @@ void ssm_process()
int idx, finished;
ssm_strike *moveup, *next_one;
ssm_info *si;
int weapon_objnum;
// process all strikes
moveup=GET_FIRST(&Ssm_used_list);
@@ -351,12 +356,16 @@ void ssm_process()
vec3d temp;
matrix orient;
vm_vec_sub(&temp, &moveup->sinfo.target, &moveup->sinfo.start_pos[idx]);
vm_vec_sub(&temp, &moveup->sinfo.target->pos, &moveup->sinfo.start_pos[idx]);
vm_vec_normalize(&temp);
vm_vector_2_matrix(&orient, &temp, NULL, NULL);
// fire the missile and flash the screen
weapon_create(&moveup->sinfo.start_pos[idx], &orient, si->weapon_info_index, -1, -1, 1);
weapon_objnum = weapon_create(&moveup->sinfo.start_pos[idx], &orient, si->weapon_info_index, -1, -1, 1);
Weapons[Objects[weapon_objnum].instance].team = moveup->sinfo.ssm_team;
Weapons[Objects[weapon_objnum].instance].homing_object = moveup->sinfo.target;
Weapons[Objects[weapon_objnum].instance].target_sig = moveup->sinfo.target->signature;
// this makes this particular missile done
moveup->done_flags[idx] = 1;
@@ -368,7 +377,7 @@ void ssm_process()
vec3d temp;
matrix orient;
vm_vec_sub(&temp, &moveup->sinfo.target, &moveup->sinfo.start_pos[idx]);
vm_vec_sub(&temp, &moveup->sinfo.target->pos, &moveup->sinfo.start_pos[idx]);
vm_vec_normalize(&temp);
vm_vector_2_matrix(&orient, &temp, NULL, NULL);
moveup->fireballs[idx] = fireball_create(&moveup->sinfo.start_pos[idx], FIREBALL_WARP_EFFECT, -1, si->warp_radius, 0, &vmd_zero_vector, si->warp_time, 0, &orient);
+6 -5
View File
@@ -82,11 +82,12 @@ typedef struct ssm_info {
// creation info for the strike (useful for multiplayer)
typedef struct ssm_firing_info {
int delay_stamp[MAX_SSM_COUNT]; // timestamps
vec3d start_pos[MAX_SSM_COUNT]; // start positions
int delay_stamp[MAX_SSM_COUNT]; // timestamps
vec3d start_pos[MAX_SSM_COUNT]; // start positions
int ssm_index; // index info ssm_info array
vec3d target; // target for the strike
int ssm_index; // index info ssm_info array
struct object* target; // target for the strike
int ssm_team; // team that fired the ssm.
} ssm_firing_info;
// the strike itself
@@ -119,7 +120,7 @@ void hud_artillery_update();
void hud_artillery_render();
// start a subspace missile effect
void ssm_create(vec3d *target, vec3d *start, int ssm_index, ssm_firing_info *override);
void ssm_create(object *target, vec3d *start, int ssm_index, ssm_firing_info *override, int team);
// Goober5000
extern int ssm_info_lookup(char *name);
+1 -1
View File
@@ -1472,7 +1472,7 @@ void hud_squadmsg_send_to_all_fighters( int command, int player_num )
continue;
// send the command to the wing
if ( Wings[i].current_count > 1 ) {
if ( Wings[i].current_count > 0 ) {
if ( hud_squadmsg_send_wing_command(i, command, send_message, player_num) ) {
send_message = 0;
}
+12 -3
View File
@@ -4657,8 +4657,11 @@ void hud_show_lead_indicator(vec3d *target_world_pos)
// if we've reached here, the lead target indicator will be displayed
Players[Player_num].lead_indicator_active = 1;
if(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY)
vm_vec_sub2(&target_moving_direction, &Player_obj->phys_info.vel);
// test if the target is moving at all
if ( vm_vec_mag_quick(&targetp->phys_info.vel) < 0.1f && !(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) ) // Find distance!
if ( vm_vec_mag_quick(&target_moving_direction) < 0.1f ) // Find distance!
Players[Player_num].lead_target_pos = *target_world_pos;
else {
vm_vec_normalize(&target_moving_direction);
@@ -4726,8 +4729,11 @@ void hud_show_lead_indicator(vec3d *target_world_pos)
// if we've reached here, the lead target indicator will be displayed
Players[Player_num].lead_indicator_active = 1;
if(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY)
vm_vec_sub2(&target_moving_direction, &Player_obj->phys_info.vel);
// test if the target is moving at all
if ( vm_vec_mag_quick(&targetp->phys_info.vel) < 0.1f && !(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) ) // Find distance!
if ( vm_vec_mag_quick(&target_moving_direction) < 0.1f ) // Find distance!
Players[Player_num].lead_target_pos = *target_world_pos;
else {
vm_vec_normalize(&target_moving_direction);
@@ -4856,8 +4862,11 @@ void hud_show_lead_indicator_quick(vec3d *target_world_pos, object *targetp)
// if we've reached here, the lead target indicator will be displayed
Players[Player_num].lead_indicator_active = 1;
if(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY)
vm_vec_sub2(&target_moving_direction, &Player_obj->phys_info.vel);
// test if the target is moving at all
if ( vm_vec_mag_quick(&targetp->phys_info.vel) < 0.1f && !(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) ) // Find distance!
if ( vm_vec_mag_quick(&target_moving_direction) < 0.1f ) // Find distance!
Players[Player_num].lead_target_pos = *target_world_pos;
else {
vm_vec_normalize(&target_moving_direction);
+1
View File
@@ -985,6 +985,7 @@ void hud_targetbox_show_extra_ship_info(ship *target_shipp, object *target_objp)
if (dock_count == 1)
{
sprintf(outstr, XSTR("Docked: %s", 339), Ships[dock_get_first_docked_object(target_objp)->instance].ship_name);
end_string_at_first_hash_symbol(outstr);
}
// docked to multiple objects
else
+3 -1
View File
@@ -1990,7 +1990,9 @@ void message_queue_process()
// if this is a ship do we use name or alt name?
if ( Message_shipnum != -1 && (Ships[Message_shipnum].flags2 & SF2_USE_ALT_NAME_AS_CALLSIGN) ) {
mission_parse_lookup_alt_index(Ships[Message_shipnum].alt_type_index, who_from);
}
}
end_string_at_first_hash_symbol(who_from);
HUD_sourced_printf( q->source, NOX("%s: %s"), who_from, buf );
+9 -2
View File
@@ -4456,10 +4456,17 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
aip->ai_flags |= AIF_NO_DYNAMIC;
// update housekeeping variables
wingp->ship_index[p_objp->pos_in_wing] = Objects[objnum].instance;
// NOTE: for the initial wing setup we use actual position to get around
// object order isses, but ships in all following waves just get
// tacked onto the end of the list
if (wingp->current_wave == 1) {
wingp->ship_index[p_objp->pos_in_wing] = Objects[objnum].instance;
} else {
wingp->ship_index[wingp->current_count] = Objects[objnum].instance;
}
// set up wingman status index
hud_wingman_status_set_index(wingp->ship_index[p_objp->pos_in_wing]);
hud_wingman_status_set_index(Objects[objnum].instance);
p_objp->wing_status_wing_index = Ships[Objects[objnum].instance].wing_status_wing_index;
p_objp->wing_status_wing_pos = Ships[Objects[objnum].instance].wing_status_wing_pos;
+1 -1
View File
@@ -742,7 +742,7 @@ extern char Mission_filename[80]; // filename of mission in The_mission (Fred o
#define MAX_GOAL_TYPE_NAMES 3
// alternate ship type names
#define MAX_ALT_TYPE_NAMES 25
#define MAX_ALT_TYPE_NAMES 100
extern char Mission_alt_types[MAX_ALT_TYPE_NAMES][NAME_LENGTH];
extern int Mission_alt_type_count;
+281 -119
View File
@@ -1951,7 +1951,7 @@ sexp_oper Operators[] = {
{ "supernova-start", OP_SUPERNOVA_START, 1, 1 },
{ "shields-on", OP_SHIELDS_ON, 1, INT_MAX }, //-Sesquipedalian
{ "shields-off", OP_SHIELDS_OFF, 1, INT_MAX }, //-Sesquipedalian
{ "ship-tag", OP_SHIP_TAG, 3, 7 }, // Goober5000
{ "ship-tag", OP_SHIP_TAG, 3, 8 }, // Goober5000
{ "ship-untag", OP_SHIP_UNTAG, 1, 1 }, // Goober5000
{ "explosion-effect", OP_EXPLOSION_EFFECT, 11, 13 }, // Goober5000
{ "warp-effect", OP_WARP_EFFECT, 12, 12 }, // Goober5000
@@ -2182,6 +2182,9 @@ arg_item Sexp_applicable_argument_list;
bool is_blank_argument_op(int op_const);
bool is_blank_of_op(int op_const);
//Karajorma
bool is_generic_subsys(char *subsy_name);
bool ship_class_unchanged(int ship_index);
// Goober5000 - arg_item class stuff, borrowed from sexp_list_item class stuff -------------
void arg_item::add_data(char *str)
@@ -6213,7 +6216,10 @@ int sexp_hits_left_subsystem(int n)
ss = GET_NEXT( ss );
}
// we reached end of ship subsys list without finding subsys_name
Error(LOCATION, "Invalid subsystem '%s' passed to hits-left-subsystem or hits-left-single-subsystem", subsys_name);
if (ship_class_unchanged(shipnum)) {
Error(LOCATION, "Invalid subsystem '%s' passed to hits-left-subsystem", subsys_name);
}
return SEXP_NAN;
} else {
percent = (int)(ship_get_subsystem_strength(&Ships[shipnum],type) * 100.0f);
@@ -6405,7 +6411,8 @@ int sexp_distance(int n)
}
// locate the subsystem on a ship - Goober5000
void sexp_get_subsystem_world_pos(vec3d *subsys_world_pos, int shipnum, char *subsys_name)
// Karajorma - switched to a boolean so that it can report failure to do so
bool sexp_get_subsystem_world_pos(vec3d *subsys_world_pos, int shipnum, char *subsys_name)
{
Assert(subsys_name);
Assert(subsys_world_pos);
@@ -6426,14 +6433,17 @@ void sexp_get_subsystem_world_pos(vec3d *subsys_world_pos, int shipnum, char *su
{
// find world position of subsystem on this object (the ship)
get_subsystem_world_pos(&Objects[Ships[shipnum].objnum], ss, subsys_world_pos);
return;
return true;
}
ss = GET_NEXT( ss );
}
// we reached end of ship subsys list without finding subsys_name
Error(LOCATION, "sexp_get_subsystem_world_pos could not find subsystem '%s'", subsys_name);
Int3();
// we reached end of ship subsys list without finding subsys_name
if (ship_class_unchanged(shipnum)) {
// this ship should have had the subsystem named as it shouldn't have changed class
Error(LOCATION, "sexp_get_subsystem_world_pos could not find subsystem '%s'", subsys_name);
}
return false;
}
// Goober5000
@@ -6463,8 +6473,9 @@ int sexp_distance_subsystem(int n)
if (ship_with_subsys_num < 0)
return SEXP_NAN;
// get the subsystem's coordinates
sexp_get_subsystem_world_pos(&subsys_pos, ship_with_subsys_num, subsys_name);
// get the subsystem's coordinates or bail if we can't
if (!sexp_get_subsystem_world_pos(&subsys_pos, ship_with_subsys_num, subsys_name))
return SEXP_NAN;
switch (oswpt.type)
{
@@ -6716,7 +6727,9 @@ int sexp_get_object_coordinate(int n, int axis)
if ((subsystem_name != NULL) && stricmp(subsystem_name, SEXP_NONE_STRING) && stricmp(subsystem_name, SEXP_HULL_STRING))
{
pos = &subsys_pos_buf;
sexp_get_subsystem_world_pos(pos, oswpt.objp->instance, subsystem_name);
// get the world pos but bail if we can't get one
if (!sexp_get_subsystem_world_pos(pos, oswpt.objp->instance, subsystem_name))
return SEXP_NAN;
}
}
@@ -7551,8 +7564,7 @@ void sexp_set_scanned_unscanned(int n, int flag)
}
// if we didn't find the subsystem -- bad
if (!subsys_set)
{
if (!subsys_set && ship_class_unchanged(shipnum)) {
Error(LOCATION, "Couldn't find subsystem '%s' on ship '%s' in sexp_set_scanned_unscanned", subsys_name, ship_name);
}
@@ -8378,10 +8390,9 @@ int sexp_is_ai_class(int n)
ss = GET_NEXT( ss );
}
Assert(class_to_test >= 0);
// if no match, return false immediately
if (ai_class != class_to_test)
// if no match (or nothing to match), return false immediately
if ((class_to_test < 0) || (ai_class != class_to_test))
return SEXP_FALSE;
}
@@ -9307,10 +9318,11 @@ void sexp_end_campaign(int n)
void sexp_sabotage_subsystem(int n)
{
char *shipname, *subsystem;
int percentage, shipnum, index;
int percentage, shipnum, index, subsys_type;
float sabotage_hits;
ship *shipp;
ship_subsys *ss;
ship_subsys *ss, *ss_start;
bool generic, do_loop = true;
shipname = CTEXT(n);
subsystem = CTEXT(CDR(n));
@@ -9352,29 +9364,56 @@ void sexp_sabotage_subsystem(int n)
return;
}
// now find the given subsystem on the ship. The subsystem should be an actual subsystem name
// and not a generic type (generic type meaning SUBSYSTEM_ENGINE, etc).
// now find the given subsystem on the ship.This could be a generic type like <All Engines>
generic = is_generic_subsys(subsystem);
subsys_type = ai_get_subsystem_type(subsystem);
ss_start = GET_FIRST(&shipp->subsys_list);
index = ship_get_subsys_index(shipp, subsystem);
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for sabotage subsystem\n", subsystem, shipp->ship_name));
return;
while (do_loop) {
if (generic) {
// loop until we find a subsystem of that type
for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
ss = NULL;
if (subsys_type == ai_get_subsystem_type(ss_start->system_info->name)) {
ss = ss_start;
ss_start = GET_NEXT(ss_start);
break;
}
}
// reached the end of the subsystem list
if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
// If the last subsystem wasn't of interest we don't need to go any further
if (ss == NULL) {
return;
}
do_loop = false;
}
}
else {
do_loop = false;
index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for sabotage subsystem\n", subsystem, shipp->ship_name));
return;
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage if current strength is > given percentage
ss = ship_get_indexed_subsys( shipp, index );
}
sabotage_hits = ss->max_hits * ((float)percentage / 100.0f);
ss->current_hits -= sabotage_hits;
if ( ss->current_hits < 0.0f )
ss->current_hits = 0.0f;
// maybe blow up subsys
if (ss->current_hits <= 0) {
do_subobj_destroyed_stuff(shipp, ss, NULL);
}
ship_recalc_subsys_strength( shipp );
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage if current strength is > given percentage
ss = ship_get_indexed_subsys( shipp, index );
sabotage_hits = ss->max_hits * ((float)percentage / 100.0f);
ss->current_hits -= sabotage_hits;
if ( ss->current_hits < 0.0f )
ss->current_hits = 0.0f;
// maybe blow up subsys
if (ss->current_hits <= 0) {
do_subobj_destroyed_stuff(shipp, ss, NULL);
}
ship_recalc_subsys_strength( shipp );
}
// repair_subsystem adds some percentage of hits to a subsystem. Anything repaired about 100% is
@@ -9382,10 +9421,11 @@ void sexp_sabotage_subsystem(int n)
void sexp_repair_subsystem(int n)
{
char *shipname, *subsystem;
int percentage, shipnum, index, do_submodel_repair;
int percentage, shipnum, index, do_submodel_repair, subsys_type;
float repair_hits;
ship *shipp;
ship_subsys *ss;
ship_subsys *ss, *ss_start;
bool generic, do_loop = true;
shipname = CTEXT(n);
subsystem = CTEXT(CDR(n));
@@ -9430,39 +9470,67 @@ void sexp_repair_subsystem(int n)
return;
}
// now find the given subsystem on the ship. The subsystem should be an actual subsystem name
// and not a generic type (generic type meaning SUBSYSTEM_ENGINE, etc).
// now find the given subsystem on the ship.This could be a generic type like <All Engines>
generic = is_generic_subsys(subsystem);
subsys_type = ai_get_subsystem_type(subsystem);
ss_start = GET_FIRST(&shipp->subsys_list);
index = ship_get_subsys_index(shipp, subsystem);
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for repair subsystem\n", subsystem, shipp->ship_name));
return;
while (do_loop) {
if (generic) {
// loop until we find a subsystem of that type
for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
ss = NULL;
if (subsys_type == ai_get_subsystem_type(ss_start->system_info->name)) {
ss = ss_start;
ss_start = GET_NEXT(ss_start);
break;
}
}
// reached the end of the subsystem list
if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
// If the last subsystem wasn't of interest we don't need to go any further
if (ss == NULL) {
return;
}
do_loop = false;
}
}
else {
do_loop = false;
index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for repair subsystem\n", subsystem, shipp->ship_name));
return;
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage if current strength is < given percentage
ss = ship_get_indexed_subsys( shipp, index );
}
repair_hits = ss->max_hits * ((float)percentage / 100.0f);
ss->current_hits += repair_hits;
if ( ss->current_hits > ss->max_hits )
ss->current_hits = ss->max_hits;
if ((ss->current_hits > 0) && (do_submodel_repair))
{
ss->submodel_info_1.blown_off = 0;
ss->submodel_info_2.blown_off = 0;
}
ship_recalc_subsys_strength( shipp );
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage if current strength is < given percentage
ss = ship_get_indexed_subsys( shipp, index );
repair_hits = ss->max_hits * ((float)percentage / 100.0f);
ss->current_hits += repair_hits;
if ( ss->current_hits > ss->max_hits )
ss->current_hits = ss->max_hits;
if ((ss->current_hits > 0) && (do_submodel_repair))
{
ss->submodel_info_1.blown_off = 0;
ss->submodel_info_2.blown_off = 0;
}
ship_recalc_subsys_strength( shipp );
}
// sexpression code to set a subsystem of a ship at a specific percentage
void sexp_set_subsystem_strength(int n)
{
char *shipname, *subsystem;
int percentage, shipnum, index, do_submodel_repair;
int percentage, shipnum, index, do_submodel_repair, subsys_type;
ship *shipp;
ship_subsys *ss;
ship_subsys *ss, *ss_start;
bool generic, do_loop = true;
shipname = CTEXT(n);
subsystem = CTEXT(CDR(n));
@@ -9515,36 +9583,63 @@ void sexp_set_subsystem_strength(int n)
return;
}
// now find the given subsystem on the ship. The subsystem should be an actual subsystem name
// and not a generic type (generic type meaning SUBSYSTEM_ENGINE, etc).
// now find the given subsystem on the ship.This could be a generic type like <All Engines>
generic = is_generic_subsys(subsystem);
subsys_type = ai_get_subsystem_type(subsystem);
ss_start = GET_FIRST(&shipp->subsys_list);
index = ship_get_subsys_index(shipp, subsystem);
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for repair subsystem\n", subsystem, shipp->ship_name));
return;
}
while (do_loop) {
if (generic) {
// loop until we find a subsystem of that type
for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
ss = NULL;
if (subsys_type == ai_get_subsystem_type(ss_start->system_info->name)) {
ss = ss_start;
ss_start = GET_NEXT(ss_start);
break;
}
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage if current strength is < given percentage
ss = ship_get_indexed_subsys( shipp, index );
// maybe blow up subsys
if (ss->current_hits > 0) {
if (percentage < 1) {
do_subobj_destroyed_stuff(shipp, ss, NULL);
// reached the end of the subsystem list
if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
// If the last subsystem wasn't of interest we don't need to go any further
if (ss == NULL) {
return;
}
do_loop = false;
}
}
else {
do_loop = false;
index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
if ( index == -1 ) {
nprintf(("Warning", "Couldn't find subsystem %s on ship %s for set subsystem strength\n", subsystem, shipp->ship_name));
return;
}
// get the pointer to the subsystem. Check it's current hits against it's max hits, and
// set the strength to the given percentage
ss = ship_get_indexed_subsys( shipp, index );
}
// maybe blow up subsys
if (ss->current_hits > 0) {
if (percentage < 1) {
do_subobj_destroyed_stuff(shipp, ss, NULL);
}
}
// set hit points
ss->current_hits = ss->max_hits * ((float)percentage / 100.0f);
if ((ss->current_hits > 0) && (do_submodel_repair))
{
ss->submodel_info_1.blown_off = 0;
ss->submodel_info_2.blown_off = 0;
}
ship_recalc_subsys_strength( shipp );
}
// set hit points
ss->current_hits = ss->max_hits * ((float)percentage / 100.0f);
if ((ss->current_hits > 0) && (do_submodel_repair))
{
ss->submodel_info_1.blown_off = 0;
ss->submodel_info_2.blown_off = 0;
}
ship_recalc_subsys_strength( shipp );
}
// function which changes the validity of a goal. The flag paramater tells us whether to mark the goals
@@ -9704,9 +9799,8 @@ void sexp_set_cargo(int n)
if (subsystem)
{
ship_subsys *ss = ship_get_subsys(&Ships[ship_num], subsystem);
if (ss == NULL)
{
Int3();
if (ss == NULL) {
Assert (!ship_class_unchanged(ship_num));
return;
}
@@ -11006,6 +11100,9 @@ void sexp_friendly_stealth_invisible(int n, int invisible)
// Goober5000
void sexp_ship_subsys_untargetable(int n, int untargetable)
{
char *subsys;
ship_subsys *ss;
// get the ship
int ship_num = ship_name_lookup(CTEXT(n));
if (ship_num < 0)
@@ -11015,14 +11112,30 @@ void sexp_ship_subsys_untargetable(int n, int untargetable)
// get the subsystems
for (; n >= 0; n = CDR(n))
{
ship_subsys *ss = ship_get_subsys(&Ships[ship_num], CTEXT(n));
if (ss == NULL)
continue;
subsys = CTEXT(n);
if (untargetable)
ss->flags |= SSF_UNTARGETABLE;
else
ss->flags &= ~SSF_UNTARGETABLE;
// deal with generic subsystem names
if (is_generic_subsys(subsys)) {
int subsys_type = ai_get_subsystem_type(subsys);
for (ss = GET_FIRST(&Ships[ship_num].subsys_list); ss != END_OF_LIST(&Ships[ship_num].subsys_list); ss = GET_NEXT(ss)) {
if (subsys_type == ai_get_subsystem_type(ss->sub_name)) {
if (untargetable)
ss->flags |= SSF_UNTARGETABLE;
else
ss->flags &= ~SSF_UNTARGETABLE;
}
}
}
else {
ss = ship_get_subsys(&Ships[ship_num], subsys);
if (ss == NULL)
continue;
if (untargetable)
ss->flags |= SSF_UNTARGETABLE;
else
ss->flags &= ~SSF_UNTARGETABLE;
}
}
}
@@ -11030,6 +11143,7 @@ void sexp_ship_subsys_untargetable(int n, int untargetable)
void sexp_ship_tag( int n, int tag )
{
int ship_num, tag_level, tag_time, ssm_index(0);
int ssm_team;
// check to see if ship destroyed or departed. In either case, do nothing.
if ( mission_log_get_time(LOG_SHIP_DEPARTED, CTEXT(n), NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, CTEXT(n), NULL, NULL) )
@@ -11079,9 +11193,20 @@ void sexp_ship_tag( int n, int tag )
if (n < 0)
return;
start.xyz.z = (float)eval_num(n);
n = CDR(n);
if (n < 0)
{
ssm_team = 0;
}
else
{
ssm_team = iff_lookup(CTEXT(n));
}
}
ship_apply_tag(ship_num, tag_level, (float)tag_time, &Objects[Ships[ship_num].objnum].pos, &start, ssm_index);
ship_apply_tag(ship_num, tag_level, (float)tag_time, &Objects[Ships[ship_num].objnum], &start, ssm_index, ssm_team);
}
// sexpression to toggle invulnerability flag of ships.
@@ -11161,11 +11286,11 @@ void sexp_ship_subsys_guardian_threshold(int num)
if ( !strcmp(hull_name, SEXP_HULL_STRING) ) {
Ships[ship_num].ship_guardian_threshold = threshold;
}
else if (!strcmp(hull_name, SEXP_ALL_ENGINES_STRING) || !strcmp(hull_name, SEXP_ALL_TURRETS_STRING)) {
else if (is_generic_subsys(hull_name)) {
subsys_type = ai_get_subsystem_type(hull_name);
// search through all subsystems
for (ss = GET_FIRST(&Ships[ship_num].subsys_list); ss != GET_LAST(&Ships[ship_num].subsys_list); ss = GET_NEXT(ss)) {
if (subsys_type == ai_get_subsystem_type(ss->sub_name)) {
for (ss = GET_FIRST(&Ships[ship_num].subsys_list); ss != END_OF_LIST(&Ships[ship_num].subsys_list); ss = GET_NEXT(ss)) {
if (subsys_type == ai_get_subsystem_type(ss->system_info->name)) {
ss->subsys_guardian_threshold = threshold;
}
}
@@ -11173,7 +11298,9 @@ void sexp_ship_subsys_guardian_threshold(int num)
else {
ss = ship_get_subsys(&Ships[ship_num], hull_name);
if ( ss == NULL ) {
Warning(LOCATION, "Invalid subsystem passed to ship-subsys-guardian-threshold: %s does not have a %s subsystem", ship_name, hull_name);
if (ship_class_unchanged(ship_num)) {
Warning(LOCATION, "Invalid subsystem passed to ship-subsys-guardian-threshold: %s does not have a %s subsystem", ship_name, hull_name);
}
}
else {
ss->subsys_guardian_threshold = threshold;
@@ -12584,7 +12711,6 @@ void sexp_change_subsystem_name(int node)
}
shipp = &Ships[ship_index];
node = CDR(node);
if (node < 0) {
@@ -12592,7 +12718,6 @@ void sexp_change_subsystem_name(int node)
}
new_name = CTEXT(node);
node = CDR(node);
// loop through all the subsystems the SEXP has provided
@@ -12600,7 +12725,9 @@ void sexp_change_subsystem_name(int node)
//Get the new subsystem name
subsystem_to_rename = ship_get_subsys(&Ships[ship_index], CTEXT(node));
ship_subsys_set_name (subsystem_to_rename, new_name);
if (subsystem_to_rename != NULL) {
ship_subsys_set_name(subsystem_to_rename, new_name);
}
node = CDR(node);
}
@@ -12970,7 +13097,8 @@ void sexp_beam_free(int node)
// get the subsystem
turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(turret == NULL){
return;
node = CDR(node);
continue;
}
// flag it as beam free :)
@@ -13037,7 +13165,8 @@ void sexp_beam_lock(int node)
// get the subsystem
turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(turret == NULL){
return;
node = CDR(node);
continue;
}
// flag it as not beam free
@@ -13102,7 +13231,8 @@ void sexp_turret_free(int node)
// get the subsystem
turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(turret == NULL){
return;
node = CDR(node);
continue;
}
// flag turret as no longer locked :)
@@ -13169,7 +13299,8 @@ void sexp_turret_lock(int node)
// get the subsystem
turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(turret == NULL){
return;
node = CDR(node);
continue;
}
// flag turret as locked
@@ -13575,7 +13706,8 @@ void sexp_turret_tagged_specific(int node)
// get the subsystem
subsys = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(subsys == NULL){
return;
node = CDR(node);
continue;
}
// flag turret as slaved to tag
@@ -13605,7 +13737,8 @@ void sexp_turret_tagged_clear_specific(int node)
// get the subsystem
subsys = ship_get_subsys(&Ships[sindex], CTEXT(node));
if(subsys == NULL){
return;
node = CDR(node);
continue;
}
// flag turret as slaved to tag
@@ -15406,6 +15539,32 @@ int sexp_script_eval(int node, int return_type)
return r;
}
//Karajorma - Returns true if the name of a subsystem is actually a generic type (e.g <all engines> or <all turrets>
bool is_generic_subsys(char *subsys_name)
{
if (!strcmp(subsys_name, SEXP_ALL_ENGINES_STRING) || !strcmp(subsys_name, SEXP_ALL_TURRETS_STRING)) {
return true;
}
return false;
}
// Karajorma - returns false if the ship class has changed since the mission was parsed in
// Changes can be from use of the change-ship-class SEXP, loadout or any future method
bool ship_class_unchanged(int ship_index)
{
p_object *p_objp;
ship *shipp = &Ships[ship_index];
p_objp = mission_parse_get_parse_object(shipp->ship_name);
if ((p_objp != NULL) && (p_objp->ship_class == shipp->ship_info_index)) {
return true;
}
return false;
}
// Goober5000 - needed because any nonzero integer value is "true"
int is_sexp_true(int cur_node, int referenced_node)
{
@@ -17667,7 +17826,7 @@ int query_operator_argument_type(int op, int argnum)
if (argnum == 0)
return OPF_SHIP;
else
return OPF_SUBSYSTEM;
return OPF_SUBSYS_OR_GENERIC;
case OP_IS_DESTROYED:
case OP_HAS_ARRIVED:
@@ -17685,6 +17844,8 @@ int query_operator_argument_type(int op, int argnum)
case OP_SHIP_TAG:
if (argnum == 0)
return OPF_SHIP;
else if (argnum == 7)
return OPF_IFF;
else
return OPF_POSITIVE;
@@ -18127,7 +18288,7 @@ int query_operator_argument_type(int op, int argnum)
if (!argnum)
return OPF_SHIP; // changed from OPF_SHIP_NOT_PLAYER by Goober5000: now it can be the player ship also
else if (argnum == 1 )
return OPF_SUBSYSTEM;
return OPF_SUBSYS_OR_GENERIC;
else
return OPF_POSITIVE;
@@ -18136,7 +18297,7 @@ int query_operator_argument_type(int op, int argnum)
if (!argnum)
return OPF_SHIP; // changed from OPF_SHIP_NOT_PLAYER by Goober5000: now it can be the player ship also
else if (argnum == 1 )
return OPF_SUBSYSTEM;
return OPF_SUBSYS_OR_GENERIC;
else if (argnum == 2)
return OPF_POSITIVE;
else
@@ -20831,14 +20992,15 @@ sexp_help_struct Sexp_help[] = {
// Goober5000
{ OP_SHIP_TAG, "ship-tag\r\n"
"\tTags a ship. Takes 3 or 7 arguments...\r\n"
"\tTags a ship. Takes 3 or 8 arguments...\r\n"
"\t1: The name of a ship.\r\n"
"\t2: The tag level (currently 1, 2, or 3).\r\n"
"\t3: The tag time (in seconds).\r\n"
"\t4: A SSM missile (optional - used only for TAG-C).\r\n"
"\t5: The X origin of the SSM missile (optional - used only for TAG-C).\r\n"
"\t6: The Y origin of the SSM missile (optional - used only for TAG-C).\r\n"
"\t7: The Z origin of the SSM missile (optional - used only for TAG-C)." },
"\t7: The Z origin of the SSM missile (optional - used only for TAG-C).\r\n"
"\t8: The team the SSM missile belongs to (optional - used only for TAG-C).\r\n" },
/* made obsolete by Goober5000 - it only works in debug builds anyway
{ OP_INT3, "Error (Debug directive)\r\n"
+2 -2
View File
@@ -1452,8 +1452,8 @@ struct ship_subsys;
// defines for string constants
#define SEXP_HULL_STRING "Hull"
#define SEXP_SIM_HULL_STRING "Simulated Hull"
#define SEXP_ALL_ENGINES_STRING "<All Engines>"
#define SEXP_ALL_TURRETS_STRING "<All Turrets>"
#define SEXP_ALL_ENGINES_STRING "<all engines>"
#define SEXP_ALL_TURRETS_STRING "<all turrets>"
#define SEXP_ARGUMENT_STRING "<argument>"
#define SEXP_NONE_STRING "<none>"
+19 -39
View File
@@ -6833,21 +6833,6 @@ void ship_render(object * obj)
model_set_fog_level(neb2_get_fog_intensity(obj));
}
if (shipp->cloak_stage>0)
{
//cloaking
if (shipp->cloak_stage==2)
{
model_setup_cloak(&shipp->current_translation,1,shipp->cloak_alpha);
render_flags |= MR_FORCE_TEXTURE | MR_NO_LIGHTING;
}
else
{
model_setup_cloak(&shipp->current_translation,0,255);
}
}
//draw weapon models
if (sip->draw_models) {
int i,k;
@@ -8231,7 +8216,9 @@ void ship_do_weapon_thruster_frame( weapon *weaponp, object *objp, float frameti
Assert( frametime > 0.0f );
if (flame_anim->first_frame >= 0) {
if ((flame_anim->first_frame >= 0) &&
(flame_anim->total_time > 0.0f))
{
weaponp->thruster_frame += frametime * rate;
// Sanity checks
@@ -8259,7 +8246,9 @@ void ship_do_weapon_thruster_frame( weapon *weaponp, object *objp, float frameti
// Do it for glow bitmaps
if (glow_anim->first_frame >= 0) {
if ((glow_anim->first_frame >= 0) &&
(glow_anim->total_time > 0.0f))
{
weaponp->thruster_glow_frame += frametime * rate;
// Sanity checks
@@ -8670,8 +8659,6 @@ void ship_process_post(object * obj, float frametime)
ship_dying_frame(obj, num);
shipfx_cloak_frame(shipp, frametime);
ship_chase_shield_energy_targets(shipp, obj, frametime);
/* if (timestamp_elapsed(shipp->boost_finish_stamp))
@@ -10702,11 +10689,6 @@ void ship_process_targeting_lasers()
fire_info.targeting_laser_offset = m->gun_banks[shipp->targeting_laser_bank].pnt[0];
shipp->targeting_laser_objnum = beam_fire_targeting(&fire_info);
if (shipp->cloak_stage ==2)
{
shipfx_start_cloak(shipp,500);
}
// hmm, why didn't it fire?
if(shipp->targeting_laser_objnum < 0){
Int3();
@@ -11225,12 +11207,7 @@ done_secondary:
Player->stats.ms_shots_fired += num_fired;
}
}
if ((shipp->cloak_stage > 0) && (shipp->cloak_stage < 3))
{
shipfx_start_cloak(shipp,500);
}
// maybe announce a shockwave weapon
ai_maybe_announce_shockwave_weapon(obj, weapon);
}
@@ -14096,6 +14073,7 @@ char *ship_return_orders(char *outbuf, ship *sp)
ai_info *aip;
ai_goal *aigp;
char *order_text;
char temp_name[256];
Assert(sp->ai_index >= 0);
aip = &Ai_info[sp->ai_index];
@@ -14111,13 +14089,18 @@ char *ship_return_orders(char *outbuf, ship *sp)
return NULL;
strcpy(outbuf, order_text);
if ( aigp->ship_name ) {
strcpy(temp_name, aigp->ship_name);
end_string_at_first_hash_symbol(temp_name);
}
switch (aigp->ai_mode ) {
case AI_GOAL_FORM_ON_WING:
case AI_GOAL_GUARD_WING:
case AI_GOAL_CHASE_WING:
if ( aigp->ship_name ) {
strcat(outbuf, aigp->ship_name);
strcat(outbuf, temp_name);
strcat(outbuf, XSTR( "'s Wing", 494));
} else {
strcpy(outbuf, XSTR( "no orders", 495));
@@ -14133,7 +14116,7 @@ char *ship_return_orders(char *outbuf, ship *sp)
case AI_GOAL_EVADE_SHIP:
case AI_GOAL_REARM_REPAIR:
if ( aigp->ship_name ) {
strcat(outbuf, aigp->ship_name);
strcat(outbuf, temp_name);
} else {
strcpy(outbuf, XSTR( "no orders", 495));
}
@@ -14142,8 +14125,8 @@ char *ship_return_orders(char *outbuf, ship *sp)
case AI_GOAL_DESTROY_SUBSYSTEM: {
char name[NAME_LENGTH];
if ( aip->targeted_subsys != NULL ) {
sprintf(outbuf, XSTR( "atk %s %s", 496), aigp->ship_name, hud_targetbox_truncate_subsys_name(aip->targeted_subsys->system_info->name));
strcat(outbuf, name);
sprintf(outbuf, XSTR( "atk %s %s", 496), temp_name, hud_targetbox_truncate_subsys_name(aip->targeted_subsys->system_info->name));
strcat(outbuf, name); //what is this for?
} else {
strcpy(outbuf, XSTR( "no orders", 495) );
}
@@ -15881,10 +15864,7 @@ void ship_update_artillery_lock()
if(aip->artillery_lock_time >= 2.0f){
HUD_printf("Firing artillery");
vec3d temp;
vm_vec_unrotate(&temp, &aip->artillery_lock_pos, &Objects[aip->artillery_objnum].orient);
vm_vec_add2(&temp, &Objects[aip->artillery_objnum].pos);
ssm_create(&temp, &Objects[so->objnum].pos, 0, NULL);
ssm_create(&Objects[aip->artillery_objnum], &cinfo->hit_point_world, 0, NULL, shipp->team);
// reset the artillery
aip->artillery_lock_time = 0.0f;
@@ -16048,7 +16028,7 @@ void ship_subsystem_set_new_ai_class(int ship_num, char *subsystem, int new_ai_c
ss = GET_NEXT( ss );
}
Int3(); // subsystem not found
// Int3(); // subsystem not found
}
// Goober5000 - will attempt to load an insignia bitmap and set it as active for the wing
+7 -10
View File
@@ -748,7 +748,7 @@
//#pragma auto_inline(off)
struct ssm_firing_info;
extern void ssm_create(vec3d *target, vec3d *start, int ssm_index, ssm_firing_info *override);
extern void ssm_create(object *target, vec3d *start, int ssm_index, ssm_firing_info *override, int team);
typedef struct spark_pair {
int index1, index2;
@@ -2808,7 +2808,7 @@ static void ship_do_damage(object *ship_obj, object *other_obj, vec3d *hitpos, f
}
// Goober5000
void ship_apply_tag(int ship_num, int tag_level, float tag_time, vec3d *target, vec3d *start, int ssm_index)
void ship_apply_tag(int ship_num, int tag_level, float tag_time, object *target, vec3d *start, int ssm_index, int ssm_team)
{
// set time first tagged
if (Ships[ship_num].time_first_tagged == 0)
@@ -2837,7 +2837,7 @@ void ship_apply_tag(int ship_num, int tag_level, float tag_time, vec3d *target,
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Firing artillery", 1570));
ssm_create(target, start, ssm_index, NULL);
ssm_create(target, start, ssm_index, NULL, ssm_team);
}
}
@@ -2850,14 +2850,12 @@ void ship_apply_local_damage(object *ship_obj, object *other_obj, vec3d *hitpos,
Assert(ship_obj); // Goober5000
Assert(other_obj); // Goober5000
ship *ship_p = &Ships[ship_obj->instance];
ship *ship_p = &Ships[ship_obj->instance];
weapon *wp = &Weapons[other_obj->instance];
// If got hit by a weapon, tell the AI so it can react. Only do this line in single player,
// or if I am the master in a multiplayer game
if ( other_obj->type == OBJ_WEAPON && ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) )) {
weapon *wp;
wp = &Weapons[other_obj->instance];
// If weapon hits ship on same team and that ship not targeted and parent of weapon not player,
// don't do damage.
// Ie, player can always do damage. AI can only damage team if that ship is targeted.
@@ -2909,11 +2907,10 @@ void ship_apply_local_damage(object *ship_obj, object *other_obj, vec3d *hitpos,
weapon_info *wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
// ssm stuff
vec3d *target = hitpos;
vec3d *start = &Objects[ship_obj->instance].pos;
vec3d *start = hitpos;
int ssm_index = wip->SSM_index;
ship_apply_tag(ship_obj->instance, wip->tag_level, wip->tag_time, target, start, ssm_index);
ship_apply_tag(ship_obj->instance, wip->tag_level, wip->tag_time, ship_obj, start, ssm_index, wp->team);
}
#ifndef NDEBUG
+1 -1
View File
@@ -133,7 +133,7 @@ struct object;
extern void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, vec3d *hitpos );
// Goober5000
extern void ship_apply_tag(int ship_num, int tag_level, float tag_time, vec3d *target, vec3d *start, int ssm_index);
extern void ship_apply_tag(int ship_num, int tag_level, float tag_time, object *target, vec3d *start, int ssm_index, int ssm_team);
// This gets called to apply damage when something hits a particular point on a ship.
// This assumes that whoever called this knows if the shield got hit or not.
+8 -1
View File
@@ -5664,7 +5664,14 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob
if(parent_objp != NULL){
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, vm_vec_dot(&parent_objp->phys_info.vel, &parent_objp->orient.vec.fvec) + objp->phys_info.max_vel.xyz.z/4 );
} else {
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z/4 );
if (!is_locked)
{
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z/4 );
}
else
{
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z );
}
}
objp->phys_info.vel = objp->phys_info.desired_vel;
objp->phys_info.speed = vm_vec_mag(&objp->phys_info.vel);
+9
View File
@@ -217,6 +217,12 @@
<File
RelativePath="..\..\code\ai\ai_profiles.h">
</File>
<File
RelativePath="..\..\code\ai\aimodular.cpp">
</File>
<File
RelativePath="..\..\code\ai\aimodular.h">
</File>
<File
RelativePath="..\..\code\ai\AiBig.cpp">
<FileConfiguration
@@ -277,6 +283,9 @@
<File
RelativePath="..\..\code\ai\AiTurret.cpp">
</File>
<File
RelativePath="..\..\code\ai\newai\newai.cpp">
</File>
</Filter>
<Filter
Name="Anim"
+52
View File
@@ -236,6 +236,34 @@
RelativePath="..\..\code\ai\ai_profiles.h"
>
</File>
<File
RelativePath="..\..\code\ai\aimodular.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
UndefinePreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
UndefinePreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\code\ai\aimodular.h"
>
</File>
<File
RelativePath="..\..\code\ai\AiBig.cpp"
>
@@ -351,6 +379,30 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\code\ai\newai\newai.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
UndefinePreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
UndefinePreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Anim"