Пример #1
0
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);
}
Пример #3
0
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);
}
Пример #5
0
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();
		}
	}
}
Пример #7
0
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;
}
Пример #8
0
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);
	}
}
Пример #9
0
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);
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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);
	}
}