/* ============ 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 ) ); }
void AICast_StartFrame( int time ) { int i, elapsed, count, clCount; cast_state_t *cs; int castcount; static int lasttime; static vmCvar_t aicast_disable; gentity_t *ent; if ( trap_Cvar_VariableIntegerValue( "savegame_loading" ) ) { 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 ); trap_Cvar_Update( &aicast_debugname ); trap_Cvar_Update( &aicast_scripts ); // 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 } //G_Printf( "AI startframe: %i\n", time ); if ( elapsed < 0 ) { elapsed = 0; lasttime = time; } // don't let the framerate drop below 10 if ( elapsed > 100 ) { elapsed = 100; } //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 was: 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->inuse ) { if ( ent->aiInactive == qfalse ) { // elapsed = time - cs->lastThink; // // if they're moving/firing think every frame if ( ( elapsed >= 50 ) && ( ( ( ( !VectorCompare( ent->client->ps.velocity, vec3_origin ) ) || ( ent->client->buttons ) || ( elapsed >= aicast_thinktime ) ) && ( count <= aicast_maxthink ) ) || ( elapsed >= aicast_thinktime * 2 ) ) ) { // make it think now AICast_Think( i, (float)elapsed / 1000 ); cs->lastThink = time; // count++; } // check for any debug info updates AICast_DebugFrame( cs ); } else if ( cs->aiFlags & AIFL_WAITINGTOSPAWN ) { // check f the space is clear yet ent->AIScript_AlertEntity( ent ); } } else { trap_UnlinkEntity( ent ); } // // see if we've checked all cast AI's if ( ++castcount >= numcast ) { break; } } } // lasttime = time; }