Ejemplo n.º 1
0
/*
==============
BotUpdateInput
==============
*/
void BotUpdateInput( bot_state_t *bs, int time ) {
	bot_input_t bi;
	int j;

	//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] ) );
	}
	//
	BotChangeViewAngles( bs, (float) time / 1000 );
	trap_EA_GetInput( bs->client, (float) time / 1000, &bi );
	//respawn hack
	if ( bi.actionflags & ACTION_RESPAWN ) {
		if ( bs->lastucmd.buttons & BUTTON_ATTACK ) {
			bi.actionflags &= ~( ACTION_RESPAWN | ACTION_ATTACK );
		}
	}
	//
	BotInputToUserCommand( &bi, &bs->lastucmd, bs->cur_ps.delta_angles, time );
	bs->lastucmd.serverTime = time;
	//subtract the delta angles
	for ( j = 0; j < 3; j++ ) {
		bs->viewangles[j] = AngleMod( bs->viewangles[j] - SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) );
	}
}
Ejemplo n.º 2
0
/*
 * BotUpdateInput
 */
void
BotUpdateInput(bot_state_t *bs, int time, int elapsed_time)
{
	bot_input_t bi;
	int j;

	/* add the delta angles to the bot's current view angles */
	for(j = 0; j < 3; j++)
		bs->viewangles[j] =
			modeuler(bs->viewangles[j] +
				SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	/* change the bot view angles */
	BotChangeViewAngles(bs, (float)elapsed_time / 1000);
	/* retrieve the bot input */
	trap_EA_GetInput(bs->client, (float)time / 1000, &bi);
	/* respawn hack */
	if(bi.actionflags & ACTION_RESPAWN)
		if(bs->lastucmd.buttons & BUTTON_PRIATTACK) bi.actionflags &=
				~(ACTION_RESPAWN|ACTION_ATTACK);
	/* convert the bot input to a usercmd */
	BotInputToUserCommand(&bi, &bs->lastucmd, bs->cur_ps.delta_angles, time);
	/* subtract the delta angles */
	for(j = 0; j < 3; j++)
		bs->viewangles[j] =
			modeuler(bs->viewangles[j] -
				SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
}
Ejemplo n.º 3
0
/*
==============
BotUpdateInput
==============
*/
void BotUpdateInput(bot_state_t *bs, int time, int elapsed_time) {
	bot_input_t bi;
	int j;

	//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]));
	}

	//change the bot view angles
	BotChangeViewAngles(bs, (float) elapsed_time / 1000);

	//retrieve the bot input
	trap_EA_GetInput(bs->client, (float) time / 1000, &bi);

	//respawn hack
	if (bi.actionflags & ACTION_RESPAWN) {
		if (bs->lastucmd.buttons & BUTTON_ATTACK) bi.actionflags &= ~(ACTION_RESPAWN|ACTION_ATTACK);
	}

	//convert the bot input to a usercmd
	BotInputToUserCommand(&bi, &g_entities[bs->client], &bs->lastucmd, bs->cur_ps.delta_angles, time, bs->noUseTime);

	//subtract the delta angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
}
Ejemplo n.º 4
0
/*
==============
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;
}
Ejemplo n.º 5
0
/*
============
AICast_Blocked
============
*/
void AICast_Blocked( cast_state_t *cs, bot_moveresult_t *moveresult, int activate, bot_goal_t *goal ) {
	vec3_t pos, dir;
	aicast_predictmove_t move;
	usercmd_t ucmd;
	bot_input_t bi;
	cast_state_t *ocs;
	int i, blockEnt = -1;
	bot_goal_t ogoal;

	if ( cs->blockedAvoidTime < level.time ) {
		if ( cs->blockedAvoidTime < level.time - 300 ) {
			if ( VectorCompare( cs->bs->cur_ps.velocity, vec3_origin ) && !cs->bs->lastucmd.forwardmove && !cs->bs->lastucmd.rightmove ) {
				// not moving, don't bother checking
				cs->blockedAvoidTime = level.time - 1;
				return;
			}
			// are we going to hit someone soon?
			trap_EA_GetInput( cs->entityNum, (float) level.time / 1000, &bi );
			AICast_InputToUserCommand( cs, &bi, &ucmd, cs->bs->cur_ps.delta_angles );
			AICast_PredictMovement( cs, 1, 0.6, &move, &ucmd, ( goal && goal->entitynum > -1 ) ? goal->entitynum : cs->entityNum );

			// blocked if we hit a client (or non-stationary mover) other than our enemy or goal
			if ( move.stopevent != PREDICTSTOP_HITCLIENT ) {
				// not blocked
				cs->blockedAvoidTime = level.time - 1;
				return;
			}

			// if we stopped passed our goal, ignore it
			if ( goal ) {
				if ( VectorDistance( cs->bs->origin, goal->origin ) < VectorDistance( cs->bs->origin, move.endpos ) ) {
					vec3_t v1, v2;
					VectorSubtract( goal->origin, cs->bs->origin, v1 );
					VectorSubtract( goal->origin, move.endpos, v2 );
					VectorNormalize( v1 );
					VectorNormalize( v2 );
					if ( DotProduct( v1, v2 ) < 0 ) {
						// we went passed the goal, so assume we can reach it
						cs->blockedAvoidTime = level.time - 1;
						return;
					}
				}
			}

			// try and get them to move, in case we can't get around them
			blockEnt = -1;
			for ( i = 0; i < move.numtouch; i++ ) {
				if ( move.touchents[i] >= MAX_CLIENTS ) {
					if ( !Q_stricmp( g_entities[move.touchents[i]].classname, "script_mover" ) ) {
						// avoid script_mover's
						blockEnt = move.touchents[i];
					}
					// if we are close to the impact point, then avoid this entity
					else if ( VectorDistance( cs->bs->origin, move.endpos ) < 10 ) {
						//G_Printf("AI (%s) avoiding %s\n", g_entities[cs->entityNum].aiName, g_entities[move.touchents[i]].classname );
						blockEnt = move.touchents[i];
					}
					continue;
				}
				//
				ocs = AICast_GetCastState( move.touchents[i] );
				if ( !ocs->bs ) {
					blockEnt = move.touchents[i];
				}
				// reject this blocker if we are following or going to them
				else if ( cs->followEntity != ocs->entityNum ) {
					// if they are moving away from us already, let them go
					if ( VectorLength( ocs->bs->cur_ps.velocity ) > 10 ) {
						vec3_t v1, v2;

						VectorSubtract( ocs->bs->origin, cs->bs->origin, v2 );
						VectorNormalize( v2 );
						VectorNormalize2( ocs->bs->cur_ps.velocity, v1 );

						if ( DotProduct( v1, v2 ) > 0.0 ) {
							continue;
						}
					}
					//
					// if they recently were asked to avoid us, then they're probably not listening
					if ( ocs->obstructingTime > level.time - 500 ) {
						blockEnt = move.touchents[i];
					}
					//
					// if they are not avoiding, ignore
					if ( !( ocs->aiFlags & AIFL_NOAVOID ) ) {
						continue;
					}
					//
					// they should avoid us
					if ( ocs->leaderNum >= 0 ) {
						ogoal.entitynum = ocs->leaderNum;
						VectorCopy( g_entities[ocs->leaderNum].r.currentOrigin, ogoal.origin );
						if ( AICast_GetAvoid( ocs, &ogoal, ocs->obstructingPos, qfalse, cs->entityNum ) ) {
							// give them time to move somewhere else
							ocs->obstructingTime = level.time + 1000;
						} else {
							// make sure they don't call GetAvoid() for another few frames to let others avoid also
							ocs->obstructingTime = level.time - 1;
							blockEnt = move.touchents[i];
						}
					} else {
						if ( AICast_GetAvoid( ocs, NULL, ocs->obstructingPos, qfalse, cs->entityNum ) ) {
							// give them time to move somewhere else
							ocs->obstructingTime = level.time + 1000;
						} else {
							// make sure they don't call GetAvoid() for another few frames to let others avoid also
							ocs->obstructingTime = level.time - 1;
							blockEnt = move.touchents[i];
						}
					}
				}
			}

		} else {
			return;
		}

		if ( blockEnt < 0 ) {
			// nothing found to be worth avoding
			cs->blockedAvoidTime = level.time - 1;
			return;
		}

		// something is blocking our path
		if ( g_entities[blockEnt].aiName && g_entities[blockEnt].client ) {
			int oldId = cs->castScriptStatus.scriptId;
			AICast_ScriptEvent( cs, "blocked", g_entities[blockEnt].aiName );
			if ( oldId != cs->castScriptStatus.scriptId ) {
				// the script has changed, so assume the scripting is handling the avoidance
				return;
			}
		}

		// avoid geometry and props, but assume clients will get out the way
		if ( /*blockEnt > MAX_CLIENTS &&*/ AICast_GetAvoid( cs, goal, pos, qfalse, blockEnt ) ) {
			VectorSubtract( pos, cs->bs->cur_ps.origin, dir );
			VectorNormalize( dir );
			cs->blockedAvoidYaw = vectoyaw( dir );
			if ( blockEnt >= MAX_CLIENTS ) {
				cs->blockedAvoidTime = level.time + 100 + rand() % 200;
			} else {
				cs->blockedAvoidTime = level.time + 300 + rand() % 400;
			}
		} else {
			cs->blockedAvoidTime = level.time - 1;    // don't look again for another few frames
			return;
		}
	}

	VectorClear( pos );
	pos[YAW] = cs->blockedAvoidYaw;
	AngleVectors( pos, dir, NULL, NULL );

	if ( moveresult->flags & MOVERESULT_ONTOPOFOBSTACLE ) {
		trap_EA_Jump( cs->bs->entitynum );
	}

	trap_EA_Move( cs->bs->entitynum, dir, 200 ); //400);

	vectoangles( dir, cs->bs->ideal_viewangles );
	cs->bs->ideal_viewangles[2] *= 0.5;
}