Bosses generated by a robot maker or even released by another robot will now teleport
Fixes issue #328.
This commit is contained in:
parent
32286ed4fc
commit
19e4c07bb0
|
@ -99,7 +99,7 @@ namespace dsx {
|
|||
void create_awareness_event(vobjptr_t objp, player_awareness_type_t type); // object *objp can create awareness of player, amount based on "type"
|
||||
ai_mode ai_behavior_to_mode(ai_behavior behavior);
|
||||
void do_ai_robot_hit(vobjptridx_t robot, player_awareness_type_t type);
|
||||
void init_ai_object(object &objp, ai_behavior initial_mode, segidx_t hide_segment);
|
||||
void init_ai_object(vobjptridx_t objp, ai_behavior initial_mode, segidx_t hide_segment);
|
||||
}
|
||||
|
||||
namespace dcx {
|
||||
|
@ -182,6 +182,7 @@ static inline void force_dump_ai_objects_all(const char *msg)
|
|||
namespace dsx {
|
||||
void start_boss_death_sequence(vobjptr_t objp);
|
||||
extern void ai_init_boss_for_ship(void);
|
||||
extern void boss_init_all_segments(const vobjptridx_t boss_objnum);
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
extern vms_vector Last_fired_upon_player_pos;
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace dsx {
|
|||
static window_event_result robot_dialog_handler(UI_DIALOG *dlg,const d_event &event, robot_dialog *r);
|
||||
|
||||
}
|
||||
static void call_init_ai_object(object &objp, ai_behavior behavior)
|
||||
static void call_init_ai_object(vobjptridx_t objp, ai_behavior behavior)
|
||||
{
|
||||
segnum_t hide_segment;
|
||||
|
||||
|
@ -110,7 +110,7 @@ static void call_init_ai_object(object &objp, ai_behavior behavior)
|
|||
static int RobotNextType()
|
||||
{
|
||||
if (Cur_object_index != object_none ) {
|
||||
const auto &&obj = vobjptr(Cur_object_index);
|
||||
const auto &&obj = vobjptridx(Cur_object_index);
|
||||
if (obj->type == OBJ_ROBOT)
|
||||
{
|
||||
obj->id++;
|
||||
|
@ -139,7 +139,7 @@ static int RobotNextType()
|
|||
static int RobotPrevType()
|
||||
{
|
||||
if (Cur_object_index != object_none ) {
|
||||
const auto &&obj = vobjptr(Cur_object_index);
|
||||
const auto &&obj = vobjptridx(Cur_object_index);
|
||||
if (obj->type == OBJ_ROBOT)
|
||||
{
|
||||
if (obj->id == 0 )
|
||||
|
@ -606,7 +606,7 @@ window_event_result robot_dialog_handler(UI_DIALOG *dlg,const d_event &event, ro
|
|||
if (GADGET_PRESSED(r->initialMode[i].get()))
|
||||
{
|
||||
const auto b = static_cast<ai_behavior>(MIN_BEHAVIOR + i);
|
||||
const auto &&objp = vobjptr(Cur_object_index);
|
||||
const auto &&objp = vobjptridx(Cur_object_index);
|
||||
auto &behavior = objp->ctype.ai_info.behavior;
|
||||
if (behavior != b) {
|
||||
behavior = b; // Set the ai_state to the cooresponding radio button
|
||||
|
|
|
@ -89,7 +89,7 @@ using std::min;
|
|||
#define BABY_SPIDER_ID 14
|
||||
|
||||
namespace dsx {
|
||||
static void init_boss_segments(boss_special_segment_array_t &segptr, int size_check, int one_wall_hack);
|
||||
static void init_boss_segments(vobjptridx_t boss_objnum, boss_special_segment_array_t &segptr, int size_check, int one_wall_hack);
|
||||
static void ai_multi_send_robot_position(object &objnum, int force);
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
|
@ -481,11 +481,25 @@ void ai_init_boss_for_ship(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void boss_init_all_segments(const vobjptridx_t boss_objnum)
|
||||
{
|
||||
if (Boss_teleport_segs.count())
|
||||
return; // already have boss segs
|
||||
|
||||
init_boss_segments(boss_objnum, Boss_gate_segs, 0, 0);
|
||||
|
||||
init_boss_segments(boss_objnum, Boss_teleport_segs, 1, 0);
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
if (Boss_teleport_segs.count() < 2)
|
||||
init_boss_segments(boss_objnum, Boss_teleport_segs, 1, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// initial_mode == -1 means leave mode unchanged.
|
||||
void init_ai_object(object &objp, ai_behavior behavior, const segidx_t hide_segment)
|
||||
void init_ai_object(vobjptridx_t objp, ai_behavior behavior, const segidx_t hide_segment)
|
||||
{
|
||||
ai_static *const aip = &objp.ctype.ai_info;
|
||||
ai_static *const aip = &objp->ctype.ai_info;
|
||||
ai_local *const ailp = &aip->ail;
|
||||
|
||||
*ailp = {};
|
||||
|
@ -525,7 +539,7 @@ void init_ai_object(object &objp, ai_behavior behavior, const segidx_t hide_segm
|
|||
|
||||
// This is astonishingly stupid! This routine gets called by matcens! KILL KILL KILL!!! Point_segs_free_ptr = Point_segs;
|
||||
|
||||
objp.mtype.phys_info.velocity = {};
|
||||
objp->mtype.phys_info.velocity = {};
|
||||
ailp->player_awareness_time = 0;
|
||||
ailp->player_awareness_type = player_awareness_type_t::PA_NONE;
|
||||
aip->GOAL_STATE = AIS_SRCH;
|
||||
|
@ -546,7 +560,7 @@ void init_ai_object(object &objp, ai_behavior behavior, const segidx_t hide_segm
|
|||
else
|
||||
aip->CLOAKED = 0;
|
||||
|
||||
objp.mtype.phys_info.flags |= (PF_BOUNCE | PF_TURNROLL);
|
||||
objp->mtype.phys_info.flags |= (PF_BOUNCE | PF_TURNROLL);
|
||||
|
||||
aip->REMOTE_OWNER = -1;
|
||||
|
||||
|
@ -555,14 +569,23 @@ void init_ai_object(object &objp, ai_behavior behavior, const segidx_t hide_segm
|
|||
aip->dying_start_time = 0;
|
||||
#endif
|
||||
aip->danger_laser_num = object_none;
|
||||
|
||||
if (robptr->boss_flag
|
||||
#if DXX_USE_EDITOR
|
||||
&& !EditorWindow
|
||||
#endif
|
||||
)
|
||||
boss_init_all_segments(objp);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
void init_ai_objects(void)
|
||||
{
|
||||
Point_segs_free_ptr = Point_segs.begin();
|
||||
Boss_gate_segs.clear();
|
||||
Boss_teleport_segs.clear();
|
||||
|
||||
range_for (const auto &&o, vobjptr)
|
||||
range_for (const auto &&o, vobjptridx)
|
||||
{
|
||||
if (o->type == OBJ_ROBOT && o->control_type == CT_AI)
|
||||
init_ai_object(o, o->ctype.ai_info.behavior, o->ctype.ai_info.hide_segment);
|
||||
|
@ -571,15 +594,10 @@ void init_ai_objects(void)
|
|||
Boss_dying_sound_playing = 0;
|
||||
Boss_dying = 0;
|
||||
|
||||
init_boss_segments(Boss_gate_segs, 0, 0);
|
||||
|
||||
init_boss_segments(Boss_teleport_segs, 1, 0);
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
Gate_interval = F1_0*5 - Difficulty_level*F1_0/2;
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
Gate_interval = F1_0*4 - Difficulty_level*i2f(2)/3;
|
||||
if (Boss_teleport_segs.count() == 1)
|
||||
init_boss_segments(Boss_teleport_segs, 1, 1);
|
||||
|
||||
ai_do_cloak_stuff();
|
||||
|
||||
|
@ -2001,29 +2019,19 @@ void create_buddy_bot(void)
|
|||
// he can reach from his initial position (calls find_connected_distance).
|
||||
// If size_check is set, then only add segment if boss can fit in it, else any segment is legal.
|
||||
// one_wall_hack added by MK, 10/13/95: A mega-hack! Set to !0 to ignore the
|
||||
static void init_boss_segments(boss_special_segment_array_t &a, int size_check, int one_wall_hack)
|
||||
static void init_boss_segments(vobjptridx_t boss_objnum, boss_special_segment_array_t &a, int size_check, int one_wall_hack)
|
||||
{
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
one_wall_hack = 0;
|
||||
#endif
|
||||
objptridx_t boss_objnum = object_none;
|
||||
|
||||
a.clear();
|
||||
#if DXX_USE_EDITOR
|
||||
Selected_segs.clear();
|
||||
#endif
|
||||
|
||||
// See if there is a boss. If not, quick out.
|
||||
range_for (const auto &&objp, vobjptridx)
|
||||
{
|
||||
if (objp->type == OBJ_ROBOT && Robot_info[get_robot_id(objp)].boss_flag)
|
||||
{
|
||||
boss_objnum = objp; // if != 1 then there is more than one boss here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert(boss_objnum->type == OBJ_ROBOT && Robot_info[get_robot_id(boss_objnum)].boss_flag);
|
||||
|
||||
if (boss_objnum != object_none)
|
||||
{
|
||||
vms_vector original_boss_pos;
|
||||
const vobjptridx_t boss_objp = boss_objnum;
|
||||
|
@ -3065,6 +3073,65 @@ _exit_cheat:
|
|||
vm_vec_zero(gun_point);
|
||||
}
|
||||
|
||||
switch (robptr->boss_flag) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case BOSS_D1:
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
|
||||
do_boss_stuff(obj);
|
||||
break;
|
||||
case BOSS_SUPER:
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
compute_vis_and_vec(obj, player_info, vis_vec_pos, ailp, vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed);
|
||||
|
||||
{ int pv = player_visibility;
|
||||
auto dtp = dist_to_player/4;
|
||||
|
||||
// If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to.
|
||||
if (player_info.powerup_flags & PLAYER_FLAGS_CLOAKED) {
|
||||
pv = 0;
|
||||
dtp = vm_vec_dist_quick(ConsoleObject->pos, obj->pos)/4;
|
||||
}
|
||||
|
||||
do_super_boss_stuff(obj, dtp, pv);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
Int3(); // Bogus boss flag value.
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
{
|
||||
int pv;
|
||||
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
|
||||
compute_vis_and_vec(obj, player_info, vis_vec_pos, ailp, vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed);
|
||||
|
||||
pv = player_visibility;
|
||||
|
||||
// If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to.
|
||||
if (player_info.powerup_flags & PLAYER_FLAGS_CLOAKED) {
|
||||
pv = 0;
|
||||
}
|
||||
|
||||
do_boss_stuff(obj, pv);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Occasionally make non-still robots make a path to the player. Based on agitation and distance from player.
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
|
@ -3267,67 +3334,6 @@ _exit_cheat:
|
|||
object_animates = 0; // If we're not doing the animation, then should pretend it doesn't animate.
|
||||
}
|
||||
|
||||
switch (robptr->boss_flag) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case BOSS_D1:
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
dist_to_player /= 4;
|
||||
|
||||
do_boss_stuff(obj);
|
||||
dist_to_player *= 4;
|
||||
break;
|
||||
case BOSS_SUPER:
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
compute_vis_and_vec(obj, player_info, vis_vec_pos, ailp, vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed);
|
||||
|
||||
{ int pv = player_visibility;
|
||||
auto dtp = dist_to_player/4;
|
||||
|
||||
// If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to.
|
||||
if (player_info.powerup_flags & PLAYER_FLAGS_CLOAKED) {
|
||||
pv = 0;
|
||||
dtp = vm_vec_dist_quick(ConsoleObject->pos, obj->pos)/4;
|
||||
}
|
||||
|
||||
do_super_boss_stuff(obj, dtp, pv);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
Int3(); // Bogus boss flag value.
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
{
|
||||
int pv;
|
||||
|
||||
if (aip->GOAL_STATE == AIS_FLIN)
|
||||
aip->GOAL_STATE = AIS_FIRE;
|
||||
if (aip->CURRENT_STATE == AIS_FLIN)
|
||||
aip->CURRENT_STATE = AIS_FIRE;
|
||||
|
||||
compute_vis_and_vec(obj, player_info, vis_vec_pos, ailp, vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed);
|
||||
|
||||
pv = player_visibility;
|
||||
|
||||
// If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to.
|
||||
if (player_info.powerup_flags & PLAYER_FLAGS_CLOAKED) {
|
||||
pv = 0;
|
||||
}
|
||||
|
||||
do_boss_stuff(obj, pv);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Time-slice, don't process all the time, purely an efficiency hack.
|
||||
// Guys whose behavior is station and are not at their hide segment get processed anyway.
|
||||
|
@ -4635,12 +4641,11 @@ int ai_restore_state(PHYSFS_File *fp, int version, int swap)
|
|||
Last_teleport_time = static_cast<fix64>(tmptime32);
|
||||
|
||||
// If boss teleported, set the looping 'see' sound -kreatordxx
|
||||
if (Last_teleport_time != 0 && Last_teleport_time != Boss_cloak_start_time
|
||||
// Also make sure any bosses that were generated/released during the game have teleport segs
|
||||
#if DXX_USE_EDITOR
|
||||
&& EditorWindow == nullptr
|
||||
if (!EditorWindow)
|
||||
#endif
|
||||
)
|
||||
range_for (const auto &&o, vcobjptridx)
|
||||
range_for (const auto &&o, vobjptridx)
|
||||
{
|
||||
if (o->type == OBJ_ROBOT)
|
||||
{
|
||||
|
@ -4650,7 +4655,11 @@ int ai_restore_state(PHYSFS_File *fp, int version, int swap)
|
|||
&& boss_id >= BOSS_D2 && Boss_teleports[boss_id - BOSS_D2]
|
||||
#endif
|
||||
)
|
||||
boss_link_see_sound(o);
|
||||
{
|
||||
if (Last_teleport_time != 0 && Last_teleport_time != Boss_cloak_start_time)
|
||||
boss_link_see_sound(o);
|
||||
boss_init_all_segments(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue