object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id) { short objnum; object *obj; int default_behavior; Players[Player_num].num_robots_level++; Players[Player_num].num_robots_total++; objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos, &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad, CT_AI, MT_PHYSICS, RT_POLYOBJ); if ( objnum < 0 ) { mprintf((1, "Can't create morph robot. Aborting morph.\n")); Int3(); return NULL; } obj = &Objects[objnum]; //Set polygon-object-specific data obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; obj->rtype.pobj_info.subobj_flags = 0; //set Physics info obj->mtype.phys_info.mass = Robot_info[obj->id].mass; obj->mtype.phys_info.drag = Robot_info[obj->id].drag; obj->mtype.phys_info.flags |= (PF_LEVELLING); obj->shields = Robot_info[obj->id].strength; default_behavior = Robot_info[obj->id].behavior; init_ai_object(obj-Objects, default_behavior, -1 ); // Note, -1 = segment this robot goes to to hide, should probably be something useful create_n_segment_path(obj, 6, -1); // Create a 6 segment path from creation point. Ai_local_info[objnum].mode = ai_behavior_to_mode(default_behavior); return obj; }
// ----------------------------------------------------------------------------- void EscortCreatePathToGoal(object *objP) { short goal_seg = -1; short objnum = OBJ_IDX (objP); ai_static *aip = &objP->ctype.ai_info; ai_local *ailp = &gameData.ai.localInfo[objnum]; if (gameData.escort.nSpecialGoal != -1) gameData.escort.nGoalObject = gameData.escort.nSpecialGoal; gameData.escort.nKillObject = -1; if (gameData.escort.bSearchingMarker != -1) { gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_MARKER, gameData.escort.nGoalObject-ESCORT_GOAL_MARKER1, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; } else { switch (gameData.escort.nGoalObject) { case ESCORT_GOAL_BLUE_KEY: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, POW_KEY_BLUE, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_GOLD_KEY: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, POW_KEY_GOLD, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_RED_KEY: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, POW_KEY_RED, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_CONTROLCEN: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_CNTRLCEN, -1, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_EXIT: case ESCORT_GOAL_EXIT2: goal_seg = FindExitSegment(); gameData.escort.nGoalIndex = goal_seg; break; case ESCORT_GOAL_ENERGY: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, POW_ENERGY, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_ENERGYCEN: goal_seg = ExistsInMine(objP->segnum, FUELCEN_CHECK, -1, -1); gameData.escort.nGoalIndex = goal_seg; break; case ESCORT_GOAL_SHIELD: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, POW_SHIELD_BOOST, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_POWERUP: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_POWERUP, -1, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_ROBOT: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_ROBOT, -1, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_HOSTAGE: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_HOSTAGE, -1, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_PLAYER_SPEW: gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, -1, -1, ESCORT_GOAL_PLAYER_SPEW); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; case ESCORT_GOAL_SCRAM: goal_seg = -3; // Kinda a hack. gameData.escort.nGoalIndex = goal_seg; break; case ESCORT_GOAL_BOSS: { int boss_id; boss_id = GetBossId(); Assert(boss_id != -1); gameData.escort.nGoalIndex = ExistsInMine(objP->segnum, OBJ_ROBOT, boss_id, -1); if (gameData.escort.nGoalIndex > -1) goal_seg = gameData.objs.objects[gameData.escort.nGoalIndex].segnum; break; } default: Int3(); // Oops, Illegal value in gameData.escort.nGoalObject. goal_seg = 0; break; } } if ((gameData.escort.nGoalIndex < 0) && (gameData.escort.nGoalIndex != -3)) { // I apologize for this statement -- MK, 09/22/95 if (gameData.escort.nGoalIndex == -1) { gameData.escort.xLastMsgTime = 0; // Force this message to get through. BuddyMessage(TXT_NOT_IN_MINE, GT (nEscortGoalText[gameData.escort.nGoalObject-1])); gameData.escort.bSearchingMarker = -1; } else if (gameData.escort.nGoalIndex == -2) { gameData.escort.xLastMsgTime = 0; // Force this message to get through. BuddyMessage(TXT_CANT_REACH, GT (nEscortGoalText[gameData.escort.nGoalObject-1])); gameData.escort.bSearchingMarker = -1; } else Int3(); gameData.escort.nGoalObject = ESCORT_GOAL_UNSPECIFIED; gameData.escort.nSpecialGoal = -1; } else { if (goal_seg == -3) { create_n_segment_path(objP, 16 + d_rand() * 16, -1); aip->path_length = polish_path(objP, &gameData.ai.pointSegs[aip->hide_index], aip->path_length); } else { CreatePathToSegment(objP, goal_seg, gameData.escort.nMaxLength, 1); // MK!: Last parm (safety_flag) used to be 1!! if (aip->path_length > 3) aip->path_length = polish_path(objP, &gameData.ai.pointSegs[aip->hide_index], aip->path_length); if ((aip->path_length > 0) && (gameData.ai.pointSegs[aip->hide_index + aip->path_length - 1].segnum != goal_seg)) { fix dist_to_player; gameData.escort.xLastMsgTime = 0; // Force this message to get through. BuddyMessage(TXT_CANT_REACH, GT (nEscortGoalText[gameData.escort.nGoalObject-1])); gameData.escort.bSearchingMarker = -1; gameData.escort.nGoalObject = ESCORT_GOAL_SCRAM; dist_to_player = FindConnectedDistance(&objP->pos, objP->segnum, &gameData.ai.vBelievedPlayerPos, gameData.ai.nBelievedPlayerSeg, 100, WID_FLY_FLAG); if (dist_to_player > MIN_ESCORT_DISTANCE) create_path_to_player(objP, gameData.escort.nMaxLength, 1); // MK!: Last parm used to be 1! else { create_n_segment_path(objP, 8 + d_rand() * 8, -1); aip->path_length = polish_path(objP, gameData.ai.pointSegs + aip->hide_index, aip->path_length); } } } ailp->mode = AIM_GOTO_OBJECT; SayEscortGoal(gameData.escort.nGoalObject); } }
// ----------------------------------------------------------------------------- // Called every frame (or something). void DoEscortFrame(object *objP, fix dist_to_player, int player_visibility) { int objnum = OBJ_IDX (objP); ai_static *aip = &objP->ctype.ai_info; ai_local *ailp = &gameData.ai.localInfo[objnum]; gameData.escort.nObjNum = OBJ_IDX (objP); if (player_visibility) { Buddy_last_seen_player = gameData.time.xGame; if (gameData.multi.players[gameData.multi.nLocalPlayer].flags & PLAYER_FLAGS_HEADLIGHT_ON) // DAMN! MK, stupid bug, fixed 12/08/95, changed PLAYER_FLAGS_HEADLIGHT to PLAYER_FLAGS_HEADLIGHT_ON if (f2i(gameData.multi.players[gameData.multi.nLocalPlayer].energy) < 40) if ((f2i(gameData.multi.players[gameData.multi.nLocalPlayer].energy)/2) & 2) if (!gameStates.app.bPlayerIsDead) BuddyMessage(TXT_HEADLIGHT_WARN); } if (gameStates.app.cheats.bMadBuddy) DoBuddyDudeStuff(); if (gameData.escort.xSorryTime + F1_0 > gameData.time.xGame) { gameData.escort.xLastMsgTime = 0; // Force this message to get through. if (gameData.escort.xSorryTime < gameData.time.xGame + F1_0*2) BuddyMessage(TXT_BUDDY_SORRY); gameData.escort.xSorryTime = -F1_0*2; } // If buddy not allowed to talk, then he is locked in his room. Make him mostly do nothing unless you're nearby. if (!gameData.escort.bMayTalk) if (dist_to_player > F1_0*100) aip->SKIP_AI_COUNT = (F1_0/4)/gameData.time.xFrame; // AIM_WANDER has been co-opted for buddy behavior (didn't want to modify aistruct.h) // It means the object has been told to get lost and has come to the end of its path. // If the player is now visible, then create a path. if (ailp->mode == AIM_WANDER) if (player_visibility) { create_n_segment_path(objP, 16 + d_rand() * 16, -1); aip->path_length = polish_path(objP, &gameData.ai.pointSegs[aip->hide_index], aip->path_length); } if (gameData.escort.nSpecialGoal == ESCORT_GOAL_SCRAM) { if (player_visibility) if (gameData.escort.xLastPathCreated + F1_0*3 < gameData.time.xGame) { #if TRACE con_printf (CON_DEBUG, "Frame %i: Buddy creating new scram path.\n", gameData.app.nFrameCount); #endif create_n_segment_path(objP, 10 + d_rand() * 16, gameData.objs.console->segnum); gameData.escort.xLastPathCreated = gameData.time.xGame; } // -- Int3(); return; } // Force checking for new goal every 5 seconds, and create new path, if necessary. if (((gameData.escort.nSpecialGoal != ESCORT_GOAL_SCRAM) && ((gameData.escort.xLastPathCreated + F1_0*5) < gameData.time.xGame)) || ((gameData.escort.nSpecialGoal == ESCORT_GOAL_SCRAM) && ((gameData.escort.xLastPathCreated + F1_0*15) < gameData.time.xGame))) { gameData.escort.nGoalObject = ESCORT_GOAL_UNSPECIFIED; gameData.escort.xLastPathCreated = gameData.time.xGame; } if ((gameData.escort.nSpecialGoal != ESCORT_GOAL_SCRAM) && TimeToVisitPlayer(objP, ailp, aip)) { int max_len; Buddy_last_player_path_created = gameData.time.xGame; ailp->mode = AIM_GOTO_PLAYER; if (!player_visibility) { if ((Last_come_back_message_time + F1_0 < gameData.time.xGame) || (Last_come_back_message_time > gameData.time.xGame)) { BuddyMessage(TXT_COMING_BACK); Last_come_back_message_time = gameData.time.xGame; } } // No point in Buddy creating very long path if he's not allowed to talk. Really kills framerate. max_len = gameData.escort.nMaxLength; if (!gameData.escort.bMayTalk) max_len = 3; create_path_to_player(objP, max_len, 1); // MK!: Last parm used to be 1! aip->path_length = polish_path(objP, &gameData.ai.pointSegs[aip->hide_index], aip->path_length); ailp->mode = AIM_GOTO_PLAYER; } else if (gameData.time.xGame - Buddy_last_seen_player > MAX_ESCORT_TIME_AWAY) { // This is to prevent buddy from looking for a goal, which he will do because we only allow path creation once/second. return; } else if ((ailp->mode == AIM_GOTO_PLAYER) && (dist_to_player < MIN_ESCORT_DISTANCE)) { gameData.escort.nGoalObject = EscortSetGoalObject(); ailp->mode = AIM_GOTO_OBJECT; // May look stupid to be before path creation, but AIDoorIsOpenable uses mode to determine what doors can be got through EscortCreatePathToGoal(objP); aip->path_length = polish_path(objP, gameData.ai.pointSegs + aip->hide_index, aip->path_length); if (aip->path_length < 3) { create_n_segment_path (objP, 5, gameData.ai.nBelievedPlayerSeg); } ailp->mode = AIM_GOTO_OBJECT; } else if (gameData.escort.nGoalObject == ESCORT_GOAL_UNSPECIFIED) { if ((ailp->mode != AIM_GOTO_PLAYER) || (dist_to_player < MIN_ESCORT_DISTANCE)) { gameData.escort.nGoalObject = EscortSetGoalObject(); ailp->mode = AIM_GOTO_OBJECT; // May look stupid to be before path creation, but AIDoorIsOpenable uses mode to determine what doors can be got through EscortCreatePathToGoal(objP); aip->path_length = polish_path(objP, &gameData.ai.pointSegs[aip->hide_index], aip->path_length); if (aip->path_length < 3) { create_n_segment_path(objP, 5, gameData.ai.nBelievedPlayerSeg); } ailp->mode = AIM_GOTO_OBJECT; } } else ; }