/* ============== BotResetState called when a bot enters the intermission or observer mode and when the level is changed ============== */ void BotResetState( bot_state_t *bs ) { int client, entitynum, inuse; int movestate, goalstate, chatstate, weaponstate; bot_settings_t settings; int character; playerState_t ps; //current player state float entergame_time; //save some things that should not be reset here memcpy( &settings, &bs->settings, sizeof( bot_settings_t ) ); memcpy( &ps, &bs->cur_ps, sizeof( playerState_t ) ); inuse = bs->inuse; client = bs->client; entitynum = bs->entitynum; character = bs->character; movestate = bs->ms; goalstate = bs->gs; chatstate = bs->cs; weaponstate = bs->ws; entergame_time = bs->entergame_time; //free checkpoints and patrol points BotFreeWaypoints( bs->checkpoints ); BotFreeWaypoints( bs->patrolpoints ); //reset the whole state memset( bs, 0, sizeof( bot_state_t ) ); //copy back some state stuff that should not be reset bs->ms = movestate; bs->gs = goalstate; bs->cs = chatstate; bs->ws = weaponstate; memcpy( &bs->cur_ps, &ps, sizeof( playerState_t ) ); memcpy( &bs->settings, &settings, sizeof( bot_settings_t ) ); bs->inuse = inuse; bs->client = client; bs->entitynum = entitynum; bs->character = character; bs->entergame_time = entergame_time; //reset several states if ( bs->ms ) { trap_BotResetMoveState( bs->ms ); } if ( bs->gs ) { trap_BotResetGoalState( bs->gs ); } if ( bs->ws ) { trap_BotResetWeaponState( bs->ws ); } if ( bs->gs ) { trap_BotResetAvoidGoals( bs->gs ); } if ( bs->ms ) { trap_BotResetAvoidReach( bs->ms ); } }
/* ============= BotResetState Called when a bot enters the intermission or observer mode and when the level is changed. ============= */ void BotResetState(bot_state_t *bs) { int client, entitynum, inuse; int movestate, chatstate; bot_settings_t settings; int character; float enter_game_time; // Only reset valid states if (!bs || !bs->inuse) return; // Save data that should not be reset memcpy(&settings, &bs->settings, sizeof(bot_settings_t)); inuse = bs->inuse; client = bs->client; entitynum = bs->entitynum; character = bs->character; movestate = bs->ms; chatstate = bs->cs; enter_game_time = bs->enter_game_time; // Free checkpoints and patrol points BotFreeWaypoints(bs->checkpoints); BotFreeWaypoints(bs->patrol); // Reset the state memset(bs, 0, sizeof(bot_state_t)); // Copy back some state stuff that should not be reset bs->ms = movestate; bs->cs = chatstate; bs->ent = &g_entities[client]; bs->ps = &bs->ent->client->ps; memcpy(&bs->settings, &settings, sizeof(bot_settings_t)); bs->inuse = inuse; bs->client = client; bs->entitynum = entitynum; bs->character = character; bs->enter_game_time = enter_game_time; // Reset the move state if (bs->ms) { trap_BotResetMoveState(bs->ms); trap_BotResetAvoidReach(bs->ms); } // Initialize internal bot data data, such as statistics and awareness BotInitialize(bs); }
/* ============== BotAIShutdownClient ============== */ int BotAIShutdownClient(int client, qboolean restart) { bot_state_t *bs; bs = botstates[client]; if (!bs || !bs->inuse) { //BotAI_Print(PRT_ERROR, "BotAIShutdownClient: client %d already shutdown\n", client); return qfalse; } if (restart) { BotWriteSessionData(bs); } if (BotChat_ExitGame(bs)) { botlib_export->ai.BotEnterChat(bs->cs, bs->client, CHAT_ALL); } botlib_export->ai.BotFreeMoveState(bs->ms); //free the goal state` botlib_export->ai.BotFreeGoalState(bs->gs); //free the chat file botlib_export->ai.BotFreeChatState(bs->cs); //free the weapon weights botlib_export->ai.BotFreeWeaponState(bs->ws); //free the bot character botlib_export->ai.BotFreeCharacter(bs->character); // BotFreeWaypoints(bs->checkpoints); BotFreeWaypoints(bs->patrolpoints); //clear activate goal stack BotClearActivateGoalStack(bs); //clear the bot state memset(bs, 0, sizeof(bot_state_t)); //set the inuse flag to qfalse bs->inuse = qfalse; //there's one bot less numbots--; //everything went ok return qtrue; }
/* ============== BotAIShutdownPlayer ============== */ int BotAIShutdownPlayer(int playernum, qboolean restart) { bot_state_t *bs; bs = botstates[playernum]; if (!bs || !bs->inuse) { //BotAI_Print(PRT_ERROR, "BotAIShutdownPlayer: player %d already shutdown\n", playernum); return qfalse; } if (restart) { BotWriteSessionData(bs); } if (BotChat_ExitGame(bs)) { BotEnterChat(bs->cs, bs->playernum, CHAT_ALL); } trap_SetConfigstring(CS_BOTINFO + bs->playernum, ""); BotFreeMoveState(bs->ms); //free the goal state BotFreeGoalState(bs->gs); //free the chat file BotFreeChatState(bs->cs); //free the weapon weights BotFreeWeaponState(bs->ws); //free the bot character BotFreeCharacter(bs->character); // BotFreeWaypoints(bs->checkpoints); BotFreeWaypoints(bs->patrolpoints); //clear activate goal stack BotClearActivateGoalStack(bs); //clear the bot state memset(bs, 0, sizeof(bot_state_t)); //set the inuse flag to qfalse bs->inuse = qfalse; //there's one bot less numbots--; //everything went ok return qtrue; }
/* ============== BotAIShutdownClient ============== */ int BotAIShutdownClient( int client ) { bot_state_t *bs; // Wolfenstein if ( g_entities[client].r.svFlags & SVF_CASTAI ) { AICast_ShutdownClient( client ); return BLERR_NOERROR; } // done. bs = botstates[client]; if ( !bs || !bs->inuse ) { // BotAI_Print(PRT_ERROR, "client %d already shutdown\n", client); return BLERR_AICLIENTALREADYSHUTDOWN; } if ( BotChat_ExitGame( bs ) ) { trap_BotEnterChat( bs->cs, bs->client, CHAT_ALL ); } trap_BotFreeMoveState( bs->ms ); //free the goal state trap_BotFreeGoalState( bs->gs ); //free the chat file trap_BotFreeChatState( bs->cs ); //free the weapon weights trap_BotFreeWeaponState( bs->ws ); //free the bot character trap_BotFreeCharacter( bs->character ); // BotFreeWaypoints( bs->checkpoints ); BotFreeWaypoints( bs->patrolpoints ); //clear the bot state memset( bs, 0, sizeof( bot_state_t ) ); //set the inuse flag to qfalse bs->inuse = qfalse; //there's one bot less numbots--; //everything went ok return BLERR_NOERROR; }
/* * BotAIShutdownClient */ int BotAIShutdownClient(int client, qbool restart) { bot_state_t *bs; bs = botstates[client]; if(!bs || !bs->inuse) /* BotAI_Print(PRT_ERROR, "BotAIShutdownClient: client %d already shutdown\n", client); */ return qfalse; if(restart) BotWriteSessionData(bs); if(BotChat_ExitGame(bs)) trap_BotEnterChat(bs->cs, bs->client, CHAT_ALL); trap_BotFreeMoveState(bs->ms); /* free the goal state` */ trap_BotFreeGoalState(bs->gs); /* free the chat file */ trap_BotFreeChatState(bs->cs); /* free the weapon weights */ trap_BotFreeWeaponState(bs->ws); /* free the bot character */ trap_BotFreeCharacter(bs->character); BotFreeWaypoints(bs->checkpoints); BotFreeWaypoints(bs->patrolpoints); /* clear activate goal stack */ BotClearActivateGoalStack(bs); /* clear the bot state */ memset(bs, 0, sizeof(bot_state_t)); /* set the inuse flag to qfalse */ bs->inuse = qfalse; /* there's one bot less */ numbots--; /* everything went ok */ return qtrue; }
/* ======================================================================================================================================= BotGetPatrolWaypoints ======================================================================================================================================= */ int BotGetPatrolWaypoints(bot_state_t *bs, bot_match_t *match) { char keyarea[MAX_MESSAGE_SIZE]; int patrolflags; bot_waypoint_t *wp, *newwp, *newpatrolpoints; bot_match_t keyareamatch; bot_goal_t goal; newpatrolpoints = NULL; patrolflags = 0; trap_BotMatchVariable(match, KEYAREA, keyarea, MAX_MESSAGE_SIZE); while (1) { if (!trap_BotFindMatch(keyarea, &keyareamatch, MTCONTEXT_PATROLKEYAREA)) { trap_EA_SayTeam(bs->client, "what do you say?"); BotFreeWaypoints(newpatrolpoints); bs->patrolpoints = NULL; return qfalse; } trap_BotMatchVariable(&keyareamatch, KEYAREA, keyarea, MAX_MESSAGE_SIZE); if (!BotGetMessageTeamGoal(bs, keyarea, &goal)) { // BotAI_BotInitialChat(bs, "cannotfind", keyarea, NULL); // trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM); BotFreeWaypoints(newpatrolpoints); bs->patrolpoints = NULL; return qfalse; } // create a new waypoint newwp = BotCreateWayPoint(keyarea, goal.origin, goal.areanum); // add the waypoint to the patrol points newwp->next = NULL; for (wp = newpatrolpoints; wp && wp->next; wp = wp->next); if (!wp) { newpatrolpoints = newwp; newwp->prev = NULL; } else { wp->next = newwp; newwp->prev = wp; } if (keyareamatch.subtype & ST_BACK) { patrolflags = PATROL_LOOP; break; } else if (keyareamatch.subtype & ST_REVERSE) { patrolflags = PATROL_REVERSE; break; } else if (keyareamatch.subtype & ST_MORE) { trap_BotMatchVariable(&keyareamatch, MORE, keyarea, MAX_MESSAGE_SIZE); } else { break; } } if (!newpatrolpoints || !newpatrolpoints->next) { trap_EA_SayTeam(bs->client, "I need more key points to patrol\n"); BotFreeWaypoints(newpatrolpoints); newpatrolpoints = NULL; return qfalse; } BotFreeWaypoints(bs->patrolpoints); bs->patrolpoints = newpatrolpoints; bs->curpatrolpoint = bs->patrolpoints; bs->patrolflags = patrolflags; return qtrue; }
/* ======================== BotMatch_PatrolWaypoints ======================== */ qboolean BotMatch_PatrolWaypoints(bot_state_t *bs, bot_match_t *match, gentity_t *sender) { char keyarea[MAX_MESSAGE_SIZE]; int flags; bot_waypoint_t *new_wp, *last_wp, *new_patrol; bot_match_t keyareamatch; bot_goal_t goal; qboolean success; // Initialize new patrol to a zero length path last_wp = new_patrol = NULL; flags = 0; success = qfalse; // Match successive waypoints in the patrol path trap_BotMatchVariable(match, KEYAREA, keyarea, MAX_MESSAGE_SIZE); while (1) { // Fail if the bot can't match the area name if (!trap_BotFindMatch(keyarea, &keyareamatch, MTCONTEXT_PATROLKEYAREA)) { trap_EA_SayTeam(bs->client, "What did you say?"); break; } // Fail if the bot can't find the requested area trap_BotMatchVariable(&keyareamatch, KEYAREA, keyarea, MAX_MESSAGE_SIZE); if (!GoalFromName(&goal, keyarea, bs)) break; // Try to create a new waypoint new_wp = BotCreateWaypoint(keyarea); if (new_wp == NULL) break; // Copy the matched goal to the waypoint memcpy(&new_wp->goal, &goal, sizeof(bot_goal_t)); // Insert waypoint into patrol point list new_wp->next = NULL; if (last_wp) { last_wp->next = new_wp; new_wp->prev = last_wp; } else { // First waypoint in list new_patrol = new_wp; new_wp->prev = NULL; } last_wp = new_wp; // Check for waypoint message completion if (keyareamatch.subtype & ST_REVERSE) { success = qtrue; flags = PATROL_REVERSE; break; } if (keyareamatch.subtype & ST_BACK) { success = qtrue; flags = PATROL_LOOP; break; } if ( !(keyareamatch.subtype & ST_MORE) ) { success = qtrue; flags = PATROL_LOOP; break; } trap_BotMatchVariable(&keyareamatch, MORE, keyarea, MAX_MESSAGE_SIZE); } // Make sure the bot has at least two patrol points if (success && (!new_patrol || !new_patrol->next) ) { trap_EA_SayTeam(bs->client, "I need more key points to patrol\n"); success = qfalse; } // Check for message match failure if (!success) { BotFreeWaypoints(new_patrol); return qfalse; } // Free old waypoints and use new waypoints BotFreeWaypoints(bs->patrol); bs->patrol = new_patrol; bs->next_patrol = bs->patrol; bs->patrol_flags = flags; return qtrue; }