void CLiteObjectMgr::PreStartWorld(bool bSwitchingWorlds) { // Can't do this in the ctor due to g_pLTServer not being valid yet... if (!g_ShowLiteObjectInfoTrack.IsInitted()) g_ShowLiteObjectInfoTrack.Init(g_pLTServer, "ShowLiteObjectInfo", LTNULL, 0.0f); // Move the objects into the delete list if (m_aDeleteObjects.empty()) m_aActiveObjects.swap(m_aDeleteObjects); else { m_aDeleteObjects.insert(m_aDeleteObjects.end(), m_aActiveObjects.begin(), m_aActiveObjects.end()); m_aActiveObjects.swap(TObjectList()); } m_nNumActiveObjects = 0; if (m_aDeleteObjects.empty()) m_aInactiveObjects.swap(m_aDeleteObjects); else { m_aDeleteObjects.insert(m_aDeleteObjects.end(), m_aInactiveObjects.begin(), m_aInactiveObjects.end()); m_aInactiveObjects.swap(TObjectList()); } m_nNumInactiveObjects = 0; // Clear the name map m_aNameMap.clear(); // Clear the initial update list m_aInitialUpdateObjects.swap(TObjectList()); // You're clean, now SetDirty(eDirty_All, false); }
void GameBase::CreateBoundingBox() { if (m_hDimsBox) return; if (!g_vtDimsAlpha.IsInitted()) { g_vtDimsAlpha.Init(g_pLTServer, "DimsAlpha", LTNULL, 1.0f); } ObjectCreateStruct theStruct; INIT_OBJECTCREATESTRUCT(theStruct); LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); theStruct.m_Pos = vPos; SAFE_STRCPY(theStruct.m_Filename, "Models\\1x1_square.abc"); SAFE_STRCPY(theStruct.m_SkinName, "Models\\1x1_square.dtx"); theStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_GOTHRUWORLD; theStruct.m_ObjectType = OT_MODEL; HCLASS hClass = g_pLTServer->GetClass("BaseClass"); LPBASECLASS pModel = g_pLTServer->CreateObject(hClass, &theStruct); if (pModel) { m_hDimsBox = pModel->m_hObject; LTVector vDims; g_pLTServer->GetObjectDims(m_hObject, &vDims); LTVector vScale; VEC_DIVSCALAR(vScale, vDims, 0.5f); g_pLTServer->ScaleObject(m_hDimsBox, &vScale); } LTVector vOffset; LTRotation rOffset; vOffset.Init(); rOffset.Init(); HATTACHMENT hAttachment; LTRESULT dRes = g_pLTServer->CreateAttachment(m_hObject, m_hDimsBox, LTNULL, &vOffset, &rOffset, &hAttachment); if (dRes != LT_OK) { g_pLTServer->RemoveObject(m_hDimsBox); m_hDimsBox = LTNULL; } LTVector vColor = GetBoundingBoxColor(); g_pLTServer->SetObjectColor(m_hDimsBox, vColor.x, vColor.y, vColor.z, g_vtDimsAlpha.GetFloat()); }
void VolumeBrush::InitialUpdate() { // TESTING!!!! if (!vtRemoveFilters.IsInitted()) { vtRemoveFilters.Init(g_pLTServer, "RemoveFilters", LTNULL, 0.0f); } if (vtRemoveFilters.GetFloat()) { g_pLTServer->CPrint("Removing Filter: %s", g_pLTServer->GetObjectName(m_hObject)); g_pLTServer->RemoveObject(m_hObject); return; } // TESTING!!!! // Tell the client about any special fx (fog)... CreateSpecialFXMsg(); // Save volume brush's initial flags... m_dwSaveFlags = g_pLTServer->GetObjectFlags(m_hObject); uint32 dwUserFlags = g_pLTServer->GetObjectUserFlags(m_hObject); dwUserFlags |= USRFLG_IGNORE_PROJECTILES; if (!m_bHidden) dwUserFlags |= USRFLG_VISIBLE; g_pLTServer->SetObjectUserFlags(m_hObject, dwUserFlags); // Create the surface if necessary. We only need to do updates if we have // a surface (in case somebody decides to move the brush, we need to update // the surface's position)... if (m_bShowSurface) { CreateSurface(); SetNextUpdate(UPDATE_DELTA); } // Normalize friction (1 = normal, 0 = no friction, 2 = double)... if (m_fFriction < 0.0) m_fFriction = 0.0f; else if (m_fFriction > 1.0) m_fFriction = 1.0f; // Normalize viscosity (1 = no movement, 0 = full movement)... if (m_fViscosity < 0.0) m_fViscosity = 0.0f; else if (m_fViscosity > 1.0) m_fViscosity = 1.0f; }
void CServerMissionMgr::SetServerSettings(ServerMissionSettings& ServerSettings) { if (!g_vtNetFriendlyFire.IsInitted()) { g_vtNetFriendlyFire.Init(g_pLTServer, "NetFriendlyFire", LTNULL, 1.0f); } if (!g_vtDifficultyFactorPlayerIncrease.IsInitted()) { g_vtDifficultyFactorPlayerIncrease.Init( g_pLTServer, "DifficultyFactorPlayerIncrease", LTNULL, 0.1f ); } if( !g_vtRunSpeed.IsInitted( )) { g_vtRunSpeed.Init( g_pLTServer, "RunSpeed", NULL, 1.0f ); } m_ServerSettings = ServerSettings; g_vtNetFriendlyFire.SetFloat( ( ServerSettings.m_bFriendlyFire ? 1.0f : 0.0f) ); if (IsDifficultyGameType()) { g_pGameServerShell->SetDifficulty((GameDifficulty)ServerSettings.m_nMPDifficulty); g_pLTServer->CPrint("CServerMissionMgr::StartGame() setting difficulty to %d",ServerSettings.m_nMPDifficulty); } else g_pGameServerShell->SetDifficulty(GD_NORMAL); g_vtDifficultyFactorPlayerIncrease.SetFloat(ServerSettings.m_fPlayerDiffFactor); // Only adjust the runspeed if this is a gametype that allows it. if( !IsCoopMultiplayerGameType( )) g_vtRunSpeed.SetFloat( (float)ServerSettings.m_nRunSpeed / 100.0f ); }
void CLipstickProx::HandleImpact(HOBJECT hObj) { CGrenade::HandleImpact(hObj); if (!g_vtProxGrenadeArmDelay.IsInitted()) { g_vtProxGrenadeArmDelay.Init(g_pLTServer, "ProxArmDelay", LTNULL, -1.0f); } if (!g_vtProxGrenadeDetonateDelay.IsInitted()) { g_vtProxGrenadeDetonateDelay.Init(g_pLTServer, "ProxDetonateDelay", LTNULL, -1.0f); } // See if we should stick to the object we just hit... SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface); if (pSurf) { // Does this surface support magnatism? If so, stick... if (pSurf->bMagnetic) { // Need to set velocity to 0.0f but account for stoping vel // being added back in... CollisionInfo info; g_pLTServer->GetLastCollision(&info); LTVector vVel(0, 0, 0); vVel -= info.m_vStopVel; g_pLTServer->SetVelocity(m_hObject, &vVel); m_vSurfaceNormal.Init(0, 1, 0); m_vSurfaceNormal = info.m_Plane.m_Normal; // Turn off gravity, solid, and touch notify.... // And turn on go-thru-world so it doesn't reflect from the ending position uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); dwFlags &= ~(FLAG_GRAVITY | FLAG_TOUCH_NOTIFY | FLAG_SOLID); dwFlags |= FLAG_GOTHRUWORLD; g_pLTServer->SetObjectFlags(m_hObject, dwFlags); // Rotate to rest... RotateToRest(); } } }
void WeaponItem::PickedUp(HMESSAGEREAD hRead) { // make the item invisible for the correct amount of time uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); g_pLTServer->SetObjectFlags(m_hObject, dwFlags & ~FLAG_VISIBLE & ~FLAG_TOUCH_NOTIFY); // Let the world know what happened... PlayPickedupSound(); // Clear our player obj, we no longer need this link... SetPlayerObj(LTNULL); // if we're supposed to trigger something, trigger it here if (m_hstrPickupTriggerTarget && m_hstrPickupTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrPickupTriggerTarget, m_hstrPickupTriggerMessage); } // get the override respawn time - if it's -1.0, use the default LTFLOAT fRespawn = g_pLTServer->ReadFromMessageFloat (hRead); if (fRespawn == -1.0f) { fRespawn = m_fRespawnDelay; } fRespawn /= g_RespawnScaleTrack.GetFloat(1.0f); if (g_pGameServerShell->GetGameType() != SINGLE && g_WeaponsStay.GetFloat() > 0.0f && m_fRespawnDelay > 0.0f) { fRespawn = 0.1f; } if (fRespawn <= 0.0f || g_pGameServerShell->GetGameType() == SINGLE) { g_pLTServer->RemoveObject(m_hObject); } else { g_pLTServer->SetNextUpdate(m_hObject, fRespawn); } }
void CLiteObjectMgr::Update() { LTCounter cUpdateTime; g_pLTServer->StartCounter(&cUpdateTime); HandlePendingDeletes(); HandlePendingInitialUpdates(); // Update the active objects // Note : This can't use an iterator, since the update might add objects or something like that... uint32 nActiveObjectSize = m_aActiveObjects.size(); for (uint32 nCurObj = 0; nCurObj < nActiveObjectSize; ++nCurObj) { GameBaseLite *pCurObj = m_aActiveObjects[nCurObj]; if (pCurObj) pCurObj->Update(); ASSERT(nCurObj < m_aActiveObjects.size()); } // Clean up, if we need to CleanObjectLists(); uint32 nUpdateTime = g_pLTServer->EndCounter(&cUpdateTime); if (g_ShowLiteObjectInfoTrack.GetFloat()) { ShowInfo(nUpdateTime); } }
LTBOOL CProjectile::CalcInvisibleImpact(IntersectInfo & iInfo, SurfaceType & eSurfType) { // Since we hit an invisible surface try and find a solid surface that // is the real surface of impact. NOTE: We assume that the solid // surface will have a normal facing basically the opposite direction... IntersectInfo iTestInfo; IntersectQuery qTestInfo; qTestInfo.m_From = iInfo.m_Point + (m_vDir * g_vtInvisibleMaxThickness.GetFloat()); qTestInfo.m_To = iInfo.m_Point - m_vDir; qTestInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY; qTestInfo.m_FilterFn = DoVectorFilterFn; qTestInfo.m_pUserData = m_hFiredFrom; if (g_pLTServer->IntersectSegment(&qTestInfo, &iTestInfo)) { eSurfType = GetSurfaceType(iTestInfo); // If we hit another invisible surface, we're done... if (eSurfType != ST_INVISIBLE) { iInfo = iTestInfo; return LTTRUE; } } return LTFALSE; }
void CMusicMgr::DoEvent(Event eEvent) { if ( !m_bEnabled ) return; if ( m_bLockedEvent ) return; if ( m_acEvents[eEvent] != 0 && (m_afEventChances[eEvent] > GetRandom(0.0, 1.0f)) ) { char szMusic[128]; uint32 iEvent = GetRandom(0, m_acEvents[eEvent]-1); sprintf(szMusic, "MUSIC PM %s %s Beat", m_szTheme, m_aaszEvents[eEvent][iEvent]); #ifndef _FINAL if ( g_ShowMusicTrack.GetFloat() > 0 ) { g_pLTServer->CPrint("Server sending client Music Message: (%s)", szMusic); } #endif HSTRING hMusic = g_pLTServer->CreateString(szMusic); CAutoMessage cMsg; cMsg.Writeuint8(MID_MUSIC); cMsg.WriteHString(hMusic); g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); FREE_HSTRING(hMusic); } }
void SendTriggerMsgToObject(LPBASECLASS pSender, HOBJECT hObj, HSTRING hMsg) { HMESSAGEWRITE hMessage; char *pSendName, *pRecvName, *pFilter; char* szMessage = g_pLTServer->GetStringData(hMsg); // Process the message as a command if it is a valid command... if (g_pCmdMgr->IsValidCmd(szMessage)) { g_pCmdMgr->Process(szMessage); return; } hMessage = g_pLTServer->StartMessageToObject(pSender, hObj, MID_TRIGGER); if (hMessage) { if (g_ShowTriggersTrack.GetFloat() != 0.0f) { if (pSender) pSendName = g_pLTServer->GetObjectName(pSender->m_hObject); else pSendName = "Command Manager"; pRecvName = g_pLTServer->GetObjectName(hObj); pFilter = g_ShowTriggersFilter.GetStr(); // Filter out displaying any unwanted messages... LTBOOL bPrintMsg = (!pFilter || !pFilter[0]); if (!bPrintMsg) { bPrintMsg = (szMessage ? !strstr(pFilter, szMessage) : LTTRUE); } if (bPrintMsg) { g_pLTServer->CPrint("Message: %s", szMessage ? szMessage : "NULL"); g_pLTServer->CPrint(" Sent from '%s', to '%s'", pSendName, pRecvName); } } g_pLTServer->WriteToMessageDWord(hMessage, (uint32)g_pLTServer->GetStringData(hMsg)); g_pLTServer->EndMessage(hMessage); } }
void Intelligence::InitialUpdate() { if (!g_IntelRespawnScale.IsInitted()) { g_IntelRespawnScale.Init(GetServerDE(), "IntelRespawnScale", LTNULL, 1.0f); } if (m_bStartHidden) { SetNextUpdate(0.001f); } m_bSkipUpdate = m_bMoveToFloor; CacheFiles(); }
void CLipstickProx::RotateToRest() { CGrenade::RotateToRest(); /* Update 1.002 LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); // Okay, rotated based on the surface normal we're on... g_pLTServer->AlignRotation(&rRot, &m_vSurfaceNormal, LTNULL); g_pLTServer->SetObjectRotation(m_hObject, &rRot); */ // Arm the grenade after a few... LTFLOAT fDelay = g_vtProxGrenadeArmDelay.GetFloat() < 0.0f ? m_pClassData->fArmDelay : g_vtProxGrenadeArmDelay.GetFloat(); m_ArmTime.Start(fDelay); }
void GameBase::UpdateBoundingBox() { int nVal = (int)g_ShowDimsTrack.GetFloat(); if (nVal < 4) { switch (GetType()) { case OT_WORLDMODEL : { if (nVal != 1) { RemoveBoundingBox(); return; } } break; case OT_MODEL : { if (nVal != 2) { RemoveBoundingBox(); return; } } break; case OT_NORMAL : { if (nVal != 3) { RemoveBoundingBox(); return; } } break; default : break; } } CreateBoundingBox(); if (m_hDimsBox) { LTVector vDims, vScale; g_pLTServer->GetObjectDims(m_hObject, &vDims); vScale = (vDims * 2.0); g_pLTServer->ScaleObject(m_hDimsBox, &vScale); } }
void PickupItem::PickedUp(ILTMessage_Read *) { // Let the world know what happened... PlayPickedupSound(); // Clear our player obj, we no longer need this link... SetPlayerObj(LTNULL); // If we're supposed to process a command, do it here... if (m_hstrPickupCommand) { const char *pCmd = g_pLTServer->GetStringData( m_hstrPickupCommand ); if( g_pCmdMgr->IsValidCmd( pCmd ) ) { g_pCmdMgr->Process( pCmd, m_hObject, m_hObject ); } } if (!m_bRespawn) { g_pLTServer->RemoveObject(m_hObject); } else { // Make the item invisible until the next update g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE); //if (m_bTouchPickup) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_TOUCH_NOTIFY); } // If we're activateable, turn of the relative flags... if (m_bActivatePickup) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_RAYHIT); g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, 0, USRFLG_CAN_ACTIVATE); } SetNextUpdate(m_fRespawnDelay / g_RespawnScaleTrack.GetFloat(1.0f)); } // Consider ourselves picked up. m_bWasPickedUp = true; }
void CMusicMgr::Update() { if ( !m_bEnabled ) return; if ( m_bLockedMood ) { if ( m_bRestoreMusicIntensity ) { char szMusic[128]; sprintf(szMusic, "MUSIC I %d measure", m_iRestoreMusicIntensity); #ifndef _FINAL if ( g_ShowMusicTrack.GetFloat() > 0 ) { g_pLTServer->CPrint("Server sending client Music Message: (%s)", szMusic); } #endif HSTRING hMusic = g_pLTServer->CreateString(szMusic); CAutoMessage cMsg; cMsg.Writeuint8(MID_MUSIC); cMsg.WriteHString(hMusic); g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); FREE_HSTRING(hMusic); m_eLastMood = eMoodInvalid; m_bRestoreMusicIntensity = LTFALSE; } return; } LTBOOL bChoseMood = LTFALSE; for ( int32 iMood = kNumMoods-1 ; iMood >= 0 ; --iMood ) { if ( !bChoseMood && (m_afMoods[iMood] != 0.0f || (iMood == eMoodNone)) ) { if ( m_eLastMood == iMood ) { bChoseMood = LTTRUE; } else { SetMood(( Mood )iMood ); bChoseMood = LTTRUE; } } m_afMoods[iMood] = Max<LTFLOAT>(m_afMoods[iMood] - g_pLTServer->GetFrameTime(), 0.0f); } }
uint32 Intelligence::ObjectMessageFn(HOBJECT hSender, uint32 messageID, HMESSAGEREAD hRead) { if (!g_pLTServer) return 0; switch(messageID) { case MID_TRIGGER: { const char* szMsg = (const char*)g_pLTServer->ReadFromMessageDWord(hRead); // ConParse does not destroy szMsg, so this is safe ConParse parse; parse.Init((char*)szMsg); while (g_pLTServer->Common()->Parse(&parse) == LT_OK) { if (parse.m_nArgs > 0 && parse.m_Args[0]) { if (_stricmp(parse.m_Args[0], s_szActivate) == 0) { if (!m_bPhotoOnly) { DoActivate(hSender); } } else if (_stricmp(parse.m_Args[0], s_szGadget) == 0) { if (m_bPhotoOnly) { HandleGadgetMsg(hSender, parse); } } else if (_stricmp(parse.m_Args[0], s_szRespawn) == 0) { SetNextUpdate( m_fRespawnDelay / g_IntelRespawnScale.GetFloat(1.0f)); } } } } break; default : break; } return Prop::ObjectMessageFn(hSender, messageID, hRead); }
void EndTimingCounter(char *msg, ...) { if (!g_pLTServer || g_ShowTimingTrack.GetFloat() < 1.0f) return; uint32 dwTicks = g_pLTServer->EndCounter(&s_counter); // parse the message char pMsg[256]; va_list marker; va_start(marker, msg); int nSuccess = vsprintf(pMsg, msg, marker); va_end(marker); if (nSuccess < 0) return; g_pLTServer->CPrint("%s : %d ticks", pMsg, dwTicks); }
bool CMusicMgr::SetMood( Mood eMood ) { char szMusic[128]; uint32 iLevel = GetRandom(0, m_acMoods[eMood]-1); sprintf(szMusic, "MUSIC I %d measure", m_aanMoods[eMood][iLevel]); #ifndef _FINAL if ( g_ShowMusicTrack.GetFloat() > 0 ) { g_pLTServer->CPrint("Server sending client Music Message: (%s)", szMusic); } #endif HSTRING hMusic = g_pLTServer->CreateString(szMusic); CAutoMessage cMsg; cMsg.Writeuint8(MID_MUSIC); cMsg.WriteHString(hMusic); g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); FREE_HSTRING(hMusic); m_eLastMood = eMood; return true; }
LTFLOAT GetDifficultyFactor() { if (!g_pGameServerShell) return g_vtDifficultyFactorHard.GetFloat(); float fPlayerMod = 0.0f; uint32 nPlayersInGame = CPlayerObj::GetNumberPlayersWithClients( ); if( nPlayersInGame > 1 ) { // Increase the difficulty by an amount per player. The // difficulty grows logrithmically. 2 players will add 100% of // fPlayerInc. 3 players adds ~150%. 4 Players adds 200%. float fPlayerInc = g_vtDifficultyFactorPlayerIncrease.GetFloat(); fPlayerMod = fPlayerInc * logf(( float )nPlayersInGame ) / logf( 2.0f ); } switch (g_pGameServerShell->GetDifficulty()) { case GD_EASY: return g_vtDifficultyFactorEasy.GetFloat() + fPlayerMod; break; case GD_NORMAL: return g_vtDifficultyFactorNormal.GetFloat() + fPlayerMod; break; case GD_VERYHARD: return g_vtDifficultyFactorVeryHard.GetFloat() + fPlayerMod; break; case GD_HARD: default : return g_vtDifficultyFactorHard.GetFloat() + fPlayerMod; break; } }
void CProjectile::Setup(CWeapon* pWeapon, WFireInfo & info) { if (!pWeapon || !info.hFiredFrom || !g_pWeaponMgr) return; if (!g_vtInvisibleMaxThickness.IsInitted()) { g_vtInvisibleMaxThickness.Init(g_pLTServer, "InvisibleMaxThickness", LTNULL, 33.0f); } if (!g_vtNetFriendlyFire.IsInitted()) { g_vtNetFriendlyFire.Init(g_pLTServer, "NetFriendlyFire", LTNULL, 0.0f); } m_vDir = info.vPath; m_vDir.Norm(); m_hFiredFrom = info.hFiredFrom; m_nWeaponId = pWeapon->GetId(); m_nAmmoId = pWeapon->GetAmmoId(); m_fLifeTime = pWeapon->GetLifeTime(); m_fInstDamage = pWeapon->GetInstDamage(); m_fProgDamage = pWeapon->GetProgDamage(); m_pWeaponData = pWeapon->GetWeaponData(); if (!m_pWeaponData) return; m_pAmmoData = pWeapon->GetAmmoData(); if (!m_pAmmoData) return; m_eInstDamageType = m_pAmmoData->eInstDamageType; m_eProgDamageType = m_pAmmoData->eProgDamageType; if (info.bOverrideVelocity) { m_fVelocity = info.fOverrideVelocity; } else if (info.bAltFire) { m_fVelocity = (LTFLOAT) (m_pAmmoData->pProjectileFX ? m_pAmmoData->pProjectileFX->nAltVelocity : 0); } else { m_fVelocity = (LTFLOAT) (m_pAmmoData->pProjectileFX ? m_pAmmoData->pProjectileFX->nVelocity : 0); } m_fRange = (LTFLOAT) m_pWeaponData->nRange; m_bSilenced = !!(pWeapon->GetSilencer()); AmmoType eAmmoType = m_pAmmoData->eType; m_vFirePos = info.vFirePos; m_vFlashPos = info.vFlashPos; m_bNumCallsToAddImpact = 0; // See if we start inside the test object... if (!TestInsideObject(info.hTestObj, eAmmoType)) { if (eAmmoType == PROJECTILE) { DoProjectile(); } else if (eAmmoType == VECTOR) { DoVector(); } else if (eAmmoType == GADGET) { ; // Do nothing for now } } }
LTBOOL DoVectorFilterFn(HOBJECT hObj, void *pUserData) { // We're not attacking our self... if (SpecificObjectFilterFn(hObj, pUserData)) { // CharacterHitBox objects are used for vector impacts, don't // impact on the character/body prop object itself.... if (IsCharacter(hObj) || IsBody(hObj) || IsKindOf(hObj, "Intelligence")) { return LTFALSE; } // Check special character hit box cases... if (IsCharacterHitBox(hObj)) { CCharacterHitBox *pCharHitBox = (CCharacterHitBox*) g_pLTServer->HandleToObject(hObj); if (pCharHitBox) { // Make sure we don't hit ourself... HOBJECT hUs = (HOBJECT)pUserData; HOBJECT hTestObj = pCharHitBox->GetModelObject(); if (!hTestObj) return LTFALSE; if (hTestObj == hUs) { return LTFALSE; } // Do special AI hitting AI case... if (IsAI(hUs) && IsAI(hTestObj)) { CAI *pAI = (CAI*) g_pLTServer->HandleToObject(hUs); if (!pAI) return LTFALSE; // We can't hit guys we like, unless they're NEUTRAL CCharacter* pB = (CCharacter*)g_pLTServer->HandleToObject(hTestObj); if (!pB) return LTFALSE; CharacterClass cc = pB->GetCharacterClass(); if (cc != NEUTRAL) { return LIKE != GetAlignement(pAI->GetCharacterClass(), cc); } } // Check for friendly fire if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && g_vtNetFriendlyFire.GetFloat() < 1.0f) { // We can't hit guys on our team unless friendly fire is turned on if (IsPlayer(hUs) && IsPlayer(hTestObj)) { CPlayerObj* pUs = (CPlayerObj*) g_pLTServer->HandleToObject(hUs); if (!pUs) return LTFALSE; CPlayerObj* pThem = (CPlayerObj*) g_pLTServer->HandleToObject(hTestObj); if (!pThem) return LTFALSE; if (pUs->GetTeamID() == pThem->GetTeamID()) return LTFALSE; } } } } return LTTRUE; } return LTFALSE; }
void CSpear::HandleImpact(HOBJECT hObj) { if (!g_vtSpearStickPercentage.IsInitted()) { g_vtSpearStickPercentage.Init(g_pLTServer, "SpearStickPercent", LTNULL, 0.9f); } if (!m_pAmmoData || !m_pAmmoData->pProjectileFX) { CProjectile::HandleImpact(hObj); return; } CollisionInfo info; g_pLTServer->GetLastCollision(&info); LTVector vPos, vVel, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); // Should we break the spear? enum SpearAction { eSpearActionBreak, eSpearActionStickWorld, eSpearActionStickAI, eSpearActionStickPlayer, eSpearActionStickBody }; SpearAction eSpearAction = eSpearActionBreak; // Randomly break even if we could sometimes stick... if (GetRandom(0.0, 1.0f) > g_vtSpearStickPercentage.GetFloat()) { eSpearAction = eSpearActionBreak; } else if (IsMainWorld(hObj)) { // Calculate where we really hit the world... g_pLTServer->GetVelocity(m_hObject, &vVel); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT(info.m_Plane.m_Normal, vP0) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(info.m_Plane.m_Normal, vP1) - info.m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos(m_hObject, &vPos); eSpearAction = eSpearActionStickWorld; } else if (IsMoveable(hObj)) { if (IsAI(hObj)) { // Attach to a AI eSpearAction = eSpearActionStickAI; } else if (IsPlayer(hObj)) { // Attach to a Player eSpearAction = eSpearActionStickPlayer; } else if (IsBody(hObj)) { // Attach to a body eSpearAction = eSpearActionStickBody; } else { // Could probably come up with a way to attach to moveable // non-character objects (like doors), but it is much easier // to just break it ;)... eSpearAction = eSpearActionBreak; } } // If the surface is too hard, the spear will just break when // it hits it... SurfaceType eSurf = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurf); if ((eSpearActionBreak == eSpearAction) || ((eSpearActionStickWorld == eSpearAction) && pSurf && pSurf->fHardness > 0.5)) { // Create spear debris... DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_pAmmoData->szName); if (pDebris) { vVel.Norm(); LTVector vNegVel = -vVel; CreatePropDebris(vPos, vNegVel, pDebris->nId); } CProjectile::HandleImpact(hObj); return; } // Create the Spear powerup... char szSpawn[512]; sprintf(szSpawn, "AmmoBox AmmoType1 %s;AmmoCount1 1;Filename %s;Skin %s", m_pAmmoData->szName, m_pAmmoData->pProjectileFX->szModel, m_pAmmoData->pProjectileFX->szSkin); LTVector vScale = m_pAmmoData->pProjectileFX->vModelScale; // Make sure the spear sticks out a little ways... vVel.Norm(); vPos -= (vVel * vScale.z/2.0f); if (eSpearActionStickWorld == eSpearAction) { g_pLTServer->AlignRotation(&rRot, &vVel, LTNULL); } BaseClass* pClass = SpawnObject(szSpawn, LTVector(-10000,-10000,-10000), rRot); if (pClass) { g_pLTServer->ScaleObject(pClass->m_hObject, &vScale); LTVector vDims; g_pLTServer->GetObjectDims(pClass->m_hObject, &vDims); vDims.x *= vScale.x; vDims.y *= vScale.y; vDims.z *= vScale.z; g_pLTServer->SetObjectDims(pClass->m_hObject, &vDims); // We don't want other projectiles to impact on us... //uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(pClass->m_hObject); //dwUsrFlags |= USRFLG_IGNORE_PROJECTILES; //g_pLTServer->SetObjectUserFlags(pClass->m_hObject, dwUsrFlags); if ( eSpearActionStickAI == eSpearAction || eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); if ( eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) | USRFLG_ATTACH_HIDE1SHOW3); } // Attach it to the character CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hObj); pCharacter->AddSpear(pClass->m_hObject, pCharacter->GetModelNodeLastHit(), rRot); } else if ( eSpearActionStickBody == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); // Attach it to the body Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); pBody->AddSpear(pClass->m_hObject, rRot); } else // ( eSpearActionStickWorld == eSpearAction ) { // Move it to the right position in the world g_pLTServer->SetObjectPos(pClass->m_hObject, &vPos); } } CProjectile::HandleImpact(hObj); }
void CLipstickProx::UpdateGrenade() { CGrenade::UpdateGrenade(); // If we're doing normal (in-air) updates, don't do any more // processing... if (m_bUpdating || !m_pClassData) return; // Make sure we aren't moving anymore... LTVector vVel(0, 0, 0); g_pLTServer->SetVelocity(m_hObject, &vVel); // Waiting to go boom... if (m_bActivated && m_DetonateTime.Stopped()) { Detonate(LTNULL); return; } // See if it is time to arm yet... if (!m_bArmed && m_ArmTime.Stopped()) { m_bArmed = LTTRUE; // Play armed sound... if (m_pClassData->szArmSound[0]) { int nVolume = IsLiquid(m_eContainerCode) ? 50 : 100; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); g_pServerSoundMgr->PlaySoundFromPos(vPos, m_pClassData->szArmSound, (LTFLOAT)m_pClassData->nArmSndRadius, SOUNDPRIORITY_MISC_MEDIUM, 0, nVolume); } } // Is there anything close enough to cause us to go boom? if (!m_bActivated && m_bArmed) { if (!m_pAmmoData) return; LTFLOAT fRadius = (LTFLOAT) m_pClassData->nActivateRadius; // NEED TO FIGURE OUT A BETTER WAY TO DO THIS!!! LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); ObjectList* pList = g_pLTServer->FindObjectsTouchingSphere(&vPos, fRadius); if (!pList) return; ObjectLink* pLink = pList->m_pFirstLink; while (pLink) { if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && IsPlayer(pLink->m_hObject) && IsPlayer(m_hFiredFrom) && g_vtNetFriendlyFire.GetFloat() < 1.0f) { CPlayerObj* pPlayer1 = (CPlayerObj*) g_pLTServer->HandleToObject(m_hFiredFrom); CPlayerObj* pPlayer2 = (CPlayerObj*) g_pLTServer->HandleToObject(pLink->m_hObject); if (pPlayer1 != pPlayer2 && pPlayer1->GetTeamID() == pPlayer2->GetTeamID()) { //go to next obj pLink = pLink->m_pNext; continue; } } if (IsCharacter(pLink->m_hObject)) { m_bActivated = LTTRUE; LTFLOAT fDelay = g_vtProxGrenadeDetonateDelay.GetFloat() < 0.0f ? m_pClassData->fActivateDelay : g_vtProxGrenadeDetonateDelay.GetFloat(); m_DetonateTime.Start(fDelay); // Play activation sound... if (m_pClassData->szActivateSound[0]) { int nVolume = IsLiquid(m_eContainerCode) ? 50 : 100; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); g_pServerSoundMgr->PlaySoundFromPos(vPos, m_pClassData->szActivateSound, (LTFLOAT) m_pClassData->nActivateSndRadius, SOUNDPRIORITY_MISC_MEDIUM, 0, nVolume); } break; } pLink = pLink->m_pNext; } g_pLTServer->RelinquishList(pList); } }
void CMusicMgr::Init(const char* szMusicControlFile) { // Start fresh. Term( ); if( !m_pMusicButeMgr ) { m_pMusicButeMgr = new CMusicButeMgr( ); if( !m_pMusicButeMgr ) return; if( !m_pMusicButeMgr->Init()) return; } strcpy(m_szTheme, szMusicControlFile); char* pchDot; if ( pchDot = strchr(m_szTheme, '.') ) { *pchDot = 0; } _strlwr(m_szTheme); for ( uint32 iMood = 0 ; iMood < kNumMoods ; ++iMood ) { m_acMoods[iMood] = 0; for ( uint32 iLevel = 0 ; iLevel < kMaxLevelsPerMood ; iLevel++ ) { char szMood[128]; sprintf(szMood, "%s%d", s_aszMusicMoods[iMood], iLevel); m_aanMoods[iMood][m_acMoods[iMood]] = m_pMusicButeMgr->GetButeMgr( )->GetInt(m_szTheme, szMood, m_aanMoods[iMood][m_acMoods[iMood]]); if ( m_pMusicButeMgr->GetButeMgr( )->Success( )) { m_acMoods[iMood]++; } else { break; } } } for ( uint32 iEvent = 0 ; iEvent < kNumEvents ; ++iEvent ) { m_acEvents[iEvent] = 0; for ( uint32 iMotif = 0 ; iMotif < kMaxMotifsPerEvent ; iMotif++ ) { char szEvent[128]; sprintf(szEvent, "%s%d", s_aszEvents[iEvent], iMotif); m_pMusicButeMgr->GetButeMgr( )->GetString(m_szTheme, szEvent, "", m_aaszEvents[iEvent][m_acEvents[iEvent]], sizeof(m_aaszEvents[iEvent][m_acEvents[iEvent]])); if ( m_pMusicButeMgr->GetButeMgr( )->Success( )) { m_acEvents[iEvent]++; } else { break; } } } m_afEventChances[eEventPlayerDie] = (LTFLOAT)m_pMusicButeMgr->GetButeMgr( )->GetDouble("settings", "DieChance"); m_afEventChances[eEventAIDie] = (LTFLOAT)m_pMusicButeMgr->GetButeMgr( )->GetDouble("settings", "DieChance"); m_afEventChances[eEventAIDodge] = (LTFLOAT)m_pMusicButeMgr->GetButeMgr( )->GetDouble("settings", "DodgeChance"); m_bInitialized = LTTRUE; #ifndef _FINAL if ( !g_ShowMusicTrack.IsInitted() ) { g_ShowMusicTrack.Init(g_pLTServer, "ShowMusicChange", LTNULL, 0.0f); } #endif }
LTBOOL PickupItem::InitialUpdate() { SetNextUpdate(UPDATE_NEVER); if (!g_RespawnScaleTrack.IsInitted()) { g_RespawnScaleTrack.Init(GetServerDE(), "RespawnScale", LTNULL, 1.0f); } // Set up our user flags... g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, m_dwUserFlags, m_dwUserFlags); // set a special fx message so that the client knows about the pickup item... // (so it can handle bouncing, rotating, and displaying the proper targeting text...) CreateSpecialFX(); g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, m_dwFlags, m_dwFlags); // Look for an animation specified in DEdit... uint32 dwAni = INVALID_ANI; if( !m_sWorldAniName.empty()) { dwAni = g_pLTServer->GetAnimIndex(m_hObject, m_sWorldAniName.c_str()); } if (dwAni != INVALID_ANI) { g_pLTServer->SetModelAnimation(m_hObject, dwAni); } else { // If we couldn't find the ani look for the world ani. ALL PickUps should have a "World" ani... dwAni = g_pLTServer->GetAnimIndex( m_hObject, "World" ); if( dwAni != INVALID_ANI ) { g_pLTServer->SetModelAnimation( m_hObject, dwAni ); } } // Set the dims based on the current animation... LTVector vDims; g_pCommonLT->GetModelAnimUserDims(m_hObject, &vDims, g_pLTServer->GetModelAnimation(m_hObject)); // Set object dims based on scale value... LTVector vNewDims; vNewDims.x = m_vScale.x * vDims.x; vNewDims.y = m_vScale.y * vDims.y; vNewDims.z = m_vScale.z * vDims.z; g_pLTServer->ScaleObject(m_hObject, &m_vScale); g_pPhysicsLT->SetObjectDims(m_hObject, &vNewDims, 0); // Make sure object starts on floor if the gravity flag is set... if(m_bMoveToFloor) { MoveObjectToFloor(m_hObject); } return LTTRUE; }
void Intelligence::DoActivate(HOBJECT hSender) { // BL 10/30/00 - fix multiple photographs of items in multiplayer { if ( g_pGameServerShell->GetGameType() != SINGLE ) { uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); if ( !(dwFlags & FLAG_VISIBLE) ) { return; } } } HOBJECT hPlayer = hSender; if (!hSender || !IsPlayer(hSender)) { // Find the player if the sender isn't one... ObjArray <HOBJECT, 1> objArray; g_pLTServer->FindNamedObjects(DEFAULT_PLAYERNAME, objArray); if (!objArray.NumObjects()) return; hPlayer = objArray.GetObject(0); } // Increment the player's intelligence count... CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hPlayer); if (pPlayer) { if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && m_nPlayerTeamFilter) { if (pPlayer->GetTeamID() != m_nPlayerTeamFilter) return; uint8 nScore = (uint8)g_vtNetIntelScore.GetFloat(); pPlayer->AddToScore(nScore); HCLIENT hClient = pPlayer->GetClient(); uint32 nPlayerID = g_pLTServer->GetClientID(hClient); HMESSAGEWRITE hWrite = g_pLTServer->StartMessage (LTNULL, MID_TEAM_SCORED); g_pLTServer->WriteToMessageDWord (hWrite, nPlayerID); g_pLTServer->WriteToMessageByte (hWrite, (uint8)pPlayer->GetTeamID()); g_pLTServer->WriteToMessageByte (hWrite, nScore); g_pLTServer->EndMessage (hWrite); } CPlayerSummaryMgr* pPSMgr = pPlayer->GetPlayerSummaryMgr(); if (pPSMgr) { pPSMgr->IncIntelligenceCount(); } HCLIENT hClient = pPlayer->GetClient(); if (hClient) { HMESSAGEWRITE hMessage = g_pLTServer->StartMessage(hClient, MID_PLAYER_INFOCHANGE); g_pLTServer->WriteToMessageByte(hMessage, IC_INTEL_PICKUP_ID); g_pLTServer->WriteToMessageByte(hMessage, 0); g_pLTServer->WriteToMessageByte(hMessage, 0); g_pLTServer->WriteToMessageFloat(hMessage, 0.0f); g_pLTServer->EndMessage(hMessage); } // Show the pop-up associated with the intelligence item, if // applicable... INTEL* pIntel = g_pIntelMgr->GetIntel(m_nIntelId); if (pIntel && m_bShowPopup) { char buf[255]; sprintf(buf, "msg %s (popup %d", DEFAULT_PLAYERNAME, m_nInfoId); // Add the scale fx... for (int i=0; i < pIntel->nNumScaleFXNames; i++) { if (pIntel->szScaleFXNames[i]) { strcat(buf, " "); strcat(buf, pIntel->szScaleFXNames[i]); } } strcat(buf, ")"); if (g_pCmdMgr->IsValidCmd(buf)) { g_pCmdMgr->Process(buf); } } // If we have a command, process it... if (m_hstrPickedUpCmd) { char* pCmd = g_pLTServer->GetStringData(m_hstrPickedUpCmd); if (pCmd && g_pCmdMgr->IsValidCmd(pCmd)) { g_pCmdMgr->Process(pCmd); } } if (g_pGameServerShell->GetGameType() == SINGLE) { g_pLTServer->RemoveObject(m_hObject); } else { uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); dwFlags &= (~FLAG_VISIBLE & ~FLAG_RAYHIT); g_pLTServer->SetObjectFlags(m_hObject, dwFlags); // Play pickup sound... LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); g_pServerSoundMgr->PlaySoundFromPos(vPos, INTEL_PICKUP_SOUND, 600.0f, SOUNDPRIORITY_MISC_HIGH); } } }
void Prop::HandleAttachmentImpact( CAttachmentPosition *pAttachPos, const LTVector& vDir ) { if( !pAttachPos ) return; // TODO: Init these somewhere else if( !s_vtAttachmentMinVel.IsInitted() ) { s_vtAttachmentMinVel.Init( g_pLTServer, "AttachmentMinVel", LTNULL, DEFAULT_ATTACH_MIN_VEL ); } if( !s_vtAttachmentMaxVel.IsInitted() ) { s_vtAttachmentMaxVel.Init( g_pLTServer, "AttachmentMaxVel", LTNULL, DEFAULT_ATTACH_MAX_VEL ); } if( !s_vtAttachmentMinYAdd.IsInitted() ) { s_vtAttachmentMinYAdd.Init( g_pLTServer, "AttachmentMinYAdd", LTNULL, DEFAULT_ATTACH_MIN_YADD ); } if( !s_vtAttachmentMaxYAdd.IsInitted() ) { s_vtAttachmentMaxYAdd.Init( g_pLTServer, "AttachmentMaxYAdd", LTNULL, DEFAULT_ATTACH_MAX_YADD ); } if( !s_vtAttachmentFadeDelay.IsInitted() ) { s_vtAttachmentFadeDelay.Init( g_pLTServer, "AttachmentFadeDelay", LTNULL, DEFAULT_ATTACH_FADE_DELAY ); } if( !s_vtAttachmentFadeDuration.IsInitted() ) { s_vtAttachmentFadeDuration.Init( g_pLTServer, "AttachmentFadeDuration", LTNULL, DEFAULT_ATTACH_FADE_DURATION ); } // Set the owner of the attachment... m_hAttachmentOwner = pAttachPos->GetAttachment()->GetObject(); uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY; g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, dwFlags, dwFlags | FLAG_GOTHRUWORLD ); // Play the world animation so the prop is flat when it comes to rest... HMODELANIM hWorldAnim = INVALID_MODEL_ANIM; if( (g_pModelLT->GetAnimIndex( m_hObject, "WORLD", hWorldAnim ) == LT_OK) && (hWorldAnim != INVALID_MODEL_ANIM) ) { g_pModelLT->SetLooping( m_hObject, MAIN_TRACKER, true ); g_pModelLT->SetCurAnim( m_hObject, MAIN_TRACKER, hWorldAnim ); } LTVector vVel = vDir; vVel.Normalize(); vVel *= GetRandom( s_vtAttachmentMinVel.GetFloat(), s_vtAttachmentMaxVel.GetFloat() ); vVel.y += GetRandom( s_vtAttachmentMinYAdd.GetFloat(), s_vtAttachmentMaxYAdd.GetFloat() ); g_pPhysicsLT->SetVelocity( m_hObject, &vVel ); // Don't play the touch animation and sounds when recieving a touch notify... m_bTouchable = LTFALSE; m_bAttachmentShotOff = LTTRUE; g_pLTServer->SetBlockingPriority( m_hObject, 0 ); g_pPhysicsLT->SetForceIgnoreLimit( m_hObject, 0.0f ); // Give it some rotation... float fVal = MATH_PI; float fVal2 = MATH_CIRCLE; m_fPitchVel = GetRandom( -fVal2, fVal2 ); m_fYawVel = GetRandom( -fVal2, fVal2 ); m_fRollVel = GetRandom( -fVal2, fVal2 ); m_bRotating = true; SetNextUpdate(UPDATE_NEXT_FRAME); }
void Prop::HandleAttachmentTouch( HOBJECT hToucher ) { if( !hToucher || !m_bAttachmentShotOff ) return; // Don't touch the owner... if( hToucher == m_hAttachmentOwner ) return; // Or any non-solid objects... uint32 dwToucherFlags; g_pCommonLT->GetObjectFlags( hToucher, OFT_Flags, dwToucherFlags ); if( !(dwToucherFlags & FLAG_SOLID) ) return; CollisionInfo info; g_pLTServer->GetLastCollision( &info ); LTVector vVel; g_pPhysicsLT->GetVelocity( m_hObject, &vVel ); // Calculate where we really hit the world... if( IsMainWorld( hToucher )) { LTVector vPos, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos( m_hObject, &vPos ); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT( info.m_Plane.m_Normal, vP0 ) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT( info.m_Plane.m_Normal, vP1 ) - info.m_Plane.m_Dist; if( fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f ) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP( vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos( m_hObject, &vPos ); } // If we're on the ground (or an object), stop movement... CollisionInfo standingInfo; g_pLTServer->GetStandingOn( m_hObject, &standingInfo ); CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info; if( pInfo->m_hObject ) { // Don't stop on walls... if( pInfo->m_Plane.m_Normal.y > 0.75f ) { vVel.Init(); // Turn off gravity, solid, and touch notify.... uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY; g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, 0, dwFlags ); // Rotate to rest... if( m_bRotating ) { LTRotation rRot( 0.0f, m_fYaw, 0.0f ); g_pLTServer->SetObjectRotation( m_hObject, &rRot ); m_bRotating = false; StartFade( s_vtAttachmentFadeDuration.GetFloat(), s_vtAttachmentFadeDelay.GetFloat() ); } } } // Remove the stoping velocity... vVel = -info.m_vStopVel; g_pPhysicsLT->SetVelocity( m_hObject, &vVel ); }
void CGrenade::HandleImpact(HOBJECT hObj) { if (!g_vtGrenadeDampenPercent.IsInitted()) { g_vtGrenadeDampenPercent.Init(g_pLTServer, "GrenadeDampenPercent", LTNULL, DEFAULT_GRENADE_DAMPEN_PERCENT); } if (!g_vtGrenadeMinVelMag.IsInitted()) { g_vtGrenadeMinVelMag.Init(g_pLTServer, "GrenadeMinVelMag", LTNULL, DEFAULT_GRENADE_MIN_VELOCITY); } LTVector vVel; g_pLTServer->GetVelocity(m_hObject, &vVel); // See if we are impacting on liquid... LTBOOL bEnteringLiquid = LTFALSE; uint16 code; if (g_pLTServer->GetContainerCode(hObj, &code)) { if (IsLiquid((ContainerCode)code)) { bEnteringLiquid = LTTRUE; } } CollisionInfo info; g_pLTServer->GetLastCollision(&info); // Do the bounce, if the object we hit isn't liquid... if (!bEnteringLiquid) { vVel += (info.m_vStopVel * 2.0f); } // Dampen the grenade's new velocity based on the surface type... LTFLOAT fDampenPercent = g_vtGrenadeDampenPercent.GetFloat(); m_eLastHitSurface = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface); if (pSurf) { // Play a bounce sound (based on the surface type) if one isn't // already playing... if ( ShouldPlayBounceSound(pSurf) ) { // Only play one sound at a time... if (m_hBounceSnd) { g_pLTServer->KillSound(m_hBounceSnd); m_hBounceSnd = LTNULL; } uint32 dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME; int nVolume = IsLiquid(m_eContainerCode) ? 50 : 100; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); m_hBounceSnd = g_pServerSoundMgr->PlaySoundFromPos(vPos, (char*)GetBounceSound(pSurf), pSurf->fGrenadeSndRadius, SOUNDPRIORITY_MISC_MEDIUM, dwFlags, nVolume); } fDampenPercent = (1.0f - pSurf->fHardness); } fDampenPercent = fDampenPercent > 1.0f ? 1.0f : (fDampenPercent < 0.0f ? 0.0f : fDampenPercent); vVel *= (1.0f - fDampenPercent); // See if we should come to a rest... LTVector vTest = vVel; vTest.y = 0.0f; if (vTest.Mag() < g_vtGrenadeMinVelMag.GetFloat()) { // If we're on the ground (or an object), stop movement... CollisionInfo standingInfo; g_pLTServer->GetStandingOn(m_hObject, &standingInfo); CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info; if (pInfo->m_hObject) { // Don't stop on walls... if (pInfo->m_Plane.m_Normal.y > 0.75f) { vVel.Init(); // Turn off gravity, solid, and touch notify.... uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); dwFlags &= ~(FLAG_GRAVITY | FLAG_TOUCH_NOTIFY | FLAG_SOLID); g_pLTServer->SetObjectFlags(m_hObject, dwFlags); // Rotate to rest... RotateToRest(); } } } // Reset rotation velocities due to the bounce... ResetRotationVel(&vVel, pSurf); // We need to subtact this out because the engine will add it back in, // kind of a kludge but necessary... vVel -= info.m_vStopVel; g_pLTServer->SetVelocity(m_hObject, &vVel); m_cBounces++; }
void StartTimingCounter() { if (!g_pLTServer || g_ShowTimingTrack.GetFloat() < 1.0f) return; g_pLTServer->StartCounter(&s_counter); }