Esempio n. 1
0
/*
============
AIChar_AIScript_AlertEntity

  triggered spawning, called from AI scripting
============
*/
void AIChar_AIScript_AlertEntity( gentity_t *ent ) {
    vec3_t mins, maxs;
    int numTouch, touch[10], i;
    cast_state_t    *cs;

    if ( !ent->aiInactive ) {
        return;
    }

    cs = AICast_GetCastState( ent->s.number );

    // if the current bounding box is invalid, then wait
    VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
    VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );
    trap_UnlinkEntity( ent );

    numTouch = trap_EntitiesInBox( mins, maxs, touch, 10 );

    // check that another client isn't inside us
    if ( numTouch ) {
        for ( i = 0; i < numTouch; i++ ) {
            // RF, note we should only check against clients since zombies need to spawn inside func_explosive (so they dont clip into view after it explodes)
            if ( g_entities[touch[i]].client && g_entities[touch[i]].r.contents == CONTENTS_BODY ) {
                //if (g_entities[touch[i]].r.contents & MASK_PLAYERSOLID)
                break;
            }
        }
        if ( i == numTouch ) {
            numTouch = 0;
        }
    }

    if ( numTouch ) {
        // invalid location
        cs->aiFlags |= AIFL_WAITINGTOSPAWN;
        return;
    }

    // RF, has to disable this so I could test some maps which have erroneously placed alertentity calls
    //ent->AIScript_AlertEntity = NULL;
    cs->aiFlags &= ~AIFL_WAITINGTOSPAWN;
    ent->aiInactive = qfalse;
    trap_LinkEntity( ent );

    // trigger a spawn script event
    AICast_ScriptEvent( AICast_GetCastState( ent->s.number ), "spawn", "" );
    // make it think so we update animations/angles
    AICast_Think( ent->s.number, (float)FRAMETIME / 1000 );
    cs->lastThink = level.time;
    AICast_UpdateInput( cs, FRAMETIME );
    trap_BotUserCommand( cs->bs->client, &( cs->lastucmd ) );
}
Esempio n. 2
0
/*
============
AICast_StartServerFrame

  Do movements, sighting, etc
============
*/
void AICast_StartServerFrame( int time ) {
	int i, elapsed, count, clCount;
	cast_state_t    *cs;
	int castcount;
	static int lasttime;
	static vmCvar_t aicast_disable;
	gentity_t *ent;
	cast_state_t *pcs;
//	int		oldLegsTimer;

	if ( trap_Cvar_VariableIntegerValue( "savegame_loading" ) ) {
		return;
	}

	if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
		return;
	}

	if ( saveGamePending ) {
		return;
	}

	// if waiting at intermission, don't think
	if ( strlen( g_missionStats.string ) > 1 ) {
		return;
	}

	if ( !aicast_disable.handle ) {
		trap_Cvar_Register( &aicast_disable, "aicast_disable", "0", CVAR_CHEAT );
	} else
	{
		trap_Cvar_Update( &aicast_disable );
		if ( aicast_disable.integer ) {
			return;
		}
	}

	trap_Cvar_Update( &aicast_debug );

	// no need to think during the intermission
	if ( level.intermissiontime ) {
		return;
	}
	//
	// make sure the AAS gets updated
	trap_BotLibStartFrame( (float) time / 1000 );
	//
	//
	elapsed = time - lasttime;
	if ( elapsed == 0 ) {
		return;         // no time has elapsed
	}

	pcs = AICast_GetCastState( 0 );

//G_Printf( "AI startserverframe: %i\n", time );

	if ( elapsed < 0 ) {
		elapsed = 0;
		lasttime = time;
	}
	// don't let the framerate drop below 10
	if ( elapsed > 100 ) {
		elapsed = 100;
	}
	//
	// process player's current script if it exists
	AICast_ScriptRun( AICast_GetCastState( 0 ), qfalse );
	//
	AICast_SightUpdate( (int)( (float)SIGHT_PER_SEC * ( (float)elapsed / 1000 ) ) );
	//
	count = 0;
	castcount = 0;
	clCount = 0;
	ent = g_entities;
	//
	//update the AI characters
	// TTimo gcc: left-hand operand of comma expression has no effect
	// initial line: for (i = 0; i < aicast_maxclients, clCount < level.numPlayingClients; i++, ent++)
	for ( i = 0; ( i < aicast_maxclients ) && ( clCount < level.numPlayingClients ) ; i++, ent++ )
	{
		if ( ent->client ) {
			clCount++;
		}
		//
		cs = AICast_GetCastState( i );
		// is this a cast AI?
		if ( cs->bs ) {
			if ( ent->aiInactive == qfalse && ent->inuse ) {
				//
				elapsed = level.time - cs->lastMoveThink;
				//
				// optimization, if they're not in the player's PVS, and they aren't trying to move, then don't bother thinking
				if (    ( ( ent->health > 0 ) && ( elapsed > 300 ) )
						||  ( g_entities[0].client && g_entities[0].client->cameraPortal )
						||  ( cs->vislist[0].visible_timestamp == cs->vislist[0].lastcheck_timestamp )
						||  ( pcs->vislist[cs->entityNum].visible_timestamp == pcs->vislist[cs->entityNum].lastcheck_timestamp )
						||  ( VectorLength( ent->client->ps.velocity ) > 0 )
						||  ( cs->bs->lastucmd.forwardmove || cs->bs->lastucmd.rightmove || cs->bs->lastucmd.upmove > 0 || cs->bs->lastucmd.buttons || cs->bs->lastucmd.wbuttons )
						||  ( trap_InPVS( cs->bs->origin, g_entities[0].s.pos.trBase ) ) ) { // do pvs check last, since it's the most expensive to call
//					oldLegsTimer = ent->client->ps.legsTimer;
					//
					// send it's movement commands
					//
					serverTime = time;
					AICast_UpdateInput( cs, elapsed );
					trap_BotUserCommand( cs->bs->client, &( cs->bs->lastucmd ) );
					cs->lastMoveThink = level.time;
					//
					// check for anim changes that may require us to stay still
					//
/*					if (oldLegsTimer != ent->client->ps.legsTimer) {
						// dont move until they are finished
						if (cs->castScriptStatus.scriptNoMoveTime < level.time + ent->client->ps.legsTimer) {
							cs->castScriptStatus.scriptNoMoveTime = level.time + ent->client->ps.legsTimer;
						}
					}
*/              }
			} else {
				trap_UnlinkEntity( ent );
			}
			//
			// see if we've checked all cast AI's
			if ( ++castcount >= numcast ) {
				break;
			}
		}
	}
	//
	lasttime = time;
}