@@ -2400,6 +2400,7 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index)
24002400
24012401 Assert(attacker != nullptr);
24022402 Assert(attacker->instance >= 0);
2403+ Assert(attacker->type == OBJ_SHIP);
24032404 Assert(Ships[attacker->instance].ai_index != -1);
24042405 // Bogus! Who tried to get me to attack myself!
24052406 if (attacker == attacked) {
@@ -10014,7 +10015,7 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
1001410015 aip->submode = SM_ATTACK;
1001510016 aip->submode_start_time = Missiontime;
1001610017 aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
10017- } else {
10018+ } else if (Objects[aip->target_objnum].type == OBJ_SHIP) {
1001810019 int num_attacking_cur, num_attacking_new;
1001910020
1002010021 num_attacking_cur = num_ships_attacking(aip->target_objnum);
@@ -10036,6 +10037,8 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
1003610037 aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
1003710038 }
1003810039 }
10040+ } else {
10041+ UNREACHABLE("The AI previously had a guard goal to guard something besides a ship, specifically an object of type %d. As we understand it, this should not happen. Please report!", Objects[aip->target_objnum].type);
1003910042 }
1004010043 }
1004110044}
@@ -14490,6 +14493,13 @@ void validate_mode_submode(ai_info *aip)
1449014493 */
1449114494void ai_frame(int objnum)
1449214495{
14496+ // Cyborg - can you believe this was added in *2022*??
14497+ Assertion (Objects[objnum].type == OBJ_SHIP, "Ai_frame was called for a non-ship of type %d. Please report!", Objects[objnum].type);
14498+
14499+ if (Objects[objnum].type != OBJ_SHIP){
14500+ return;
14501+ }
14502+
1449314503 ship *shipp = &Ships[Objects[objnum].instance];
1449414504 ai_info *aip = &Ai_info[shipp->ai_index];
1449514505 int target_objnum;
@@ -14572,7 +14582,7 @@ void ai_frame(int objnum)
1457214582 } else if (aip->resume_goal_time == -1) {
1457314583 // AL 12-9-97: Don't allow cargo and navbuoys to set their aip->target_objnum
1457414584 if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks]) ) {
14575- target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 25K units away.
14585+ target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 2.5K units away.
1457614586 if (target_objnum != -1) {
1457714587 if (aip->target_objnum != target_objnum)
1457814588 aip->aspect_locked_time = 0.0f;
@@ -15109,9 +15119,9 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t
1510915119
1511015120void ai_do_default_behavior(object *obj)
1511115121{
15112- Assert (obj != NULL );
15113- Assert( obj->instance != -1 );
15114- Assert (Ships[obj->instance].ai_index != -1 );
15122+ Assertion (obj != nullptr, "Ai_do_default_behavior() was given a bad information. Specifically obj is a nullptr. This is a coder error, please report!" );
15123+ Assertion(( obj->type == OBJ_SHIP) && (obj->instance > -1) && (obj->instance < MAX_SHIPS), "This function that requires an object to be a ship was passed an invalid ship. Please report\n\nObject type: %d\nInstance #: %d", obj->type, obj->instance );
15124+ Assertion (Ships[obj->instance].ai_index >= 0, "A ship has been found to have an invalid ai_index of %d. This should have been assigned and is coder mistake, please report!", Ships[obj->instance].ai_index );
1511515125
1511615126 ai_info *aip = &Ai_info[Ships[obj->instance].ai_index];
1511715127 ship_info* sip = &Ship_info[Ships[obj->instance].ship_info_index];
@@ -15209,118 +15219,125 @@ void maybe_process_friendly_hit(object *objp_hitter, object *objp_hit, object *o
1520915219 return;
1521015220 }
1521115221
15212- if ((obj_team(objp_hitter) == obj_team(objp_hit)) && (objp_hitter == Player_obj)) {
15222+ // Cyborg -- I had to switch around the logic here because it was potentially
15223+ // sending non-ships to obj_team, which would trigger an assert
15224+ if (objp_hitter == Player_obj){
1521315225
15214- // AL 12-4-97: It is possible the Player is a OBJ_GHOST at this point. If so, bail out.
15226+ // Cyborg - So check if this is a ship first. Probably true, but you never know, with FSO
15227+ // (especially in multi)
1521515228 if ( objp_hitter->type != OBJ_SHIP ) {
1521615229 return;
1521715230 }
1521815231
15219- Assert(objp_hitter->type == OBJ_SHIP);
15232+ // And assert that obj_hit is a ship as well.
1522015233 Assert(objp_hit->type == OBJ_SHIP);
15221- Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
15222-
15223- ship *shipp_hitter = &Ships[objp_hitter->instance];
15224- ship *shipp_hit = &Ships[objp_hit->instance];
15225-
15226- if (shipp_hitter->team != shipp_hit->team) {
15227- return;
15228- }
1522915234
15230- // get the player
15231- player *pp = &Players[Player_num];
15235+ if (obj_team(objp_hitter) == obj_team(objp_hit)) {
1523215236
15233- // wacky stuff here
15234- if (pp->friendly_hits != 0) {
15235- float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
15236- if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
15237- if (time_since_last_hit > 60.0f) {
15238- pp->friendly_hits = 0;
15239- pp->friendly_damage = 0.0f;
15240- } else if (time_since_last_hit > 2.0f) {
15241- pp->friendly_hits -= (int) time_since_last_hit/2;
15242- pp->friendly_damage -= time_since_last_hit;
15243- }
15237+ Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
1524415238
15245- if (pp->friendly_damage < 0.0f) {
15246- pp->friendly_damage = 0.0f;
15247- }
15239+ ship *shipp_hitter = &Ships[objp_hitter->instance];
15240+ ship *shipp_hit = &Ships[objp_hit->instance];
1524815241
15249- if (pp->friendly_hits < 0) {
15250- pp->friendly_hits = 0;
15251- }
15242+ if (shipp_hitter->team != shipp_hit->team) {
15243+ return;
1525215244 }
15253- }
1525415245
15255- float damage; // Damage done by weapon. Gets scaled down based on size of ship.
15246+ // get the player
15247+ player *pp = &Players[Player_num];
1525615248
15257- if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
15258- damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
15259- else
15260- damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
15261-
15262- // wacky stuff here
15263- ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
15264- if (shipp_hit->ship_max_hull_strength > 1000.0f) {
15265- float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
15266- factor = MIN(100.0f, factor);
15267- damage /= factor;
15268- }
15269-
15270- // Don't penalize much at all for hitting cargo
15271- if (sip->class_type > -1) {
15272- damage *= Ship_types[sip->class_type].ff_multiplier;
15273- }
15249+ // wacky stuff here
15250+ if (pp->friendly_hits != 0) {
15251+ float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
15252+ if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
15253+ if (time_since_last_hit > 60.0f) {
15254+ pp->friendly_hits = 0;
15255+ pp->friendly_damage = 0.0f;
15256+ } else if (time_since_last_hit > 2.0f) {
15257+ pp->friendly_hits -= (int) time_since_last_hit/2;
15258+ pp->friendly_damage -= time_since_last_hit;
15259+ }
1527415260
15275- // Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
15276- if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
15277- damage /= 5.0f;
15278- }
15261+ if (pp->friendly_damage < 0.0f) {
15262+ pp->friendly_damage = 0.0f;
15263+ }
1527915264
15280- pp->friendly_last_hit_time = Missiontime;
15281- pp->friendly_hits++;
15265+ if (pp->friendly_hits < 0) {
15266+ pp->friendly_hits = 0;
15267+ }
15268+ }
15269+ }
1528215270
15283- // cap damage and number of hits done this frame
15284- float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
15285- pp->friendly_damage += accredited_damage;
15286- pp->damage_this_burst += accredited_damage;
15271+ float damage; // Damage done by weapon. Gets scaled down based on size of ship.
1528715272
15288- // Done with adjustments to damage. Evaluate based on current friendly_damage
15289- nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
15290-
15291- if (is_instructor(objp_hit)) {
15292- // it's not nice to hit your instructor
15293- if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
15294- message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15295- pp->last_warning_message_time = Missiontime;
15296- ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
15273+ if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
15274+ damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
15275+ else
15276+ damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
15277+
15278+ // wacky stuff here
15279+ ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
15280+ if (shipp_hit->ship_max_hull_strength > 1000.0f) {
15281+ float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
15282+ factor = MIN(100.0f, factor);
15283+ damage /= factor;
15284+ }
1529715285
15298- training_fail();
15286+ // Don't penalize much at all for hitting cargo
15287+ if (sip->class_type > -1) {
15288+ damage *= Ship_types[sip->class_type].ff_multiplier;
15289+ }
1529915290
15300- // Instructor leaves.
15301- mission_do_departure(objp_hit);
15302- gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
15303- } else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
15304- // warning every 4 sec
15305- // use NULL as the message sender here since it is the Terran Command persona
15306- message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15307- pp->last_warning_message_time = Missiontime;
15291+ // Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
15292+ if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
15293+ damage /= 5.0f;
1530815294 }
1530915295
15310- // not nice to hit your friends
15311- } else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
15312- process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
15313- mission_goal_fail_all();
15314- ai_abort_rearm_request( Player_obj );
15296+ pp->friendly_last_hit_time = Missiontime;
15297+ pp->friendly_hits++;
1531515298
15316- Player_ship->team = Iff_traitor;
15299+ // cap damage and number of hits done this frame
15300+ float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
15301+ pp->friendly_damage += accredited_damage;
15302+ pp->damage_this_burst += accredited_damage;
1531715303
15318- } else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
15319- // no closer than 4 sec intervals
15320- // Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
15321- // many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
15322- process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
15323- pp->last_warning_message_time = Missiontime;
15304+ // Done with adjustments to damage. Evaluate based on current friendly_damage
15305+ nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
15306+
15307+ if (is_instructor(objp_hit)) {
15308+ // it's not nice to hit your instructor
15309+ if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
15310+ message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15311+ pp->last_warning_message_time = Missiontime;
15312+ ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
15313+
15314+ training_fail();
15315+
15316+ // Instructor leaves.
15317+ mission_do_departure(objp_hit);
15318+ gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
15319+ } else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
15320+ // warning every 4 sec
15321+ // use NULL as the message sender here since it is the Terran Command persona
15322+ message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
15323+ pp->last_warning_message_time = Missiontime;
15324+ }
15325+
15326+ // not nice to hit your friends
15327+ } else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
15328+ process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
15329+ mission_goal_fail_all();
15330+ ai_abort_rearm_request( Player_obj );
15331+
15332+ Player_ship->team = Iff_traitor;
15333+
15334+ } else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
15335+ // no closer than 4 sec intervals
15336+ // Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
15337+ // many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
15338+ process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
15339+ pp->last_warning_message_time = Missiontime;
15340+ }
1532415341 }
1532515342 }
1532615343}
@@ -15545,11 +15562,14 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
1554515562 return;
1554615563
1554715564 hitter_objnum = hit_objp->parent;
15548- Assert ((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS));
15565+ Assertion ((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS), "hitter_objnum in this function is an invalid index of %d. This can cause random behavior, and is a coder mistake. Please report!", hitter_objnum );
1554915566 objp_hitter = &Objects[hitter_objnum];
1555015567
15568+ Assertion((objp_hitter->type == OBJ_SHIP) || (objp_hitter->type == OBJ_WEAPON) || (objp_hitter->type == OBJ_ASTEROID) || (objp_hitter->type == OBJ_BEAM) || (objp_hitter->type == OBJ_DEBRIS),
15569+ "The ai code is passing an invalid object type of %d to a function when trying to decide how to respond to something hitting it. This is a bug in the code, please report!", objp_hitter->type);
15570+
1555115571 // lets not check hits by ghosts any further either
15552- if(objp_hitter->type == OBJ_GHOST )
15572+ if(objp_hitter->type != OBJ_SHIP && objp_hitter->type != OBJ_WEAPON && objp_hitter->type != OBJ_ASTEROID && objp_hitter->type != OBJ_BEAM && objp_hitter->type != OBJ_DEBRIS )
1555315573 return;
1555415574
1555515575 // Hit by a protected ship, don't attack it.
@@ -16147,6 +16167,12 @@ void maybe_cheat_fire_synaptic(object *objp)
1614716167 ship *shipp;
1614816168 int wing_index, time;
1614916169
16170+ Assertion(objp->type == OBJ_SHIP, "This ai function requires a ship, but was called with a non-ship object type of %d. Please report!", objp->type);
16171+
16172+ if (objp->type != OBJ_SHIP) {
16173+ return;
16174+ }
16175+
1615016176 shipp = &Ships[objp->instance];
1615116177
1615216178 if (!(strnicmp(shipp->ship_name, NOX("delta"), 5)))
0 commit comments