//----------------------------------------------------------------------------- // Purpose: Called when spawning, after keyvalues have been set. //----------------------------------------------------------------------------- void CFuncRotating::Spawn( ) { #ifdef TF_DLL AddSpawnFlags( SF_BRUSH_ROTATE_CLIENTSIDE ); #endif // // Maintain compatibility with previous maps. // if (m_flVolume == 0.0) { m_flVolume = 1.0; } // // If the designer didn't set a sound attenuation, default to one. // if ( HasSpawnFlags(SF_BRUSH_ROTATE_SMALLRADIUS) ) { m_flAttenuation = ATTN_IDLE; } else if ( HasSpawnFlags(SF_BRUSH_ROTATE_MEDIUMRADIUS) ) { m_flAttenuation = ATTN_STATIC; } else if ( HasSpawnFlags(SF_BRUSH_ROTATE_LARGERADIUS) ) { m_flAttenuation = ATTN_NORM; } else { m_flAttenuation = ATTN_NORM; } // // Prevent divide by zero if level designer forgets friction! // if ( m_flFanFriction == 0 ) { m_flFanFriction = 1; } // // Build the axis of rotation based on spawnflags. // if ( HasSpawnFlags(SF_BRUSH_ROTATE_Z_AXIS) ) { m_vecMoveAng = QAngle(0,0,1); } else if ( HasSpawnFlags(SF_BRUSH_ROTATE_X_AXIS) ) { m_vecMoveAng = QAngle(1,0,0); } else { m_vecMoveAng = QAngle(0,1,0); // y-axis } // // Check for reverse rotation. // if ( HasSpawnFlags(SF_BRUSH_ROTATE_BACKWARDS) ) { m_vecMoveAng = m_vecMoveAng * -1; } SetSolid( SOLID_VPHYSICS ); // // Some rotating objects like fake volumetric lights will not be solid. // if ( HasSpawnFlags(SF_ROTATING_NOT_SOLID) ) { AddSolidFlags( FSOLID_NOT_SOLID ); SetMoveType( MOVETYPE_PUSH ); } else { RemoveSolidFlags( FSOLID_NOT_SOLID ); SetMoveType( MOVETYPE_PUSH ); } SetModel( STRING( GetModelName() ) ); SetUse( &CFuncRotating::RotatingUse ); // // Did level designer forget to assign a maximum speed? Prevent a divide by // zero in RampPitchVol as well as allowing the rotator to work. // m_flMaxSpeed = fabs( m_flMaxSpeed ); if (m_flMaxSpeed == 0) { m_flMaxSpeed = 100; } // // If the brush should be initially rotating, use it in a little while. // if ( HasSpawnFlags(SF_BRUSH_ROTATE_START_ON) ) { SetThink( &CFuncRotating::SUB_CallUseToggle ); SetNextThink( gpGlobals->curtime + .2 ); // leave a magic delay for client to start up } // // Can this brush inflict pain? // if ( HasSpawnFlags(SF_BRUSH_HURT) ) { SetTouch( &CFuncRotating::HurtTouch ); } // // Set speed to 0 in case there's an old "speed" key lying around. // m_flSpeed = 0; Precache( ); CreateVPhysics(); m_angStart = GetLocalAngles(); // Slam the object back to solid - if we really want it to be solid. if ( m_bSolidBsp ) { SetSolid( SOLID_BSP ); } if ( HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) ) { m_vecClientOrigin = GetLocalOrigin(); m_vecClientAngles = GetLocalAngles(); } }
void CWeaponHL2MPBase::FallInit( void ) { #ifndef CLIENT_DLL SetModel( GetWorldModel() ); VPhysicsDestroyObject(); if ( HasSpawnFlags( SF_NORESPAWN ) == false ) { SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_TRIGGER ); UTIL_DropToFloor( this, MASK_SOLID ); } else { if ( !VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ) ) { SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_TRIGGER ); } else { #if !defined( CLIENT_DLL ) // Constrained start? if ( HasSpawnFlags( SF_WEAPON_START_CONSTRAINED ) ) { //Constrain the weapon in place IPhysicsObject *pReferenceObject, *pAttachedObject; pReferenceObject = g_PhysWorldObject; pAttachedObject = VPhysicsGetObject(); if ( pReferenceObject && pAttachedObject ) { constraint_fixedparams_t fixed; fixed.Defaults(); fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject ); fixed.constraint.forceLimit = lbs2kg( 10000 ); fixed.constraint.torqueLimit = lbs2kg( 10000 ); IPhysicsConstraint *pConstraint = GetConstraint(); pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed ); pConstraint->SetGameData( (void *) this ); } } #endif //CLIENT_DLL } } SetPickupTouch(); SetThink( &CBaseCombatWeapon::FallThink ); SetNextThink( gpGlobals->curtime + 0.1f ); #endif }
bool CStatueProp::CreateVPhysicsFromOBBs( CBaseAnimating *pInitBaseAnimating ) { // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ m_pInitOBBs->Count() ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < m_pInitOBBs->Count(); i++ ) { const outer_collision_obb_t *pOBB = &((*m_pInitOBBs)[ i ]); // Accumulate volume and area Vector flDimentions = pOBB->vecMaxs - pOBB->vecMins; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pOBB->vecMins, pOBB->angAngles, vecMins ); VectorRotate( pOBB->vecMaxs, pOBB->angAngles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = pOBB->vecPos + vecMins; Vector vecMaxCorner = pOBB->vecPos + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( pOBB->angAngles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, m_pInitOBBs->Count() ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); m_pInitOBBs = NULL; return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Combine_Cannon::Spawn( void ) { Precache(); /// HACK: SetModel( "models/combine_soldier.mdl" ); // Setup our ancillary beams but keep them hidden for now CreateLaser(); CreateAncillaryBeams(); m_iAmmoType = GetAmmoDef()->Index( "CombineHeavyCannon" ); SetHullType( HULL_HUMAN ); SetHullSizeNormal(); UTIL_SetSize( this, Vector( -16, -16 , 0 ), Vector( 16, 16, 64 ) ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_FLY ); m_bloodColor = DONT_BLEED; m_iHealth = 10; m_flFieldOfView = DOT_45DEGREE; m_NPCState = NPC_STATE_NONE; if( HasSpawnFlags( SF_STARTDISABLED ) ) { m_fEnabled = false; } else { m_fEnabled = true; } CapabilitiesClear(); CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_SIMPLE_RADIUS_DAMAGE ); m_HackedGunPos = Vector ( 0, 0, 0 ); AddSpawnFlags( SF_NPC_LONG_RANGE | SF_NPC_ALWAYSTHINK ); NPCInit(); // Limit our look distance SetDistLook( m_flSightDist ); AddEffects( EF_NODRAW ); AddSolidFlags( FSOLID_NOT_SOLID ); // Point the cursor straight ahead so that the sniper's // first sweep of the laser doesn't look weird. Vector vecForward; AngleVectors( GetLocalAngles(), &vecForward ); m_vecPaintCursor = GetBulletOrigin() + vecForward * 1024; // none! GetEnemies()->SetFreeKnowledgeDuration( 0.0f ); GetEnemies()->SetEnemyDiscardTime( 2.0f ); m_flTimeLastAttackedPlayer = 0.0f; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CSprite::Spawn( void ) { SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); m_flFrame = 0; Precache(); SetModel( STRING( GetModelName() ) ); CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE ); m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1; AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW ); #if defined( CLIENT_DLL ) SetNextClientThink( CLIENT_THINK_ALWAYS ); #endif #if !defined( CLIENT_DLL ) if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) ) { TurnOff(); } else #endif { TurnOn(); } // Worldcraft only sets y rotation, copy to Z if ( GetLocalAngles().y != 0 && GetLocalAngles().z == 0 ) { QAngle angles = GetLocalAngles(); angles.z = angles.y; angles.y = 0; SetLocalAngles( angles ); } // Clamp our scale if necessary float scale = m_flSpriteScale; if ( scale < 0 || scale > MAX_SPRITE_SCALE ) { #if !defined( CLIENT_DLL ) #ifndef _LINUX DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale, MAX_SPRITE_SCALE ); #endif #endif scale = clamp( m_flSpriteScale, 0, MAX_SPRITE_SCALE ); } //Set our state SetBrightness( m_clrRender->a ); SetScale( scale ); #if defined( CLIENT_DLL ) m_flStartScale = m_flDestScale = m_flSpriteScale; m_nStartBrightness = m_nDestBrightness = m_nBrightness; #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Ichthyosaur::Spawn( void ) { Precache(); SetModel( ICHTHYOSAUR_MODEL ); SetHullType(HULL_LARGE_CENTERED); SetHullSizeNormal(); SetDefaultEyeOffset(); SetNavType( NAV_FLY ); m_NPCState = NPC_STATE_NONE; SetBloodColor( BLOOD_COLOR_RED ); m_iHealth = sk_ichthyosaur_health.GetFloat(); m_iMaxHealth = m_iHealth; m_flFieldOfView = -0.707; // 270 degrees SetDistLook( 1024 ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_STEP ); AddFlag( FL_FLY | FL_STEPMOVEMENT ); m_flGroundSpeed = ICH_SWIM_SPEED_RUN; m_bIgnoreSurface = false; m_flSwimSpeed = 0.0f; m_flTailYaw = 0.0f; m_flTailPitch = 0.0f; m_flNextBiteTime = gpGlobals->curtime; m_flHoldTime = gpGlobals->curtime; m_flNextPingTime = gpGlobals->curtime; m_flNextGrowlTime = gpGlobals->curtime; #if FEELER_COLLISION Vector forward; GetVectors( &forward, NULL, NULL ); m_vecCurrentVelocity = forward * m_flGroundSpeed; #endif //SetTouch( IchTouch ); CapabilitiesClear(); CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_INNATE_MELEE_ATTACK1 ); NPCInit(); //m_pSwimSound = ENVELOPE_CONTROLLER.SoundCreate( edict(), CHAN_BODY, "xxxCONVERTTOGAMESOUNDS!!!npc/ichthyosaur/ich_amb1wav", ATTN_NORM ); //m_pVoiceSound = ENVELOPE_CONTROLLER.SoundCreate( edict(), CHAN_VOICE, "xxxCONVERTTOGAMESOUNDS!!!npc/ichthyosaur/water_breathwav", ATTN_IDLE ); //ENVELOPE_CONTROLLER.Play( m_pSwimSound, 1.0f, 100 ); //ENVELOPE_CONTROLLER.Play( m_pVoiceSound,1.0f, 100 ); BaseClass::Spawn(); }
//----------------------------------------------------------------------------- // Purpose: Input handler for making the explosion explode. //----------------------------------------------------------------------------- void CEnvExplosion::InputExplode( inputdata_t &inputdata ) { trace_t tr; SetModelName( NULL_STRING );//invisible SetSolid( SOLID_NONE );// intangible Vector vecSpot = GetAbsOrigin() + Vector( 0 , 0 , 8 ); UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -40 ), (MASK_SOLID_BRUSHONLY | MASK_WATER), this, COLLISION_GROUP_NONE, &tr ); // Pull out of the wall a bit. We used to move the explosion origin itself, but that seems unnecessary, not to mention a // little weird when you consider that it might be in hierarchy. Instead we just calculate a new virtual position at // which to place the explosion. We don't use that new position to calculate radius damage because according to Steve's // comment, that adversely affects the force vector imparted on explosion victims when they ragdoll. Vector vecExplodeOrigin = GetAbsOrigin(); if ( tr.fraction != 1.0 ) { vecExplodeOrigin = tr.endpos + (tr.plane.normal * 24 ); } // draw decal if (! ( m_spawnflags & SF_ENVEXPLOSION_NODECAL)) { UTIL_DecalTrace( &tr, "Scorch" ); } // It's stupid that this entity's spawnflags and the flags for the // explosion temp ent don't match up. But because they don't, we // have to reinterpret some of the spawnflags to determine which // flags to pass to the temp ent. int nFlags = TE_EXPLFLAG_NONE; if( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) { nFlags |= TE_EXPLFLAG_NOFIREBALL; } if( m_spawnflags & SF_ENVEXPLOSION_NOSOUND ) { nFlags |= TE_EXPLFLAG_NOSOUND; } if ( m_spawnflags & SF_ENVEXPLOSION_RND_ORIENT ) { nFlags |= TE_EXPLFLAG_ROTATE; } if ( m_nRenderMode == kRenderTransAlpha ) { nFlags |= TE_EXPLFLAG_DRAWALPHA; } else if ( m_nRenderMode != kRenderTransAdd ) { nFlags |= TE_EXPLFLAG_NOADDITIVE; } if( m_spawnflags & SF_ENVEXPLOSION_NOPARTICLES ) { nFlags |= TE_EXPLFLAG_NOPARTICLES; } if( m_spawnflags & SF_ENVEXPLOSION_NODLIGHTS ) { nFlags |= TE_EXPLFLAG_NODLIGHTS; } if ( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALLSMOKE ) { nFlags |= TE_EXPLFLAG_NOFIREBALLSMOKE; } //Get the damage override if specified int iRadius = ( m_iRadiusOverride > 0 ) ? m_iRadiusOverride : ( m_iMagnitude * 2.5f ); CPASFilter filter( vecExplodeOrigin ); te->Explosion( filter, 0.0, &vecExplodeOrigin, ( m_sFireballSprite < 1 ) ? g_sModelIndexFireball : m_sFireballSprite, !( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) ? ( m_spriteScale / 10.0 ) : 0.0, 15, nFlags, iRadius, m_iMagnitude ); // do damage if ( !( m_spawnflags & SF_ENVEXPLOSION_NODAMAGE ) ) { CBaseEntity *pAttacker = GetOwnerEntity() ? GetOwnerEntity() : this; // Only calculate damage type if we didn't get a custom one passed in int iDamageType = m_iCustomDamageType; if ( iDamageType == -1 ) { iDamageType = HasSpawnFlags( SF_ENVEXPLOSION_GENERIC_DAMAGE ) ? DMG_GENERIC : DMG_BLAST; } CTakeDamageInfo info( m_hInflictor ? m_hInflictor : this, pAttacker, m_iMagnitude, iDamageType ); if( HasSpawnFlags( SF_ENVEXPLOSION_SURFACEONLY ) ) { info.AddDamageType( DMG_BLAST_SURFACE ); } if ( m_flDamageForce ) { // Not the right direction, but it'll be fixed up by RadiusDamage. info.SetDamagePosition( GetAbsOrigin() ); info.SetDamageForce( Vector( m_flDamageForce, 0, 0 ) ); } RadiusDamage( info, GetAbsOrigin(), iRadius, m_iClassIgnore, m_hEntityIgnore.Get() ); } SetThink( &CEnvExplosion::Smoke ); SetNextThink( gpGlobals->curtime + 0.3 ); // Only do these effects if we're not submerged if ( UTIL_PointContents( GetAbsOrigin() ) & CONTENTS_WATER ) { // draw sparks if ( !( m_spawnflags & SF_ENVEXPLOSION_NOSPARKS ) ) { int sparkCount = random->RandomInt(0,3); for ( int i = 0; i < sparkCount; i++ ) { QAngle angles; VectorAngles( tr.plane.normal, angles ); Create( "spark_shower", vecExplodeOrigin, angles, NULL ); } } } }
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll ) { SetCollisionGroup( collisionGroup ); // Make sure it's interactive debris for at most 5 seconds if ( collisionGroup == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext ); } SetMoveType( MOVETYPE_VPHYSICS ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); m_takedamage = DAMAGE_EVENTS_ONLY; ragdollparams_t params; params.pGameData = static_cast<void *>( static_cast<CBaseEntity *>(this) ); params.modelIndex = GetModelIndex(); params.pCollide = modelinfo->GetVCollide( params.modelIndex ); params.pStudioHdr = GetModelPtr(); params.forceVector = forceVector; params.forceBoneIndex = forceBone; params.forcePosition = forcePos; params.pPrevBones = pPrevBones; params.pCurrentBones = pBoneToWorld; params.boneDt = dt; params.jointFrictionScale = 1.0; RagdollCreate( m_ragdoll, params, physenv ); if ( m_anglesOverrideString != NULL_STRING && Q_strlen(m_anglesOverrideString.ToCStr()) > 0 ) { char szToken[2048]; const char *pStr = nexttoken(szToken, STRING(m_anglesOverrideString), ','); // anglesOverride is index,angles,index,angles (e.g. "1, 22.5 123.0 0.0, 2, 0 0 0, 3, 0 0 180.0") while ( szToken[0] != 0 ) { int objectIndex = atoi(szToken); // sanity check to make sure this token is an integer Assert( atof(szToken) == ((float)objectIndex) ); pStr = nexttoken(szToken, pStr, ','); Assert( szToken[0] ); if ( objectIndex >= m_ragdoll.listCount ) { Warning("Bad ragdoll pose in entity %s, model (%s) at %s, model changed?\n", GetDebugName(), GetModelName().ToCStr(), VecToString(GetAbsOrigin()) ); } else if ( szToken[0] != 0 ) { QAngle angles; Assert( objectIndex >= 0 && objectIndex < RAGDOLL_MAX_ELEMENTS ); UTIL_StringToVector( angles.Base(), szToken ); int boneIndex = m_ragdoll.boneIndex[objectIndex]; AngleMatrix( angles, pBoneToWorld[boneIndex] ); const ragdollelement_t &element = m_ragdoll.list[objectIndex]; Vector out; if ( element.parentIndex >= 0 ) { int parentBoneIndex = m_ragdoll.boneIndex[element.parentIndex]; VectorTransform( element.originParentSpace, pBoneToWorld[parentBoneIndex], out ); } else { out = GetAbsOrigin(); } MatrixSetColumn( out, 3, pBoneToWorld[boneIndex] ); element.pObject->SetPositionMatrix( pBoneToWorld[boneIndex], true ); } pStr = nexttoken(szToken, pStr, ','); } } if ( activateRagdoll ) { MEM_ALLOC_CREDIT(); RagdollActivate( m_ragdoll, params.pCollide, GetModelIndex() ); } for ( int i = 0; i < m_ragdoll.listCount; i++ ) { UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); g_pPhysSaveRestoreManager->AssociateModel( m_ragdoll.list[i].pObject, GetModelIndex() ); physcollision->CollideGetAABB( m_ragdollMins[i], m_ragdollMaxs[i], m_ragdoll.list[i].pObject->GetCollide(), vec3_origin, vec3_angle ); } VPhysicsSetObject( m_ragdoll.list[0].pObject ); CalcRagdollSize(); }
bool CreateVPhysics() { SetSolid(SOLID_VPHYSICS); SetMoveType(MOVETYPE_NONE); return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Crow::Spawn( void ) { BaseClass::Spawn(); #ifdef _XBOX // Always fade the corpse AddSpawnFlags( SF_NPC_FADE_CORPSE ); #endif // _XBOX const char *szModel = (char *)STRING( GetModelName() ); if (!szModel || !*szModel) { szModel = "models/crow.mdl"; SetModelName( AllocPooledString(szModel) ); } Precache(); SetModel( szModel ); m_iHealth = sk_crow_health.GetFloat(); SetHullType(HULL_TINY); SetHullSizeNormal(); SetSolid( SOLID_BBOX ); SetMoveType( MOVETYPE_STEP ); m_flFieldOfView = VIEW_FIELD_FULL; SetViewOffset( Vector(6, 0, 11) ); // Position of the eyes relative to NPC's origin. m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 0.0f, 5.0f ); SetBloodColor( BLOOD_COLOR_RED ); m_NPCState = NPC_STATE_NONE; m_nMorale = random->RandomInt( 0, 12 ); SetCollisionGroup( HL2COLLISION_GROUP_CROW ); CapabilitiesClear(); bool bFlying = ( ( m_spawnflags & SF_CROW_FLYING ) != 0 ); SetFlyingState( bFlying ? FlyState_Flying : FlyState_Walking ); // We don't mind zombies so much. They smell good! AddClassRelationship( CLASS_ZOMBIE, D_NU, 0 ); m_bSoar = false; m_bOnJeep = false; m_flSoarTime = gpGlobals->curtime; NPCInit(); m_iBirdType = BIRDTYPE_CROW; m_vLastStoredOrigin = vec3_origin; m_flLastStuckCheck = gpGlobals->curtime; m_flDangerSoundTime = gpGlobals->curtime; SetGoalEnt( NULL ); }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::Spawn() { Precache(); Wake( false ); SetModel("models/props_combine/combine_mine01.mdl"); SetSolid( SOLID_VPHYSICS ); m_hSprite.Set( NULL ); m_takedamage = DAMAGE_EVENTS_ONLY; // Find my feet! m_iHookN = LookupPoseParameter( "blendnorth" ); m_iHookE = LookupPoseParameter( "blendeast" ); m_iHookS = LookupPoseParameter( "blendsouth" ); m_iAllHooks = LookupPoseParameter( "blendstates" ); m_flHookPositions = 0; SetHealth( 100 ); m_bBounce = true; SetSequence( SelectWeightedSequence( ACT_IDLE ) ); OpenHooks( true ); m_bHeldByPhysgun = false; m_iFlipAttempts = 0; if( !GetParent() ) { // Create vphysics now if I'm not being carried. CreateVPhysics(); } m_flTimeGrabbed = FLT_MAX; if( m_bDisarmed ) { SetMineState( MINE_STATE_DORMANT ); } else { SetMineState( MINE_STATE_DEPLOY ); } // default to a different skin for cavern turrets (unless explicitly overridden) if ( m_iModification == MINE_MODIFICATION_CAVERN ) { // look for this value in the first datamap // loop through the data description list, restoring each data desc block datamap_t *dmap = GetDataDescMap(); bool bFoundSkin = false; // search through all the readable fields in the data description, looking for a match for ( int i = 0; i < dmap->dataNumFields; ++i ) { if ( dmap->dataDesc[i].flags & (FTYPEDESC_OUTPUT | FTYPEDESC_KEY) ) { if ( !Q_stricmp(dmap->dataDesc[i].externalName, "Skin") ) { bFoundSkin = true; break; } } } if (!bFoundSkin) { // select a random skin for the mine. Actually, we'll cycle through the available skins // using a static variable to provide better distribution. The static isn't saved but // really it's only cosmetic. static unsigned int nextSkin = MINE_CITIZEN_SKIN_MIN; m_nSkin = nextSkin; // increment the skin for next time nextSkin = (nextSkin >= MINE_CITIZEN_SKIN_MAX) ? MINE_CITIZEN_SKIN_MIN : nextSkin + 1; } // pretend like the player set me down. m_bPlacedByPlayer = true; } }
//--------------------------------------------------------- //--------------------------------------------------------- void CAI_RadialLinkController::Spawn() { SetSolid( SOLID_NONE ); AddEffects( EF_NODRAW ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_GroundTurret::Spawn( void ) { Precache(); UTIL_SetModel( this, "models/combine_turrets/ground_turret.mdl" ); SetNavType( NAV_FLY ); SetSolid( SOLID_VPHYSICS ); SetBloodColor( DONT_BLEED ); m_iHealth = 125; m_flFieldOfView = cos( ((GROUNDTURRET_VIEWCONE / 2.0f) * M_PI / 180.0f) ); m_NPCState = NPC_STATE_NONE; m_vecSpread.x = 0.5; m_vecSpread.y = 0.5; m_vecSpread.z = 0.5; CapabilitiesClear(); AddEFlags( EFL_NO_DISSOLVE ); NPCInit(); CapabilitiesAdd( bits_CAP_SIMPLE_RADIUS_DAMAGE ); m_iAmmoType = GetAmmoDef()->Index( "PISTOL" ); m_pSmoke = NULL; m_bHasExploded = false; m_bEnabled = false; if( ai_newgroundturret.GetBool() ) { m_flSensingDist = 384; SetDistLook( m_flSensingDist ); } else { m_flSensingDist = 2048; } if( !GetParent() ) { DevMsg("ERROR! npc_ground_turret with no parent!\n"); UTIL_Remove(this); return; } m_flTimeNextShoot = gpGlobals->curtime; m_flTimeNextPing = gpGlobals->curtime; m_vecClosedPos = GetAbsOrigin(); StudioFrameAdvance(); Vector vecPos; GetAttachment( "eyes", vecPos ); SetViewOffset( vecPos - GetAbsOrigin() ); GetAttachment( "light", vecPos ); m_vecLightOffset = vecPos - GetAbsOrigin(); }
//----------------------------------------------------------------------------- // Purpose: Spawn the new ent //----------------------------------------------------------------------------- void CEnvHudTasklist::Spawn( void ) { Precache(); SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); }
void CRotButton::Spawn( void ) { //---------------------------------------------------- //determine sounds for buttons //a sound of 0 should not make a sound //---------------------------------------------------- if ( m_sounds ) { m_sNoise = MakeButtonSound( m_sounds ); PrecacheScriptSound(m_sNoise.ToCStr()); } else { m_sNoise = NULL_STRING; } // set the axis of rotation CBaseToggle::AxisDir(); // check for clockwise rotation if ( HasSpawnFlags( SF_DOOR_ROTATE_BACKWARDS) ) { m_vecMoveAng = m_vecMoveAng * -1; } SetMoveType( MOVETYPE_PUSH ); #ifdef HL1_DLL SetSolid( SOLID_BSP ); #else SetSolid( SOLID_VPHYSICS ); #endif if ( HasSpawnFlags( SF_ROTBUTTON_NOTSOLID ) ) { AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); AddSolidFlags( FSOLID_NOT_SOLID ); } SetModel( STRING( GetModelName() ) ); if (m_flSpeed == 0) m_flSpeed = 40; if (m_flWait == 0) m_flWait = 1; if (m_iHealth > 0) { m_takedamage = DAMAGE_YES; } m_toggle_state = TS_AT_BOTTOM; m_vecAngle1 = GetLocalAngles(); m_vecAngle2 = GetLocalAngles() + m_vecMoveAng * m_flMoveDistance; ASSERTSZ(m_vecAngle1 != m_vecAngle2, "rotating button start/end positions are equal\n"); m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE); m_fRotating = TRUE; SetUse(&CRotButton::ButtonUse); // // If touching activates the button, set its touch function. // if (!HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) { SetTouch ( NULL ); } else { SetTouch( &CRotButton::ButtonTouch ); } CreateVPhysics(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_AntlionGrub::Spawn( void ) { Precache(); SetModel( ANTLIONGRUB_MODEL ); m_NPCState = NPC_STATE_NONE; m_iHealth = sk_antliongrub_health.GetFloat(); m_iMaxHealth = m_iHealth; m_flFieldOfView = 0.5f; SetSolid( SOLID_BBOX ); SetMoveType( MOVETYPE_NONE ); SetCollisionGroup( COLLISION_GROUP_DEBRIS ); SetHullSizeNormal(); SetHullType( HULL_SMALL_CENTERED ); SetBloodColor( BLOOD_COLOR_YELLOW ); CapabilitiesClear(); m_flNextVoiceChange = gpGlobals->curtime; m_flSquashTime = gpGlobals->curtime; m_flNearTime = gpGlobals->curtime; m_flHealthTime = gpGlobals->curtime; m_flEnemyHostileTime = gpGlobals->curtime; m_bMoving = false; m_bSquashed = false; m_bSquashValid = false; m_bHealing = false; m_nHealthReserve = 10; SetTouch( GrubTouch ); // Attach to the surface under our belly AttachToSurface(); // Use detailed collision because we're an odd shape CollisionProp()->SetSurroundingBoundsType( USE_HITBOXES ); /* CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); CPASAttenuationFilter filter( this ); m_pMovementSound = controller.SoundCreate( filter, entindex(), CHAN_BODY, "NPC_Antlion.Movement", 3.9f ); m_pVoiceSound = controller.SoundCreate( filter, entindex(), CHAN_VOICE, "NPC_Antlion.Voice", 3.9f ); m_pHealSound = controller.SoundCreate( filter, entindex(), CHAN_STATIC, "NPC_Antlion.Heal", 3.9f ); controller.Play( m_pMovementSound, 0.0f, 100 ); controller.Play( m_pVoiceSound, 0.0f, 100 ); controller.Play( m_pHealSound, 0.0f, 100 ); */ m_pGlowSprite = CSprite::SpriteCreate( "sprites/blueflare1.vmt", GetLocalOrigin(), false ); Assert( m_pGlowSprite ); if ( m_pGlowSprite == NULL ) return; Vector vecUp; GetVectors( NULL, NULL, &vecUp ); m_pGlowSprite->TurnOn(); m_pGlowSprite->SetTransparency( kRenderWorldGlow, 156, 169, 121, 164, kRenderFxNoDissipation ); m_pGlowSprite->SetAbsOrigin( GetAbsOrigin() + vecUp * 8.0f ); m_pGlowSprite->SetScale( 1.0f ); m_pGlowSprite->SetGlowProxySize( 16.0f ); // We don't want to teleport at this point AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); // We get a bogus error otherwise NPCInit(); AddSolidFlags( FSOLID_TRIGGER ); }
//----------------------------------------------------------------------------- // Purpose: Called when spawning, after keyvalues have been handled. //----------------------------------------------------------------------------- void CMomentaryRotButton::Spawn( void ) { CBaseToggle::AxisDir(); m_bUpdateTarget = true; if ( m_flSpeed == 0 ) { m_flSpeed = 100; } // Clamp start position and issue bounds warning if (m_flStartPosition < 0.0 || m_flStartPosition > 1.0) { Warning("WARNING: Momentary door (%s) start position not between 0 and 1. Clamping.\n",GetDebugName()); m_flStartPosition = clamp(m_IdealYaw, 0, 1); } // Check direction fields (for backward compatibility) if (m_direction != 1 && m_direction != -1) { m_direction = 1; } if (m_flMoveDistance < 0) { m_vecMoveAng = m_vecMoveAng * -1; m_flMoveDistance = -m_flMoveDistance; } m_start = GetLocalAngles() - m_vecMoveAng * m_flMoveDistance * m_flStartPosition; m_end = GetLocalAngles() + m_vecMoveAng * m_flMoveDistance * (1-m_flStartPosition); m_IdealYaw = m_flStartPosition; // Force start direction at end points if (m_flStartPosition == 0.0) { m_direction = -1; } else if (m_flStartPosition == 1.0) { m_direction = 1; } if (HasSpawnFlags(SF_BUTTON_LOCKED)) { m_bLocked = true; } if ( HasSpawnFlags( SF_BUTTON_USE_ACTIVATES ) ) { if ( m_sounds ) { m_sNoise = MakeButtonSound( m_sounds ); PrecacheScriptSound(m_sNoise.ToCStr()); } else { m_sNoise = NULL_STRING; } m_lastUsed = 0; UpdateTarget(0,this); } #ifdef HL1_DLL SetSolid( SOLID_BSP ); #else SetSolid( SOLID_VPHYSICS ); #endif if (HasSpawnFlags(SF_ROTBUTTON_NOTSOLID)) { AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); AddSolidFlags( FSOLID_NOT_SOLID ); } SetMoveType( MOVETYPE_PUSH ); SetModel( STRING( GetModelName() ) ); CreateVPhysics(); // Slam the object back to solid - if we really want it to be solid. if ( m_bSolidBsp ) { SetSolid( SOLID_BSP ); } m_bDisabled = false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void QUA_helicopter::Spawn( void ) { m_aimYaw = 0; m_aimPitch = 0; m_bSuppressSound = false; m_flSiguienteAtaque=gpGlobals->curtime; m_flSiguienteSummon=gpGlobals->curtime; Precache(); SetModel(HELI_MODEL); //SetVehicleType( VEHICLE_TYPE_CAR_RAYCAST ); BaseClass::Spawn(); SetCollisionGroup(COLLISION_GROUP_VEHICLE); m_flSequenceTime=gpGlobals->curtime+4.0f; m_flNextShootingTime=gpGlobals->curtime; aux=true; m_iAmmoType = GetAmmoDef()->Index("StriderMinigun"); m_bInhelicopter=false; m_bhelicopterTurbo=false; acl=0; aclizq=0; aclder=0; //SetBlocksLOS( true ); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_FLY ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); m_iCaps = FCAP_IMPULSE_USE; // SetBloodColor( BLOOD_COLOR_YELLOW ); UTIL_SetSize(this,Vector(-220,-40,-80),Vector(170, 40, 40)); //See if we're supposed to start burrowed // Do not dissolve //AddEFlags( EFL_NO_DISSOLVE ); // We get a minute of free knowledge about the target // We need to bloat the absbox to encompass all the hitboxes /*Vector absMin = -Vector(100,100,0); Vector absMax = Vector(100,100,128); CollisionProp()->SetSurroundingBoundsType( USE_SPECIFIED_BOUNDS, &absMin, &absMax ); */InitializeRotorSound(); m_iHealth=500; // Indispensable para que sea vulnerable m_takedamage = DAMAGE_YES; m_iAmmoCount=40; m_iCannonCount=100; m_fReloadTime=gpGlobals->curtime+0.5f; m_fCannonCharge=gpGlobals->curtime+0.05f; m_vOriginalSpawnOrigin = GetAbsOrigin(); m_vOriginalSpawnAngles = GetAbsAngles(); m_flRespawnTime=gpGlobals->curtime+7.0f; m_bSpawn=false; SetActivity( ACT_IDLE ); SetThink(&QUA_helicopter::Think); SetNextThink(gpGlobals->curtime); Vector maxcull,mincull; ExtractBbox(SelectHeaviestSequence(ACT_IDLE),maxcull,mincull); //CollisionProp()->SetSurroundingBoundsType( USE_BEST_COLLISION_BOUNDS ); }
//----------------------------------------------------------------------------- // Place the canister in the world //----------------------------------------------------------------------------- CSkyCamera *CEnvHeadcrabCanister::PlaceCanisterInWorld() { CSkyCamera *pCamera = NULL; // Are we launching from a point? If so, use that point. if ( m_iszLaunchPositionName != NULL_STRING ) { // Get the launch position entity CBaseEntity *pLaunchPos = gEntList.FindEntityByName( NULL, m_iszLaunchPositionName ); if ( !pLaunchPos ) { Warning("%s (%s) could not find an entity matching LaunchPositionName of '%s'\n", GetEntityName().ToCStr(), GetDebugName(), STRING(m_iszLaunchPositionName) ); SUB_Remove(); } else { SetupWorldModel(); Vector vecForward, vecImpactDirection; GetVectors( &vecForward, NULL, NULL ); VectorMultiply( vecForward, -1.0f, vecImpactDirection ); m_Shared.InitInWorld( gpGlobals->curtime, pLaunchPos->GetAbsOrigin(), GetAbsAngles(), vecImpactDirection, m_vecImpactPosition, true ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } else if ( DetectInSkybox() ) { pCamera = GetEntitySkybox(); SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); SetSolid( SOLID_NONE ); Vector vecForward; GetVectors( &vecForward, NULL, NULL ); vecForward *= -1.0f; m_Shared.InitInSkybox( gpGlobals->curtime, m_vecImpactPosition, GetAbsAngles(), vecForward, m_vecImpactPosition, pCamera->m_skyboxData.origin, pCamera->m_skyboxData.scale ); AddEFlags( EFL_IN_SKYBOX ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxOnlyThink ); SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() + TICK_INTERVAL ); } else { Vector vecStartPosition, vecDirection; QAngle vecStartAngles; ComputeWorldEntryPoint( &vecStartPosition, &vecStartAngles, &vecDirection ); // Figure out which skybox to place the entity in. pCamera = GetCurrentSkyCamera(); if ( pCamera ) { m_Shared.InitInSkybox( gpGlobals->curtime, vecStartPosition, vecStartAngles, vecDirection, m_vecImpactPosition, pCamera->m_skyboxData.origin, pCamera->m_skyboxData.scale ); if ( m_Shared.IsInSkybox() ) { SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); SetSolid( SOLID_NONE ); AddEFlags( EFL_IN_SKYBOX ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxThink ); SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() ); } else { SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } else { m_Shared.InitInWorld( gpGlobals->curtime, vecStartPosition, vecStartAngles, vecDirection, m_vecImpactPosition ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } Vector vecEndPosition; QAngle vecEndAngles; m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles ); SetAbsOrigin( vecEndPosition ); SetAbsAngles( vecEndAngles ); return pCamera; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CFuncLadder::Spawn() { BaseClass::Spawn(); // Entity is symbolid SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); SetCollisionGroup( COLLISION_GROUP_NONE ); //AddFlag( FL_WORLDBRUSH ); SetModelName( NULL_STRING ); // Make entity invisible AddEffects( EF_NODRAW ); // No model but should still network AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); Vector playerMins = VEC_HULL_MIN; Vector playerMaxs = VEC_HULL_MAX; // This will swap them if they are inverted SetEndPoints( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionBottom ); #if !defined( CLIENT_DLL ) trace_t bottomtrace, toptrace; UTIL_TraceHull( m_vecPlayerMountPositionBottom, m_vecPlayerMountPositionBottom, playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &bottomtrace ); UTIL_TraceHull( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionTop, playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &toptrace ); if ( bottomtrace.startsolid || toptrace.startsolid ) { if ( bottomtrace.startsolid ) { DevMsg( 1, "Warning, funcladder with blocked bottom point (%.2f %.2f %.2f) stuck in (%s)\n", m_vecPlayerMountPositionBottom.GetX(), m_vecPlayerMountPositionBottom.GetY(), m_vecPlayerMountPositionBottom.GetZ(), bottomtrace.m_pEnt ? UTIL_VarArgs( "%s/%s", bottomtrace.m_pEnt->GetClassname(), bottomtrace.m_pEnt->GetEntityName().ToCStr() ) //UTIL_VarArgs( "%s/%s", bottomtrace.m_pEnt->GetClassname(), STRING(bottomtrace.m_pEnt->GetEntityName()) ) ? : "NULL" ); } if ( toptrace.startsolid ) { DevMsg( 1, "Warning, funcladder with blocked top point (%.2f %.2f %.2f) stuck in (%s)\n", m_vecPlayerMountPositionTop.GetX(), m_vecPlayerMountPositionTop.GetY(), m_vecPlayerMountPositionTop.GetZ(), toptrace.m_pEnt ? UTIL_VarArgs( "%s/%s", toptrace.m_pEnt->GetClassname(), toptrace.m_pEnt->GetEntityName().ToCStr() ) //UTIL_VarArgs( "%s/%s", toptrace.m_pEnt->GetClassname(), STRING(toptrace.m_pEnt->GetEntityName()) ) ? : "NULL" ); } // Force geometry overlays on, but only if developer 2 is set... if ( developer.GetInt() > 1 ) { m_debugOverlays |= OVERLAY_TEXT_BIT; } } m_vecPlayerMountPositionTop -= GetAbsOrigin(); m_vecPlayerMountPositionBottom -= GetAbsOrigin(); // Compute mins, maxs of points // Vector mins( MAX_COORD_INTEGER, MAX_COORD_INTEGER, MAX_COORD_INTEGER ); Vector maxs( -MAX_COORD_INTEGER, -MAX_COORD_INTEGER, -MAX_COORD_INTEGER ); int i; for ( i = 0; i < 3; i++ ) { if ( m_vecPlayerMountPositionBottom.m_Value[ i ] < mins[ i ] ) { mins[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ]; } if ( m_vecPlayerMountPositionBottom.m_Value[ i ] > maxs[ i ] ) { maxs[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ]; } if ( m_vecPlayerMountPositionTop.m_Value[ i ] < mins[ i ] ) { mins[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ]; } if ( m_vecPlayerMountPositionTop.m_Value[ i ] > maxs[ i ] ) { maxs[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ]; } } // Expand mins/maxs by player hull size mins += playerMins; maxs += playerMaxs; UTIL_SetSize( this, mins, maxs ); m_bFakeLadder = HasSpawnFlags(SF_LADDER_DONTGETON); #endif }
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType ) { #if !defined( CLIENT_DLL ) SetModelName( NULL_STRING );//invisible AddSolidFlags( FSOLID_NOT_SOLID ); m_takedamage = DAMAGE_NO; // Pull out of the wall a bit if ( pTrace->fraction != 1.0 ) { SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) ); } Vector vecAbsOrigin = GetAbsOrigin(); int contents = UTIL_PointContents ( vecAbsOrigin ); #if defined( TF_DLL ) // Since this code only runs on the server, make sure it shows the tempents it creates. // This solves a problem with remote detonating the pipebombs (client wasn't seeing the explosion effect) CDisablePredictionFiltering disabler; #endif if ( pTrace->fraction != 1.0 ) { Vector vecNormal = pTrace->plane.normal; surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps ); CPASFilter filter( vecAbsOrigin ); te->Explosion( filter, -1.0, // don't apply cl_interp delay &vecAbsOrigin, !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion, m_DmgRadius * .03, 25, TE_EXPLFLAG_NONE, m_DmgRadius, m_flDamage, &vecNormal, (char) pdata->game.material ); } else { CPASFilter filter( vecAbsOrigin ); te->Explosion( filter, -1.0, // don't apply cl_interp delay &vecAbsOrigin, !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion, m_DmgRadius * .03, 25, TE_EXPLFLAG_NONE, m_DmgRadius, m_flDamage ); } #if !defined( CLIENT_DLL ) CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 ); #endif // Use the thrower's position as the reported position Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin; CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported ); RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); UTIL_DecalTrace( pTrace, "Scorch" ); EmitSound( "BaseGrenade.Explode" ); SetThink( &CBaseGrenade::SUB_Remove ); SetTouch( NULL ); SetSolid( SOLID_NONE ); AddEffects( EF_NODRAW ); SetAbsVelocity( vec3_origin ); #if HL2_EPISODIC // Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for // the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and // throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes // intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not // hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound) // before the env_microphone thinks and hears the sound. SetNextThink( gpGlobals->curtime + 0.1 ); #else SetNextThink( gpGlobals->curtime ); #endif//HL2_EPISODIC #if defined( HL2_DLL ) CBasePlayer *pPlayer = ToBasePlayer( m_hThrower.Get() ); if ( pPlayer ) { gamestats->Event_WeaponHit( pPlayer, true, "weapon_frag", info ); } #endif #endif }
//----------------------------------------------------------------------------- // Purpose: // NOTE: Doesn't call the base call enter vehicle on purpose! //----------------------------------------------------------------------------- void CPropVehicleManhack::EnterVehicle( CBaseCombatCharacter *pPassenger ) { if ( pPassenger == NULL ) return; DevMsg("CPropVehicleManhack: EnterVehicl(...)\n"); CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); if ( pPlayer != NULL ) { // Remove any player who may be in the vehicle at the moment if ( m_hPlayer ) { ExitVehicle( VEHICLE_ROLE_DRIVER ); } m_hPlayer = pPlayer; m_bHadDriver = true; if (GetNumberOfHacks(false)>1 && m_iHintTimesShown < 2) { m_iHintTimesShown++; m_iHintNoSwapTimesShown++; UTIL_HudHintText( pPlayer, "#HLSS_Hint_ManhackSwap" ); } else if (m_iHintNoSwapTimesShown < 2) { m_iHintNoSwapTimesShown++; UTIL_HudHintText( pPlayer, "#HLSS_Hint_ManhackExit" ); } else UTIL_HudHintText( pPlayer, "" ); pPlayer->SetViewOffset( vec3_origin ); pPlayer->ShowCrosshair( false ); CHL2_Player *pHL2Player = dynamic_cast<CHL2_Player*>( pPlayer ); if ( pHL2Player ) { if ( pHL2Player->IsSprinting() ) { pHL2Player->StopSprinting(); } if ( pHL2Player->FlashlightIsOn() ) { pHL2Player->FlashlightTurnOff(); } } CNPC_Manhack *pManhack = dynamic_cast<CNPC_Manhack*>((CBaseEntity*)m_hManhack); if (pManhack!=NULL) { pManhack->SetControllable(true); if (manhack_dont_draw.GetBool()) { pManhack->AddEffects( EF_NODRAW ); pManhack->ShowRedGlow(false); } m_vecLastEyeTarget = pManhack->GetManhackView(); m_vecLastEyePos = pManhack->GetManhackView(); m_vecTargetSpeed = pManhack->GetAbsVelocity(); m_vecFlyingDirection = pManhack->GetAbsVelocity(); } //We want to see and feel the "vehicle" in manhack mode //SetRenderMode(kRenderNormal); RemoveEffects( EF_NODRAW ); SetSolid(SOLID_BBOX); RemoveSolidFlags( FSOLID_NOT_SOLID ); if (m_bDriverDucked) { SetCollisionBounds( Vector(-16,-16,0), Vector(16,16,45) ); int nSequence = LookupSequence( "crouch" ); DevMsg("Player is ducking\n"); // Set to the desired anim, or default anim if the desired is not present if ( nSequence > ACTIVITY_NOT_AVAILABLE ) { SetCycle( 0 ); m_flAnimTime = gpGlobals->curtime; ResetSequence( nSequence ); ResetClientsideFrame(); } else { // Not available try to get default anim Msg( "Manhack Controller %s: missing crouch sequence\n", GetDebugName() ); SetSequence( 0 ); } } else { SetCollisionBounds( Vector(-16,-16,0), Vector(16,16,72) ); int nSequence = LookupSequence( "idle" ); // Set to the desired anim, or default anim if the desired is not present if ( nSequence > ACTIVITY_NOT_AVAILABLE ) { SetCycle( 0 ); m_flAnimTime = gpGlobals->curtime; ResetSequence( nSequence ); ResetClientsideFrame(); } } // Start Thinking SetNextThink( gpGlobals->curtime ); } else { // NPCs not yet supported - jdw Assert( 0 ); } }
void CRuleEntity::Spawn( void ) { SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); AddEffects( EF_NODRAW ); }
//----------------------------------------------------------------------------- // Spawn //----------------------------------------------------------------------------- void CNPC_Breen::Spawn() { // Breen is allowed to use multiple models, because he has a torso version for monitors. // He defaults to his normal model. char *szModel = (char *)STRING( GetModelName() ); if (!szModel || !*szModel) { szModel = "models/breen.mdl"; SetModelName( AllocPooledString(szModel) ); } Precache(); SetModel( szModel ); BaseClass::Spawn(); SetHullType(HULL_HUMAN); SetHullSizeNormal(); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_STEP ); SetBloodColor( BLOOD_COLOR_RED ); m_iHealth = 8; m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) m_NPCState = NPC_STATE_NONE; CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); NPCInit(); DevMsg("Spawning Breen\n"); m_faceAPI = GetFaceAPI(); // head orientation m_poses.push_back(new DrivenFeature(this, POSE_YAW)); m_poses.push_back(new DrivenFeature(this, POSE_PITCH)); m_poses.push_back(new DrivenFeature(this, POSE_ROLL)); // blink m_flexors.push_back(new DrivenFeature(this, RIGHT_LID_CLOSER)); m_flexors.push_back(new DrivenFeature(this, LEFT_LID_CLOSER)); // right eyebrow m_flexors.push_back(new DrivenFeature(this, RIGHT_INNER_RAISER)); m_flexors.push_back(new DrivenFeature(this, RIGHT_OUTER_RAISER)); m_flexors.push_back(new DrivenFeature(this, RIGHT_LOWERER)); // left eyebrow m_flexors.push_back(new DrivenFeature(this, LEFT_INNER_RAISER)); m_flexors.push_back(new DrivenFeature(this, LEFT_OUTER_RAISER)); m_flexors.push_back(new DrivenFeature(this, LEFT_LOWERER)); // horizontal mouth movement m_flexors.push_back(new DrivenFeature(this, RIGHT_CORNER_PULLER)); m_flexors.push_back(new DrivenFeature(this, RIGHT_PUCKERER)); m_flexors.push_back(new DrivenFeature(this, LEFT_CORNER_PULLER)); m_flexors.push_back(new DrivenFeature(this, LEFT_PUCKERER)); // vertical mouth movement m_flexors.push_back(new DrivenFeature(this, RIGHT_UPPER_RAISER)); m_flexors.push_back(new DrivenFeature(this, RIGHT_CORNER_DEPRESSOR)); m_flexors.push_back(new DrivenFeature(this, LEFT_UPPER_RAISER)); m_flexors.push_back(new DrivenFeature(this, LEFT_CORNER_DEPRESSOR)); // overall mouth movements m_flexors.push_back(new DrivenFeature(this, MOUTH_STRETCH)); //m_flexors.push_back(new DrivenFeature(this, SMILE)); m_lastThink = engine->Time(); m_adaptive_p = 1.0f; m_lastTrackingTime = 0.0f; m_smileFlex = FindFlexController("smile"); m_smileAmount = 0.0f; m_nextSmilePick = 0.0f; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseViewModel::Spawn( void ) { Precache( ); SetSize( Vector( -8, -4, -2), Vector(8, 4, 2) ); SetSolid( SOLID_NONE ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseDoor::Spawn() { Precache(); #ifdef HL1_DLL SetSolid( SOLID_BSP ); #else if ( GetMoveParent() && GetRootMoveParent()->GetSolid() == SOLID_BSP ) { SetSolid( SOLID_BSP ); } else { SetSolid( SOLID_VPHYSICS ); } #endif // Convert movedir from angles to a vector QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); AngleVectors( angMoveDir, &m_vecMoveDir ); SetModel( STRING( GetModelName() ) ); m_vecPosition1 = GetLocalOrigin(); // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big Vector vecOBB = CollisionProp()->OBBSize(); vecOBB -= Vector( 2, 2, 2 ); m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecOBB ) - m_flLip)); if ( !IsRotatingDoor() ) { if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) || HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) { // swap pos1 and pos2, put door at pos2 UTIL_SetOrigin( this, m_vecPosition2); m_toggle_state = TS_AT_TOP; } else { m_toggle_state = TS_AT_BOTTOM; } } if (HasSpawnFlags(SF_DOOR_LOCKED)) { m_bLocked = true; } SetMoveType( MOVETYPE_PUSH ); if (m_flSpeed == 0) { m_flSpeed = 100; } SetTouch( &CBaseDoor::DoorTouch ); if ( !FClassnameIs( this, "func_water" ) ) { if ( HasSpawnFlags(SF_DOOR_PASSABLE) ) { //normal door AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); AddSolidFlags( FSOLID_NOT_SOLID ); } if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) { SetCollisionGroup( COLLISION_GROUP_PASSABLE_DOOR ); // HACKHACK: Set this hoping that any children of the door that get blocked by the player // will get fixed up by vphysics // NOTE: We could decouple this as a separate behavior, but managing player collisions is already complex enough. // NOTE: This is necessary to prevent the player from blocking the wrecked train car in ep2_outland_01 AddFlag( FL_UNBLOCKABLE_BY_PLAYER ); } if ( m_bIgnoreDebris ) { // both of these flags want to set the collision group and // there isn't a combo group Assert( !HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ); if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) { Warning("Door %s with conflicting collision settings, removing ignoredebris\n", GetDebugName() ); } else { SetCollisionGroup( COLLISION_GROUP_INTERACTIVE ); } } } if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) && HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) { Warning("Door %s using obsolete 'Start Open' spawnflag with 'Spawn Position' set to 'Open'. Reverting to old behavior.\n", GetDebugName() ); } CreateVPhysics(); }
bool CStatueProp::CreateVPhysicsFromHitBoxes( CBaseAnimating *pInitBaseAnimating ) { if ( !pInitBaseAnimating ) return false; // Use the current animation sequence and cycle CopyAnimationDataFrom( pInitBaseAnimating ); // Copy over any render color color24 colorRender = pInitBaseAnimating->GetRenderColor(); SetRenderColor( colorRender.r, colorRender.g, colorRender.b ); SetRenderAlpha( pInitBaseAnimating->GetRenderAlpha() ); // Get hitbox data CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) return false; mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set ) return false; Vector position; QAngle angles; // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ set->numhitboxes ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < set->numhitboxes; i++ ) { // Get the hitbox info mstudiobbox_t *pbox = set->pHitbox( i ); GetBonePosition( pbox->bone, position, angles ); // Accumulate volume and area Vector flDimentions = pbox->bbmax - pbox->bbmin; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pbox->bbmin, angles, vecMins ); VectorRotate( pbox->bbmax, angles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = position + vecMins; Vector vecMaxCorner = position + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( angles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, set->numhitboxes ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); if ( pInitBaseAnimating != this ) { // Transfer children from the init base animating TransferChildren( pInitBaseAnimating, this ); CBaseEntity *pChild = FirstMoveChild(); while ( pChild ) { CEntityFreezing *pFreezing = dynamic_cast<CEntityFreezing*>( pChild ); if ( pFreezing ) { pFreezing->FinishFreezing(); } pChild = pChild->NextMovePeer(); } } return true; }
void CBaseButton::Spawn( ) { //---------------------------------------------------- //determine sounds for buttons //a sound of 0 should not make a sound //---------------------------------------------------- if ( m_sounds ) { m_sNoise = MakeButtonSound( m_sounds ); PrecacheScriptSound(m_sNoise.ToCStr()); } else { m_sNoise = NULL_STRING; } Precache(); if ( HasSpawnFlags( SF_BUTTON_SPARK_IF_OFF ) )// this button should spark in OFF state { SetThink ( &CBaseButton::ButtonSpark ); SetNextThink( gpGlobals->curtime + 0.5f );// no hurry, make sure everything else spawns } // Convert movedir from angles to a vector QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); AngleVectors( angMoveDir, &m_vecMoveDir ); SetMoveType( MOVETYPE_PUSH ); SetSolid( SOLID_BSP ); SetModel( STRING( GetModelName() ) ); if (m_flSpeed == 0) { m_flSpeed = 40; } m_takedamage = DAMAGE_YES; if (m_flWait == 0) { m_flWait = 1; } if (m_flLip == 0) { m_flLip = 4; } m_toggle_state = TS_AT_BOTTOM; m_vecPosition1 = GetLocalOrigin(); // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big Vector vecButtonOBB = CollisionProp()->OBBSize(); vecButtonOBB -= Vector( 2, 2, 2 ); m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecButtonOBB ) - m_flLip)); // Is this a non-moving button? if ( ((m_vecPosition2 - m_vecPosition1).Length() < 1) || HasSpawnFlags(SF_BUTTON_DONTMOVE) ) { m_vecPosition2 = m_vecPosition1; } m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE); m_fRotating = FALSE; if (HasSpawnFlags(SF_BUTTON_LOCKED)) { m_bLocked = true; } // // If using activates the button, set its use function. // if (HasSpawnFlags(SF_BUTTON_USE_ACTIVATES)) { SetUse(&CBaseButton::ButtonUse); } else { SetUse(NULL); } // // If touching activates the button, set its touch function. // if (HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) { SetTouch( &CBaseButton::ButtonTouch ); } else { SetTouch ( NULL ); } CreateVPhysics(); }
// Landmark class void CPointEntity::Spawn( void ) { SetSolid( SOLID_NONE ); // UTIL_SetSize(this, vec3_origin, vec3_origin); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CObjectSapper::OnGoActive( void ) { // set new model CBaseObject *pObject = dynamic_cast<CBaseObject *>( m_hBuiltOnEntity.Get() ); Assert( pObject ); if ( !pObject ) { DestroyObject(); return; } switch( pObject->GetType() ) { case OBJ_SENTRYGUN: { // what level? CObjectSentrygun *pSentry = dynamic_cast<CObjectSentrygun *>( pObject ); Assert( pSentry ); if ( !pSentry ) { DestroyObject(); return; } int iLevel = pSentry->GetUpgradeLevel(); switch( iLevel ) { case 1: SetModel( SAPPER_MODEL_SENTRY_1 ); break; case 2: SetModel( SAPPER_MODEL_SENTRY_2 ); break; case 3: SetModel( SAPPER_MODEL_SENTRY_3 ); break; default: Assert(0); break; } } break; case OBJ_TELEPORTER: SetModel( SAPPER_MODEL_TELEPORTER ); break; case OBJ_DISPENSER: SetModel( SAPPER_MODEL_DISPENSER ); break; default: Assert( !"what kind of object are we trying to place a sapper on?" ); break; } UTIL_SetSize( this, SAPPER_MINS, SAPPER_MAXS ); SetSolid( SOLID_NONE ); BaseClass::OnGoActive(); }