CGameRules *InstallGameRules( void ) { SERVER_COMMAND( "exec game.rc\n" ); g_engfuncs.pfnServerExecute(); ALERT( at_aiconsole, "InstallGameRules\n" ); if ( !gpGlobals->deathmatch ) { // generic half-life g_teamplay = 0; return new CHalfLifeRules; } else { if( CVAR_GET_FLOAT( "mp_teamplay" ) > 0 ) { // teamplay g_teamplay = 1; return new CHalfLifeTeamplay; } if ((int)gpGlobals->deathmatch == 1) { // vanilla deathmatch g_teamplay = 0; return new CHalfLifeMultiplay; } else { // vanilla deathmatch?? g_teamplay = 0; return new CHalfLifeMultiplay; } } }
// sets the round state // ben notes : bSkipAutoRoundThink will avoid calling the round think function // ben notes : after updating the status void CBaseRoundRules::SetRoundState(ROUND_STATE iRoundState, bool bSkipAutoRoundThink) { // check validity of what we have been sent if((iRoundState < ROUND_NOTSTARTED) || (iRoundState > ROUND_NOPLAYERS)) { // - report the error ALERT(at_console, "Bad Round State being set - (%i)\n", (int)iRoundState); UTIL_LogPrintf(ROUND_LOGGING, "World triggered \"Bad Round State\" (round_state \"%i\") (old_round_state \"%i\")\n", (int)iRoundState, (int)m_iRoundState); // - give the round state a dummy value to keep it going iRoundState = ROUND_WAITING_FOR_PLAYERS; } // - log the change UTIL_LogPrintf(ALL_LOGGING, "World triggered \"Round State Change\" (round_state \"%i\") (old_round_state \"%i\")\n", (int)iRoundState, (int)m_iRoundState); // - set the round state m_iRoundState = iRoundState; // - call round think to update the round progress. // ben notes : after set round state is called we should leave the round think // ben notes : function or wierd bugs could creep in if(GetRoundState() != ROUND_NOPLAYERS && bSkipAutoRoundThink == false) this->RoundThink(); }
//========================================================= // ********** DeadGenericMonster SPAWN ********** //========================================================= void CDeadGenericMonster :: Spawn( void ) { Precache(); SET_MODEL(ENT(pev), STRING(pev->model)); pev->effects = 0; pev->yaw_speed = 8; //LRC -- what? pev->sequence = 0; if (pev->netname) { pev->sequence = LookupSequence( STRING(pev->netname) ); if (pev->sequence == -1) { ALERT ( at_debug, "Invalid sequence name \"%s\" in monster_generic_dead\n", STRING(pev->netname) ); } } else { pev->sequence = LookupActivity( pev->frags ); // if (pev->sequence == -1) // { // ALERT ( at_error, "monster_generic_dead - specify a sequence name or choose a different death type: model \"%s\" has no available death sequences.\n", STRING(pev->model) ); // } //...and if that doesn't work, forget it. } // Corpses have less health pev->health = 8; MonsterInitDead(); ResetSequenceInfo( ); pev->frame = 255; // pose at the _end_ of its death sequence. }
/* <cd466> ../cstrike/dlls/h_cycler.cpp:96 */ void CCycler::GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax) { if (!szModel || !szModel[0]) { ALERT(at_error, "cycler at %.0f %.0f %0.f missing modelname", pev->origin.x, pev->origin.y, pev->origin.z); REMOVE_ENTITY(ENT(pev)); return; } if (pev->classname) { RemoveEntityHashValue(pev, STRING(pev->classname), CLASSNAME); } MAKE_STRING_CLASS("cycler", pev); AddEntityHashValue(pev, STRING(pev->classname), CLASSNAME); PRECACHE_MODEL(szModel); SET_MODEL(ENT(pev), szModel); CCycler::Spawn(); UTIL_SetSize(pev, vecMin, vecMax); }
void CGrappleHook::Killed(entvars_t *pev, int gib) { ALERT( at_console, "^2HLU -> ^3weapon_grapple ^2-> Tongue was killed.\n"); // Fograin92: Clear player myowner->pev->movetype = MOVETYPE_WALK; //Re-apply gravity myowner->m_afPhysicsFlags &= ~PFLAG_ON_GRAPPLE; //Remove "on grapple" flag myowner->m_iGrappleExists = 0; myowner->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0; // Fograin92: Clear monster if( (m_iHitMonster == 2) && (myHitMonster->IsAlive()) ) myHitMonster->pev->movetype = MOVETYPE_STEP; // Re-apply gravity to the pulled monster, if it's alive // Fograin92: Clear tongue leftovers bPullBack = false; UTIL_Remove( m_pTongue ); m_pTongue = NULL; m_iHitMonster = 0; SetThink(NULL); SetTouch(NULL); SUB_Remove( ); }
int R_AllocateCinematicTexture( unsigned int txFlags ) { int i = tr.num_cin_used; if( i >= MAX_MOVIE_TEXTURES ) { ALERT( at_error, "R_AllocateCinematicTexture: cine textures limit exceeded!\n" ); return 0; // disable } tr.num_cin_used++; if( !tr.cinTextures[i] ) { char txName[16]; Q_snprintf( txName, sizeof( txName ), "*cinematic%i", i ); // create new cinematic texture // NOTE: dimension of texture is no matter because CIN_UPLOAD_FRAME will be rescale texture tr.cinTextures[i] = CREATE_TEXTURE( txName, 256, 256, NULL, txFlags ); } return (i+1); }
void eeReadAll() { fill_file_index() ; if (!eeLoadGeneral() ) { generalDefault(); modelDefault(0); ALERT(STR_EEPROMWARN, STR_BADEEPROMDATA, AU_BAD_EEPROM); MESSAGE(STR_EEPROMWARN, STR_EEPROMFORMATTING, NULL, AU_EEPROM_FORMATTING); /* we remove all models */ for (uint32_t i=0; i<MAX_MODELS; i++) eeDeleteModel(i); eeDirty(EE_GENERAL); eeDirty(EE_MODEL); } else { eeLoadModelHeaders() ; } // TODO common! stickMode = g_eeGeneral.stickMode; #if defined(CPUARM) for (uint8_t i=0; languagePacks[i]!=NULL; i++) { if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) { currentLanguagePackIdx = i; currentLanguagePack = languagePacks[i]; } } #endif }
void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData ) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if( pEntity && pSaveData ) { // ALERT( at_console, "DispatchSave( %s, %i )\n", STRING( pent->v.classname ), pent->serialnumber ); ENTITYTABLE *pTable = &pSaveData->pTable[ pSaveData->currentIndex ]; if( pTable->pent != pent ) ALERT( at_error, "ENTITY TABLE OR INDEX IS WRONG!!!!\n" ); if( pEntity->ObjectCaps() & FCAP_DONT_SAVE ) return; // These don't use ltime & nextthink as times really, but we'll fudge around it. if( pEntity->pev->movetype == MOVETYPE_PUSH ) { float delta = gpGlobals->time - pEntity->pev->ltime; pEntity->pev->ltime += delta; pEntity->pev->nextthink += delta; pEntity->m_fPevNextThink = pEntity->pev->nextthink; pEntity->m_fNextThink += delta; } if( gpGlobals->changelevel ) pEntity->ClearPointers(); pTable->location = pSaveData->size; // Remember entity position for file I/O pTable->classname = pEntity->pev->classname; // Remember entity class for respawn CSave saveHelper( pSaveData ); pEntity->Save( saveHelper ); pTable->size = pSaveData->size - pTable->location;// Size of entity block is data size written to block } }
static long ioctl_unload_vmm(void) { int i; int64_t ret; long status = BF_IOCTL_SUCCESS; ret = common_unload_vmm(); if (ret != BF_SUCCESS) { ALERT("IOCTL_UNLOAD_VMM: failed to unload vmm: %lld\n", ret); status = BF_IOCTL_FAILURE; } for (i = 0; i < g_num_files; i++) platform_free(files[i], files_sizes[i]); g_num_files = 0; if (status == BF_IOCTL_SUCCESS) DEBUG("IOCTL_UNLOAD_VMM: succeeded\n"); return status; }
void CBigMomma::NodeStart( int iszNextNode ) { pev->netname = iszNextNode; CBaseEntity *pTarget = NULL; if ( pev->netname ) { edict_t *pentTarget = FIND_ENTITY_BY_TARGETNAME ( NULL, STRING(pev->netname) ); if ( !FNullEnt(pentTarget) ) pTarget = Instance( pentTarget ); } if ( !pTarget ) { ALERT( at_aiconsole, "BM: Finished the path!!\n" ); Remember( bits_MEMORY_PATH_FINISHED ); return; } Remember( bits_MEMORY_ON_PATH ); m_hTargetEnt = pTarget; }
void CISlave :: CallForHelp( char *szClassname, float flDist, EHANDLE hEnemy, Vector &vecLocation ) { ALERT( at_aiconsole, "help " ); // skip ones not on my netname if ( FStringNull( pev->netname )) return; CBaseEntity *pEntity = NULL; while ((pEntity = UTIL_FindEntityByString( pEntity, "netname", STRING( pev->netname ))) != NULL) { float d = (pev->origin - pEntity->pev->origin).Length(); if (d < flDist) { CBaseMonster *pMonster = pEntity->MyMonsterPointer( ); if (pMonster) { pMonster->m_afMemory |= bits_MEMORY_PROVOKED; pMonster->PushEnemy( hEnemy, vecLocation ); } } } }
//========================================================= // IAllocSound - moves a sound from the Free list to the // Active list returns the index of the alloc'd sound //========================================================= int CSoundEnt :: IAllocSound( void ) { int iNewSound; if ( m_iFreeSound == SOUNDLIST_EMPTY ) { // no free sound! ALERT ( at_console, "Free Sound List is full!\n" ); return SOUNDLIST_EMPTY; } // there is at least one sound available, so move it to the // Active sound list, and return its SoundPool index. iNewSound = m_iFreeSound;// copy the index of the next free sound m_iFreeSound = m_SoundPool[ m_iFreeSound ].m_iNext;// move the index down into the free list. m_SoundPool[ iNewSound ].m_iNext = m_iActiveSound;// point the new sound at the top of the active list. m_iActiveSound = iNewSound;// now make the new sound the top of the active list. You're done. return iNewSound; }
// Assumes this is ALWAYS enabled CPathTrack *CPathTrack :: Nearest( Vector origin ) { int deadCount; float minDist, dist; Vector delta; CPathTrack *ppath, *pnearest; delta = origin - pev->origin; delta.z = 0; minDist = delta.Length(); pnearest = this; ppath = GetNext(); // Hey, I could use the old 2 racing pointers solution to this, but I'm lazy :) deadCount = 0; while ( ppath && ppath != this ) { deadCount++; if ( deadCount > 9999 ) { ALERT( at_error, "Bad sequence of path_tracks from %s", STRING(pev->targetname) ); return NULL; } delta = origin - ppath->pev->origin; delta.z = 0; dist = delta.Length(); if ( dist < minDist ) { minDist = dist; pnearest = ppath; } ppath = ppath->GetNext(); } return pnearest; }
int snd_init(void) { char info_buf[256]; PaError p_err; if((p_err = Pa_Initialize()) != paNoError) { snprintf(info_buf, sizeof(info_buf), _("PortAudio init failed:\n%s\n"), Pa_GetErrorText(p_err)); ALERT(info_buf); return 1; } srconv_stream.data_in = (float*)malloc(pa_frames*2 * sizeof(float)); srconv_stream.data_out = (float*)malloc(pa_frames*2 * 10 * sizeof(float)); srconv_record.data_in = (float*)malloc(pa_frames*2 * sizeof(float)); srconv_record.data_out = (float*)malloc(pa_frames*2 * 10 * sizeof(float)); reconnect = 0; buf_index = 0; return 0; }
CHalfLifeMultiplay :: CHalfLifeMultiplay() { g_VoiceGameMgr.Init(&g_GameMgrHelper, gpGlobals->maxClients); RefreshSkillData(); m_flIntermissionEndTime = 0; g_flIntermissionStartTime = 0; // 11/8/98 // Modified by YWB: Server .cfg file is now a cvar, so that // server ops can run multiple game servers, with different server .cfg files, // from a single installed directory. // Mapcyclefile is already a cvar. // 3/31/99 // Added lservercfg file cvar, since listen and dedicated servers should not // share a single config file. (sjb) if ( IS_DEDICATED_SERVER() ) { // this code has been moved into engine, to only run server.cfg once } else { // listen server char *lservercfgfile = (char *)CVAR_GET_STRING( "lservercfgfile" ); if ( lservercfgfile && lservercfgfile[0] ) { char szCommand[256]; ALERT( at_console, "Executing listen server config file\n" ); sprintf( szCommand, "exec %s\n", lservercfgfile ); SERVER_COMMAND( szCommand ); } } }
int CFuncCollideWall :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { ALERT ( at_notice, "TakeDamage()\n"); TraceResult trace = UTIL_GetGlobalTrace( ); //== 1) //metal //== 5) //wood //== 5) //water //== -1/0) //not defined (default concrete) float flVolume = RANDOM_FLOAT ( 0.7 , 1.0 );//random volume range BOOL b_CanMakeParticles = TRUE; if ( CVAR_GET_FLOAT( "r_paintball" ) == 0 ) if ( CVAR_GET_FLOAT( "cl_wallpuff" ) >= 1 ) { if (pev->frags == 1) //metal { UTIL_Ricochet( trace.vecEndPos, 0.5 ); switch ( RANDOM_LONG(0,2) ) { case 0: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/metal1.wav", flVolume, ATTN_NORM, 0, 100); break; case 1: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/metal2.wav", flVolume, ATTN_NORM, 0, 100); break; case 2: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/metal3.wav", flVolume, ATTN_NORM, 0, 100); break; } if (RANDOM_LONG( 0, 99 ) < 40) UTIL_WhiteSparks( trace.vecEndPos, trace.vecPlaneNormal, 0, 5, 500, 500 );//chispas UTIL_WhiteSparks( trace.vecEndPos, trace.vecPlaneNormal, 9, 5, 5, 100 );//puntos UTIL_WhiteSparks( trace.vecEndPos, trace.vecPlaneNormal, 0, 5, 500, 20 );//chispas b_CanMakeParticles = FALSE; } if (pev->frags == 5) //wood { switch ( RANDOM_LONG(0,2) ) { case 0: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/wood1.wav", flVolume, ATTN_NORM, 0, 100); break; case 1: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/wood2.wav", flVolume, ATTN_NORM, 0, 100); break; case 2: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/wood3.wav", flVolume, ATTN_NORM, 0, 100); break; } } else if (pev->frags == 6) //water { switch ( RANDOM_LONG(0,2) ) { case 0: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/water1.wav", flVolume, ATTN_NORM, 0, 100); break; case 1: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/water2.wav", flVolume, ATTN_NORM, 0, 100); break; case 2: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/water3.wav", flVolume, ATTN_NORM, 0, 100); break; } } else if (pev->frags == 7) //gas canister { switch ( RANDOM_LONG(0,1) ) { case 0: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/gascan1.wav", flVolume, ATTN_NORM, 0, 100); break; case 1: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/gascan2.wav", flVolume, ATTN_NORM, 0, 100); break; } } else { switch ( RANDOM_LONG(0,2) ) { case 0: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/concrete1.wav", flVolume, ATTN_NORM, 0, 100); break; case 1: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/concrete2.wav", flVolume, ATTN_NORM, 0, 100); break; case 2: UTIL_EmitAmbientSound(ENT(0), trace.vecEndPos, "weapons/bulletimpact/concrete3.wav", flVolume, ATTN_NORM, 0, 100); break; } } if (b_CanMakeParticles) { if ( CVAR_GET_FLOAT("r_particles" ) != 0 ) { MESSAGE_BEGIN(MSG_ALL, gmsgParticles); WRITE_SHORT(0); WRITE_BYTE(0); WRITE_COORD( trace.vecEndPos.x ); WRITE_COORD( trace.vecEndPos.y ); WRITE_COORD( trace.vecEndPos.z ); WRITE_COORD( 0 ); WRITE_COORD( 0 ); WRITE_COORD( 0 ); if (pev->frags == 5) //wood WRITE_SHORT(iDefaultHitWood1); else if (pev->frags == 6) //water WRITE_SHORT(iDefaultWaterSplash); else if (pev->frags == 7) //gas canister WRITE_SHORT(iDefaultGasCanister); else WRITE_SHORT(iDefaultWallSmoke); MESSAGE_END(); } } }//eo cvar check return 1; }
void CCyclerSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { m_animate = !m_animate; ALERT( at_console, "Sprite: %s\n", STRING(pev->model) ); }
/* ============== ChangeLevel Server is changing to a new level, check mapcycle.txt for map name and setup info ============== */ void CHalfLifeMultiplay :: ChangeLevel( void ) { static char szPreviousMapCycleFile[ 256 ]; static mapcycle_t mapcycle; char szNextMap[32]; char szFirstMapInList[32]; char szCommands[ 1500 ]; char szRules[ 1500 ]; int minplayers = 0, maxplayers = 0; strcpy( szFirstMapInList, "hldm1" ); // the absolute default level is hldm1 int curplayers; BOOL do_cycle = TRUE; // find the map to change to char *mapcfile = (char*)CVAR_GET_STRING( "mapcyclefile" ); ASSERT( mapcfile != NULL ); szCommands[ 0 ] = '\0'; szRules[ 0 ] = '\0'; curplayers = CountPlayers(); // Has the map cycle filename changed? if ( stricmp( mapcfile, szPreviousMapCycleFile ) ) { strcpy( szPreviousMapCycleFile, mapcfile ); DestroyMapCycle( &mapcycle ); if ( !ReloadMapCycleFile( mapcfile, &mapcycle ) || ( !mapcycle.items ) ) { ALERT( at_console, "Unable to load map cycle file %s\n", mapcfile ); do_cycle = FALSE; } } if ( do_cycle && mapcycle.items ) { BOOL keeplooking = FALSE; BOOL found = FALSE; mapcycle_item_s *item; // Assume current map strcpy( szNextMap, STRING(gpGlobals->mapname) ); strcpy( szFirstMapInList, STRING(gpGlobals->mapname) ); // Traverse list for ( item = mapcycle.next_item; item->next != mapcycle.next_item; item = item->next ) { keeplooking = FALSE; ASSERT( item != NULL ); if ( item->minplayers != 0 ) { if ( curplayers >= item->minplayers ) { found = TRUE; minplayers = item->minplayers; } else { keeplooking = TRUE; } } if ( item->maxplayers != 0 ) { if ( curplayers <= item->maxplayers ) { found = TRUE; maxplayers = item->maxplayers; } else { keeplooking = TRUE; } } if ( keeplooking ) continue; found = TRUE; break; } if ( !found ) { item = mapcycle.next_item; } // Increment next item pointer mapcycle.next_item = item->next; // Perform logic on current item strcpy( szNextMap, item->mapname ); ExtractCommandString( item->rulebuffer, szCommands ); strcpy( szRules, item->rulebuffer ); } if ( !IS_MAP_VALID(szNextMap) ) { strcpy( szNextMap, szFirstMapInList ); } g_fGameOver = TRUE; ALERT( at_console, "CHANGE LEVEL: %s\n", szNextMap ); if ( minplayers || maxplayers ) { ALERT( at_console, "PLAYER COUNT: min %i max %i current %i\n", minplayers, maxplayers, curplayers ); } if ( strlen( szRules ) > 0 ) { ALERT( at_console, "RULES: %s\n", szRules ); } CHANGE_LEVEL( szNextMap, NULL ); if ( strlen( szCommands ) > 0 ) { SERVER_COMMAND( szCommands ); } }
/* ============== ReloadMapCycleFile Parses mapcycle.txt file into mapcycle_t structure ============== */ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) { char szBuffer[ MAX_RULE_BUFFER ]; char szMap[ 32 ]; int length; char *pFileList; char *aFileList = pFileList = (char*)LOAD_FILE_FOR_ME( filename, &length ); int hasbuffer; mapcycle_item_s *item, *newlist = NULL, *next; if ( pFileList && length ) { // the first map name in the file becomes the default while ( 1 ) { hasbuffer = 0; memset( szBuffer, 0, MAX_RULE_BUFFER ); pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) <= 0 ) break; strcpy( szMap, com_token ); // Any more tokens on this line? if ( COM_TokenWaiting( pFileList ) ) { pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) > 0 ) { hasbuffer = 1; strcpy( szBuffer, com_token ); } } // Check map if ( IS_MAP_VALID( szMap ) ) { // Create entry char *s; item = new mapcycle_item_s; strcpy( item->mapname, szMap ); item->minplayers = 0; item->maxplayers = 0; memset( item->rulebuffer, 0, MAX_RULE_BUFFER ); if ( hasbuffer ) { s = g_engfuncs.pfnInfoKeyValue( szBuffer, "minplayers" ); if ( s && s[0] ) { item->minplayers = atoi( s ); item->minplayers = max( item->minplayers, 0 ); item->minplayers = min( item->minplayers, gpGlobals->maxClients ); } s = g_engfuncs.pfnInfoKeyValue( szBuffer, "maxplayers" ); if ( s && s[0] ) { item->maxplayers = atoi( s ); item->maxplayers = max( item->maxplayers, 0 ); item->maxplayers = min( item->maxplayers, gpGlobals->maxClients ); } // Remove keys // g_engfuncs.pfnInfo_RemoveKey( szBuffer, "minplayers" ); g_engfuncs.pfnInfo_RemoveKey( szBuffer, "maxplayers" ); strcpy( item->rulebuffer, szBuffer ); } item->next = cycle->items; cycle->items = item; } else { ALERT( at_console, "Skipping %s from mapcycle, not a valid map\n", szMap ); } } FREE_FILE( aFileList ); } // Fixup circular list pointer item = cycle->items; // Reverse it to get original order while ( item ) { next = item->next; item->next = newlist; newlist = item; item = next; } cycle->items = newlist; item = cycle->items; // Didn't parse anything if ( !item ) { return 0; } while ( item->next ) { item = item->next; } item->next = cycle->items; cycle->next_item = item->next; return 1; }
// make the entity carry out the scripted sequence instructions, but without // destroying the monster's state. void CCineAI::PossessEntity(void) { Schedule_t *pNewSchedule; CBaseEntity * pEntity = m_hTargetEnt; CBaseMonster *pTarget = NULL; if(pEntity) pTarget = pEntity->MyMonsterPointer(); if(pTarget) { if(!pTarget->CanPlaySequence(FCanOverrideState(), SS_INTERRUPT_AI)) { ALERT(at_aiconsole, "(AI)Can't possess entity %s\n", STRING(pTarget->pev->classname)); return; } pTarget->m_pGoalEnt = this; pTarget->m_pCine = this; pTarget->m_hTargetEnt = this; m_saved_movetype = pTarget->pev->movetype; m_saved_solid = pTarget->pev->solid; m_saved_effects = pTarget->pev->effects; pTarget->pev->effects |= pev->effects; switch(m_fMoveTo) { case 0: case 5: pTarget->m_scriptState = SCRIPT_WAIT; break; case 1: pTarget->m_scriptState = SCRIPT_WALK_TO_MARK; break; case 2: pTarget->m_scriptState = SCRIPT_RUN_TO_MARK; break; case 4: // zap the monster instantly to the site of the script entity. UTIL_SetOrigin(pTarget->pev, pev->origin); pTarget->pev->ideal_yaw = pev->angles.y; pTarget->pev->avelocity = Vector(0, 0, 0); pTarget->pev->velocity = Vector(0, 0, 0); pTarget->pev->effects |= EF_NOINTERP; pTarget->pev->angles.y = pev->angles.y; pTarget->m_scriptState = SCRIPT_WAIT; m_startTime = gpGlobals->time + 1E6; // UNDONE: Add a flag to do this so people can fixup physics after teleporting monsters pTarget->pev->flags &= ~FL_ONGROUND; break; default: ALERT(at_aiconsole, "aiscript: invalid Move To Position value!"); break; } ALERT(at_aiconsole, "\"%s\" found and used\n", STRING(pTarget->pev->targetname)); pTarget->m_IdealMonsterState = MONSTERSTATE_SCRIPT; /* if (m_iszIdle) { StartSequence( pTarget, m_iszIdle, FALSE ); if (FStrEq( STRING(m_iszIdle), STRING(m_iszPlay))) { pTarget->pev->framerate = 0; } } */ // Already in a scripted state? if(pTarget->m_MonsterState == MONSTERSTATE_SCRIPT) { pNewSchedule = pTarget->GetScheduleOfType(SCHED_AISCRIPT); pTarget->ChangeSchedule(pNewSchedule); } } }
// make the entity enter a scripted sequence void CCineMonster::PossessEntity(void) { CBaseEntity * pEntity = m_hTargetEnt; CBaseMonster *pTarget = NULL; if(pEntity) pTarget = pEntity->MyMonsterPointer(); if(pTarget) { // FindEntity() just checked this! #if 0 if ( !pTarget->CanPlaySequence( FCanOverrideState() ) ) { ALERT( at_aiconsole, "Can't possess entity %s\n", STRING(pTarget->pev->classname) ); return; } #endif pTarget->m_pGoalEnt = this; pTarget->m_pCine = this; pTarget->m_hTargetEnt = this; m_saved_movetype = pTarget->pev->movetype; m_saved_solid = pTarget->pev->solid; m_saved_effects = pTarget->pev->effects; pTarget->pev->effects |= pev->effects; switch(m_fMoveTo) { case 0: pTarget->m_scriptState = SCRIPT_WAIT; break; case 1: pTarget->m_scriptState = SCRIPT_WALK_TO_MARK; DelayStart(1); break; case 2: pTarget->m_scriptState = SCRIPT_RUN_TO_MARK; DelayStart(1); break; case 4: UTIL_SetOrigin(pTarget->pev, pev->origin); pTarget->pev->ideal_yaw = pev->angles.y; pTarget->pev->avelocity = Vector(0, 0, 0); pTarget->pev->velocity = Vector(0, 0, 0); pTarget->pev->effects |= EF_NOINTERP; pTarget->pev->angles.y = pev->angles.y; pTarget->m_scriptState = SCRIPT_WAIT; m_startTime = gpGlobals->time + 1E6; // UNDONE: Add a flag to do this so people can fixup physics after teleporting monsters // pTarget->pev->flags &= ~FL_ONGROUND; break; } // ALERT( at_aiconsole, "\"%s\" found and used (INT: %s)\n", STRING( pTarget->pev->targetname ), FBitSet(pev->spawnflags, SF_SCRIPT_NOINTERRUPT)?"No":"Yes" ); pTarget->m_IdealMonsterState = MONSTERSTATE_SCRIPT; if(m_iszIdle) { StartSequence(pTarget, m_iszIdle, FALSE); if(FStrEq(STRING(m_iszIdle), STRING(m_iszPlay))) { pTarget->pev->framerate = 0; } } } }
// Used for context sensitive mouse and for processing right-click // Must be shared, uses prediction code // Fill in target index or target point, depending on type of order decided upon AvHOrderType AvHGetDefaultOrderType(AvHTeamNumber inTeam, const vec3_t& inOrigin, const vec3_t& inNormRay, int& outTargetIndex, vec3_t& outTargetPoint, AvHUser3& outUser3, AvHOrderTargetType& outTargetType) { vec3_t theTraceStart; vec3_t theTraceEnd; AvHOrderType theOrderType = ORDERTYPE_UNDEFINED; // // Look for a player order // if(!AvHOrderTracePlayers(inTeam, inOrigin, inNormRay, theOrderType, outTargetIndex)) // { // // If couldn't find one, create a non-player order if possible // //AvHOrderTraceNonPlayers(inTeam, inOrigin, inNormRay, theOrderType, outTargetIndex, outTargetPoint); // } // Offset a little so we don't hit the commander VectorMA(inOrigin, kSelectionStartRange, inNormRay, theTraceStart); VectorMA(inOrigin, kSelectionEndRange, inNormRay, theTraceEnd); int theFoundIndex = -1; vec3_t theFoundLocation; AvHTeamNumber theTeamOfThingHit; bool thePlayerHit = false; int theUserThree = 0; int theUserFour = 0; if(AvHSHUTraceTangible(theTraceStart, theTraceEnd, theFoundIndex, theFoundLocation, theTeamOfThingHit, thePlayerHit, theUserThree, theUserFour)) { float theHealthPercentage=100.0f; float theArmorPercentage=100.0f; bool theSighted=false; #ifdef AVH_SERVER CBaseEntity *theEntity=AvHSUGetEntityFromIndex(theFoundIndex); if ( theEntity ) { theHealthPercentage=theEntity->pev->health/theEntity->pev->max_health; } else { ALERT(at_console, "Not a buildable\n"); } theArmorPercentage = theEntity->pev->armorvalue/AvHPlayerUpgrade::GetMaxArmorLevel(theEntity->pev->iuser4, (AvHUser3)theEntity->pev->iuser3); theSighted=GetHasUpgrade(theEntity->pev->iuser4, MASK_VIS_SIGHTED); #endif // Did we hit an enemy? If so, issue an attack order on him, then we're done, it's highest priority if(thePlayerHit ) { // Did we hit a player on our team? If so check for welding, if not guard if((theTeamOfThingHit == inTeam ) && (theTeamOfThingHit != TEAM_IND) ) { theOrderType = ORDERTYPET_GUARD; if ( theArmorPercentage < 0.90f ) { theOrderType = ORDERTYPET_WELD; outTargetType = ORDERTARGETTYPE_TARGET; } outTargetIndex = theFoundIndex; outUser3 = (AvHUser3)theUserThree; } } // Something to pick up? if(!thePlayerHit ) { // if ( ( theTeamOfThingHit ) != inTeam && (theTeamOfThingHit != TEAM_IND) && theSighted ) // { // // Use it's center for the height // VectorCopy(theFoundLocation, outTargetPoint); // theOrderType = ORDERTYPET_ATTACK; // outTargetIndex = theFoundIndex; // outUser3 = (AvHUser3)theUserThree; // outTargetType = ORDERTARGETTYPE_LOCATION; // } // else if ( theUserThree == AVH_USER3_MARINEITEM) { // Use it's center for the height VectorCopy(theFoundLocation, outTargetPoint); outTargetIndex = theFoundIndex; outUser3 = (AvHUser3)theUserThree; // We're done theOrderType = ORDERTYPET_GET; } // Buildable? else if(GetHasUpgrade(theUserFour, MASK_BUILDABLE) && (theTeamOfThingHit == inTeam) && (theTeamOfThingHit != TEAM_IND)) { // Use it's center for the height VectorCopy(theFoundLocation, outTargetPoint); outTargetIndex = theFoundIndex; outUser3 = (AvHUser3)theUserThree; // We're done theOrderType = ORDERTYPET_BUILD; } // Weldable? else if(theUserThree == AVH_USER3_WELD ) { // Use it's center for the height VectorCopy(theFoundLocation, outTargetPoint); outTargetIndex = theFoundIndex; // We're done theOrderType = ORDERTYPET_WELD; } // Hit the ground? Move to, we're done else if(theUserThree == AVH_USER3_WAYPOINT || (( theTeamOfThingHit != inTeam) && !theSighted )) { // Use it's center for the height VectorCopy(theFoundLocation, outTargetPoint); // We're done theOrderType = ORDERTYPEL_MOVE; } // Did we hit an entity on our team? Repair/guard it, we're done else if((theTeamOfThingHit == inTeam) && (theTeamOfThingHit != TEAM_IND)) { theOrderType = ORDERTYPET_GUARD; if ( theHealthPercentage < 0.90f ) { theOrderType = ORDERTYPET_WELD; VectorCopy(theFoundLocation, outTargetPoint); outTargetType = ORDERTARGETTYPE_LOCATION; } outTargetIndex = theFoundIndex; outUser3 = (AvHUser3)theUserThree; } } // else if(!thePlayerHit && (theUserThree == AVH_USER3_USEABLE)) // { // // Use it's center for the height // VectorCopy(theFoundLocation, outTargetPoint); // outTargetIndex = theFoundIndex; // // // We're done // theOrderType = ORDERTYPEL_USE; // } } return theOrderType; }
void CWorld :: Precache( void ) { g_pLastSpawn = NULL; CVAR_SET_STRING("sv_gravity", "800"); // 67ft/sec CVAR_SET_STRING("sv_stepsize", "18"); CVAR_SET_STRING("room_type", "0"); // clear DSP // Create all the arenas for (int i = 0; i < MAX_ARENAS; i++) { g_pArenaList[i] = GetClassPtr( ( CDiscArena *)NULL ); g_pArenaList[i]->Spawn(); } // Set up game rules if (g_pGameRules) { delete g_pGameRules; } g_pGameRules = InstallGameRules( ); //!!!UNDONE why is there so much Spawn code in the Precache function? I'll just keep it here ///!!!LATER - do we want a sound ent in deathmatch? (sjb) //pSoundEnt = CBaseEntity::Create( "soundent", g_vecZero, g_vecZero, edict() ); pSoundEnt = GetClassPtr( ( CSoundEnt *)NULL ); pSoundEnt->Spawn(); if ( !pSoundEnt ) { ALERT ( at_console, "**COULD NOT CREATE SOUNDENT**\n" ); } InitBodyQue(); // init sentence group playback stuff from sentences.txt. // ok to call this multiple times, calls after first are ignored. SENTENCEG_Init(); // init texture type array from materials.txt TEXTURETYPE_Init(); // the area based ambient sounds MUST be the first precache_sounds // player precaches W_Precache (); // get weapon precaches ClientPrecache(); // sounds used from C physics code PRECACHE_SOUND("common/null.wav"); // clears sound channels PRECACHE_SOUND( "items/suitchargeok1.wav" );//!!! temporary sound for respawning weapons. PRECACHE_SOUND( "items/gunpickup2.wav" );// player picks up a gun. PRECACHE_SOUND( "common/bodydrop3.wav" );// dead bodies hitting the ground (animation events) PRECACHE_SOUND( "common/bodydrop4.wav" ); PRECACHE_SOUND( "r_tele1.wav" ); // respawn sound PRECACHE_SOUND( "scream1.wav" ); // falling scream sound PRECACHE_SOUND( "scream2.wav" ); // falling scream sound PRECACHE_SOUND( "scream3.wav" ); // falling scream sound PRECACHE_SOUND( "decap.wav" ); // decapitation sound PRECACHE_SOUND( "shatter.wav" ); // freeze decapitation sound PRECACHE_MODEL( "models/head.mdl" ); // head g_Language = (int)CVAR_GET_FLOAT( "sv_language" ); if ( g_Language == LANGUAGE_GERMAN ) { PRECACHE_MODEL( "models/germangibs.mdl" ); } else { PRECACHE_MODEL( "models/hgibs.mdl" ); PRECACHE_MODEL( "models/agibs.mdl" ); } PRECACHE_SOUND ("weapons/ric1.wav"); PRECACHE_SOUND ("weapons/ric2.wav"); PRECACHE_SOUND ("weapons/ric3.wav"); PRECACHE_SOUND ("weapons/ric4.wav"); PRECACHE_SOUND ("weapons/ric5.wav"); // // Setup light animation tables. 'a' is total darkness, 'z' is maxbright. // // 0 normal LIGHT_STYLE(0, "m"); // 1 FLICKER (first variety) LIGHT_STYLE(1, "mmnmmommommnonmmonqnmmo"); // 2 SLOW STRONG PULSE LIGHT_STYLE(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); // 3 CANDLE (first variety) LIGHT_STYLE(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); // 4 FAST STROBE LIGHT_STYLE(4, "mamamamamama"); // 5 GENTLE PULSE 1 LIGHT_STYLE(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj"); // 6 FLICKER (second variety) LIGHT_STYLE(6, "nmonqnmomnmomomno"); // 7 CANDLE (second variety) LIGHT_STYLE(7, "mmmaaaabcdefgmmmmaaaammmaamm"); // 8 CANDLE (third variety) LIGHT_STYLE(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); // 9 SLOW STROBE (fourth variety) LIGHT_STYLE(9, "aaaaaaaazzzzzzzz"); // 10 FLUORESCENT FLICKER LIGHT_STYLE(10, "mmamammmmammamamaaamammma"); // 11 SLOW PULSE NOT FADE TO BLACK LIGHT_STYLE(11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); // 12 UNDERWATER LIGHT MUTATION // this light only distorts the lightmap - no contribution // is made to the brightness of affected surfaces LIGHT_STYLE(12, "mmnnmmnnnmmnn"); // styles 32-62 are assigned by the light program for switchable lights // 63 testing LIGHT_STYLE(63, "a"); for ( i = 0; i < ARRAYSIZE(gDecals); i++ ) gDecals[i].index = DECAL_INDEX( gDecals[i].name ); // init the WorldGraph. WorldGraph.InitGraph(); // make sure the .NOD file is newer than the .BSP file. if ( !WorldGraph.CheckNODFile ( ( char * )STRING( gpGlobals->mapname ) ) ) {// NOD file is not present, or is older than the BSP file. WorldGraph.AllocNodes (); } else {// Load the node graph for this level if ( !WorldGraph.FLoadGraph ( (char *)STRING( gpGlobals->mapname ) ) ) {// couldn't load, so alloc and prepare to build a graph. ALERT ( at_console, "*Error opening .NOD file\n" ); WorldGraph.AllocNodes (); } else { ALERT ( at_console, "\n*Graph Loaded!\n" ); } } if ( pev->speed > 0 ) CVAR_SET_FLOAT( "sv_zmax", pev->speed ); else CVAR_SET_FLOAT( "sv_zmax", 4096 ); if ( pev->netname ) { ALERT( at_aiconsole, "Chapter title: %s\n", STRING(pev->netname) ); CBaseEntity *pEntity = CBaseEntity::Create( "env_message", g_vecZero, g_vecZero, NULL ); if ( pEntity ) { pEntity->SetThink( SUB_CallUseToggle ); pEntity->pev->message = pev->netname; pev->netname = 0; pEntity->pev->nextthink = gpGlobals->time + 0.3; pEntity->pev->spawnflags = SF_MESSAGE_ONCE; } } if ( pev->spawnflags & SF_WORLD_DARK ) CVAR_SET_FLOAT( "v_dark", 1.0 ); else CVAR_SET_FLOAT( "v_dark", 0.0 ); if ( pev->spawnflags & SF_WORLD_TITLE ) gDisplayTitle = TRUE; // display the game title if this key is set else gDisplayTitle = FALSE; if ( pev->spawnflags & SF_WORLD_FORCETEAM ) { CVAR_SET_FLOAT( "mp_defaultteam", 1 ); } else { CVAR_SET_FLOAT( "mp_defaultteam", 0 ); } // Discwar if ( g_iPlayersPerTeam < 1 ) g_iPlayersPerTeam = CVAR_GET_FLOAT("rc_playersperteam"); }
extern "C" void GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals ) #endif { // get the engine functions from the engine... memcpy( &g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t) ); // get the globals from the engine gpGlobals = pGlobals; // get the directory name of the currently running game or mod // this now returns just the mod directory's name: http://metamod.org/engine_notes.html#GetGameDir char szGameDir[256]; char *szLibraryPath = ""; GET_GAME_DIR(szGameDir); if( !strcmpi( szGameDir, "valve" ) ) { mod_id = VALVE_DLL; #ifndef __linux__ szLibraryPath = "valve/dlls/hl.dll"; #else szLibraryPath = "valve/dlls/hl.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "bshift" ) ) { mod_id = BSHIFT_DLL; #ifndef __linux__ szLibraryPath = "bshift/dlls/hl.dll"; #else szLibraryPath = "bshift/dlls/bshift.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "gearbox" ) ) { mod_id = GEARBOX_DLL; #ifndef __linux__ szLibraryPath = "gearbox/dlls/opfor.dll"; #else szLibraryPath = "gearbox/dlls/opfor.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "decay" ) ) { mod_id = DECAY_DLL; #ifndef __linux__ szLibraryPath = "decay/dlls/decay.dll"; #else szLibraryPath = "decay/dlls/decay_i386.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "cstrike" ) ) { mod_id = CSTRIKE_DLL; #ifndef __linux__ szLibraryPath = "cstrike/dlls/mp.dll"; #else szLibraryPath = "cstrike/dlls/cs.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "czero" ) ) { mod_id = CZERO_DLL; #ifndef __linux__ szLibraryPath = "czero/dlls/mp.dll"; #else szLibraryPath = "czero/dlls/cs.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "czeror" ) ) { mod_id = CZEROR_DLL; #ifndef __linux__ szLibraryPath = "czeror/dlls/cz.dll"; #else szLibraryPath = "czeror/dlls/cz.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "dod" ) ) { mod_id = DOD_DLL; #ifndef __linux__ szLibraryPath = "dod/dlls/dod.dll"; #else szLibraryPath = "dod/dlls/dod.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "tfc" ) ) { mod_id = TFC_DLL; #ifndef __linux__ szLibraryPath = "tfc/dlls/tfc.dll"; #else szLibraryPath = "tfc/dlls/tfc.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( !strcmpi( szGameDir, "rewolf" ) ) { mod_id = REWOLF_DLL; #ifndef __linux__ szLibraryPath = "rewolf/dlls/gunman.dll"; #else szLibraryPath = nullptr; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = nullptr; #endif } } else if( !strcmpi( szGameDir, "hunger" ) ) { mod_id = HUNGER_DLL; #ifndef __linux__ szLibraryPath = "hunger/dlls/einar.dll"; #else szLibraryPath = nullptr; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = nullptr; #endif } } else if( !strcmpi( szGameDir , "ns") ) { mod_id = NS_DLL; #ifndef __linux__ szLibraryPath = "ns/dlls/ns.dll"; #else szLibraryPath = "ns/dlls/ns_i386.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } else if( strcmpi( szGameDir, "ship" ) ) { mod_id = SHIP_DLL; #ifndef __linux__ szLibraryPath = "ship/dlls/ship.dll"; #else szLibraryPath = "ship/dlls/ship_i386.so"; #endif if( !g_bIsMMPlugin ) { #ifndef __linux__ h_Library = LoadLibrary( szLibraryPath ); #else h_Library = dlopen( szLibraryPath, RTLD_NOW ); #endif } } strncpy( g_szLibraryPath, szLibraryPath, strlen( szLibraryPath ) ); if( !g_bIsMMPlugin && h_Library == nullptr ) { ALERT( at_error, "Library not found or not supported!\n" ); } extern bot_player_t g_valveBots[]; extern bot_player_t g_gearboxBots[]; extern bot_player_t g_dodBots[]; extern bot_player_t g_gunmanBots[]; extern bot_player_t g_nsBots[]; extern bot_player_t g_hungerBots[]; extern bot_player_t g_shipBots[]; if( mod_id == VALVE_DLL || mod_id == TFC_DLL ) { pBotData = g_valveBots; } else if( mod_id == GEARBOX_DLL ) { pBotData = g_gearboxBots; } else if( mod_id == DOD_DLL ) { pBotData = g_dodBots; } else if( mod_id == REWOLF_DLL ) { pBotData = g_gunmanBots; } else if( mod_id == NS_DLL ) { pBotData = g_nsBots; } else if( mod_id == HUNGER_DLL ) { pBotData = g_hungerBots; } else if( mod_id == SHIP_DLL ) { pBotData = g_shipBots; } LoadExtraExports(); if( g_bIsMMPlugin ) { return; } GetEngineFunctions( pengfuncsFromEngine, nullptr ); // give the engine functions to the other DLL... (*(GIVEFNPTRSTODLL)GetProcAddress( h_Library, "GiveFnptrsToDll" ))(pengfuncsFromEngine, pGlobals); // finished, interfacing from gamedll to engine complete return; }
void CController :: Move ( float flInterval ) { float flWaypointDist; float flCheckDist; float flDist;// how far the lookahead check got before hitting an object. float flMoveDist; Vector vecDir; Vector vecApex; CBaseEntity *pTargetEnt; // Don't move if no valid route if ( FRouteClear() ) { ALERT( at_aiconsole, "Tried to move with no route!\n" ); TaskFail(); return; } if ( m_flMoveWaitFinished > gpGlobals->time ) return; // Debug, test movement code #if 0 // if ( CVAR_GET_FLOAT("stopmove" ) != 0 ) { if ( m_movementGoal == MOVEGOAL_ENEMY ) RouteSimplify( m_hEnemy ); else RouteSimplify( m_hTargetEnt ); FRefreshRoute(); return; } #else // Debug, draw the route // DrawRoute( pev, m_Route, m_iRouteIndex, 0, 0, 255 ); #endif // if the monster is moving directly towards an entity (enemy for instance), we'll set this pointer // to that entity for the CheckLocalMove and Triangulate functions. pTargetEnt = NULL; if (m_flGroundSpeed == 0) { m_flGroundSpeed = 100; // TaskFail( ); // return; } flMoveDist = m_flGroundSpeed * flInterval; do { // local move to waypoint. vecDir = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Normalize(); flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length(); // MakeIdealYaw ( m_Route[ m_iRouteIndex ].vecLocation ); // ChangeYaw ( pev->yaw_speed ); // if the waypoint is closer than CheckDist, CheckDist is the dist to waypoint if ( flWaypointDist < DIST_TO_CHECK ) { flCheckDist = flWaypointDist; } else { flCheckDist = DIST_TO_CHECK; } if ( (m_Route[ m_iRouteIndex ].iType & (~bits_MF_NOT_TO_MASK)) == bits_MF_TO_ENEMY ) { // only on a PURE move to enemy ( i.e., ONLY MF_TO_ENEMY set, not MF_TO_ENEMY and DETOUR ) pTargetEnt = m_hEnemy; } else if ( (m_Route[ m_iRouteIndex ].iType & ~bits_MF_NOT_TO_MASK) == bits_MF_TO_TARGETENT ) { pTargetEnt = m_hTargetEnt; } // !!!BUGBUG - CheckDist should be derived from ground speed. // If this fails, it should be because of some dynamic entity blocking this guy. // We've already checked this path, so we should wait and time out if the entity doesn't move flDist = 0; if ( CheckLocalMove ( pev->origin, pev->origin + vecDir * flCheckDist, pTargetEnt, &flDist ) != LOCALMOVE_VALID ) { CBaseEntity *pBlocker; // Can't move, stop Stop(); // Blocking entity is in global trace_ent pBlocker = CBaseEntity::Instance( gpGlobals->trace_ent ); if (pBlocker) { DispatchBlocked( edict(), pBlocker->edict() ); } if ( pBlocker && m_moveWaitTime > 0 && pBlocker->IsMoving() && !pBlocker->IsPlayer() && (gpGlobals->time-m_flMoveWaitFinished) > 3.0 ) { // Can we still move toward our target? if ( flDist < m_flGroundSpeed ) { // Wait for a second m_flMoveWaitFinished = gpGlobals->time + m_moveWaitTime; // ALERT( at_aiconsole, "Move %s!!!\n", STRING( pBlocker->pev->classname ) ); return; } } else { // try to triangulate around whatever is in the way. if ( FTriangulate( pev->origin, m_Route[ m_iRouteIndex ].vecLocation, flDist, pTargetEnt, &vecApex ) ) { InsertWaypoint( vecApex, bits_MF_TO_DETOUR ); RouteSimplify( pTargetEnt ); } else { ALERT ( at_aiconsole, "Couldn't Triangulate\n" ); Stop(); if ( m_moveWaitTime > 0 ) { FRefreshRoute(); m_flMoveWaitFinished = gpGlobals->time + m_moveWaitTime * 0.5; } else { TaskFail(); ALERT( at_aiconsole, "Failed to move!\n" ); //ALERT( at_aiconsole, "%f, %f, %f\n", pev->origin.z, (pev->origin + (vecDir * flCheckDist)).z, m_Route[m_iRouteIndex].vecLocation.z ); } return; } } } // UNDONE: this is a hack to quit moving farther than it has looked ahead. if (flCheckDist < flMoveDist) { MoveExecute( pTargetEnt, vecDir, flCheckDist / m_flGroundSpeed ); // ALERT( at_console, "%.02f\n", flInterval ); AdvanceRoute( flWaypointDist ); flMoveDist -= flCheckDist; } else { MoveExecute( pTargetEnt, vecDir, flMoveDist / m_flGroundSpeed ); if ( ShouldAdvanceRoute( flWaypointDist - flMoveDist ) ) { AdvanceRoute( flWaypointDist ); } flMoveDist = 0; } if ( MovementIsComplete() ) { Stop(); RouteClear(); } } while (flMoveDist > 0 && flCheckDist > 0); // cut corner? if (flWaypointDist < 128) { if ( m_movementGoal == MOVEGOAL_ENEMY ) RouteSimplify( m_hEnemy ); else RouteSimplify( m_hTargetEnt ); FRefreshRoute(); if (m_flGroundSpeed > 100) m_flGroundSpeed -= 40; } else { if (m_flGroundSpeed < 400) m_flGroundSpeed += 10; } }
//========================================================= // Start task - selects the correct activity and performs // any necessary calculations to start the next task on the // schedule. //========================================================= void CBaseMonster :: StartTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_TURN_RIGHT: { float flCurrentYaw; flCurrentYaw = UTIL_AngleMod( pev->angles.y ); pev->ideal_yaw = UTIL_AngleMod( flCurrentYaw - pTask->flData ); SetTurnActivity(); break; } case TASK_TURN_LEFT: { float flCurrentYaw; flCurrentYaw = UTIL_AngleMod( pev->angles.y ); pev->ideal_yaw = UTIL_AngleMod( flCurrentYaw + pTask->flData ); SetTurnActivity(); break; } case TASK_REMEMBER: { Remember ( (int)pTask->flData ); TaskComplete(); break; } case TASK_FORGET: { Forget ( (int)pTask->flData ); TaskComplete(); break; } case TASK_FIND_HINTNODE: { m_iHintNode = FindHintNode(); if ( m_iHintNode != NO_NODE ) { TaskComplete(); } else { TaskFail(); } break; } case TASK_STORE_LASTPOSITION: { m_vecLastPosition = pev->origin; TaskComplete(); break; } case TASK_CLEAR_LASTPOSITION: { m_vecLastPosition = g_vecZero; TaskComplete(); break; } case TASK_CLEAR_HINTNODE: { m_iHintNode = NO_NODE; TaskComplete(); break; } case TASK_STOP_MOVING: { if ( m_IdealActivity == m_movementActivity ) { m_IdealActivity = GetStoppedActivity(); } RouteClear(); TaskComplete(); break; } case TASK_PLAY_SEQUENCE_FACE_ENEMY: case TASK_PLAY_SEQUENCE_FACE_TARGET: case TASK_PLAY_SEQUENCE: { m_IdealActivity = ( Activity )( int )pTask->flData; break; } case TASK_PLAY_ACTIVE_IDLE: { // monsters verify that they have a sequence for the node's activity BEFORE // moving towards the node, so it's ok to just set the activity without checking here. m_IdealActivity = ( Activity )WorldGraph.m_pNodes[ m_iHintNode ].m_sHintActivity; break; } case TASK_SET_SCHEDULE: { Schedule_t *pNewSchedule; pNewSchedule = GetScheduleOfType( (int)pTask->flData ); if ( pNewSchedule ) { ChangeSchedule( pNewSchedule ); } else { TaskFail(); } break; } case TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY: { if ( m_hEnemy == NULL ) { TaskFail(); return; } if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, 0, pTask->flData ) ) { // try for cover farther than the FLData from the schedule. TaskComplete(); } else { // no coverwhatsoever. TaskFail(); } break; } case TASK_FIND_FAR_NODE_COVER_FROM_ENEMY: { if ( m_hEnemy == NULL ) { TaskFail(); return; } if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, pTask->flData, CoverRadius() ) ) { // try for cover farther than the FLData from the schedule. TaskComplete(); } else { // no coverwhatsoever. TaskFail(); } break; } case TASK_FIND_NODE_COVER_FROM_ENEMY: { if ( m_hEnemy == NULL ) { TaskFail(); return; } if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, 0, CoverRadius() ) ) { // try for cover farther than the FLData from the schedule. TaskComplete(); } else { // no coverwhatsoever. TaskFail(); } break; } case TASK_FIND_COVER_FROM_ENEMY: { entvars_t *pevCover; if ( m_hEnemy == NULL ) { // Find cover from self if no enemy available pevCover = pev; // TaskFail(); // return; } else pevCover = m_hEnemy->pev; if ( FindLateralCover( pevCover->origin, pevCover->view_ofs ) ) { // try lateral first m_flMoveWaitFinished = gpGlobals->time + pTask->flData; TaskComplete(); } else if ( FindCover( pevCover->origin, pevCover->view_ofs, 0, CoverRadius() ) ) { // then try for plain ole cover m_flMoveWaitFinished = gpGlobals->time + pTask->flData; TaskComplete(); } else { // no coverwhatsoever. TaskFail(); } break; } case TASK_FIND_COVER_FROM_ORIGIN: { if ( FindCover( pev->origin, pev->view_ofs, 0, CoverRadius() ) ) { // then try for plain ole cover m_flMoveWaitFinished = gpGlobals->time + pTask->flData; TaskComplete(); } else { // no cover! TaskFail(); } } break; case TASK_FIND_COVER_FROM_BEST_SOUND: { CSound *pBestSound; pBestSound = PBestSound(); ASSERT( pBestSound != NULL ); /* if ( pBestSound && FindLateralCover( pBestSound->m_vecOrigin, g_vecZero ) ) { // try lateral first m_flMoveWaitFinished = gpGlobals->time + pTask->flData; TaskComplete(); } */ if ( pBestSound && FindCover( pBestSound->m_vecOrigin, g_vecZero, pBestSound->m_iVolume, CoverRadius() ) ) { // then try for plain ole cover m_flMoveWaitFinished = gpGlobals->time + pTask->flData; TaskComplete(); } else { // no coverwhatsoever. or no sound in list TaskFail(); } break; } case TASK_FACE_HINTNODE: { pev->ideal_yaw = WorldGraph.m_pNodes[ m_iHintNode ].m_flHintYaw; SetTurnActivity(); break; } case TASK_FACE_LASTPOSITION: MakeIdealYaw ( m_vecLastPosition ); SetTurnActivity(); break; case TASK_FACE_TARGET: if ( m_hTargetEnt != NULL ) { MakeIdealYaw ( m_hTargetEnt->pev->origin ); SetTurnActivity(); } else TaskFail(); break; case TASK_FACE_ENEMY: { MakeIdealYaw ( m_vecEnemyLKP ); SetTurnActivity(); break; } case TASK_FACE_IDEAL: { SetTurnActivity(); break; } case TASK_FACE_ROUTE: { if (FRouteClear()) { ALERT(at_aiconsole, "No route to face!\n"); TaskFail(); } else { MakeIdealYaw(m_Route[m_iRouteIndex].vecLocation); SetTurnActivity(); } break; } case TASK_WAIT_PVS: case TASK_WAIT_INDEFINITE: { // don't do anything. break; } case TASK_WAIT: case TASK_WAIT_FACE_ENEMY: {// set a future time that tells us when the wait is over. m_flWaitFinished = gpGlobals->time + pTask->flData; break; } case TASK_WAIT_RANDOM: {// set a future time that tells us when the wait is over. m_flWaitFinished = gpGlobals->time + RANDOM_FLOAT( 0.1, pTask->flData ); break; } case TASK_MOVE_TO_TARGET_RANGE: { if ( (m_hTargetEnt->pev->origin - pev->origin).Length() < 1 ) TaskComplete(); else { m_vecMoveGoal = m_hTargetEnt->pev->origin; if ( !MoveToTarget( ACT_WALK, 2 ) ) TaskFail(); } break; } case TASK_RUN_TO_SCRIPT: case TASK_WALK_TO_SCRIPT: { Activity newActivity; if ( !m_pGoalEnt || (m_pGoalEnt->pev->origin - pev->origin).Length() < 1 ) TaskComplete(); else { if ( pTask->iTask == TASK_WALK_TO_SCRIPT ) newActivity = ACT_WALK; else newActivity = ACT_RUN; // This monster can't do this! if ( LookupActivity( newActivity ) == ACTIVITY_NOT_AVAILABLE ) TaskComplete(); else { if ( m_pGoalEnt != NULL ) { Vector vecDest; vecDest = m_pGoalEnt->pev->origin; if ( !MoveToLocation( newActivity, 2, vecDest ) ) { TaskFail(); ALERT( at_aiconsole, "%s Failed to reach script!!!\n", STRING(pev->classname) ); RouteClear(); } } else { TaskFail(); ALERT( at_aiconsole, "%s: MoveTarget is missing!?!\n", STRING(pev->classname) ); RouteClear(); } } } TaskComplete(); break; } case TASK_CLEAR_MOVE_WAIT: { m_flMoveWaitFinished = gpGlobals->time; TaskComplete(); break; } case TASK_MELEE_ATTACK1_NOTURN: case TASK_MELEE_ATTACK1: { m_IdealActivity = ACT_MELEE_ATTACK1; break; } case TASK_MELEE_ATTACK2_NOTURN: case TASK_MELEE_ATTACK2: { m_IdealActivity = ACT_MELEE_ATTACK2; break; } case TASK_RANGE_ATTACK1_NOTURN: case TASK_RANGE_ATTACK1: { m_IdealActivity = ACT_RANGE_ATTACK1; break; } case TASK_RANGE_ATTACK2_NOTURN: case TASK_RANGE_ATTACK2: { m_IdealActivity = ACT_RANGE_ATTACK2; break; } case TASK_RELOAD_NOTURN: case TASK_RELOAD: { m_IdealActivity = ACT_RELOAD; break; } case TASK_SPECIAL_ATTACK1: { m_IdealActivity = ACT_SPECIAL_ATTACK1; break; } case TASK_SPECIAL_ATTACK2: { m_IdealActivity = ACT_SPECIAL_ATTACK2; break; } case TASK_SET_ACTIVITY: { m_IdealActivity = (Activity)(int)pTask->flData; TaskComplete(); break; } case TASK_GET_PATH_TO_ENEMY_LKP: { if ( BuildRoute ( m_vecEnemyLKP, bits_MF_TO_LOCATION, NULL ) ) { TaskComplete(); } else if (BuildNearestRoute( m_vecEnemyLKP, pev->view_ofs, 0, (m_vecEnemyLKP - pev->origin).Length() )) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToEnemyLKP failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_ENEMY: { CBaseEntity *pEnemy = m_hEnemy; if ( pEnemy == NULL ) { TaskFail(); return; } if ( BuildRoute ( pEnemy->pev->origin, bits_MF_TO_ENEMY, pEnemy ) ) { TaskComplete(); } else if (BuildNearestRoute( pEnemy->pev->origin, pEnemy->pev->view_ofs, 0, (pEnemy->pev->origin - pev->origin).Length() )) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToEnemy failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_ENEMY_CORPSE: { UTIL_MakeVectors( pev->angles ); if ( BuildRoute ( m_vecEnemyLKP - gpGlobals->v_forward * 64, bits_MF_TO_LOCATION, NULL ) ) { TaskComplete(); } else { ALERT ( at_aiconsole, "GetPathToEnemyCorpse failed!!\n" ); TaskFail(); } } break; case TASK_GET_PATH_TO_SPOT: { CBaseEntity *pPlayer = UTIL_FindEntityByClassname( NULL, "player" ); if ( BuildRoute ( m_vecMoveGoal, bits_MF_TO_LOCATION, pPlayer ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_TARGET: { RouteClear(); if ( m_hTargetEnt != NULL && MoveToTarget( m_movementActivity, 1 ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_SCRIPT: { RouteClear(); if ( m_pCine != NULL && MoveToLocation( m_movementActivity, 1, m_pCine->pev->origin ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_HINTNODE:// for active idles! { if ( MoveToLocation( m_movementActivity, 2, WorldGraph.m_pNodes[ m_iHintNode ].m_vecOrigin ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToHintNode failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_LASTPOSITION: { m_vecMoveGoal = m_vecLastPosition; if ( MoveToLocation( m_movementActivity, 2, m_vecMoveGoal ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToLastPosition failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_BESTSOUND: { CSound *pSound; pSound = PBestSound(); if ( pSound && MoveToLocation( m_movementActivity, 2, pSound->m_vecOrigin ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToBestSound failed!!\n" ); TaskFail(); } break; } case TASK_GET_PATH_TO_BESTSCENT: { CSound *pScent; pScent = PBestScent(); if ( pScent && MoveToLocation( m_movementActivity, 2, pScent->m_vecOrigin ) ) { TaskComplete(); } else { // no way to get there =( ALERT ( at_aiconsole, "GetPathToBestScent failed!!\n" ); TaskFail(); } break; } case TASK_RUN_PATH: { // UNDONE: This is in some default AI and some monsters can't run? -- walk instead? if ( LookupActivity( ACT_RUN ) != ACTIVITY_NOT_AVAILABLE ) { m_movementActivity = ACT_RUN; } else { m_movementActivity = ACT_WALK; } TaskComplete(); break; } case TASK_WALK_PATH: { if ( pev->movetype == MOVETYPE_FLY ) { m_movementActivity = ACT_FLY; } if ( LookupActivity( ACT_WALK ) != ACTIVITY_NOT_AVAILABLE ) { m_movementActivity = ACT_WALK; } else { m_movementActivity = ACT_RUN; } TaskComplete(); break; } case TASK_STRAFE_PATH: { Vector2D vec2DirToPoint; Vector2D vec2RightSide; // to start strafing, we have to first figure out if the target is on the left side or right side UTIL_MakeVectors ( pev->angles ); vec2DirToPoint = ( m_Route[ 0 ].vecLocation - pev->origin ).Make2D().Normalize(); vec2RightSide = gpGlobals->v_right.Make2D().Normalize(); if ( DotProduct ( vec2DirToPoint, vec2RightSide ) > 0 ) { // strafe right m_movementActivity = ACT_STRAFE_RIGHT; } else { // strafe left m_movementActivity = ACT_STRAFE_LEFT; } TaskComplete(); break; } case TASK_WAIT_FOR_MOVEMENT: { if (FRouteClear()) { TaskComplete(); } break; } case TASK_EAT: { Eat( pTask->flData ); TaskComplete(); break; } case TASK_SMALL_FLINCH: { m_IdealActivity = GetSmallFlinchActivity(); break; } case TASK_DIE: { RouteClear(); m_IdealActivity = GetDeathActivity(); pev->deadflag = DEAD_DYING; break; } case TASK_SOUND_WAKE: { AlertSound(); TaskComplete(); break; } case TASK_SOUND_DIE: { DeathSound(); TaskComplete(); break; } case TASK_SOUND_IDLE: { IdleSound(); TaskComplete(); break; } case TASK_SOUND_PAIN: { PainSound(); TaskComplete(); break; } case TASK_SOUND_DEATH: { DeathSound(); TaskComplete(); break; } case TASK_SOUND_ANGRY: { // sounds are complete as soon as we get here, cause we've already played them. ALERT ( at_aiconsole, "SOUND\n" ); TaskComplete(); break; } case TASK_WAIT_FOR_SCRIPT: { if ( m_pCine->m_iDelay <= 0 && gpGlobals->time >= m_pCine->m_startTime ) { TaskComplete(); //LRC - start playing immediately } else if (!m_pCine->IsAction() && m_pCine->m_iszIdle) { m_pCine->StartSequence( (CBaseMonster *)this, m_pCine->m_iszIdle, FALSE ); if (FStrEq( STRING(m_pCine->m_iszIdle), STRING(m_pCine->m_iszPlay))) { pev->framerate = 0; } } else m_IdealActivity = ACT_IDLE; break; } case TASK_PLAY_SCRIPT: { if (m_pCine->IsAction()) { //ALERT(at_console,"PlayScript: setting idealactivity %d\n",m_pCine->m_fAction); switch(m_pCine->m_fAction) { case 0: m_IdealActivity = ACT_RANGE_ATTACK1; break; case 1: m_IdealActivity = ACT_RANGE_ATTACK2; break; case 2: m_IdealActivity = ACT_MELEE_ATTACK1; break; case 3: m_IdealActivity = ACT_MELEE_ATTACK2; break; case 4: m_IdealActivity = ACT_SPECIAL_ATTACK1; break; case 5: m_IdealActivity = ACT_SPECIAL_ATTACK2; break; case 6: m_IdealActivity = ACT_RELOAD; break; case 7: m_IdealActivity = ACT_HOP; break; } pev->framerate = 1.0; // shouldn't be needed, but just in case pev->movetype = MOVETYPE_FLY; ClearBits(pev->flags, FL_ONGROUND); } else { m_pCine->StartSequence( (CBaseMonster *)this, m_pCine->m_iszPlay, TRUE ); if ( m_fSequenceFinished ) ClearSchedule(); pev->framerate = 1.0; //ALERT( at_aiconsole, "Script %s has begun for %s\n", STRING( m_pCine->m_iszPlay ), STRING(pev->classname) ); } m_scriptState = SCRIPT_PLAYING; break; } case TASK_ENABLE_SCRIPT: { m_pCine->DelayStart( 0 ); TaskComplete(); break; } //LRC case TASK_END_SCRIPT: { m_pCine->SequenceDone( this ); TaskComplete(); break; } case TASK_PLANT_ON_SCRIPT: { if ( m_pCine != NULL ) { // Plant on script // LRC - if it's a teleport script, do the turn too if (m_pCine->m_fMoveTo == 4 || m_pCine->m_fMoveTo == 6) { if (m_pCine->m_fTurnType == 0) //LRC pev->angles.y = m_hTargetEnt->pev->angles.y; else if (m_pCine->m_fTurnType == 1) pev->angles.y = UTIL_VecToYaw(m_hTargetEnt->pev->origin - pev->origin); pev->ideal_yaw = pev->angles.y; pev->avelocity = Vector( 0, 0, 0 ); pev->velocity = Vector( 0, 0, 0 ); pev->effects |= EF_NOINTERP; } if (m_pCine->m_fMoveTo != 6) pev->origin = m_pGoalEnt->pev->origin; } TaskComplete(); break; } case TASK_FACE_SCRIPT: { if ( m_pCine != NULL && m_pCine->m_fMoveTo != 0) // movetype "no move" makes us ignore turntype { switch (m_pCine->m_fTurnType) { case 0: pev->ideal_yaw = UTIL_AngleMod( m_pCine->pev->angles.y ); break; case 1: // yes, this is inconsistent- turn to face uses the "target" and turn to angle uses the "cine". if (m_hTargetEnt) MakeIdealYaw ( m_hTargetEnt->pev->origin ); else MakeIdealYaw ( m_pCine->pev->origin ); break; // default: don't turn } } TaskComplete(); m_IdealActivity = ACT_IDLE; RouteClear(); break; } case TASK_SUGGEST_STATE: { m_IdealMonsterState = (MONSTERSTATE)(int)pTask->flData; TaskComplete(); break; } case TASK_SET_FAIL_SCHEDULE: m_failSchedule = (int)pTask->flData; TaskComplete(); break; case TASK_CLEAR_FAIL_SCHEDULE: m_failSchedule = SCHED_NONE; TaskComplete(); break; default: { ALERT ( at_aiconsole, "No StartTask entry for %d\n", (SHARED_TASKS)pTask->iTask ); break; } } }
int DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); if(pEntity && pSaveData) { entvars_t tmpVars; Vector oldOffset; CRestore restoreHelper(pSaveData); if(globalEntity) { CRestore tmpRestore(pSaveData); tmpRestore.PrecacheMode(0); tmpRestore.ReadEntVars("ENTVARS", &tmpVars); // HACKHACK - reset the save pointers, we're going to restore for real this time pSaveData->size = pSaveData->pTable[pSaveData->currentIndex].location; pSaveData->pCurrentData = pSaveData->pBaseData + pSaveData->size; // ------------------- const globalentity_t *pGlobal = gGlobalState.EntityFromTable(tmpVars.globalname); // Don't overlay any instance of the global that isn't the latest // pSaveData->szCurrentMapName is the level this entity is coming from // pGlobla->levelName is the last level the global entity was active in. // If they aren't the same, then this global update is out of date. if(!FStrEq(pSaveData->szCurrentMapName, pGlobal->levelName)) return 0; // Compute the new global offset oldOffset = pSaveData->vecLandmarkOffset; CBaseEntity *pNewEntity = FindGlobalEntity(tmpVars.classname, tmpVars.globalname); if(pNewEntity) { // ALERT( at_console, "Overlay %s with %s\n", STRING(pNewEntity->pev->classname), STRING(tmpVars.classname) ); // Tell the restore code we're overlaying a global entity from another level restoreHelper.SetGlobalMode(1); // Don't overwrite global fields pSaveData->vecLandmarkOffset = (pSaveData->vecLandmarkOffset - pNewEntity->pev->mins) + tmpVars.mins; pEntity = pNewEntity; // we're going to restore this data OVER the old entity pent = ENT(pEntity->pev); // Update the global table to say that the global definition of this entity should come from this level gGlobalState.EntityUpdate(pEntity->pev->globalname, gpGlobals->mapname); } else { // This entity will be freed automatically by the engine. If we don't do a restore on a matching entity (below) // or call EntityUpdate() to move it to this level, we haven't changed global state at all. return 0; } } if(pEntity->ObjectCaps() & FCAP_MUST_SPAWN) { pEntity->Restore(restoreHelper); pEntity->Spawn(); } else { pEntity->Restore(restoreHelper); pEntity->Precache(); } // Again, could be deleted, get the pointer again. pEntity = (CBaseEntity *)GET_PRIVATE(pent); #if 0 if ( pEntity && pEntity->pev->globalname && globalEntity ) { ALERT( at_console, "Global %s is %s\n", STRING(pEntity->pev->globalname), STRING(pEntity->pev->model) ); } #endif // Is this an overriding global entity (coming over the transition), or one restoring in a level if(globalEntity) { // ALERT( at_console, "After: %f %f %f %s\n", pEntity->pev->origin.x, pEntity->pev->origin.y, pEntity->pev->origin.z, STRING(pEntity->pev->model) ); pSaveData->vecLandmarkOffset = oldOffset; if(pEntity) { UTIL_SetOrigin(pEntity->pev, pEntity->pev->origin); pEntity->OverrideReset(); } } else if(pEntity && pEntity->pev->globalname) { const globalentity_t *pGlobal = gGlobalState.EntityFromTable(pEntity->pev->globalname); if(pGlobal) { // Already dead? delete if(pGlobal->state == GLOBAL_DEAD) return -1; else if(!FStrEq(STRING(gpGlobals->mapname), pGlobal->levelName)) { pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive } // In this level & not dead, continue on as normal } else { ALERT(at_error, "Global Entity %s (%s) not in table!!!\n", STRING(pEntity->pev->globalname), STRING(pEntity->pev->classname)); // Spawned entities default to 'On' gGlobalState.EntityAdd(pEntity->pev->globalname, gpGlobals->mapname, GLOBAL_ON); } } } return 0; }
void CBigMomma::StartTask( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_FIND_NODE: { CBaseEntity *pTarget = m_hTargetEnt; if ( !HasMemory( bits_MEMORY_ADVANCE_NODE ) ) { if ( pTarget ) pev->netname = m_hTargetEnt->pev->target; } NodeStart( pev->netname ); TaskComplete(); ALERT( at_aiconsole, "BM: Found node %s\n", STRING(pev->netname) ); } break; case TASK_NODE_DELAY: m_nodeTime = gpGlobals->time + pTask->flData; TaskComplete(); ALERT( at_aiconsole, "BM: FAIL! Delay %.2f\n", pTask->flData ); break; case TASK_PROCESS_NODE: ALERT( at_aiconsole, "BM: Reached node %s\n", STRING(pev->netname) ); NodeReach(); TaskComplete(); break; case TASK_PLAY_NODE_PRESEQUENCE: case TASK_PLAY_NODE_SEQUENCE: { int sequence; if ( pTask->iTask == TASK_PLAY_NODE_SEQUENCE ) sequence = GetNodeSequence(); else sequence = GetNodePresequence(); ALERT( at_aiconsole, "BM: Playing node sequence %s\n", STRING(sequence) ); if ( sequence ) { sequence = LookupSequence( STRING( sequence ) ); if ( sequence != -1 ) { pev->sequence = sequence; pev->frame = 0; ResetSequenceInfo( ); ALERT( at_aiconsole, "BM: Sequence %s\n", STRING(GetNodeSequence()) ); return; } } TaskComplete(); } break; case TASK_NODE_YAW: pev->ideal_yaw = GetNodeYaw(); TaskComplete(); break; case TASK_WAIT_NODE: m_flWait = gpGlobals->time + GetNodeDelay(); if ( m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT ) ALERT( at_aiconsole, "BM: Wait at node %s forever\n", STRING(pev->netname) ); else ALERT( at_aiconsole, "BM: Wait at node %s for %.2f\n", STRING(pev->netname), GetNodeDelay() ); break; case TASK_MOVE_TO_NODE_RANGE: { CBaseEntity *pTarget = m_hTargetEnt; if ( !pTarget ) TaskFail(); else { if ( (pTarget->pev->origin - pev->origin).Length() < GetNodeRange() ) TaskComplete(); else { Activity act = ACT_WALK; if ( pTarget->pev->spawnflags & SF_INFOBM_RUN ) act = ACT_RUN; m_vecMoveGoal = pTarget->pev->origin; if ( !MoveToTarget( act, 2 ) ) { TaskFail(); } } } } ALERT( at_aiconsole, "BM: Moving to node %s\n", STRING(pev->netname) ); break; case TASK_MELEE_ATTACK1: // Play an attack sound here EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAttackSounds), 1.0, ATTN_NORM, 0, PITCH_NORM ); CBaseMonster::StartTask( pTask ); break; default: CBaseMonster::StartTask( pTask ); break; } }
int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir ) { studiohdr_t *pstudiohdr; pstudiohdr = (studiohdr_t *)pmodel; if (! pstudiohdr) return iGoalAnim; mstudioseqdesc_t *pseqdesc; pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex); // bail if we're going to or from a node 0 if (pseqdesc[iEndingAnim].entrynode == 0 || pseqdesc[iGoalAnim].entrynode == 0) { return iGoalAnim; } int iEndNode; // ALERT( at_console, "from %d to %d: ", pEndNode->iEndNode, pGoalNode->iStartNode ); if (*piDir > 0) { iEndNode = pseqdesc[iEndingAnim].exitnode; } else { iEndNode = pseqdesc[iEndingAnim].entrynode; } if (iEndNode == pseqdesc[iGoalAnim].entrynode) { *piDir = 1; return iGoalAnim; } byte *pTransition = ((byte *)pstudiohdr + pstudiohdr->transitionindex); int iInternNode = pTransition[(iEndNode-1)*pstudiohdr->numtransitions + (pseqdesc[iGoalAnim].entrynode-1)]; if (iInternNode == 0) return iGoalAnim; int i; // look for someone going for (i = 0; i < pstudiohdr->numseq; i++) { if (pseqdesc[i].entrynode == iEndNode && pseqdesc[i].exitnode == iInternNode) { *piDir = 1; return i; } if (pseqdesc[i].nodeflags) { if (pseqdesc[i].exitnode == iEndNode && pseqdesc[i].entrynode == iInternNode) { *piDir = -1; return i; } } } ALERT( at_console, "error in transition graph" ); return iGoalAnim; }
//========================================================= // MakeMonster- this is the code that drops the monster //========================================================= void CMonsterMaker::MakeMonster( void ) { edict_t *pent; entvars_t *pevCreate; if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren ) {// not allowed to make a new one yet. Too many live ones out right now. return; } if ( !m_flGround ) { // set altitude. Now that I'm activated, any breakables, etc should be out from under me. TraceResult tr; UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0, 0, 2048 ), ignore_monsters, ENT(pev), &tr ); m_flGround = tr.vecEndPos.z; } Vector mins = pev->origin - Vector( 34, 34, 0 ); Vector maxs = pev->origin + Vector( 34, 34, 0 ); maxs.z = pev->origin.z; mins.z = m_flGround; CBaseEntity *pList[2]; int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER ); if ( count ) { // don't build a stack of monsters! return; } pent = CREATE_NAMED_ENTITY( m_iszMonsterClassname ); if ( FNullEnt( pent ) ) { ALERT ( at_console, "NULL Ent in MonsterMaker!\n" ); return; } // If I have a target, fire! if ( !FStringNull ( pev->target ) ) { // delay already overloaded for this entity, so can't call SUB_UseTargets() FireTargets( STRING(pev->target), this, this, USE_TOGGLE, 0 ); } pevCreate = VARS( pent ); pevCreate->origin = pev->origin; pevCreate->angles = pev->angles; SetBits( pevCreate->spawnflags, SF_MONSTER_FALL_TO_GROUND ); // Children hit monsterclip brushes if ( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP ) SetBits( pevCreate->spawnflags, SF_MONSTER_HITMONSTERCLIP ); DispatchSpawn( ENT( pevCreate ) ); pevCreate->owner = edict(); if ( !FStringNull( pev->netname ) ) { // if I have a netname (overloaded), give the child monster that name as a targetname pevCreate->targetname = pev->netname; } m_cLiveChildren++;// count this monster m_cNumMonsters--; if ( m_cNumMonsters == 0 ) { // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } }