//----------------------------------------------------------------------------- // Purpose: For create nodes in wc edit mode // Input : // Output : //----------------------------------------------------------------------------- void NWCEdit::CreateAINode( CBasePlayer *pPlayer ) { // ------------------------------------------------------------- // Check that WC is running with the right map version // ------------------------------------------------------------- if ( !IsWCVersionValid() || !pPlayer ) return; pPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); UTIL_Relink(pPlayer); int hullType = g_pAINetworkManager->GetEditOps()->m_iHullDrawNum; // ----------------------------------- // Get position of node to create // ----------------------------------- Vector vNewNodePos = vec3_origin; bool bPositionValid = false; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { vNewNodePos = NWCEdit::AirNodePlacementPosition(); // Make sure we can see the node trace_t tr; UTIL_TraceLine(pPlayer->EyePosition(), vNewNodePos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); if (tr.fraction == 1.0) { bPositionValid = true; } } else { // Place node by where the player is looking Vector forward; pPlayer->EyeVectors( &forward ); Vector startTrace = pPlayer->EyePosition(); Vector endTrace = pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH; trace_t tr; UTIL_TraceLine(startTrace,endTrace,MASK_NPCSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0) { // Raise the end position up off the floor, place the node and drop him down tr.endpos.z += 48; vNewNodePos = tr.endpos; bPositionValid = true; } } // ------------------------------------------------------------------------------- // Now check that this is a valid location for the new node bu using test hull // ------------------------------------------------------------------------------- if (bPositionValid) { CBaseEntity *testHull = (CBaseEntity*)CAI_TestHull::GetTestHull(); // Set the size of the test hull UTIL_SetSize(testHull, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType)); // Set origin of test hull testHull->SetLocalOrigin( vNewNodePos ); // ----------------------------------------------------------------------- // If a ground node, drop to floor and make sure can stand at test postion // ----------------------------------------------------------------------- if (!g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { UTIL_DropToFloor( testHull, MASK_NPCSOLID ); vNewNodePos = testHull->GetAbsOrigin(); CTraceFilterSimple traceFilter( testHull, COLLISION_GROUP_NONE ); if (!UTIL_CheckBottom(testHull, &traceFilter, sv_stepsize.GetFloat())) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } } // ----------------------------------------------------------------------- // Make sure hull fits at location by seeing if it can move up a fraction // ----------------------------------------------------------------------- Vector vUpBit = testHull->GetAbsOrigin(); vUpBit.z += 1; trace_t tr; UTIL_TraceHull( testHull->GetAbsOrigin(), vUpBit, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), MASK_NPCSOLID, testHull, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid || tr.fraction != 1.0) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } // <<TEMP>> Round position till DS fixed WC bug testHull->SetLocalOrigin( Vector( floor(testHull->GetAbsOrigin().x), floor(testHull->GetAbsOrigin().y ), floor(testHull->GetAbsOrigin().z) ) ); // --------------------------------------- // Send new node to WC // --------------------------------------- int status; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { status = Editor_CreateNode("info_node_air", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } else { // Create slightly higher in WC so it can be dropped when its loaded again Vector origin = testHull->GetLocalOrigin(); origin.z += 24.0; testHull->SetLocalOrigin( origin ); status = Editor_CreateNode("info_node", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } if (status == Editor_BadCommand) { Msg( "Worldcraft failed on creation...\n" ); CAI_TestHull::ReturnTestHull(); } else if (status == Editor_OK) { // ----------------------- // Create a new ai node // ----------------------- CNodeEnt *pNodeEnt; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node_air"); } else { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node"); } // Note this is a new entity being created as part of wc editing pNodeEnt->SetLocalOrigin( testHull->GetLocalOrigin() ); CAI_TestHull::ReturnTestHull(); pNodeEnt->m_nWCNodeID = g_pAINetworkManager->GetEditOps()->m_nNextWCIndex; pNodeEnt->m_debugOverlays |= OVERLAY_WC_CHANGE_ENTITY; pNodeEnt->Spawn(); } } DoneCreate: // ---------------------------------------------------------- // Flash a red box as a warning that the hull won't fit here // ---------------------------------------------------------- if (!bPositionValid) { NDebugOverlay::Box(vNewNodePos, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), 255,0,0,0,0.1); } // Restore player collidability pPlayer->SetSolid( SOLID_BBOX ); UTIL_Relink(pPlayer); }
//----------------------------------------------------------------------------- // Purpose: Creates the NPC. //----------------------------------------------------------------------------- void CNPCMaker::MakeNPC( void ) { if (!CanMakeNPC()) return; CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName( STRING(m_iszNPCClassname) ); if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString( m_RelationshipString ); m_OnSpawnNPC.Set( pent, pent, this ); pent->SetAbsOrigin( GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); if ( m_spawnflags & SF_NPCMAKER_FADE ) { pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } pent->m_spawnEquipment = m_spawnEquipment; pent->SetSquadName( m_SquadName ); pent->SetHintGroup( m_strHintGroup ); ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); if ( m_ChildTargetName != NULL_STRING ) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName( m_ChildTargetName ); } 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 ); } } }
//----------------------------------------------------------------------------- // Purpose: Creates a flame and attaches it to a target entity. // Input : pTarget - //----------------------------------------------------------------------------- CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, const char *pMaterialName, float flStartTime, int nDissolveType, bool *pRagdollCreated ) { if ( pRagdollCreated ) { *pRagdollCreated = false; } if ( !pMaterialName ) { pMaterialName = DISSOLVE_SPRITE_NAME; } if ( pTarget->IsPlayer() ) { // Simply immediately kill the player. CBasePlayer *pPlayer = assert_cast< CBasePlayer* >( pTarget ); pPlayer->SetArmorValue( 0 ); CTakeDamageInfo info( pPlayer, pPlayer, pPlayer->GetHealth(), DMG_GENERIC | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE ); pPlayer->TakeDamage( info ); return NULL; } CEntityDissolve *pDissolve = (CEntityDissolve *) CreateEntityByName( "env_entity_dissolver" ); if ( pDissolve == NULL ) return NULL; pDissolve->m_nDissolveType = nDissolveType; if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) { if ( pTarget->IsNPC() && pTarget->MyNPCPointer()->CanBecomeRagdoll() ) { CTakeDamageInfo info; CBaseEntity *pRagdoll = CreateServerRagdoll( pTarget->MyNPCPointer(), 0, info, COLLISION_GROUP_DEBRIS, true ); pRagdoll->SetCollisionBounds( pTarget->CollisionProp()->OBBMins(), pTarget->CollisionProp()->OBBMaxs() ); // Necessary to cause it to do the appropriate death cleanup if ( pTarget->m_lifeState == LIFE_ALIVE ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); CTakeDamageInfo ragdollInfo( pPlayer, pPlayer, 10000.0, DMG_SHOCK | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE ); pTarget->TakeDamage( ragdollInfo ); } if ( pRagdollCreated ) { *pRagdollCreated = true; } UTIL_Remove( pTarget ); pTarget = pRagdoll; } } pDissolve->SetModelName( AllocPooledString(pMaterialName) ); pDissolve->AttachToEntity( pTarget ); pDissolve->SetStartTime( flStartTime ); pDissolve->Spawn(); // Send to the client even though we don't have a model pDissolve->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); // Play any appropriate noises when we start to dissolve if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) { pTarget->DispatchResponse( "TLK_ELECTROCUTESCREAM" ); } else { pTarget->DispatchResponse( "TLK_DISSOLVESCREAM" ); } return pDissolve; }
//----------------------------------------------------------------------------- // Purpose: Creates the NPC. //----------------------------------------------------------------------------- void CNPCMakerXenInvasion::MakeNPC(void) { if (!CanMakeNPC()) return; if (g_pGameRules->bHasRandomized) { if (g_pGameRules->iRandomGamemode == FIREFIGHT_PRIMARY_XENINVASION) { int nNPCs = ARRAYSIZE(g_charNPCSXenInvasionSupport); int randomChoice = rand() % nNPCs; const char *pRandomName = g_charNPCSXenInvasionSupport[randomChoice]; CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName(pRandomName); if (!pent) { Warning("npc_maker_firefight: Entity classname does not exist in database.\n"); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString(m_RelationshipString); m_OnSpawnNPC.Set(pent, pent, this); pent->SetAbsOrigin(GetAbsOrigin()); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles(angles); pent->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); if (m_spawnflags & SF_NPCMAKER_FADE) { pent->AddSpawnFlags(SF_NPC_FADE_CORPSE); } pent->m_isRareEntity = false; pent->SetSquadName(m_SquadName); pent->SetHintGroup(m_strHintGroup); ChildPreSpawn(pent); DispatchSpawn(pent); pent->SetOwnerEntity(this); DispatchActivate(pent); if (m_ChildTargetName != NULL_STRING) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName(m_ChildTargetName); } ChildPostSpawn(pent); } else { CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName(STRING(m_iszNPCClassname)); if (!pent) { Warning("npc_maker_firefight: Entity classname does not exist in database.\n"); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString(m_RelationshipString); m_OnSpawnNPC.Set(pent, pent, this); pent->SetAbsOrigin(GetAbsOrigin()); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles(angles); pent->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); if (m_spawnflags & SF_NPCMAKER_FADE) { pent->AddSpawnFlags(SF_NPC_FADE_CORPSE); } pent->m_spawnEquipment = m_spawnEquipment; pent->m_isRareEntity = false; pent->SetSquadName(m_SquadName); pent->SetHintGroup(m_strHintGroup); ChildPreSpawn(pent); DispatchSpawn(pent); pent->SetOwnerEntity(this); DispatchActivate(pent); if (m_ChildTargetName != NULL_STRING) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName(m_ChildTargetName); } ChildPostSpawn(pent); } } else { if (g_pGameRules->GetGamemode() == FIREFIGHT_PRIMARY_XENINVASION) { int nNPCs = ARRAYSIZE(g_charNPCSXenInvasionSupport); int randomChoice = rand() % nNPCs; const char *pRandomName = g_charNPCSXenInvasionSupport[randomChoice]; CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName(pRandomName); if (!pent) { Warning("npc_maker_firefight: Entity classname does not exist in database.\n"); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString(m_RelationshipString); m_OnSpawnNPC.Set(pent, pent, this); pent->SetAbsOrigin(GetAbsOrigin()); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles(angles); pent->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); if (m_spawnflags & SF_NPCMAKER_FADE) { pent->AddSpawnFlags(SF_NPC_FADE_CORPSE); } pent->m_isRareEntity = false; pent->SetSquadName(m_SquadName); pent->SetHintGroup(m_strHintGroup); ChildPreSpawn(pent); DispatchSpawn(pent); pent->SetOwnerEntity(this); DispatchActivate(pent); if (m_ChildTargetName != NULL_STRING) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName(m_ChildTargetName); } ChildPostSpawn(pent); } else { CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName(STRING(m_iszNPCClassname)); if (!pent) { Warning("npc_maker_firefight: Entity classname does not exist in database.\n"); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString(m_RelationshipString); m_OnSpawnNPC.Set(pent, pent, this); pent->SetAbsOrigin(GetAbsOrigin()); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles(angles); pent->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); if (m_spawnflags & SF_NPCMAKER_FADE) { pent->AddSpawnFlags(SF_NPC_FADE_CORPSE); } pent->m_spawnEquipment = m_spawnEquipment; pent->m_isRareEntity = false; pent->SetSquadName(m_SquadName); pent->SetHintGroup(m_strHintGroup); ChildPreSpawn(pent); DispatchSpawn(pent); pent->SetOwnerEntity(this); DispatchActivate(pent); if (m_ChildTargetName != NULL_STRING) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName(m_ChildTargetName); } ChildPostSpawn(pent); } } m_nLiveChildren++;// count this NPC }
//----------------------------------------------------------------------------- // Create a corpse //----------------------------------------------------------------------------- void CPropAPC2::CreateCorpse( ) { m_lifeState = LIFE_DEAD; for ( int i = 0; i < APC_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 ); } // CPropAPC2 *pAPC = (CPropAPC2 *)CreateEntityByName( "prop_vehicle_apc2" ); if ( pAPC ) { pAPC->InicialSpawn=m_vOriginalSpawnOrigin; pAPC->InicialAngle=m_vOriginalSpawnAngles; pAPC->m_bSpawn=true; pAPC->SetThink( &CPropAPC2::Materialize ); pAPC->SetContextThink( &CPropAPC2::Materialize, gpGlobals->curtime + 5.0f, "RESPAWNING" ); pAPC->SetNextThink( gpGlobals->curtime + 5.0f ); } else { Warning("Respawn failed to create %s!\n", GetClassname() ); } // AddSolidFlags( FSOLID_NOT_SOLID ); AddEffects( EF_NODRAW ); UTIL_Remove( this ); }