//========================================================= // Verifica las condiciones y devuelve si es // conveniente/posible crear un NPC en las coordenadas. //========================================================= bool CSurvivalZombieSpawn::CanMakeNPC(CAI_BaseNPC *pNPC, Vector *pResult) { // Desactivado if ( Disabled || !sv_spawn_zombies.GetBool() ) { UTIL_RemoveImmediate(pNPC); return false; } Vector origin; // Verificamos si es posible crear el NPC en el radio especificado. if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, true) ) { if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, false) ) { DevWarning("[SURVIVAL ZOMBIE MAKER] No se encontro un lugar valido para crear un zombie. \r\n"); UTIL_RemoveImmediate(pNPC); return false; } } // Crear en la misma altura que el spawn (Y así evitamos que se cree por debajo del suelo) origin.z = GetAbsOrigin().z; *pResult = origin; return true; }
//========================================================= // Guardar los objetos necesarios en caché. //========================================================= void CDirectorSpawn::Precache() { BaseClass::Precache(); // NPC's int pNpcs = ARRAYSIZE(iNpcs) - 1; for ( int i = 0; i < pNpcs; ++i ) { if ( iNpcs[i] == NULL_STRING ) continue; // Buscamos si hay una plantilla con este nombre. string_t NpcData = Templates_FindByTargetName(STRING(iNpcs[i])); // No, se trata de una clase. if ( NpcData == NULL_STRING ) UTIL_PrecacheOther(STRING(iNpcs[i])); else { // Guardamos en caché la plantilla. CBaseEntity *pEntity = NULL; MapEntity_ParseEntity(pEntity, STRING(NpcData), NULL); if ( pEntity != NULL ) { pEntity->Precache(); UTIL_RemoveImmediate(pEntity); } } } // JEFES int pBoss = ARRAYSIZE(iBoss) - 1; for ( int i = 0; i < pBoss; ++i ) { if ( iBoss[i] == NULL_STRING ) continue; // Buscamos si hay una plantilla con este nombre. string_t NpcData = Templates_FindByTargetName(STRING(iBoss[i])); // No, se trata de una clase. if ( NpcData == NULL_STRING ) UTIL_PrecacheOther(STRING(iBoss[i])); else { // Guardamos en caché la plantilla. CBaseEntity *pEntity = NULL; MapEntity_ParseEntity(pEntity, STRING(NpcData), NULL); if ( pEntity != NULL ) { pEntity->Precache(); UTIL_RemoveImmediate(pEntity); } } } }
//========================================================= // Verificaciones después de crear al NPC. //========================================================= bool CDirector_Manager::PostSpawn(CAI_BaseNPC *pNPC) { bool bStuck = true; while ( bStuck ) { trace_t tr; UTIL_TraceHull(pNPC->GetAbsOrigin(), pNPC->GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), MASK_NPCSOLID, pNPC, COLLISION_GROUP_NONE, &tr); if ( tr.fraction != 1.0 && tr.m_pEnt ) { // Nos hemos atorado en un objeto con fisicas. if ( FClassnameIs(tr.m_pEnt, "prop_physics") ) { // Lo ajustamos como "No solido" para que el bucle lo ignore. tr.m_pEnt->AddSolidFlags(FSOLID_NOT_SOLID); // Removemos el objeto. UTIL_RemoveImmediate(tr.m_pEnt); continue; } // Nos hemos atorado con una pared o algo del mundo. if ( tr.m_pEnt->IsWorld() ) { // No... no podemos eliminar una pared... // Removemos el NPC para evitar eventos sobrenaturales. UTIL_RemoveImmediate(pNPC); return false; } // No es un objeto con físicas ni del mundo. // Intentamos encontrar una nueva ubicación para el hijo. //DevMsg("[MANAGER] <%s> STUCK!!!! \r\n", tr.m_pEnt->GetClassname()); CAI_Node *pNode = GetRandomNode(); // Nada if ( !pNode ) UTIL_RemoveImmediate(pNPC); pNPC->SetAbsOrigin(pNode->GetPosition(HULL_HUMAN)); } bStuck = false; } return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : *szClassname - // *modelName - //----------------------------------------------------------------------------- void UTIL_PrecacheOther( const char *szClassname, const char *modelName ) { #if defined( PRECACHE_OTHER_ONCE ) // already done this one?, if not, mark as done if ( !g_PrecacheOtherList.AddOrMarkPrecached( szClassname ) ) return; #endif CBaseEntity *pEntity = CreateEntityByName( szClassname ); if ( !pEntity ) { Warning( "NULL Ent in UTIL_PrecacheOther for %s\n", szClassname ); return; } // If we have a specified model, set it before calling precache if ( modelName && modelName[0] ) { VFuncs::SetModelName(pEntity, AllocPooledString( modelName ) ); } if (pEntity) VFuncs::Precache( pEntity ); UTIL_RemoveImmediate( pEntity ); }
void CHL2MP_Player::CreateRagdollEntity( void ) { if ( m_hRagdoll ) { UTIL_RemoveImmediate( m_hRagdoll ); m_hRagdoll = NULL; } // If we already have a ragdoll, don't make another one. CHL2MPRagdoll *pRagdoll = dynamic_cast< CHL2MPRagdoll* >( m_hRagdoll.Get() ); if ( !pRagdoll ) { // create a new one pRagdoll = dynamic_cast< CHL2MPRagdoll* >( CreateEntityByName( "hl2mp_ragdoll" ) ); } if ( pRagdoll ) { pRagdoll->m_hPlayer = this; pRagdoll->m_vecRagdollOrigin = GetAbsOrigin(); pRagdoll->m_vecRagdollVelocity = GetAbsVelocity(); pRagdoll->m_nModelIndex = m_nModelIndex; pRagdoll->m_nForceBone = m_nForceBone; pRagdoll->m_vecForce = m_vecTotalBulletForce; pRagdoll->SetAbsOrigin( GetAbsOrigin() ); } // ragdolls will be removed on round restart automatically m_hRagdoll = pRagdoll; }
void Test_SpawnRandomEntities( const CCommand &args ) { if ( args.ArgC() < 3 ) { Error( "Test_SpawnRandomEntities <min # entities> <max # entities> missing arguments." ); } if ( g_StressEntities.Count() == 0 ) { Error( "Test_SpawnRandomEntities: not initialized (call Test_InitRandomEntitySpawner frst)." ); } int nMin = atoi( args[ 1 ] ); int nMax = atoi( args[ 2 ] ); int count = RandomInt( nMin, nMax ); for ( int i=0; i < count; i++ ) { int iSlot = RandomInt( 0, g_StressEntities.Count() - 1 ); // Remove any old entity in this slot. if ( g_StressEntities[iSlot].Get() ) UTIL_RemoveImmediate( g_StressEntities[iSlot] ); // Create a new one in this slot. int iType = RandomInt( 0, g_StressEntityRegs.Count() - 1 ); g_StressEntities[iSlot] = g_StressEntityRegs[iType]->GetFn()(); } }
void CWorldItem::Spawn( void ) { CBaseEntity *pEntity = NULL; switch (m_iType) { case 44: // ITEM_BATTERY: pEntity = CBaseEntity::Create( "item_battery", GetLocalOrigin(), GetLocalAngles() ); break; case 45: // ITEM_SUIT: pEntity = CBaseEntity::Create( "item_suit", GetLocalOrigin(), GetLocalAngles() ); break; } if (!pEntity) { Warning("unable to create world_item %d\n", m_iType ); } else { pEntity->m_target = m_target; pEntity->SetName( GetEntityName() ); pEntity->ClearSpawnFlags(); pEntity->AddSpawnFlags( m_spawnflags ); } UTIL_RemoveImmediate( this ); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pChild - //----------------------------------------------------------------------------- void CBaseNPCMaker::ChildPostSpawn( CAI_BaseNPC *pChild ) { // If I'm stuck inside any props, remove them bool bFound = true; while ( bFound ) { trace_t tr; UTIL_TraceHull( pChild->GetAbsOrigin(), pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), MASK_NPCSOLID, pChild, COLLISION_GROUP_NONE, &tr ); //NDebugOverlay::Box( pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), 0, 255, 0, 32, 5.0 ); if ( tr.fraction != 1.0 && tr.m_pEnt ) { if ( FClassnameIs( tr.m_pEnt, "prop_physics" ) ) { // Set to non-solid so this loop doesn't keep finding it tr.m_pEnt->AddSolidFlags( FSOLID_NOT_SOLID ); UTIL_RemoveImmediate( tr.m_pEnt ); continue; } } bFound = false; } if ( m_hIgnoreEntity != NULL ) { pChild->SetOwnerEntity( m_hIgnoreEntity ); } }
void CASW_Base_Spawner::RemoveObstructingProps( CBaseEntity *pChild ) { // If I'm stuck inside any props, remove them bool bFound = true; while ( bFound ) { trace_t tr; UTIL_TraceHull( pChild->GetAbsOrigin(), pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), MASK_NPCSOLID, pChild, COLLISION_GROUP_NONE, &tr ); if (asw_debug_spawners.GetBool()) { NDebugOverlay::Box( pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), 0, 255, 0, 32, 5.0 ); } if ( tr.fraction != 1.0 && tr.m_pEnt ) { if ( dynamic_cast<CBaseProp*>(tr.m_pEnt) ) { // Set to non-solid so this loop doesn't keep finding it tr.m_pEnt->AddSolidFlags( FSOLID_NOT_SOLID ); UTIL_RemoveImmediate( tr.m_pEnt ); continue; } } bFound = false; } }
//----------------------------------------------------------------------------- // Purpose: Get the test hull (create if none) // Input : // Output : //----------------------------------------------------------------------------- void CAI_TestHull::ReturnTestHull(void) { CAI_TestHull::pTestHull->bInUse = false; CAI_TestHull::pTestHull->AddSolidFlags( FSOLID_NOT_SOLID ); UTIL_SetSize(CAI_TestHull::pTestHull, vec3_origin, vec3_origin); UTIL_RemoveImmediate( pTestHull ); pTestHull = NULL; }
void CASW_Marine_Hint_Ent::Spawn() { Assert( MarineHintManager() ); MarineHintManager()->AddHint( this ); BaseClass::Spawn(); UTIL_RemoveImmediate( this ); }
//----------------------------------------------------------------------------- // Purpose: Place NPC somewhere on the perimeter of my radius. //----------------------------------------------------------------------------- void CTemplateNPCMaker::MakeNPCInRadius( void ) { if ( !CanMakeNPC(true)) return; CAI_BaseNPC *pent = NULL; CBaseEntity *pEntity = NULL; MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); if ( pEntity != NULL ) { pent = (CAI_BaseNPC *)pEntity; } if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } if ( !PlaceNPCInRadius( pent ) ) { // Failed to place the NPC. Abort UTIL_RemoveImmediate( pent ); return; } m_OnSpawnNPC.Set( pEntity, pEntity, this ); pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); ChildPostSpawn( pent ); m_nLiveChildren++;// count this NPC if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) { m_nMaxNumNPCs--; if ( IsDepleted() ) { m_OnAllSpawned.FireOutput( this, this ); // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } } }
void CHL2MP_Player::UpdateOnRemove( void ) { if ( m_hRagdoll ) { UTIL_RemoveImmediate( m_hRagdoll ); m_hRagdoll = NULL; } BaseClass::UpdateOnRemove(); }
void FreeContainingEntity( edict_t *ed ) { if ( ed ) { CBaseEntity *ent = GetContainingEntity( ed ); if ( ent ) { ed->SetEdict( NULL, false ); CBaseEntity::PhysicsRemoveTouchedList( ent ); CBaseEntity::PhysicsRemoveGroundList( ent ); UTIL_RemoveImmediate( ent ); } } }
//========================================================= // Verificaciones después de crear al NPC. //========================================================= bool CDirectorSpawn::PostSpawn(CAI_BaseNPC *pNPC) { bool bStuck = true; while ( bStuck ) { trace_t tr; UTIL_TraceHull(pNPC->GetAbsOrigin(), pNPC->GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), MASK_NPCSOLID, pNPC, COLLISION_GROUP_NONE, &tr); if (tr.fraction != 1.0 && tr.m_pEnt) { // Nos hemos atorado en un objeto con fisicas. if ( FClassnameIs(tr.m_pEnt, "prop_physics") ) { // Lo ajustamos como "No solido" para que el bucle lo ignore. tr.m_pEnt->AddSolidFlags(FSOLID_NOT_SOLID); // Removemos el objeto. UTIL_RemoveImmediate(tr.m_pEnt); continue; } // Nos hemos atorado con una pared o algo del mundo. if ( tr.m_pEnt->IsWorld() ) { // No... no podemos eliminar una pared... // Removemos el NPC para evitar eventos sobrenaturales. UTIL_RemoveImmediate(pNPC); return false; } } bStuck = false; } return true; }
void QUA_helicopter::CreateCorpse( ) { m_lifeState = LIFE_DEAD; for ( int i = 0; i < HELICOPTER_MAX_GIBS; ++i ) { CPhysicsProp *pGib = assert_cast<CPhysicsProp*>(CreateEntityByName( "prop_physics_multiplayer" )); pGib->SetAbsOrigin( GetAbsOrigin() ); pGib->SetAbsAngles( GetAbsAngles() ); pGib->SetAbsVelocity( GetAbsVelocity() ); pGib->SetModel( s_pGibModelName[i] ); pGib->Spawn(); pGib->SetMoveType( MOVETYPE_VPHYSICS ); float flMass = pGib->GetMass(); /*if ( flMass < 200 ) {*/ Vector vecVelocity; pGib->GetMassCenter( &vecVelocity ); vecVelocity -= WorldSpaceCenter(); vecVelocity.z = fabs(vecVelocity.z); VectorNormalize( vecVelocity ); // Apply a force that would make a 100kg mass travel 150 - 300 m/s float flRandomVel = random->RandomFloat( 150, 300 ); vecVelocity *= (100 * flRandomVel) / flMass; vecVelocity.z += 100.0f; AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); IPhysicsObject *pObj = pGib->VPhysicsGetObject(); if ( pObj != NULL ) { pObj->AddVelocity( &vecVelocity, &angImpulse ); } pGib->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); /*}*/ pGib->Ignite( 60, false ); pGib->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); } AddSolidFlags( FSOLID_NOT_SOLID ); AddEffects( EF_NODRAW ); UTIL_RemoveImmediate( this ); }
void CTemplateNPCMaker::Precache() { BaseClass::Precache(); if ( !m_iszTemplateData ) { // // This must be the first time we're activated, not a load from save game. // Look up the template in the template database. // if (!m_iszTemplateName) { Warning( "npc_template_maker %s has no template NPC!\n", STRING(GetEntityName()) ); UTIL_Remove( this ); return; } else { m_iszTemplateData = Templates_FindByTargetName(STRING(m_iszTemplateName)); if ( m_iszTemplateData == NULL_STRING ) { DevWarning( "npc_template_maker %s: template NPC %s not found!\n", STRING(GetEntityName()), STRING(m_iszTemplateName) ); UTIL_Remove( this ); return; } } } Assert( m_iszTemplateData != NULL_STRING ); // If the mapper marked this as "preload", then instance the entity preache stuff and delete the entity //if ( !HasSpawnFlags(SF_NPCMAKER_NOPRELOADMODELS) ) if ( m_iszTemplateData != NULL_STRING ) { CBaseEntity *pEntity = NULL; MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); if ( pEntity != NULL ) { PrecacheTemplateEntity( pEntity ); UTIL_RemoveImmediate( pEntity ); } } }
//----------------------------------------------------------------------------- // Purpose: Spawn a player //----------------------------------------------------------------------------- bp::object PyRespawnPlayer( CBasePlayer *pPlayer, const char *classname ) { if( !pPlayer || !pPlayer->edict() ) { PyErr_SetString(PyExc_ValueError, "Invalid player"); throw boost::python::error_already_set(); return bp::object(); } if( !classname ) { PyErr_SetString(PyExc_ValueError, "Invalid player class"); throw boost::python::error_already_set(); return bp::object(); } // Save edict + player name edict_t *pEdict = pPlayer->edict(); const char *playername = pPlayer->GetPlayerName(); // Destroy the old player entity UTIL_RemoveImmediate( pPlayer ); // Create a new player using the provided player class CBasePlayer *pPlayerNew = dynamic_cast<CBasePlayer *>(CBasePlayer::CreatePlayer( classname, pEdict )); if( !pPlayerNew ) { PyErr_SetString(PyExc_ValueError, "Invalid player entity class"); throw boost::python::error_already_set(); return bp::object(); } pPlayerNew->SetPlayerName( playername ); pPlayerNew->InitialSpawn(); pPlayerNew->Spawn(); return pPlayerNew->GetPyHandle(); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pEntData - //----------------------------------------------------------------------------- void MapEntity_PrecacheEntity( const char *pEntData, int &nStringSize ) { CEntityMapData entData( (char*)pEntData, nStringSize ); char className[MAPKEY_MAXLENGTH]; if (!entData.ExtractValue("classname", className)) { Error( "classname missing from entity!\n" ); } // Construct via the LINK_ENTITY_TO_CLASS factory. CBaseEntity *pEntity = CreateEntityByName(className); // // Set up keyvalues, which can set the model name, which is why we don't just do UTIL_PrecacheOther here... // if ( pEntity != NULL ) { pEntity->ParseMapData(&entData); pEntity->Precache(); UTIL_RemoveImmediate( pEntity ); } }
void CBaseNetworkedPlayer::RemoveRagdollEntity() { if ( m_hRagdoll.Get() ) UTIL_RemoveImmediate( m_hRagdoll.Get() ); }
//========================================================= // Verifica las condiciones y devuelve si es // conveniente/posible crear un NPC en las coordenadas. //========================================================= bool CDirectorSpawn::CanMakeNPC(CAI_BaseNPC *pNPC, Vector *pResult) { // Desactivado // Esta entidad no funciona en Multiplayer. if ( Disabled ) { UTIL_RemoveImmediate(pNPC); return false; } Vector origin; ConVarRef director_force_spawn_outview("director_force_spawn_outview"); // Verificamos si es posible crear el NPC en el radio especificado. if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, director_force_spawn_outview.GetBool()) ) { if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, false) ) { DevWarning("[DIRECTOR SPAWN] No se encontro un lugar valido para crear un NPC. \r\n"); UTIL_RemoveImmediate(pNPC); return false; } } // Crear en la misma altura que el spawn (Y así evitamos que se cree por debajo del suelo) origin.z = GetAbsOrigin().z; // Si esta activado la opción de forzar la creación fuera de la visibilidad del usuario. // Hay que asegurarnos de que el usuario no esta viendo el lugar de creación... if ( director_force_spawn_outview.GetBool() ) { CDirector *pDirector = GetDirector(); if ( !pDirector ) return false; // En Climax con que no lo vea directamente es suficiente... //if ( pDirector->GetStatus() == CLIMAX ) //{ if ( UTIL_IsPlayersVisible(origin) ) { DevWarning("[DIRECTOR SPAWN] El lugar de creacion estaba en el campo de vision. \r\n"); UTIL_RemoveImmediate(pNPC); return false; } //} // En cualquier otro modo no debe ser visible ni estar en el cono de visibilidad del jugador. /*else { if ( UTIL_IsPlayersVisibleCone(origin) ) { Warning("[DIRECTOR SPAWN] El lugar de creacion estaba en el campo de vision. \r\n"); UTIL_RemoveImmediate(pNPC); return false; } }*/ } *pResult = origin; return true; }
void CServerTools::RemoveEntityImmediate( CBaseEntity *pEntity ) { UTIL_RemoveImmediate( pEntity ); }
//========================================================= //========================================================= void CNodeEnt::Spawn( void ) { // --------------------------------------------------------------------------------- // If just a hint node (not used for navigation) just create a hint and bail // --------------------------------------------------------------------------------- if (FClassnameIs( this, "info_hint" )) { if (m_eHintType) { CAI_Hint::CreateHint(GetEntityName(),GetAbsOrigin(),(Hint_e)m_eHintType,NO_NODE,m_strGroup); } else { Msg("WARNING: Hint node with no hint type!\n"); } UTIL_RemoveImmediate( this ); return; } // --------------------------------------------------------------------------------- // First check if this node has a hint. If so create a hint entity // --------------------------------------------------------------------------------- CAI_Hint *pHint = NULL; if (m_eHintType || m_strGroup != NULL_STRING) { pHint = CAI_Hint::CreateHint(GetEntityName(),GetAbsOrigin(),(Hint_e)m_eHintType,m_nNodeCount,m_strGroup); } // --------------------------------------------------------------------------------- // If we loaded from disk, we can discard all these node ents as soon as they spawn // unless we are in WC edited mode // --------------------------------------------------------------------------------- if ( g_pAINetworkManager->NetworksLoaded() && !engine->IsInEditMode()) { // If hint exists for this node, set it if (pHint) { CAI_Node *pNode = g_pBigAINet->GetNode(m_nNodeCount); if (pNode) pNode->SetHint( pHint ); else { Msg("AI node graph corrupt\n"); } } m_nNodeCount++; UTIL_RemoveImmediate( this ); return; } else { m_nNodeCount++; } // --------------------------------------------------------------------------------- // Add a new node to the network // --------------------------------------------------------------------------------- // For now just using one big AI network CAI_Node *new_node = g_pBigAINet->AddNode( GetAbsOrigin(), GetAbsAngles().y ); new_node->SetHint( pHint ); // ------------------------------------------------------------------------- // Update table of how each WC id relates to each engine ID // ------------------------------------------------------------------------- if (g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) { g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[new_node->GetId()] = m_nWCNodeID; } // Keep track of largest index used by WC if (g_pAINetworkManager->GetEditOps()->m_nNextWCIndex <= m_nWCNodeID) { g_pAINetworkManager->GetEditOps()->m_nNextWCIndex = m_nWCNodeID+1; } // ------------------------------------------------------------------------- // If in WC edit mode: // Remember the original positions of the nodes before // they drop so we can send the undropped positions to wc. // ------------------------------------------------------------------------- if (engine->IsInEditMode()) { if (g_pAINetworkManager->GetEditOps()->m_pWCPosition) { g_pAINetworkManager->GetEditOps()->m_pWCPosition[new_node->GetId()] = new_node->GetOrigin(); } } if (FClassnameIs( this, "info_node_air" ) || FClassnameIs( this, "info_node_air_hint" )) { new_node->SetType( NODE_AIR ); } else if (FClassnameIs( this, "info_node_climb" )) { new_node->SetType( NODE_CLIMB ); } else { new_node->SetType( NODE_GROUND ); } // If changed as part of WC editing process note that network must be rebuilt if (m_debugOverlays & OVERLAY_WC_CHANGE_ENTITY) { g_pAINetworkManager->GetEditOps()->SetRebuildFlags(); new_node->m_eNodeInfo |= bits_NODE_WC_CHANGED; // Initialize the new nodes position. The graph may not be rebuild // right away but the node should at least be positioned correctly g_AINetworkBuilder.InitNodePosition( g_pBigAINet, new_node ); } UTIL_RemoveImmediate( this ); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pMapData - //----------------------------------------------------------------------------- int CNodeEnt::Spawn( const char *pMapData ) { m_NodeData.strEntityName = GetEntityName(); m_NodeData.vecPosition = GetAbsOrigin(); m_NodeData.nNodeID = NO_NODE; if ( m_NodeData.minState == NPC_STATE_NONE ) m_NodeData.minState = NPC_STATE_IDLE; if ( m_NodeData.maxState == NPC_STATE_NONE ) m_NodeData.maxState = NPC_STATE_COMBAT; // --------------------------------------------------------------------------------- // If just a hint node (not used for navigation) just create a hint and bail // --------------------------------------------------------------------------------- if (FClassnameIs( this, "info_hint" )) { if (m_NodeData.nHintType) { CAI_HintManager::CreateHint( &m_NodeData, pMapData ); } else { Warning("info_hint (HammerID: %d, position (%.2f, %.2f, %.2f)) with no hint type.\n", m_NodeData.nWCNodeID, m_NodeData.vecPosition.x, m_NodeData.vecPosition.y, m_NodeData.vecPosition.z ); } UTIL_RemoveImmediate( this ); return -1; } // --------------------------------------------------------------------------------- // First check if this node has a hint. If so create a hint entity // --------------------------------------------------------------------------------- CAI_Hint *pHint = NULL; if ( ClassMatches( "info_node_hint" ) || ClassMatches( "info_node_air_hint" ) ) { if ( m_NodeData.nHintType || m_NodeData.strGroup != NULL_STRING || m_NodeData.strEntityName != NULL_STRING ) { m_NodeData.nNodeID = m_nNodeCount; pHint = CAI_HintManager::CreateHint( &m_NodeData, pMapData ); pHint->AddSpawnFlags( GetSpawnFlags() ); } } // --------------------------------------------------------------------------------- // If we loaded from disk, we can discard all these node ents as soon as they spawn // unless we are in WC edited mode // --------------------------------------------------------------------------------- if ( g_pAINetworkManager->NetworksLoaded() && !engine->IsInEditMode()) { // If hint exists for this node, set it if (pHint) { CAI_Node *pNode = g_pBigAINet->GetNode(m_nNodeCount); if (pNode) pNode->SetHint( pHint ); else { DevMsg("AI node graph corrupt\n"); } } m_nNodeCount++; UTIL_RemoveImmediate( this ); return -1; } else { m_nNodeCount++; } // --------------------------------------------------------------------------------- // Add a new node to the network // --------------------------------------------------------------------------------- // For now just using one big AI network CAI_Node *new_node = g_pBigAINet->AddNode( GetAbsOrigin(), GetAbsAngles().y ); new_node->SetHint( pHint ); // ------------------------------------------------------------------------- // Update table of how each WC id relates to each engine ID // ------------------------------------------------------------------------- if (g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) { g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[new_node->GetId()] = m_NodeData.nWCNodeID; } // Keep track of largest index used by WC if (g_pAINetworkManager->GetEditOps()->m_nNextWCIndex <= m_NodeData.nWCNodeID) { g_pAINetworkManager->GetEditOps()->m_nNextWCIndex = m_NodeData.nWCNodeID+1; } // ------------------------------------------------------------------------- // If in WC edit mode: // Remember the original positions of the nodes before // they drop so we can send the undropped positions to wc. // ------------------------------------------------------------------------- if (engine->IsInEditMode()) { if (g_pAINetworkManager->GetEditOps()->m_pWCPosition) { g_pAINetworkManager->GetEditOps()->m_pWCPosition[new_node->GetId()] = new_node->GetOrigin(); } } if (FClassnameIs( this, "info_node_air" ) || FClassnameIs( this, "info_node_air_hint" )) { new_node->SetType( NODE_AIR ); } else if (FClassnameIs( this, "info_node_climb" )) { new_node->SetType( NODE_CLIMB ); } else { new_node->SetType( NODE_GROUND ); } new_node->m_eNodeInfo = ( m_spawnflags << NODE_ENT_FLAGS_SHIFT ); // If changed as part of WC editing process note that network must be rebuilt if (m_debugOverlays & OVERLAY_WC_CHANGE_ENTITY) { g_pAINetworkManager->GetEditOps()->SetRebuildFlags(); new_node->m_eNodeInfo |= bits_NODE_WC_CHANGED; // Initialize the new nodes position. The graph may not be rebuild // right away but the node should at least be positioned correctly g_AINetworkBuilder.InitNodePosition( g_pBigAINet, new_node ); } UTIL_RemoveImmediate( this ); return -1; }
//------------------------------------------------------------------------------ // Purpose : Initializes src and dest IDs for all dynamic links // // Input : // Output : //------------------------------------------------------------------------------ void CAI_DynamicLink::InitDynamicLinks(void) { if (!g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) { Warning("ERROR: Trying initialize links with no WC ID table!\n"); return; } if ( gm_bInitialized ) return; gm_bInitialized = true; bool bUpdateZones = false; GenerateControllerLinks(); CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; while (pDynamicLink) { // ------------------------------------------------------------- // First convert this links WC IDs to engine IDs // ------------------------------------------------------------- if ( !pDynamicLink->m_bFixedUpIds ) { int nSrcID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nSrcEditID ); if (nSrcID == -1) { DevMsg( "ERROR: Dynamic link source WC node %d not found\n", pDynamicLink->m_nSrcEditID ); nSrcID = NO_NODE; } int nDestID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nDestEditID ); if (nDestID == -1) { DevMsg( "ERROR: Dynamic link dest WC node %d not found\n", pDynamicLink->m_nDestEditID ); nDestID = NO_NODE; } pDynamicLink->m_nSrcID = nSrcID; pDynamicLink->m_nDestID = nDestID; pDynamicLink->m_bFixedUpIds = true; } if ( pDynamicLink->m_nSrcID != NO_NODE && pDynamicLink->m_nDestID != NO_NODE ) { if ( ( pDynamicLink->GetSpawnFlags() & bits_HULL_BITS_MASK ) != 0 ) { CAI_Link *pLink = pDynamicLink->FindLink(); if ( !pLink ) { CAI_Node *pNode1, *pNode2; pNode1 = g_pBigAINet->GetNode( pDynamicLink->m_nSrcID ); pNode2 = g_pBigAINet->GetNode( pDynamicLink->m_nDestID ); if ( pNode1 && pNode2 ) { pLink = g_pBigAINet->CreateLink( pDynamicLink->m_nSrcID, pDynamicLink->m_nDestID ); if ( !pLink ) { DevMsg( "Failed to create dynamic link (%d <--> %d)\n", pDynamicLink->m_nSrcEditID, pDynamicLink->m_nDestEditID ); } } } if ( pLink ) { bUpdateZones = true; int hullBits = ( pDynamicLink->GetSpawnFlags() & bits_HULL_BITS_MASK ); for ( int i = 0; i < NUM_HULLS; i++ ) { if ( hullBits & HullToBit( Hull_t(i) ) ) { pLink->m_iAcceptedMoveTypes[i] = pDynamicLink->m_nLinkType; } } } } // Now set the link's state pDynamicLink->SetLinkState(); // Go on to the next dynamic link pDynamicLink = pDynamicLink->m_pNextDynamicLink; } else { CAI_DynamicLink *pBadDynamicLink = pDynamicLink; // Go on to the next dynamic link pDynamicLink = pDynamicLink->m_pNextDynamicLink; UTIL_RemoveImmediate( pBadDynamicLink ); } } if ( bUpdateZones ) { g_AINetworkBuilder.InitZones( g_pBigAINet ); } }