void FlagObject::ReturnToFlagStand() { // If we're already in our flag stand, just return... if (m_bInStand) return; // Set our "stand" position... DRotation rTemp; g_pServerDE->SetupEuler(&rTemp, 1, 1, 1); g_pServerDE->SetObjectRotation(m_hObject, &rTemp); g_pServerDE->SetObjectPos(m_hObject, &m_vStand); g_pServerDE->SetObjectRotation(m_hObject, &m_rStand); // Play a cool respawn sound... char* sSound = "sounds_multipatch\\CtfFlagRespawn.WAV"; PlaySoundFromPos(&m_vStand, sSound, 2000.0f, SOUNDPRIORITY_MISC_MEDIUM, DFALSE, DFALSE, DFALSE); // Flag that we are back in our stand... m_bInStand = DTRUE; m_bOnGround = DFALSE; m_bWithPlayer = DFALSE; }
void PickupObject::PickedUp (HMESSAGEREAD hRead) { // get the override respawn time - if it's -1.0, use the default float nRespawn = g_pServerDE->ReadFromMessageFloat (hRead); if (nRespawn == -1.0f) nRespawn = m_fRespawnTime; // make the item invisible for the correct amount of time DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hObject); g_pServerDE->SetObjectFlags(m_hObject, dwFlags & ~FLAG_VISIBLE & ~FLAG_TOUCH_NOTIFY ); if( nRespawn <= 0.0f || g_pBloodServerShell->GetGameType() == GAMETYPE_SINGLE) g_pServerDE->RemoveObject( m_hObject ); else g_pServerDE->SetNextUpdate(m_hObject, (DFLOAT) nRespawn); // Let the world know what happened... if (m_szPickupSound) { DVector vPos; g_pServerDE->GetObjectPos( m_hObject, &vPos ); PlaySoundFromPos( &vPos, m_szPickupSound, 300.0f, SOUNDPRIORITY_MISC_HIGH); } // if we're supposed to trigger something, trigger it here if (m_hstrPickupTriggerTarget && m_hstrPickupTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrPickupTriggerTarget, m_hstrPickupTriggerMessage); } }
DDWORD Cat::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead) { switch(messageID) { case MID_DAMAGE: { CServerDE* pServerDE = GetServerDE(); if (!pServerDE) break; DVector vDir; pServerDE->ReadFromMessageVector(hRead, &vDir); DFLOAT fDamage = pServerDE->ReadFromMessageFloat(hRead); DamageType eType = (DamageType)pServerDE->ReadFromMessageByte(hRead); HOBJECT hHeHitMe = pServerDE->ReadFromMessageObject(hRead); if (eType == DT_SQUEAKY) { if (m_hstrSqueakedAtSound) { char* pSound = pServerDE->GetStringData(m_hstrSqueakedAtSound); if (pSound) PlaySoundFromObject(m_hObject, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM ); } // If we're supposed to trigger something, trigger it here if (m_hstrSqueakyTarget && m_hstrSqueakyMessage) { SendTriggerMsgToObjects(this, m_hstrSqueakyTarget, m_hstrSqueakyMessage); } } else { if (m_hstrDeathSound) { DVector vPos; pServerDE->GetObjectPos(m_hObject, &vPos); char* pSound = pServerDE->GetStringData(m_hstrDeathSound); if (pSound) PlaySoundFromPos(&vPos, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM ); } if (m_hstrDeathTriggerTarget && m_hstrDeathTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrDeathTriggerTarget, m_hstrDeathTriggerMessage); } pServerDE->RemoveObject(m_hObject); } break; } default : break; } return InventoryItem::ObjectMessageFn(hSender, messageID, hRead); }
void Explosion::CreateExplosion(DVector *pvPos) { if (!g_pServerDE) return; ObjectCreateStruct ocStruct; INIT_OBJECTCREATESTRUCT(ocStruct); ocStruct.m_Flags = FLAG_VISIBLE; VEC_COPY(ocStruct.m_Pos, *pvPos); // DRotation rRot; // g_pServerDE->GetObjectRotation(m_hObject, &rRot); // ROT_COPY(ocStruct.m_Rotation, rRot); DFLOAT fPitch = g_pServerDE->Random(-MATH_PI, MATH_PI); DFLOAT fYaw = g_pServerDE->Random(-MATH_PI, MATH_PI); DFLOAT fRoll = g_pServerDE->Random(-MATH_PI, MATH_PI); g_pServerDE->SetupEuler(&ocStruct.m_Rotation, fPitch, fYaw, fRoll); if (m_hstrModelName) _mbscpy((unsigned char*)ocStruct.m_Filename, (const unsigned char*)g_pServerDE->GetStringData(m_hstrModelName)); else _mbscpy((unsigned char*)ocStruct.m_Filename, (const unsigned char*)szDefExplosionModel ); if (m_hstrSkinName) _mbscpy((unsigned char*)ocStruct.m_SkinName, (const unsigned char*)g_pServerDE->GetStringData(m_hstrSkinName)); else _mbscpy((unsigned char*)ocStruct.m_SkinName, (const unsigned char*)szDefExplosionSkin ); // Create the explosion model HCLASS hClass = g_pServerDE->GetClass("CModelObject"); if (!hClass) return; CModelObject* pImpact = (CModelObject*)g_pServerDE->CreateObject(hClass, &ocStruct); if (!pImpact) return; // Initialize the object... pImpact->Setup(m_fDuration, &m_vRotation, DFALSE, DTRUE); m_hModel = pImpact->m_hObject; // Gouraud shade and make full bright... DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hModel); g_pServerDE->SetObjectFlags(m_hModel, dwFlags | FLAG_MODELGOURAUDSHADE | FLAG_NOLIGHT); g_pServerDE->SetObjectColor(m_hModel, 1.0f, 1.0f, 1.0f, 1.0f); if (m_bCreateLight) CreateLight(pvPos); if (m_bCreateShockwave) AddShockwave(pvPos); if (m_bCreateMark) CreateMark(pvPos); if (m_bCreateSmoke) CreateSmoke(pvPos); // CreateFX(pvPos); // Play sound DVector vPos; g_pServerDE->GetObjectPos(m_hObject, &vPos); if ( m_hstrSound ) { char* pSound = g_pServerDE->GetStringData(m_hstrSound); if (pSound) PlaySoundFromPos(&vPos, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_HIGH ); } }
void CClientExplosionSFX::SetupFX() { CServerDE* pServerDE = GetServerDE(); if (!pServerDE) return; HMESSAGEWRITE hMessage = pServerDE->StartInstantSpecialEffectMessage(&m_vPos); pServerDE->WriteToMessageByte(hMessage, SFX_EXPLOSIONFX_ID); pServerDE->WriteToMessageVector(hMessage, &m_vPos); pServerDE->WriteToMessageVector(hMessage, &m_vNormal); pServerDE->WriteToMessageDWord(hMessage, m_nType); pServerDE->EndMessage(hMessage); DamageObjectsInRadius(m_hObject, NULL, m_vPos, m_fDamageRadius, m_fDamage); if (m_hstrSound) PlaySoundFromPos(&m_vPos, pServerDE->GetStringData(m_hstrSound), 1000.0f, SOUNDPRIORITY_MISC_HIGH ); }
void CProjectile::AddExplosion(DVector vPos, DVector vNormal) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; DDWORD nType = EXP_GRENADE; DVector vUp; VEC_SET(vUp, 0.0f, 1.0f, 0.0f); HMESSAGEWRITE hMessage = pServerDE->StartInstantSpecialEffectMessage(&vPos); pServerDE->WriteToMessageByte(hMessage, SFX_EXPLOSIONFX_ID); pServerDE->WriteToMessageVector(hMessage, &vPos); pServerDE->WriteToMessageVector(hMessage, &vUp); pServerDE->WriteToMessageDWord(hMessage, nType); pServerDE->EndMessage2(hMessage, MESSAGE_GUARANTEED | MESSAGE_NAGGLEFAST); PlaySoundFromPos(&vPos, "Sounds\\Weapons\\c4\\explosion_1.wav", 1000.0f, SOUNDPRIORITY_MISC_MEDIUM); }
void CDebris::AddExplosion(DVector &vPos) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; DDWORD nType = EXP_GRENADE; DVector vUp; VEC_SET(vUp, 0.0f, 1.0f, 0.0f); HMESSAGEWRITE hMessage = pServerDE->StartInstantSpecialEffectMessage(&vPos); pServerDE->WriteToMessageByte(hMessage, SFX_EXPLOSIONFX_ID); pServerDE->WriteToMessageVector(hMessage, &vPos); pServerDE->WriteToMessageVector(hMessage, &vUp); pServerDE->WriteToMessageDWord(hMessage, nType); pServerDE->EndMessage(hMessage); PlaySoundFromPos(&vPos, "Sounds\\Weapons\\c4\\explosion_1.wav", 1000.0f, SOUNDPRIORITY_MISC_MEDIUM); // Do some damage if (m_fExplodeDamage && m_fDamageRadius) DamageObjectsInRadius(m_hObject, pServerDE->HandleToObject(m_hObject), vPos, m_fDamageRadius, m_fExplodeDamage, DAMAGE_TYPE_EXPLODE); }
DBOOL CShellCasingFX::Update() { if (!m_hObject || !m_pClientDE) return DFALSE; if (m_pClientDE->GetTime() > m_fExpireTime) return DFALSE; if (m_bInVisible) { m_bInVisible = DFALSE; m_pClientDE->SetObjectFlags(m_hObject, FLAG_VISIBLE); } if (m_bResting) return DTRUE; DRotation rRot; // If velocity slows enough, and we're on the ground, just stop bouncing and just wait to expire. if (m_movingObj.m_PhysicsFlags & MO_RESTING) { m_bResting = DTRUE; // Stop the spinning... m_pClientDE->SetupEuler(&rRot, 0, m_fYaw, 0); m_pClientDE->SetObjectRotation(m_hObject, &rRot); /* // Shell is at rest, we can add a check here to see if we really want // to keep it around depending on detail settings... HLOCALOBJ hObjs[1]; DDWORD nNumFound, nBogus; m_pClientDE->FindObjectsInSphere(&m_movingObj.m_Pos, 64.0f, hObjs, 1, &nBogus, &nNumFound); // Remove thyself... if (nNumFound > 15) return DFALSE; */ } else { if (m_fPitchVel != 0 || m_fYawVel != 0) { DFLOAT fDeltaTime = m_pClientDE->GetFrameTime(); m_fPitch += m_fPitchVel * fDeltaTime; m_fYaw += m_fYawVel * fDeltaTime; m_pClientDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f); m_pClientDE->SetObjectRotation(m_hObject, &rRot); } } DVector vNewPos; if (UpdateMovingObject(DNULL, &m_movingObj, &vNewPos)) { ClientIntersectInfo info; SurfaceType eType = SURFTYPE_UNKNOWN; if (BounceMovingObject(DNULL, &m_movingObj, &vNewPos, &info, &eType)) { if (m_nBounceCount > 0) { char sType[10]; char sFile[MAX_CS_FILENAME_LEN]; switch(eType) { // case SURFTYPE_FLESH: _mbscpy((unsigned char*)sType, (const unsigned char*)"Flesh"); break; case SURFTYPE_GLASS: _mbscpy((unsigned char*)sType, (const unsigned char*)"Glass"); break; case SURFTYPE_METAL: _mbscpy((unsigned char*)sType, (const unsigned char*)"Metal"); break; case SURFTYPE_PLASTIC: _mbscpy((unsigned char*)sType, (const unsigned char*)"Plastic"); break; case SURFTYPE_TERRAIN: _mbscpy((unsigned char*)sType, (const unsigned char*)"Terrain"); break; case SURFTYPE_LIQUID: _mbscpy((unsigned char*)sType, (const unsigned char*)"Water"); break; case SURFTYPE_WOOD: _mbscpy((unsigned char*)sType, (const unsigned char*)"Wood"); break; case SURFTYPE_STONE: default: _mbscpy((unsigned char*)sType, (const unsigned char*)"Stone"); break; } sprintf(sFile, "Sounds\\Weapons\\ShellDrops\\%s\\Shell%d.wav", sType, GetRandom(1, 2)); PlaySoundFromPos(&vNewPos, sFile, 150.0f, SOUNDPRIORITY_MISC_LOW); } // Adjust the bouncing.. m_fPitchVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_fYawVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_nBounceCount--; if (m_nBounceCount <= 0) { m_movingObj.m_PhysicsFlags |= MO_RESTING; } } VEC_COPY(m_movingObj.m_Pos, vNewPos); if (m_pClientDE->GetPointStatus(&vNewPos) == DE_OUTSIDE) { return DFALSE; } m_pClientDE->SetObjectPos(m_hObject, &vNewPos); } return DTRUE; }
LTBOOL CParticleExplosionFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (!CBaseParticleSystemFX::Update()) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; } // Check to see if we should start fading the system... if (fTime > m_fStartTime + m_fFadeTime) { LTFLOAT fEndTime = m_fStartTime + m_fLifeTime; if (fTime > fEndTime) { return LTFALSE; } LTFLOAT fScale = (fEndTime - fTime) / (m_fLifeTime - m_fFadeTime); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); } // See if it is time to create a new Particle puff... if (fTime >= m_fLastTime + m_fOffsetTime) { // Loop over our list of emmitters, creating new particles... for (int i=0; i < m_nNumEmmitters; i++) { if (m_ActiveEmmitters[i]) { AddParticles(&m_Emmitters[i]); } } m_fLastTime = fTime; } // Loop over our list of emmitters, updating the position of each for (int i=0; i < m_nNumEmmitters; i++) { if (m_ActiveEmmitters[i]) { LTBOOL bBounced = LTFALSE; if (bBounced = UpdateEmmitter(&m_Emmitters[i])) { if (!(m_Emmitters[i].m_PhysicsFlags & MO_LIQUID) && (m_hDebris[i])) { char* pSound = GetDebrisBounceSound(DBT_STONE_BIG); // Play appropriate sound... PlaySoundFromPos(&m_Emmitters[i].m_Pos, pSound, 300.0f, SOUNDPRIORITY_MISC_LOW); } m_BounceCount[i]--; if (m_BounceCount[i] <= 0) { m_Emmitters[i].m_PhysicsFlags |= MO_RESTING; } } if (m_Emmitters[i].m_PhysicsFlags & MO_RESTING) { m_ActiveEmmitters[i] = LTFALSE; if (m_hDebris[i]) { m_pClientDE->RemoveObject(m_hDebris[i]); m_hDebris[i] = LTNULL; } } else if (m_hDebris[i]) { m_pClientDE->SetObjectPos(m_hDebris[i], &(m_Emmitters[i].m_Pos)); if (m_bRotateDebris) { if (bBounced) { // Adjust due to the bounce... m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE); m_fYawVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE); } if (m_fPitchVel != 0 || m_fYawVel != 0) { LTFLOAT fDeltaTime = m_pClientDE->GetFrameTime(); m_fPitch += m_fPitchVel * fDeltaTime; m_fYaw += m_fYawVel * fDeltaTime; LTRotation rRot; m_pClientDE->Common()->SetupEuler(rRot, m_fPitch, m_fYaw, 0.0f); m_pClientDE->SetObjectRotation(m_hDebris[i], &rRot); } } } } } return LTTRUE; }
void SoccerBall::Update( ) { DVector vVel, vAccel, vAccelAdd, vPos, vForward, vCross, vTemp, vTemp2; CollisionInfo collInfo; float fVelMag, fDistTraveled, fTime, fRotAmount, fExp; DRotation rRot; g_pServerDE->GetObjectPos( m_hObject, &vPos ); g_pServerDE->GetVelocity( m_hObject, &vVel ); fVelMag = VEC_MAG( vVel ); fTime = g_pServerDE->GetTime( ); // Remove the ball if it's been sitting around for a while. if( fTime > m_fRespawnTime ) { g_pServerDE->RemoveObject( m_hObject ); return; } // Update the on ground info g_pServerDE->GetStandingOn( m_hObject, &collInfo ); m_bOnGround = ( collInfo.m_hObject ) ? DTRUE : DFALSE; if( m_bOnGround ) { m_fLastTimeOnGround = fTime; } // Get how far we've traveled. VEC_SUB( vForward, vPos, m_vLastPos ); fDistTraveled = VEC_MAG( vForward ); VEC_COPY( m_vLastPos, vPos ); // Rotate the ball if( fDistTraveled > 0.0f ) { VEC_MULSCALAR( vForward, vForward, 1.0f / fDistTraveled ); if( m_bOnGround ) { VEC_COPY( m_vLastNormal, collInfo.m_Plane.m_Normal ); VEC_CROSS( vCross, vForward, m_vLastNormal ); fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius; } else { VEC_CROSS( vCross, vForward, m_vLastNormal ); fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius; } if( fRotAmount > 0.0f ) { VEC_NORM( vCross ); g_pServerDE->GetObjectRotation( m_hObject, &rRot ); g_pServerDE->RotateAroundAxis( &rRot, &vCross, fRotAmount ); g_pServerDE->SetObjectRotation( m_hObject, &rRot ); } } // Adjust the velocity and accel if( fVelMag < MINBALLVEL ) { VEC_INIT( vVel ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } else if( fVelMag > MAXBALLVEL ) { VEC_MULSCALAR( vVel, vVel, MAXBALLVEL / fVelMag ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } else { // new velocity is given by: v = ( a / k ) + ( v_0 - a / k ) * exp( -k * t ) g_pServerDE->GetAcceleration( m_hObject, &vAccel ); fExp = ( float )exp( -BALLDRAG * g_pServerDE->GetFrameTime( )); VEC_DIVSCALAR( vTemp, vAccel, BALLDRAG ); VEC_SUB( vTemp2, vVel, vTemp ); VEC_MULSCALAR( vTemp2, vTemp2, fExp ); VEC_ADD( vVel, vTemp2, vTemp ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } // Make sure we're rolling if we're on a slope. This counteracts the way the // engine stops objects on slopes. if( m_bOnGround ) { if( collInfo.m_Plane.m_Normal.y < 0.9f && fabs( vVel.y ) < 50.0f ) { g_pServerDE->GetGlobalForce( &vAccelAdd ); vAccel.y += vAccelAdd.y * 0.5f; g_pServerDE->SetAcceleration( m_hObject, &vAccel ); } } // Play a bounce sound if enough time has elapsed if( m_bBounced ) { if( fTime > m_fLastBounceTime + TIMEBETWEENBOUNCESOUNDS ) { // Play a bounce sound... PlaySoundFromPos( &vPos, "Sounds_ao\\events\\soccerball.wav", 750, SOUNDPRIORITY_MISC_MEDIUM ); } m_bBounced = DFALSE; } g_pServerDE->SetNextUpdate( m_hObject, 0.001f ); }
void SoccerGoal::OnTouchNotify( HOBJECT hObj ) { CollisionInfo colInfo; DVector vBallVel; DBOOL bGoal; SoccerBall *pSoccerBall; DVector vPos, vDir, vDims; HOBJECT hPlayer; LMessage *pMsg; if( g_pServerDE->IsKindOf( g_pServerDE->GetObjectClass(hObj), m_hSoccerBall )) { pSoccerBall = ( SoccerBall * )g_pServerDE->HandleToObject( hObj ); if( !pSoccerBall ) return; // Already recorded this goal. Ball should delete itself soon. if( pSoccerBall->IsMadeGoal( )) return; // Ball has to enter from correct side for directional goals if( m_bDirectional ) { // Assume no goal bGoal = DFALSE; g_pServerDE->GetVelocity( hObj, &vBallVel ); // Check if going in the right direction if( VEC_DOT( vBallVel, m_vGoalDirection ) > 0.0f ) { bGoal = DTRUE; } } else bGoal = DTRUE; if( bGoal ) { if(( hPlayer = pSoccerBall->GetLastPlayerTouched( )) == DNULL ) return; // Send message to player and ball if( g_pServerDE->Common( )->CreateMessage( pMsg ) != LT_OK ) return; pMsg->WriteByte( m_nTeamID ); g_pServerDE->SendToObject( *pMsg, MID_GOAL, m_hObject, hPlayer, 0 ); g_pServerDE->SendToObject( *pMsg, MID_GOAL, m_hObject, hObj, 0 ); pMsg->Release(); // Create special effects g_pServerDE->GetObjectPos( hObj, &vPos ); g_pServerDE->GetVelocity( hObj, &vDir ); VEC_MULSCALAR( vDir, vDir, -1.0f ); VEC_SET( vDims, 25.0f, 25.0f, 25.0f ); SetupClientGibFX( &vPos, &vDir, &vDims, ( SURFTYPE_FLESH/10 ) | SIZE_SMALL | TRAIL_BLOOD, 1.0f, 5 ); // Play the sound if( m_hstrScoreSound ) { g_pServerDE->GetObjectPos( m_hObject, &vPos ); PlaySoundFromPos( &vPos, g_pServerDE->GetStringData( m_hstrScoreSound ), m_fRadius, SOUNDPRIORITY_MISC_MEDIUM ); } SendTrigger( ); } } }
DBOOL PickupObject::Update(DVector* pMovement) { if (!g_pServerDE) return DFALSE; // Only need update for bouncers... if (m_bBouncing) { g_pServerDE->SetNextUpdate(m_hObject, 0.001f); } else { g_pServerDE->SetNextUpdate(m_hObject, 0.0f); } DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hObject); // If we aren't visible we've been hit and we're now respawning... if (!(dwFlags & FLAG_VISIBLE)) { g_pServerDE->SetObjectFlags(m_hObject, m_dwFlags ); if (m_szRespawnSound) { DVector vPos; g_pServerDE->GetObjectPos(m_hObject, &vPos); PlaySoundFromPos( &vPos, m_szRespawnSound, 300.0f, SOUNDPRIORITY_MISC_HIGH); } } // Check if we've been bouncing... if( m_bBouncing ) { DVector vVel; g_pServerDE->GetVelocity( m_hObject, &vVel ); // Check if bounce almost done... if( fabs( vVel.y ) < 1.0f && fabs( m_fBounce ) < 1.0f ) { DVector vZero; VEC_INIT( vZero ); m_fBounce = 0.0f; m_bBouncing = DFALSE; g_pServerDE->SetObjectPos( m_hObject, &m_vRestPos ); g_pServerDE->SetVelocity( m_hObject, &vZero ); g_pServerDE->SetAcceleration( m_hObject, &vZero ); } // Continue bouncing... else { DVector vAccel, vPos; g_pServerDE->GetObjectPos( m_hObject, &vPos ); VEC_SET( vAccel, 0.0f, m_fBounce, 0.0f ); g_pServerDE->SetAcceleration( m_hObject, &vAccel ); m_fBounce = ( 50.0f ) * ( m_vRestPos.y - vPos.y ) - ( 3.0f ) * vVel.y; } } return DTRUE; }