void CWeaponFX::PlayImpactSound() { IMPACTFX* pImpactFX = m_pAmmo->pImpactFX; if (IsLiquid(m_eCode)) { pImpactFX = m_pAmmo->pUWImpactFX; } if (!pImpactFX) return; if (m_pAmmo->eType == VECTOR) { if ((m_nDetailLevel == RS_LOW) && GetRandom(1, 2) != 1) return; else if ((m_nDetailLevel == RS_MED) && GetRandom(1, 3) == 1) return; } char* pSnd = GetImpactSound(m_eSurfaceType, m_nAmmoId); LTFLOAT fSndRadius = (LTFLOAT) pImpactFX->nSoundRadius; if (pSnd) { uint32 dwFlags = 0; float fPitchShift = 1.0f; if (g_cvarImpactPitchShift.GetFloat() > 0.0f) { dwFlags |= PLAYSOUND_CTRL_PITCH; } uint8 nVolume = IsLiquid(m_eCode) ? 50 : 100; g_pClientSoundMgr->PlaySoundFromPos(m_vPos, pSnd, fSndRadius, SOUNDPRIORITY_MISC_LOW, dwFlags, nVolume, fPitchShift); } }
// find the place to go for air when bot is underwater Vector CBotNav::AirGoal() { if (!m_pBot->IsInWater() && !m_pBot->IsInLava() && !m_pBot->IsInSlime()) return NULLVEC; // bot isn't underwater, don't bother Vector start = m_pBot->GetOrigin(), end = m_pBot->GetOrigin() + Vector(0, 0, 1000); // trace up until we hit solid traceresult_t tr = TestLine(start, end, true, NULL); end = tr.endpos; end.z -= 16; // lower a bit if (IsLiquid(end) || !PointBelongsToWorld(end)) return NULLVEC; // no enough space above water, fail // find the surface of the water while (end.z - start.z > 1) { // find the mid point Vector mid(start.x, start.y, (start.z + end.z) / 2); if (IsLiquid(mid)) { start.z = mid.z; // surface is ABOVE the mid point } else { end.z = mid.z; // surface is BELOW the mid point } } end.z += 16; // raise the point a bit to make sure bot will get air return end; // success! }
//========================================================= // FVisible - returns true if a line can be traced from // the caller's eyes to the target //========================================================= bool CEntity::FVisible(const Vector &vecDest) { // don't look through water if (IsLiquid(GetGunPosition()) != IsLiquid(vecDest)) return false; // check if line of sight to object is not blocked (i.e. visible) return (TestLine(EyePosition(), vecDest).fraction >= 1.0); }
void Tile::Sort() { for (int i=0;i<MAXMAT;i++) for (int j=i+1;j<MAXMAT;j++) { Material *mm; if ((IsLiquid(i)&&IsSolid(j))||(IsGas(i)&&(IsLiquid(j)||IsSolid(j)))) { mm=mats[i]; mats[i]=mats[j]; mats[j]=mm; } } }
void Tile::TransferMass(ITile *t) { int &myh=matterh;//GetHeight(); if (myh<0) return ; if (//(t->GetHeight()<myh)&& (t->GetHeight()<MAXMAT+1)) if (IsLiquid(myh)||IsGas(myh)) { TransferTemp(t); //t->mats[t->GetHeight()+1]=mats[myh]; t->AddTop(mats[myh]); RemoveMatter(); //if (myh==0)temp=0;//actual ambient temp? neturetu but svarbu nes VV metodas taip veikia } if(stack) for(unsigned i=0;i<stack->GetCount();i++) { IItem *it=stack->GetItem(i); if(it->GetSize()<=SIZE_CAT) { stack->RemoveItem(i); t->AddItem(it); return; } } }
void CWeaponFX::CreateMark(LTVector vPos, LTVector vNorm, LTRotation rRot, SurfaceType eType) { IMPACTFX* pImpactFX = m_pAmmo->pImpactFX; if (IsLiquid(m_eCode)) { pImpactFX = m_pAmmo->pUWImpactFX; } if (!pImpactFX) return; CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; MARKCREATESTRUCT mark; mark.m_vPos = vPos; mark.m_Rotation = rRot; // Randomly rotate the bullet hole... g_pLTClient->RotateAroundAxis(&mark.m_Rotation, &vNorm, GetRandom(0.0f, MATH_CIRCLE)); mark.m_fScale = pImpactFX->fMarkScale; mark.nAmmoId = m_nAmmoId; mark.nSurfaceType = eType; psfxMgr->CreateSFX(SFX_MARK_ID, &mark); }
bool Tile::IsLiquid() { int top=GetHeight(); if (top<0) return false; return IsLiquid(top); // return (temp > mymat->MeltTemp)&&(temp<mymat->BoilTemp); };
int Tile::GetDeepness() { int h=0; for (int i=MAXMAT-1;i>=0;i--) if (mats[i]) if (IsLiquid(i)) h++; return h; }
void CWeaponFX::CreateExitDebris() { int i; // Create the surface specific exit fx... SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eExitSurface); if (!pSurf || !pSurf->bCanShootThrough) return; if (IsLiquid(m_eExitCode)) { // Create underwater fx... // Create any exit particle shower fx associated with this surface... for (i=0; i < pSurf->nNumUWExitPShowerFX; i++) { CPShowerFX* pPShowerFX = g_pSurfaceMgr->GetPShowerFX(pSurf->aUWExitPShowerFXIds[i]); g_pFXButeMgr->CreatePShowerFX(pPShowerFX, m_vExitPos, m_vExitNormal, m_vSurfaceNormal); } } else { // Create normal fx... // Create any exit scale fx associated with this surface... for (i=0; i < pSurf->nNumExitScaleFX; i++) { CScaleFX* pScaleFX = g_pSurfaceMgr->GetScaleFX(pSurf->aExitScaleFXIds[i]); g_pFXButeMgr->CreateScaleFX(pScaleFX, m_vExitPos, m_vExitNormal, &m_vExitNormal, &m_rSurfaceRot); } // Create any exit particle shower fx associated with this surface... for (i=0; i < pSurf->nNumExitPShowerFX; i++) { CPShowerFX* pPShowerFX = g_pSurfaceMgr->GetPShowerFX(pSurf->aExitPShowerFXIds[i]); g_pFXButeMgr->CreatePShowerFX(pPShowerFX, m_vExitPos, m_vExitNormal, m_vSurfaceNormal); } // Create any exit poly debris fx associated with this surface... for (i=0; i < pSurf->nNumExitPolyDebrisFX; i++) { CPolyDebrisFX* pPolyDebrisFX = g_pSurfaceMgr->GetPolyDebrisFX(pSurf->aExitPolyDebrisFXIds[i]); g_pFXButeMgr->CreatePolyDebrisFX(pPolyDebrisFX, m_vExitPos, m_vExitNormal, m_vExitNormal); } } // Determine if we should create a beam of light through the surface... CreateLightBeamFX(pSurf); }
void CGibFX::CreateLingeringSmoke(int nIndex) { CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return; uint8 nDetailLevel = pSettings->SpecialFXSetting(); if (nDetailLevel == RS_LOW) return; SMCREATESTRUCT sm; char* pTexture = "Sprites\\SmokeTest.spr"; VEC_SET(sm.vColor1, 100.0f, 100.0f, 100.0f); VEC_SET(sm.vColor2, 125.0f, 125.0f, 125.0f); VEC_SET(sm.vMinDriftVel, -10.0f, 25.0f, -10.0f); VEC_SET(sm.vMaxDriftVel, 10.0f, 50.0f, 10.0f); LTFLOAT fVolumeRadius = 10.0f; LTFLOAT fLifeTime = GetRandom(m_fLifeTime * 0.75f, m_fLifeTime); LTFLOAT fRadius = 1500; LTFLOAT fParticleCreateDelta = 0.1f; LTFLOAT fMinParticleLife = 1.0f; LTFLOAT fMaxParticleLife = 5.0f; uint8 nNumParticles = 3; LTBOOL bIgnoreWind = LTFALSE; if (IsLiquid(m_eCode)) { GetLiquidColorRange(m_eCode, &sm.vColor1, &sm.vColor2); pTexture = DEFAULT_BUBBLE_TEXTURE; fRadius = 750.0f; bIgnoreWind = LTTRUE; fMinParticleLife = 1.0f; fMaxParticleLife = 1.5f; } sm.vPos = m_Emitters[nIndex].m_vPos; sm.hServerObj = m_hGib[nIndex]; sm.fVolumeRadius = fVolumeRadius; sm.fLifeTime = fLifeTime; sm.fRadius = fRadius; sm.fParticleCreateDelta = fParticleCreateDelta; sm.fMinParticleLife = fMinParticleLife; sm.fMaxParticleLife = fMaxParticleLife; sm.nNumParticles = nNumParticles; sm.bIgnoreWind = bIgnoreWind; sm.hstrTexture = m_pClientDE->CreateString(pTexture); psfxMgr->CreateSFX(SFX_SMOKE_ID, &sm); m_pClientDE->FreeString(sm.hstrTexture); }
void CGibFX::CreateMiniBloodExplosion(int nIndex) { // Add a mini blood explosion... CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return; uint8 nDetailLevel = pSettings->SpecialFXSetting(); if (nDetailLevel == RS_LOW) return; char* szBlood[2] = { "SpecialFX\\ParticleTextures\\Blood_1.dtx", "SpecialFX\\ParticleTextures\\Blood_2.dtx" }; PARTICLESHOWERCREATESTRUCT ps; ps.vPos = m_Emitters[nIndex].m_vPos; ps.vPos.y += 30.0f; ps.vDir.Init(0, 100, 0); VEC_SET(ps.vColor1, 200.0f, 200.0f, 200.0f); VEC_SET(ps.vColor2, 255.0f, 255.0f, 255.0f); ps.pTexture = szBlood[GetRandom(0,1)];; ps.nParticles = 50; ps.fDuration = 1.0f; ps.fEmissionRadius = 0.3f; ps.fRadius = 800.0f; ps.fGravity = PSFX_DEFAULT_GRAVITY; if (IsLiquid(m_eCode)) { ps.vDir *= 3.0f; ps.fEmissionRadius = 0.2f; ps.fRadius = 700.0f; } psfxMgr->CreateSFX(SFX_PARTICLESHOWER_ID, &ps); // Play appropriate sound... char* pSound = GetGibDieSound(); if (pSound) { g_pClientSoundMgr->PlaySoundFromPos(ps.vPos, pSound, 300.0f, SOUNDPRIORITY_MISC_LOW); } }
void CWeaponFX::CreateWeaponSpecificFX() { // Do fire fx beam fx... if (m_pAmmo->pFireFX && m_pAmmo->pFireFX->nNumBeamFX > 0) { for (int i=0; i < m_pAmmo->pFireFX->nNumBeamFX; i++) { g_pFXButeMgr->CreateBeamFX(m_pAmmo->pFireFX->pBeamFX[i], m_vFirePos, m_vPos); } } // Only do impact fx if the client can see the impact position // or the impact fx may last a little while... if (g_bCanSeeImpactPos || m_pAmmo->fProgDamage > 0.0f || m_pAmmo->nAreaDamage > 0) { if (IsLiquid(m_eCode)) { // Create underwater weapon fx... IFXCS cs; cs.eCode = m_eCode; cs.eSurfType = m_eSurfaceType; cs.rSurfRot = m_rSurfaceRot; cs.vDir = m_vDir; cs.vPos = m_vPos; cs.vSurfNormal = m_vSurfaceNormal; cs.fBlastRadius = (LTFLOAT) m_pAmmo->nAreaDamageRadius; cs.fTintRange = (LTFLOAT) (m_pAmmo->nAreaDamageRadius * 5); g_pFXButeMgr->CreateImpactFX(m_pAmmo->pUWImpactFX, cs); } else { IFXCS cs; cs.eCode = m_eCode; cs.eSurfType = m_eSurfaceType; cs.rSurfRot = m_rSurfaceRot; cs.vDir = m_vDir; cs.vPos = m_vPos; cs.vSurfNormal = m_vSurfaceNormal; cs.fBlastRadius = (LTFLOAT) m_pAmmo->nAreaDamageRadius; cs.fTintRange = (LTFLOAT) (m_pAmmo->nAreaDamageRadius * 5); g_pFXButeMgr->CreateImpactFX(m_pAmmo->pImpactFX, cs); } } }
void CWeaponFX::CreateMuzzleFX() { CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; char* pTexture = "SFX\\Impact\\Spr\\Smoke.spr"; if (IsLiquid(m_eFirePosCode)) { pTexture = DEFAULT_BUBBLE_TEXTURE; } PARTICLESHOWERCREATESTRUCT sp; sp.vPos = m_vFirePos; sp.vDir = m_vSurfaceNormal * 10.0f; sp.pTexture = pTexture; sp.nParticles = 1; sp.fRadius = 400.0f; sp.fDuration = 1.0f; sp.fEmissionRadius = 0.05f; sp.fRadius = 800.0f; sp.fGravity = 0.0f; sp.vColor1.Init(100.0f, 100.0f, 100.0f); sp.vColor2.Init(125.0f, 125.0f, 125.0f); if (IsLiquid(m_eFirePosCode)) { GetLiquidColorRange(m_eFirePosCode, &sp.vColor1, &sp.vColor2); sp.fRadius = 600.0f; sp.fGravity = 50.0f; } psfxMgr->CreateSFX(SFX_PARTICLESHOWER_ID, &sp); }
int Tile::GetPic() { const unsigned int LEVEL_PIX[]={250,',','_','-',223,176,177,178}; int h=GetHeight(); //performance!!! if (h<0) return ' '; if (IsSolid(h)) return LEVEL_PIX[h]; if (IsLiquid(h)) //return '0'+h+1; return (h%2)?126:184; if (IsGas(h)) if (h>2) return '%'; else return '.'; return ' '; }
void InitMovingObject(MovingObject *pObject, DVector *pPos, DVector *pVelocity) { memset(pObject, 0, sizeof(MovingObject)); VEC_COPY(pObject->m_Pos, *pPos); VEC_COPY(pObject->m_LastPos, *pPos); VEC_COPY(pObject->m_Velocity, *pVelocity); ClientDE* pClientDE = g_normalPhysicsState.m_pClientDE; if (!pClientDE) return; // Determine if we are in any containers (like liquid) that would // affect physics... DDWORD dwUserFlags; HLOCALOBJ objList[1]; DDWORD dwNum = pClientDE->GetPointContainers(&pObject->m_Pos, objList, 1); if (dwNum > 0 && objList[0]) { pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); } if(dwNum > 0) { D_WORD code; if (pClientDE->GetContainerCode(objList[0], &code)) { ContainerCode eCode = (ContainerCode)code; if (IsLiquid(eCode)) { pObject->m_PhysicsFlags |= MO_LIQUID; } } } }
LTBOOL CWeaponFX::CreateObject(ILTClient* pClientDE) { if (!CSpecialFX::CreateObject(pClientDE) || !g_pWeaponMgr) return LTFALSE; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTFALSE; // Set up our data members... // Set the local client id... uint32 dwId; g_pLTClient->GetLocalClientID(&dwId); m_nLocalId = (uint8)dwId; m_nDetailLevel = pSettings->SpecialFXSetting(); // Fire pos may get tweaked a little... m_vFirePos = CalcFirePos(m_vFirePos); m_vDir = m_vPos - m_vFirePos; m_fFireDistance = m_vDir.Mag(); m_vDir.Norm(); g_pLTClient->AlignRotation(&m_rSurfaceRot, &m_vSurfaceNormal, LTNULL); g_pLTClient->AlignRotation(&m_rDirRot, &m_vDir, LTNULL); SetupExitInfo(); // Calculate if the camera can see the fire position and the impact // position... g_bCanSeeImpactPos = LTTRUE; g_bCanSeeFirePos = LTTRUE; g_bDistantImpactPos = LTFALSE; g_bDistantFirePos = LTFALSE; if (g_vtWeaponFXUseFOVPerformance.GetFloat()) { HOBJECT hCamera = g_pGameClientShell->GetCamera(); LTVector vCameraPos, vU, vR, vF, vDir; LTRotation rCameraRot; g_pLTClient->GetObjectPos(hCamera, &vCameraPos); g_pLTClient->GetObjectRotation(hCamera, &rCameraRot); g_pLTClient->GetRotationVectors(&rCameraRot, &vU, &vR, &vF); vDir = m_vPos - vCameraPos; LTFLOAT fImpactDist = vDir.Mag(); if (fImpactDist > g_vtWeaponFXMaxImpactDist.GetFloat()) { g_bDistantImpactPos = LTTRUE; } vDir.Norm(); LTFLOAT fMul = VEC_DOT(vDir, vF); g_bCanSeeImpactPos = (fMul < g_vtWeaponFXMinImpactDot.GetFloat() ? LTFALSE : LTTRUE); // In multiplayer we need to account for impacts that occur around // our camera that we didn't cause (this is also an issue in single // player, but due to the singler player gameplay dynamics it isn't // as noticeable)... if (!g_bCanSeeImpactPos && IsMultiplayerGame()) { // Somebody else shot this...if the impact is close enough, we // "saw" it... if (m_nLocalId != m_nShooterId && fImpactDist <= g_vtWeaponFXMaxMultiImpactDist.GetFloat()) { g_bCanSeeImpactPos = LTTRUE; } } vDir = m_vFirePos - vCameraPos; if (vDir.Mag() > g_vtWeaponFXMaxFireDist.GetFloat()) { g_bDistantFirePos = LTTRUE; } vDir.Norm(); fMul = VEC_DOT(vDir, vF); g_bCanSeeFirePos = (fMul < g_vtWeaponFXMinFireDot.GetFloat() ? LTFALSE : LTTRUE); } // Determine what container the sfx is in... HLOCALOBJ objList[1]; LTVector vTestPos = m_vPos + m_vSurfaceNormal; // Test a little closer... uint32 dwNum = g_pLTClient->GetPointContainers(&vTestPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; g_pLTClient->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (g_pLTClient->GetContainerCode(objList[0], &dwCode)) { m_eCode = (ContainerCode)dwCode; } } } // Determine if the fire point is in liquid vTestPos = m_vFirePos + m_vDir; // Test a little further in... dwNum = g_pLTClient->GetPointContainers(&vTestPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; g_pLTClient->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (g_pLTClient->GetContainerCode(objList[0], &dwCode)) { m_eFirePosCode = (ContainerCode)dwCode; } } } if (IsLiquid(m_eCode)) { m_wImpactFX = m_pAmmo->pUWImpactFX ? m_pAmmo->pUWImpactFX->nFlags : 0; } else { m_wImpactFX = m_pAmmo->pImpactFX ? m_pAmmo->pImpactFX->nFlags : 0; } m_wFireFX = m_pAmmo->pFireFX ? m_pAmmo->pFireFX->nFlags : 0; // Assume alt-fire, silenced, and tracer...these will be cleared by // IgnoreFX if not used... m_wFireFX |= WFX_ALTFIRESND | WFX_SILENCED | WFX_TRACER; // Assume impact ding, it will be cleared if not used... m_wImpactFX |= WFX_IMPACTDING; // Clear all the fire fx we want to ignore... m_wFireFX &= ~m_wIgnoreFX; m_wImpactFX &= ~m_wIgnoreFX; // See if this is a redundant weapon fx (i.e., this client shot the // weapon so they've already seen this fx)... if (g_pGameClientShell->IsMultiplayerGame()) { if (m_pAmmo->eType != PROJECTILE) { if (!m_bLocal && m_nLocalId >= 0 && m_nLocalId == m_nShooterId) { if (m_wImpactFX & WFX_IMPACTDING) { if (g_vtMultiDing.GetFloat()) { PlayImpactDing(); } } return LTFALSE; } } } // Show the fire path...(debugging...) if (g_cvarShowFirePath.GetFloat() > 0) { PLFXCREATESTRUCT pls; pls.vStartPos = m_vFirePos; pls.vEndPos = m_vPos; pls.vInnerColorStart = LTVector(GetRandom(127.0f, 255.0f), GetRandom(127.0f, 255.0f), GetRandom(127.0f, 255.0f)); pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = 1.0f; pls.fAlphaEnd = 1.0f; pls.fMinWidth = 0; pls.fMaxWidth = 10; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 10.0f; pls.fAlphaLifeTime = 10.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTFALSE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = 2; CSpecialFX* pFX = g_pGameClientShell->GetSFXMgr()->CreateSFX(SFX_POLYLINE_ID, &pls); if (pFX) pFX->Update(); } // If the surface is the sky, don't create any impact related fx... if (m_eSurfaceType != ST_SKY || (m_wImpactFX & WFX_IMPACTONSKY)) { CreateWeaponSpecificFX(); if (g_bCanSeeImpactPos) { if ((m_wImpactFX & WFX_MARK) && ShowsMark(m_eSurfaceType) && (LTBOOL)GetConsoleInt("MarkShow", 1)) { LTBOOL bCreateMark = LTTRUE; if (g_bDistantImpactPos && m_nLocalId == m_nShooterId) { // Assume we'll see the mark if we're zoomed in ;) bCreateMark = g_pGameClientShell->IsZoomed(); } if (bCreateMark) { CreateMark(m_vPos, m_vSurfaceNormal, m_rSurfaceRot, m_eSurfaceType); } } CreateSurfaceSpecificFX(); } PlayImpactSound(); } if (IsBulletTrailWeapon()) { if (IsLiquid(m_eFirePosCode)) { if (m_nDetailLevel != RS_LOW) { CreateBulletTrail(&m_vFirePos); } } } // No tracers under water... if ((LTBOOL)GetConsoleInt("Tracers", 1) && (m_wFireFX & WFX_TRACER) && !IsLiquid(m_eCode)) { CreateTracer(); } if (g_bCanSeeFirePos) { // Only do muzzle fx for the client (not for AIs)... if ((m_wFireFX & WFX_MUZZLE) && (m_nLocalId == m_nShooterId)) { CreateMuzzleFX(); } if (!g_bDistantFirePos && (LTBOOL)GetConsoleInt("ShellCasings", 1) && (m_wFireFX & WFX_SHELL)) { CreateShell(); } if ((m_wFireFX & WFX_LIGHT)) { CreateMuzzleLight(); } } if ((m_wFireFX & WFX_FIRESOUND) || (m_wFireFX & WFX_ALTFIRESND) || (m_wFireFX & WFX_SILENCED)) { PlayFireSound(); } // Only do fly-by sounds for weapons that leave bullet trails... if (IsBulletTrailWeapon()) { PlayBulletFlyBySound(); } return LTFALSE; // Just delete me, I'm done :) }
LTBOOL CParticleTrailSegmentFX::CreateObject(ILTClient *pClientDE) { if (!pClientDE || !m_hServerObject) return LTFALSE; if (m_nType & PT_SMOKE_LONG) { m_pTextureName = "SFX\\Smoke\\Spr\\WhiteTrailLong.spr"; m_basecs.bAdjustParticleScale = LTTRUE; m_basecs.fStartParticleScale = g_cvarSmokeTrailStartScale.GetFloat(); m_basecs.fEndParticleScale = g_cvarSmokeTrailLWEndScale.GetFloat(); m_basecs.bAdjustParticleAlpha = LTTRUE; m_basecs.fStartParticleAlpha = g_cvarSmokeTrailStartAlpha.GetFloat(); m_basecs.fEndParticleAlpha = g_cvarSmokeTrailEndAlpha.GetFloat(); } else if (m_nType & PT_SMOKE) { m_pTextureName = "SFX\\Smoke\\Spr\\WhiteTrailShort.spr"; m_basecs.bAdjustParticleScale = LTTRUE; m_basecs.fStartParticleScale = g_cvarSmokeTrailStartScale.GetFloat(); m_basecs.fEndParticleScale = g_cvarSmokeTrailSWEndScale.GetFloat(); m_basecs.bAdjustParticleAlpha = LTTRUE; m_basecs.fStartParticleAlpha = g_cvarSmokeTrailStartAlpha.GetFloat(); m_basecs.fEndParticleAlpha = g_cvarSmokeTrailEndAlpha.GetFloat(); } else if (m_nType & PT_SMOKE_BLACK) { m_pTextureName = "SFX\\Smoke\\Spr\\BlackTrailShort.spr"; m_basecs.bAdjustParticleScale = LTTRUE; m_basecs.fStartParticleScale = g_cvarSmokeTrailStartScale.GetFloat(); m_basecs.fEndParticleScale = g_cvarSmokeTrailSBEndScale.GetFloat(); m_basecs.bAdjustParticleAlpha = LTTRUE; m_basecs.fStartParticleAlpha = g_cvarSmokeTrailStartAlpha.GetFloat(); m_basecs.fEndParticleAlpha = g_cvarSmokeTrailEndAlpha.GetFloat(); } else if ((m_nType & PT_GIBSMOKE)) { m_pTextureName = "SFX\\Impact\\Spr\\Smoke.spr"; m_basecs.bAdjustParticleScale = LTTRUE; m_basecs.fStartParticleScale = g_cvarSmokeTrailStartScale.GetFloat(); m_basecs.fEndParticleScale = g_cvarSmokeTrailSWEndScale.GetFloat(); m_basecs.bAdjustParticleAlpha = LTTRUE; m_basecs.fStartParticleAlpha = g_cvarSmokeTrailStartAlpha.GetFloat(); m_basecs.fEndParticleAlpha = g_cvarSmokeTrailEndAlpha.GetFloat(); } else if (m_nType & PT_BLOOD) { if (GetRandom(0, 1) == 0) { m_pTextureName = "SFX\\Particle\\Blood_1.dtx"; } else { m_pTextureName = "SFX\\Particle\\Blood_2.dtx"; } } // Determine if we are in a liquid... LTVector vPos; pClientDE->GetObjectPos(m_hServerObject, &vPos); HLOCALOBJ objList[1]; uint32 dwNum = pClientDE->GetPointContainers(&vPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (pClientDE->GetContainerCode(objList[0], &dwCode)) { if (IsLiquid((ContainerCode)dwCode)) { // Don't create blood under water... if (m_nType & PT_BLOOD) { m_bWantRemove = LTTRUE; m_fLifeTime = 0.0f; m_fFadeTime = 0.0f; return LTFALSE; } m_fRadius = 500.0f; m_fGravity = 5.0f; m_nNumPerPuff *= 3; m_bIgnoreWind = LTTRUE; m_pTextureName = DEFAULT_BUBBLE_TEXTURE; GetLiquidColorRange((ContainerCode)dwCode, &m_vColor1, &m_vColor2); } } } } return CBaseParticleSystemFX::CreateObject(pClientDE); }
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 VolumeBrush::UpdatePhysics(ContainerPhysics* pCPStruct) { CServerDE* pServerDE = GetServerDE(); if (m_bHidden || !pServerDE || !pCPStruct || !pCPStruct->m_hObject) return; DFLOAT fUpdateDelta = pServerDE->GetFrameTime(); // Check to see if this object is the player object... if (!pServerDE->IsKindOf(pServerDE->GetObjectClass(pCPStruct->m_hObject), m_hPlayerClass)) { // Check to see if this object is a character object... DBOOL bCharacter = DFALSE; HCLASS hBaseCharClass = pServerDE->GetClass("CBaseCharacter"); if (pServerDE->IsKindOf(pServerDE->GetObjectClass(pCPStruct->m_hObject), hBaseCharClass)) { bCharacter = DTRUE; if (m_bLocked) { // See if they have the key we need to unlock HMESSAGEWRITE hMessage = pServerDE->StartMessageToObject((LPBASECLASS)this, pCPStruct->m_hObject, MID_KEYQUERY); pServerDE->WriteToMessageHString(hMessage, m_hstrKeyName); pServerDE->EndMessage(hMessage); } } // Update velocity... // Dampen velocity and acceleration based on the viscosity of the container... if (m_fViscosity > 0.0f) { VEC_MULSCALAR(pCPStruct->m_Velocity, pCPStruct->m_Velocity, m_fViscosity); VEC_MULSCALAR(pCPStruct->m_Acceleration, pCPStruct->m_Acceleration, m_fViscosity); } // Do special liquid / zero gravity handling... if (IsLiquid(m_eContainerCode)) { UpdateLiquidPhysics(pCPStruct, bCharacter); } // Add any current... // Make current relative to update delta (actually change the REAL velocity)... DVector vCurrent; VEC_MULSCALAR(vCurrent, m_vCurrent, fUpdateDelta); VEC_ADD(pCPStruct->m_Velocity, pCPStruct->m_Velocity, vCurrent); } // Update damage... // Make damage relative to update delta... if (m_fDamage) { DFLOAT fTime = pServerDE->GetTime(); DFLOAT fDamageDeltaTime = fTime - m_fLastDamageTime; if (fDamageDeltaTime >= DAMAGE_UPDATE_DELTA || fTime == m_fLastDamageTime) { m_fLastDamageTime = fTime; DVector vDir; VEC_INIT(vDir); DamageObject(m_hObject, this, pCPStruct->m_hObject, m_fDamage * DAMAGE_UPDATE_DELTA, vDir, vDir, m_nDamageType); } } }
void VolumeBrush::UpdatePhysics(ContainerPhysics* pCPStruct) { if (m_bHidden || !pCPStruct || !pCPStruct->m_hObject) return; LTFLOAT fUpdateDelta = g_pLTServer->GetFrameTime(); // Let the character know if they are in liquid... if (IsLiquid(m_eContainerCode) && IsCharacter(pCPStruct->m_hObject)) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(pCPStruct->m_hObject); if (pCharacter) { pCharacter->UpdateInLiquid(this, pCPStruct); } } // Player container physics is done on the client... if (!IsPlayer(pCPStruct->m_hObject)) { // Dampen velocity based on the viscosity of the container... LTVector vVel, vCurVel; vVel = vCurVel = pCPStruct->m_Velocity; if (m_fViscosity > 0.0f && VEC_MAG(vCurVel) > 1.0f) { LTVector vDir; VEC_COPY(vDir, vCurVel); VEC_NORM(vDir); LTFLOAT fAdjust = MAX_CONTAINER_VISCOSITY * m_fViscosity * fUpdateDelta; vVel = (vDir * fAdjust); if (VEC_MAG(vVel) < VEC_MAG(vCurVel)) { VEC_SUB(vVel, vCurVel, vVel); } else { VEC_INIT(vVel); } vVel += (m_vCurrent * fUpdateDelta); pCPStruct->m_Velocity = vVel; } // Do special liquid handling... if (IsLiquid(m_eContainerCode)) { UpdateLiquidPhysics(pCPStruct); } } // Update damage... // Make damage relative to update delta... LTFLOAT fDamage = 0.0f; if (m_fDamage > 0.0f) { fDamage = m_fDamage * fUpdateDelta; } // Damage using progressive damage. This insures that the correct // damage effect is shown on the client... if (fDamage) { DamageStruct damage; damage.eType = m_eDamageType; damage.fDamage = fDamage; damage.hDamager = m_hObject; // Use progressive damage... damage.fDuration = 0.25f; damage.hContainer = m_hObject; damage.DoDamage(this, pCPStruct->m_hObject); } }
void CWeaponFX::CreateSurfaceSpecificFX() { CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return; // Don't do gore fx... if (m_eSurfaceType == ST_FLESH) { if (!pSettings->Gore()) { return; } if (m_pAmmo->eType == VECTOR && m_pAmmo->eInstDamageType == DT_BULLET) { CreateBloodSplatFX(); } } if ((m_wFireFX & WFX_EXITMARK) && ShowsMark(m_eExitSurface)) { CreateExitMark(); } if (m_wFireFX & WFX_EXITDEBRIS) { CreateExitDebris(); } if (!m_pAmmo || !m_pAmmo->pImpactFX) return; if (!m_pAmmo->pImpactFX->bDoSurfaceFX) return; // Create the surface specific fx... int i; SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eSurfaceType); if (pSurf) { if (IsLiquid(m_eCode)) { // Create underwater fx... // Create any impact particle shower fx associated with this surface... for (i=0; i < pSurf->nNumUWImpactPShowerFX; i++) { CPShowerFX* pPShowerFX = g_pSurfaceMgr->GetPShowerFX(pSurf->aUWImpactPShowerFXIds[i]); g_pFXButeMgr->CreatePShowerFX(pPShowerFX, m_vPos, m_vDir, m_vSurfaceNormal); } } else { // Create normal fx... // Create any impact scale fx associated with this surface... for (i=0; i < pSurf->nNumImpactScaleFX; i++) { CScaleFX* pScaleFX = g_pSurfaceMgr->GetScaleFX(pSurf->aImpactScaleFXIds[i]); g_pFXButeMgr->CreateScaleFX(pScaleFX, m_vPos, m_vDir, &m_vSurfaceNormal, &m_rSurfaceRot); } // Create any impact particle shower fx associated with this surface... for (i=0; i < pSurf->nNumImpactPShowerFX; i++) { CPShowerFX* pPShowerFX = g_pSurfaceMgr->GetPShowerFX(pSurf->aImpactPShowerFXIds[i]); g_pFXButeMgr->CreatePShowerFX(pPShowerFX, m_vPos, m_vDir, m_vSurfaceNormal); } // Create any impact poly debris fx associated with this surface... if (g_vtCreatePolyDebris.GetFloat()) { for (i=0; i < pSurf->nNumImpactPolyDebrisFX; i++) { CPolyDebrisFX* pPolyDebrisFX = g_pSurfaceMgr->GetPolyDebrisFX(pSurf->aImpactPolyDebrisFXIds[i]); g_pFXButeMgr->CreatePolyDebrisFX(pPolyDebrisFX, m_vPos, m_vDir, m_vSurfaceNormal); } } } } }
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++; }