/* ============== BotChangeViewAngles ============== */ void BotChangeViewAngles( bot_state_t *bs, float thinktime ) { float diff, factor, maxchange, anglespeed; int i; if ( bs->ideal_viewangles[PITCH] > 180 ) { bs->ideal_viewangles[PITCH] -= 360; } // if ( bs->enemy >= 0 ) { factor = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_VIEW_FACTOR, 0.01, 1 ); maxchange = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_VIEW_MAXCHANGE, 1, 1800 ); } else { factor = 0.25; maxchange = 300; } maxchange *= thinktime; for ( i = 0; i < 2; i++ ) { diff = abs( AngleDifference( bs->viewangles[i], bs->ideal_viewangles[i] ) ); anglespeed = diff * factor; if ( anglespeed > maxchange ) { anglespeed = maxchange; } bs->viewangles[i] = BotChangeViewAngle( bs->viewangles[i], bs->ideal_viewangles[i], anglespeed ); //BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);` //bs->viewangles[i] = bs->ideal_viewangles[i]; } if ( bs->viewangles[PITCH] > 180 ) { bs->viewangles[PITCH] -= 360; } //elementary action: view trap_EA_View( bs->client, bs->viewangles ); }
/* ============== BotChangeViewAngles ============== */ void BotChangeViewAngles(bot_state_t * bs, float thinktime) { float diff, factor, maxchange, anglespeed, disired_speed; int i; if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360; // if (bs->enemy >= 0) { factor = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_FACTOR, 0.01f, 1); maxchange = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_MAXCHANGE, 1, 1800); } else { factor = 0.05f; maxchange = 360; } if (maxchange < 240) maxchange = 240; maxchange *= thinktime; for (i = 0; i < 2; i++) { // if (bot_challenge.integer) { //smooth slowdown view model diff = abs(AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i])); anglespeed = diff * factor; if (anglespeed > maxchange) anglespeed = maxchange; bs->viewangles[i] = BotChangeViewAngle(bs->viewangles[i], bs->ideal_viewangles[i], anglespeed); } else { //over reaction view model bs->viewangles[i] = AngleMod(bs->viewangles[i]); bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]); diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]); disired_speed = diff * factor; bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed); if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange; if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange; anglespeed = bs->viewanglespeed[i]; if (anglespeed > maxchange) anglespeed = maxchange; if (anglespeed < -maxchange) anglespeed = -maxchange; bs->viewangles[i] += anglespeed; bs->viewangles[i] = AngleMod(bs->viewangles[i]); //demping bs->viewanglespeed[i] *= 0.45 * (1 - factor); } //BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);` //bs->viewangles[i] = bs->ideal_viewangles[i]; } //bs->viewangles[PITCH] = 0; if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360; //elementary action: view trap_EA_View(bs->client, bs->viewangles); }
/* ============== AICast_ChangeViewAngles ============== */ void AICast_ChangeViewAngles( cast_state_t *cs, float thinktime ) { float diff, factor, maxchange, anglespeed; int i; bot_state_t *bs; bs = cs->bs; // // restoire locked viewangles if required if ( cs->aiFlags & AIFL_VIEWLOCKED ) { VectorCopy( cs->viewlock_viewangles, bs->ideal_viewangles ); } // if ( bs->ideal_viewangles[PITCH] > 180 ) { bs->ideal_viewangles[PITCH] -= 360; } // maxchange = cs->attributes[YAW_SPEED]; //300; if ( cs->aiState >= AISTATE_COMBAT ) { factor = 2.0; maxchange *= 2.0; } else { factor = 0.7; } // if ( cs->lockViewAnglesTime < level.time ) { maxchange *= thinktime; for ( i = 0; i < 3; i++ ) { diff = c::fabs( AngleDifference( bs->viewangles[i], bs->ideal_viewangles[i] ) ); anglespeed = diff * factor; if ( anglespeed > maxchange ) { anglespeed = maxchange; } bs->viewangles[i] = BotChangeViewAngle( bs->viewangles[i], bs->ideal_viewangles[i], anglespeed ); //BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);` //bs->viewangles[i] = bs->ideal_viewangles[i]; } } if ( bs->viewangles[PITCH] > 180 ) { bs->viewangles[PITCH] -= 360; } //elementary action: view trap_EA_View( bs->client, bs->viewangles ); }
/* ============== BotCommandView Set the bot's user command view angles ============== */ void BotCommandView(bot_state_t *bs, vec3_t view) { int angle; usercmd_t *cmd; // Set this data as bot input // // NOTE: This just sets data used in the bot_input_t structure, accessed by // the trap_EA_GetInput() command. The view data isn't actually used from // that command though. This code just sets the data for safety should another // programmer want to use that structure. trap_EA_View(bs->client, view); // Set the view angles for the bot's command cmd = &bs->cmd; for (angle = PITCH; angle <= ROLL; angle++) cmd->angles[angle] = (short) (ANGLE2SHORT(view[angle]) - bs->ps->delta_angles[angle]); // Extract the view angles this command will send to the server-- due to // short rounding, this will probably differ from the inputted view angles MoveCmdToViewAngles(cmd, bs->ps->delta_angles, bs->now.view); }
/* ============== BotChangeViewAngles ============== */ void BotChangeViewAngles(bot_state_t *bs, float thinktime) { float diff, factor, maxchange, anglespeed, disired_speed; int i; if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360; factor = bs->skills.turnspeed; if (factor > 1) { factor = 1; } if (factor < 0.25) { factor = 0.25f; } maxchange = bs->skills.maxturn; //if (maxchange < 240) maxchange = 240; maxchange *= thinktime; for (i = 0; i < 2; i++) { bs->viewangles[i] = AngleMod(bs->viewangles[i]); bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]); diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]); disired_speed = diff * factor; bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed); if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange; if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange; anglespeed = bs->viewanglespeed[i]; if (anglespeed > maxchange) anglespeed = maxchange; if (anglespeed < -maxchange) anglespeed = -maxchange; bs->viewangles[i] += anglespeed; bs->viewangles[i] = AngleMod(bs->viewangles[i]); bs->viewanglespeed[i] *= 0.45 * (1 - factor); } if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360; trap_EA_View(bs->client, bs->viewangles); }
/* ============== AICast_UpdateInput ============== */ void AICast_UpdateInput( cast_state_t *cs, int time ) { bot_input_t bi; bot_state_t *bs; int j; float speed; bs = cs->bs; //add the delta angles to the bot's current view angles for ( j = 0; j < 3; j++ ) { bs->viewangles[j] = AngleMod( bs->viewangles[j] + SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) ); } // AICast_ChangeViewAngles( cs, (float) time / 1000 ); // if ( cs->pauseTime > level.time ) { trap_EA_View( bs->client, bs->viewangles ); trap_EA_GetInput( bs->client, (float) time / 1000, &bi ); AICast_InputToUserCommand( cs, &bi, &bs->lastucmd, bs->cur_ps.delta_angles ); g_entities[cs->bs->entitynum].client->ps.pm_flags &= ~PMF_RESPAWNED; // //subtract the delta angles for ( j = 0; j < 3; j++ ) { bs->viewangles[j] = AngleMod( bs->viewangles[j] - SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) ); } // return; } // trap_EA_GetInput( bs->client, (float) time / 1000, &bi ); // // restrict the speed according to the character and their current speedScale // HACK, don't slow down while crouching if ( bi.actionflags & ACTION_CROUCH && cs->speedScale < 1.0 ) { cs->speedScale = 1.0; } // // check some Cast AI specific movement flags if ( cs->actionFlags & CASTACTION_WALK ) { if ( cs->speedScale > ( cs->attributes[WALKING_SPEED] / cs->attributes[RUNNING_SPEED] ) ) { cs->speedScale = ( cs->attributes[WALKING_SPEED] / cs->attributes[RUNNING_SPEED] ); } } // don't ever let the speed get too low if ( cs->speedScale < 0.25 ) { cs->speedScale = 0.25; } if ( cs->speedScale > 1.2 ) { cs->speedScale = 1.2; } // speed = cs->speedScale * cs->attributes[RUNNING_SPEED]; // //if (speed <= (cs->attributes[WALKING_SPEED] + (cs->attributes[WALKING_SPEED] + 50 < cs->attributes[RUNNING_SPEED] ? 50 : -1))) // do a fast shuffle if slightly over walking speed if ( speed <= cs->attributes[WALKING_SPEED] ) { cs->actionFlags |= CASTACTION_WALK; } // // we use 300 here, because the default player speed is 300, so Cast AI's can't move faster than that if ( ( bi.speed / 400.0 ) > ( speed / 300.0 ) ) { bi.speed = 400.0 * ( speed / 300.0 ); if ( bi.speed > 400.0 ) { bi.speed = 400.0; // just in case, we should never exceed this } } // // do a fast shuffle if slightly over walking speed if ( bi.speed <= ( 400.0 / 300.0 ) * ( cs->attributes[WALKING_SPEED] + ( cs->attributes[WALKING_SPEED] + 50 < cs->attributes[RUNNING_SPEED] ? 50 : -1 ) ) ) { cs->actionFlags |= CASTACTION_WALK; } // AICast_InputToUserCommand( cs, &bi, &bs->lastucmd, bs->cur_ps.delta_angles ); // // check some Cast AI specific movement flags if ( cs->actionFlags & CASTACTION_WALK ) { bs->lastucmd.buttons |= BUTTON_WALKING; // play the walking animation } // //subtract the delta angles for ( j = 0; j < 3; j++ ) { bs->viewangles[j] = AngleMod( bs->viewangles[j] - SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) ); } // // make sure the respawn flag is disabled (causes problems after multiple "map xxx" commands) g_entities[cs->bs->entitynum].client->ps.pm_flags &= ~PMF_RESPAWNED; // set the aiState g_entities[cs->bs->entitynum].client->ps.aiState = cs->aiState; }