uint32 CDestructibleModel::ObjectMessageFn(LPBASECLASS pObject, HOBJECT hSender, ILTMessage_Read *pMsg) { uint32 dwRet = CDestructible::ObjectMessageFn(pObject, hSender, pMsg); pMsg->SeekTo(0); uint32 messageID = pMsg->Readuint32(); switch(messageID) { case MID_DAMAGE: { if (IsDead() && !( m_DestructibleModelFlags & kDestructibleModelFlag_Destroyed )) { //read in the damage structure DamageStruct ds; ds.InitFromMessage(pMsg); HandleObjectDestroyed(ds); m_DestructibleModelFlags |= kDestructibleModelFlag_Destroyed; } } break; default : break; } return dwRet; }
void Breakable::Destroy() { // Destroy us... HOBJECT hObj = LTNULL; LTVector vDir(0, 0, 0); DamageStruct damage; damage.eType = DT_EXPLODE; damage.fDamage = damage.kInfiniteDamage; damage.hDamager = hObj; damage.vDir = vDir; damage.DoDamage(this, m_hObject); }
uint32 Body::ObjectMessageFn(HOBJECT hSender, uint32 messageID, HMESSAGEREAD hRead) { switch(messageID) { case MID_DAMAGE: { DamageStruct damage; damage.InitFromMessage(hRead); HandleDamage(damage); } break; default : break; } return Prop::ObjectMessageFn(hSender, messageID, hRead); }
void Breakable::CrushObject(HOBJECT hObj) { if (!hObj) return; LTVector vPos; LTVector vHisPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); g_pLTServer->GetObjectPos(m_hObject, &vHisPos); LTVector vDir = vPos - vHisPos; vDir.Norm(); DamageStruct damage; damage.eType = DT_CRUSH; damage.fDamage = damage.kInfiniteDamage; damage.hDamager = m_hObject; damage.vDir = vDir; damage.DoDamage(this, hObj); }
void WorldModel::RemoveAtachments( ) { // Remove all the objects attached to us. while( m_AttachmentList.size( )) { HOBJECT hObj = *m_AttachmentList.begin( ); if( !hObj ) { m_AttachmentList.erase( m_AttachmentList.begin( )); continue; } // This will remove it from our attachment list. DetachObject( hObj ); if( m_bRemoveAttachments ) { g_pLTServer->RemoveObject( hObj ); } else // Let the object destroy itself... { DamageStruct damage; damage.eType = DT_EXPLODE; damage.fDamage = damage.kInfiniteDamage; damage.hDamager = m_hObject; damage.vDir.Init( 0.0f, 1.0f, 0.0f ); damage.DoDamage( this, hObj ); } } // Clear our other lists. m_AttachMsgObjList.clear( ); m_MarkList.clear( ); m_hAttachDirObj = NULL; }
void CProjectile::ImpactDamageObject(HOBJECT hDamager, HOBJECT hObj) { DamageStruct damage; damage.hDamager = hDamager; damage.vDir = m_vDir; // Do Instant damage... if (m_fInstDamage > 0.0f) { damage.eType = m_eInstDamageType; damage.fDamage = m_fInstDamage; damage.DoDamage(this, hObj); } // Do Progressive damage...(if the progressive damage is supposed to // happen over time, it will be done in the explosion object).... if (m_fProgDamage > 0.0f && m_pAmmoData->fProgDamageLifetime <= 0.0f) { damage.eType = m_eProgDamageType; damage.fDamage = m_fProgDamage; damage.fDuration = m_pAmmoData->fProgDamageDuration; damage.DoDamage(this, hObj); } // Update player summary info... CPlayerObj* pPlayer; if (IsPlayer(hDamager) && IsCharacter(hObj) && IsAccuracyType(m_eInstDamageType)) { CCharacter* pChar = (CCharacter*) g_pLTServer->HandleToObject(hObj); pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hDamager); if (pPlayer) { ModelNode eModelNode = pChar->GetModelNodeLastHit(); if (eModelNode != eModelNodeInvalid) { HitLocation eLoc = g_pModelButeMgr->GetSkeletonNodeLocation(pChar->GetModelSkeleton(),eModelNode); pPlayer->GetPlayerSummaryMgr()->IncNumHits(eLoc); } else { pPlayer->GetPlayerSummaryMgr()->IncNumHits(HL_UNKNOWN); } } } if (IsPlayer(hObj)) { pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hObj); if (pPlayer) { pPlayer->GetPlayerSummaryMgr()->IncNumTimesHit(); } } }
bool DoomsDayDevice::DamageVictims( bool& bAllDead ) { TRACE( "DoomsDayDevice::DamageVictims\n" ); char szDamageType[256]; if( !g_pServerButeMgr->GetDoomsDayDeviceDamageType( szDamageType, ARRAY_LEN( szDamageType ))) { return false; } DamageStruct damage; damage.eType = StringToDamageType( szDamageType ); damage.fDamage = g_pServerButeMgr->GetDoomsDayDeviceDamageAmount( ); damage.hDamager = m_hObject; damage.fDuration = 30.0f; // Initialize the status to all the players being dead. bAllDead = true; // Find all the victim teams and kill them. uint8 nNumTeams = CTeamMgr::Instance( ).GetNumTeams( ); for( uint8 nTeam = 0; nTeam < nNumTeams; nTeam++ ) { // Skip the activating team. if( nTeam == m_nOwningTeamID ) continue; CTeam* pTeam = CTeamMgr::Instance( ).GetTeam( nTeam ); if( !pTeam ) { ASSERT( !"DoomsDayDevice::DamageVictims: Invalid team." ); continue; } // Iterate over each player on the team and kill him. PlayerIDSet const& players = pTeam->GetPlayerIDSet( ); PlayerIDSet::const_iterator iter = players.begin( ); while( iter != players.end( )) { uint32 nClientId = *iter; iter++; HCLIENT hClient = g_pLTServer->GetClientHandle( nClientId ); if( !hClient ) continue; CPlayerObj* pTeamPlayer = ( CPlayerObj* )g_pLTServer->GetClientUserData( hClient ); if( !pTeamPlayer ) continue; // Skip if already dead. if( pTeamPlayer->IsDead( )) continue; // This player is still alive, so update the status variable. bAllDead = false; // Do the damage. damage.DoDamage( this, pTeamPlayer->m_hObject ); } } return true; }
void Lock::HandleGadgetMsg(HOBJECT hSender, ConParse & parse) { if (parse.m_nArgs < 2 || !parse.m_Args[1]) return; AMMO* pAmmo = g_pWeaponMgr->GetAmmo(atol(parse.m_Args[1])); if (!pAmmo) return; LTBOOL bProcess = LTFALSE; if (m_bWeldable && pAmmo->eInstDamageType == DT_GADGET_WELDER) { bProcess = LTTRUE; } else if (m_bLightable && pAmmo->eInstDamageType == DT_GADGET_LIGHTER) { bProcess = LTTRUE; } else if (!m_bWeldable && pAmmo->eInstDamageType == DT_GADGET_LOCK_PICK) { bProcess = LTTRUE; } if (!bProcess) return; // Pick the lock by doing lock-pick damage to it... DamageStruct damage; damage.eType = pAmmo->eInstDamageType; damage.fDamage = GetRandom(m_fMinUnlockHitPts, m_fMaxUnlockHitPts); damage.vDir.Init(0, 1, 0); damage.hDamager = m_hObject; damage.DoDamage(this, m_hObject); // Play the lock pick sound... LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); if (m_hstrPickSnd) { char* pSound = g_pLTServer->GetStringData(m_hstrPickSnd); if (pSound) { g_pServerSoundMgr->PlaySoundFromPos(vPos, pSound, m_fSndRadius, SOUNDPRIORITY_MISC_MEDIUM); } } // Do fx for welding the lock... if (m_bWeldable && pAmmo->eInstDamageType == DT_GADGET_WELDER) { WEAPON* pWeapon = g_pWeaponMgr->GetWeapon("Lighter"); if (!pWeapon) return; SURFACE* pSurf = g_pSurfaceMgr->GetSurface("Metal"); if (!pSurf) return; LTVector vHisPos; g_pLTServer->GetObjectPos(hSender, &vHisPos); LTVector vDir = vHisPos - vPos; vDir.Norm(); CLIENTWEAPONFX fxStruct; fxStruct.hFiredFrom = hSender; fxStruct.vSurfaceNormal = vDir; fxStruct.vFirePos = vHisPos; fxStruct.vPos = vPos + vDir; fxStruct.hObj = m_hObject; fxStruct.nWeaponId = pWeapon->nId; fxStruct.nAmmoId = pAmmo->nId; fxStruct.nSurfaceType = pSurf->eType; // This should be a player object, get the client id... if (IsPlayer(hSender)) { CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hSender); if (pPlayer) { fxStruct.nShooterId = (uint8) g_pLTServer->GetClientID(pPlayer->GetClient()); } } CreateClientWeaponFX(fxStruct); } }
uint32 Lock::ObjectMessageFn(HOBJECT hSender, uint32 messageID, HMESSAGEREAD hRead) { if (!g_pLTServer) return 0; switch(messageID) { case MID_TRIGGER: { ILTCommon* pCommon = g_pLTServer->Common(); if (!pCommon) return 0; 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 (pCommon->Parse(&parse) == LT_OK) { if (parse.m_nArgs > 0 && parse.m_Args[0]) { if (_stricmp(parse.m_Args[0], s_szGadget) == 0) { HandleGadgetMsg(hSender, parse); } } } } break; case MID_DAMAGE: { if (m_bUnlocked) break; uint32 dwRet = 0; DamageStruct damage; damage.InitFromMessage(hRead); LTBOOL bProcessDamage = m_bShootable; if (!bProcessDamage) { if (m_bWeldable) { bProcessDamage = (damage.eType == DT_GADGET_WELDER); } else if (m_bLightable) { bProcessDamage = (damage.eType == DT_GADGET_LIGHTER); } else { bProcessDamage = (damage.eType == DT_GADGET_LOCK_PICK); } } if (bProcessDamage) { dwRet = Prop::ObjectMessageFn(hSender, messageID, hRead); if (m_damage.IsDead()) { SetupUnlockState(); } } return dwRet; } break; default : break; } return Prop::ObjectMessageFn(hSender, messageID, hRead); }
bool CAISensorInstantDeath::UpdateSensor() { if( !super::UpdateSensor() ) { return false; } // This sensor is somewhat of a hack. It was added because the AIActionInstantDeath // runs a couple frames too late to catch all situations where we would like AI to // die instantly. Ideally, we would refactor the way we handle damage to allow // more immediate planner reaction. // This sensor is irrelevant once the AI has targeted something. if( m_pAI->GetAIBlackBoard()->GetBBTargetType() != kTarget_None ) { m_pAI->GetAISensorMgr()->RemoveAISensor( kSensor_InstantDeath ); return false; } // Sanity check. CDestructible *pDestructible = m_pAI->GetDestructible(); if( !pDestructible ) { return false; } // No new damage. if( pDestructible->GetLastDamageTime() == 0.f ) { return false; } // This sensor is irrelevant after the first time we have been damaged. m_pAI->GetAISensorMgr()->RemoveAISensor( kSensor_InstantDeath ); // Don't die instantly if NeverDestroy is set. if( pDestructible->GetNeverDestroy() ) { return false; } // AI cannot take damage. if ( !m_pAI->GetDestructible()->GetCanDamage() ) { return false; } // AI does not accept this type of damage. DamageStruct Damage = m_pAI->GetAIBlackBoard()->GetBBLastDamage(); if( pDestructible->IsCantDamageType( Damage.eType ) ) { return false; } // Die instantly if taken by surprise and hit in the head or torso. if( m_pAI->GetAIBlackBoard()->GetBBTargetType() == kTarget_None ) { // Determine which body part was hit. ModelsDB::HNODE hModelNode = m_pAI->GetModelNodeLastHit(); if( hModelNode ) { EnumAnimProp eBodyAnipProp = g_pModelsDB->GetNodeBodyAnimProp( hModelNode ); if( ( eBodyAnipProp == kAP_BODY_Head ) || ( eBodyAnipProp == kAP_BODY_Torso ) ) { // Die instantly! Use the data from the last damage received -- just // lower the AI's hitpoints to less than 1. This will insure this action behaves // exactly like a standard death without any additional prompting. pDestructible->SetHitPoints( 0.1f ); pDestructible->SetArmorPoints( 0.0f ); Damage.fDamage = 2.0f; Damage.DoDamage( m_pAI->m_hObject, m_pAI->m_hObject ); // Die silently. m_pAI->SetLastPainVolume( 0.1f ); return true; } } } // Always allow other sensors to update. return false; }
bool ServerPhysicsCollisionMgr::StartDamageResponse( CollisionResponse& collisionResponse ) { // Get the other actor in this pair. CollisionActor const* pOtherActor = collisionResponse.GetCollisionActor()->GetOtherCollisionActor(); // If the other actor doesn't have an object, then there's nothing to damage. if( !pOtherActor->GetObject( )) return false; // Get the damage struct. HATTRIBUTE hStruct = DATABASE_CATEGORY( CollisionProperty ).GETSTRUCTSTRUCT( Responses, collisionResponse.GetResponses(), collisionResponse.GetResponsesIndex( ), Damage ); if( !hStruct ) return false; // Get the damageresponses struct. HATTRIBUTE hResponses = DATABASE_CATEGORY( CollisionProperty ).GETSTRUCTSTRUCT( Damage, hStruct, 0, DamageResponses ); if( !hResponses ) return false; uint32 nIndexFound; uint32 nImpulseFound; if( !FindImpulseInTable( collisionResponse.GetImpulse( ), hResponses, DamageImpulseAccessCB, nIndexFound, nImpulseFound )) return false; // Get the damagetype record. HRECORD hDamageRecord = DATABASE_CATEGORY( CollisionProperty ).GETSTRUCTATTRIB( DamageResponses, hResponses, nIndexFound, DamageType ); if( !hDamageRecord ) return false; // Get who to damage. DamageWho eDamageWho = FindDamageWho( hStruct ); // Do the damage. DamageStruct damage; damage.eType = g_pDTDB->GetDamageType( hDamageRecord ); damage.fDamage = DATABASE_CATEGORY( CollisionProperty ).GETSTRUCTATTRIB( DamageResponses, hResponses, nIndexFound, Amount ); damage.fPenetration = 0.0f; damage.fImpulseForce = 0.0f; // No impulse force, since we're already doing that. damage.hContainer = NULL; damage.SetPositionalInfo( collisionResponse.GetCollisionPoint( ), collisionResponse.GetCollisionNormal( )); // Do the damage to appropriate object. if( eDamageWho == eDamageWho_Me || eDamageWho == eDamageWho_Both ) { damage.hDamager = pOtherActor->GetObject( ); damage.DoDamage( pOtherActor->GetObject( ), collisionResponse.GetCollisionActor( )->GetObject( )); } if( eDamageWho == eDamageWho_Them || eDamageWho == eDamageWho_Both ) { damage.hDamager = collisionResponse.GetCollisionActor( )->GetObject( ); damage.DoDamage( collisionResponse.GetCollisionActor( )->GetObject( ), pOtherActor->GetObject( )); } #ifndef _FINAL uint32 nStatsLevel; bool bServer; HRECORD hCollisionPropertyFilter = NULL; CollisionStatsLevel( nStatsLevel, bServer, hCollisionPropertyFilter ); if( nStatsLevel > 0 && ( !hCollisionPropertyFilter || hCollisionPropertyFilter == collisionResponse.GetCollisionProperty())) { g_pLTBase->CPrint( "S: DamageType(%s) Amount(%.3f)", g_pLTDatabase->GetRecordName( hDamageRecord ), damage.fDamage ); } #endif // _FINAL return true; }
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); } }