예제 #1
0
void GearItem::PickedUp(ILTMessage_Read *pMsg)
{
	// Did we really pick it up?

	bool bPickedUp = (pMsg ? pMsg->Readbool() : true);

	// If we were touched by a player, our m_hPlayerObj data member will be
	// set.  Send a message to that player's client letting it know that an
	// item has been picked up...

	if (m_hPlayerObj)
	{
        CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hPlayerObj);
		if (pPlayer && !pPlayer->IsDead())
		{
			HCLIENT hClient = pPlayer->GetClient();
			if (hClient)
			{
				CAutoMessage cMsg;
				cMsg.Writeuint8(MID_GEAR_PICKEDUP);
				cMsg.Writeuint8((uint8)m_nGearId);
				cMsg.Writebool(bPickedUp);
				g_pLTServer->SendToClient(cMsg.Read(), hClient, MESSAGE_GUARANTEED);
			}
		}
	}

	if (bPickedUp)
	{
		PickupItem::PickedUp(pMsg);
		
		if( m_bRespawn )
		{
			GEAR const *pGear = g_pWeaponMgr->GetGear( m_nGearId );
			if( !pGear )
				return;

			// Change the skins and renderstyles to the waiting to respawn files...

			ObjectCreateStruct ocs;

			pGear->blrRespawnWaitSkins.CopyList( 0, ocs.m_SkinNames[0], MAX_CS_FILENAME_LEN + 1 );
			pGear->blrRespawnWaitRenderStyles.CopyList( 0, ocs.m_RenderStyleNames[0], MAX_CS_FILENAME_LEN + 1 );

			if( pGear->blrRespawnWaitRenderStyles.GetNumItems() < 1 )
				LTStrCpy( ocs.m_RenderStyleNames[0], s_szDefaultRS, ARRAY_LEN( s_szDefaultRS ));
			
			g_pCommonLT->SetObjectFilenames( m_hObject, &ocs );

			// Stop playing PowerupFX and play RespawnWaitFX...
		
			SetClientFX( pGear->szRespawnWaitFX );

			// Set our visibility...

			g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, pGear->bRespawnWaitVisible ? FLAG_VISIBLE : 0, FLAG_VISIBLE );
			g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags2, pGear->bRespawnWaitTranslucent ? FLAG2_FORCETRANSLUCENT : 0, FLAG2_FORCETRANSLUCENT );
		}
	}
}
예제 #2
0
LTBOOL PlayerTrigger::Activate()
{
	if (g_pGameServerShell->IsPaused())
	{
		return LTFALSE;
	}

	// Find all the objects within the trigger...

	LTVector vDims;
	g_pPhysicsLT->GetObjectDims( m_hObject, &vDims );

	LTVector vPos;
	g_pLTServer->GetObjectPos( m_hObject, &vPos );

	LTVector vMin = vPos - vDims;
	LTVector vMax = vPos + vDims;

	ObjectList *pObjList = g_pLTServer->GetBoxIntersecters( &vMin, &vMax );
	if( !pObjList )
		return LTFALSE;

	// Count the number of players in the trigger and activate only if
	// ALL players in the game are within the trigger...

	HOBJECT hObj;
	uint32	nPlayersInGame = CPlayerObj::GetNumberPlayersWithClients( );

	// Don't trigger if there are no players in the game.
	if( nPlayersInGame == 0 )
		return LTFALSE;

	uint32	nPlayersInTrigger = 0;

	ObjectLink *pLink = pObjList->m_pFirstLink;
	while( pLink )
	{
		hObj = pLink->m_hObject;
		CPlayerObj* pPlayerObj = dynamic_cast< CPlayerObj* >( g_pLTServer->HandleToObject( hObj ));

		// Only count live players with loaded clients.
		if( pPlayerObj && !pPlayerObj->IsDead( ) && pPlayerObj->IsClientLoaded( ))
		{
			++nPlayersInTrigger;
		}
	
		pLink = pLink->m_pNext;
	}
	
	g_pLTServer->RelinquishList( pObjList );

	if( nPlayersInTrigger != nPlayersInGame )
		return LTFALSE;

	// Ok! All the players are acounted for.
	// Let the base Trigger object activate.

	return Trigger::Activate();
}
예제 #3
0
bool PickupItem::OnTrigger(HOBJECT hSender, const CParsedMsg &cMsg)
{
	static CParsedMsg::CToken s_cTok_Activate("ACTIVATE");
	static CParsedMsg::CToken s_cTok_Team( "TEAM" );

	if( cMsg.GetArg(0) == s_cTok_Activate )
	{
		// Can't activate before we've respawned.
		if( m_bWasPickedUp )
			return true;

		// If the object is dead, it can't pick up stuff...

		if (IsPlayer(hSender))
		{
			CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hSender);

			if (!pPlayer || pPlayer->IsDead()) return true;

			SetPlayerObj(hSender);

			ObjectTouch(hSender);
		}
		else
		{
			SetPlayerObj(LTNULL);
			return true;
		}
	}
	else if (cMsg.GetArg(0) == s_cTok_Team)
	{
		if( cMsg.GetArgCount( ) > 1 )
		{
			uint32 nTeamId = atoi( cMsg.GetArg( 1 ));
			if( nTeamId < MAX_TEAMS )
			{
				SetTeamId( nTeamId );
			}
			else
			{
				SetTeamId( INVALID_TEAM );
			}

			return true;
		}
	}
	else
		return GameBase::OnTrigger(hSender, cMsg);

	return true;
}
void GearItem::ObjectTouch(HOBJECT hObject)
{
	if (!hObject) return;

	// If we hit non-player objects, just ignore them...

	if (IsPlayer(hObject))
	{
        CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObject);

		if (pPlayer && !pPlayer->IsDead())
		{
            HMESSAGEWRITE hMessage = g_pLTServer->StartMessageToObject(this, hObject, MID_ADDGEAR);
            g_pLTServer->WriteToMessageByte(hMessage, m_nGearId);
            g_pLTServer->EndMessage(hMessage);
		}
	}
}
예제 #5
0
void ModItem::ObjectTouch(HOBJECT hObject, bool bForcePickup/*=false*/)
{
    if (!hObject) return;

    // If we hit non-player objects, just ignore them...

    if (IsPlayer(hObject))
    {
        CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObject);

        if (pPlayer && !pPlayer->IsDead())
        {
            SetPlayerObj(hObject);

            CAutoMessage cMsg;
            cMsg.Writeuint32(MID_ADDMOD);
            cMsg.Writeuint8((uint8)m_nModId);
            g_pLTServer->SendToObject(cMsg.Read(), m_hObject, hObject, MESSAGE_GUARANTEED);
        }
    }
}
void GearItem::PickedUp(HMESSAGEREAD hRead)
{
	// If we were touched by a player, our m_hPlayerObj data member will be
	// set.  Send a message to that player's client letting it know that an
	// item has been picked up...

	if (m_hPlayerObj)
	{
        CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hPlayerObj);
		if (pPlayer && !pPlayer->IsDead())
		{
			HCLIENT hClient = pPlayer->GetClient();
			if (hClient)
			{
                HMESSAGEWRITE hWrite = g_pLTServer->StartMessage(hClient, MID_GEAR_PICKEDUP);
                g_pLTServer->WriteToMessageByte(hWrite, m_nGearId);
                g_pLTServer->EndMessage(hWrite);
			}
		}
	}

	PickupItem::PickedUp(hRead);
}
예제 #7
0
uint32 PickupItem::EngineMessageFn(uint32 messageID, void *pData, LTFLOAT fData)
{
	switch(messageID)
	{
		case MID_UPDATE:
		{
			Update();
		}
		break;

		case MID_TOUCHNOTIFY:
		{
			if( !m_bTouchPickup ) break;

			HOBJECT hObj = (HOBJECT)pData;

			// If this is a character hit box, use its object...

			CCharacterHitBox* pHitBox = LTNULL;
			if (IsCharacterHitBox(hObj))
			{
				pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj);
				if (pHitBox)
				{
					hObj = pHitBox->GetModelObject();
				}
			}


			// If the object is dead, it can't pick up stuff...

			if (IsPlayer(hObj))
			{
                CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObj);

				if (!pPlayer || pPlayer->IsDead()) break;

				SetPlayerObj(hObj);
			}
			else
			{
                SetPlayerObj(LTNULL);
				break;
			}

			ObjectTouch(hObj);
		}
		break;

		case MID_PRECREATE:
		{
			ObjectCreateStruct* pInfo = (ObjectCreateStruct*)pData;
	
			if (fData == PRECREATE_WORLDFILE)
			{
				ReadProp(pInfo);
			}
			else if (fData == PRECREATE_STRINGPROP)
			{
				ReadProp(pInfo);

				// Show ourself...

				pInfo->m_Flags |= FLAG_VISIBLE;
			}

			PostPropRead(pInfo);
		}
		break;

		case MID_INITIALUPDATE:
		{
			if (fData != INITIALUPDATE_SAVEGAME)
			{
				InitialUpdate();
			}
		}
		break;

		case MID_SAVEOBJECT:
		{
            Save((ILTMessage_Write*)pData, (uint32)fData);
		}
		break;

		case MID_LOADOBJECT:
		{
            Load((ILTMessage_Read*)pData, (uint32)fData);
			
			uint32 dwRet = GameBase::EngineMessageFn(messageID, pData, fData);
			
			// We need to reset our sfx message since values
			// could have changed across save versions.

			CreateSpecialFX( );

			return dwRet;
		}
		break;

		default : break;
	}

	return GameBase::EngineMessageFn(messageID, pData, fData);
}
예제 #8
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;
}
예제 #9
0
void CDestructable::HandleDamage(HOBJECT hSender, HMESSAGEREAD hRead)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	DVector vDir,vPos;

	pServerDE->ReadFromMessageVector(hRead, &vDir);
	DFLOAT fDamage = pServerDE->ReadFromMessageFloat(hRead);
	DBYTE nDamageType	= pServerDE->ReadFromMessageByte(hRead);
	HOBJECT hWhoHit = pServerDE->ReadFromMessageObject(hRead);
	pServerDE->ReadFromMessageVector(hRead, &vPos);

//	char buf[50];
	DFLOAT fOldHitPoints = m_fHitPoints;
	fDamage = fDamage * m_fResistance;

	// Just return if we can't take damage
	if (m_bGodMode || (m_bTriggerOnly && nDamageType != DAMAGE_TYPE_DEATH) || fDamage < 0)
	{
		return;
	}

	if (!IsPlayerToPlayerDamageOk(hSender, hWhoHit))
	{
		return;
	}

	// If instant death, don't bother calculating stuff.. 
	if( m_bDestructable && nDamageType == DAMAGE_TYPE_DEATH)
	{
		m_fArmorPoints = 0;
		m_fHitPoints = 0;
		m_fDeathHitPoints = 0;
		m_fLastDamagePercent = 100.0f;
		m_fLastDamageAmount = (DFLOAT)m_fMaxHitPoints;

		nDamageType &= 0x0f;	// Mask off the damage type flags
		m_nLastDamageType = nDamageType;
	}
	else
	{
		// Special pre-damage base character modifiers
		if (IsAICharacter(m_hObject))
		{
			m_nNodeHit = CalculateHitLimb(vDir,vPos,fDamage);

			if(m_nNodeHit == -1 && !(nDamageType & DAMAGE_TYPE_NORMAL))
				m_nNodeHit = SetProperNode(pServerDE->IntRandom(0,NUM_ALL_NODES - 3));
			else if(m_nNodeHit >= 0)
				m_nNodeHit = SetProperNode(m_nNodeHit);
			else
				return;

			//Compute one side got hit for recoils
			DVector vU, vR, vF, vTmpDir;
			DRotation rRot;
			pServerDE->GetObjectRotation(m_hObject, &rRot);
			pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF);

			VEC_COPY(vTmpDir, vDir);

			VEC_MULSCALAR(vTmpDir,vTmpDir,-1.0f);
			DFLOAT fAmount = (DFLOAT) atan2(vTmpDir.x, vTmpDir.z);    
			DFLOAT fAmount2 = (DFLOAT) atan2(vF.x, vF.z);

			if(fAmount < 0.0f)
				fAmount = (MATH_PI*2) + fAmount;
			if(fAmount2 < 0.0f)
				fAmount2 = (MATH_PI*2) + fAmount2;

			DFLOAT fAngle = fAmount2 - fAmount;

			if(fAngle <= MATH_PI/2 || fAngle >= 3*MATH_PI/2)	//Hit the front
			{
				m_nSideHit = 0;
			}
			else //Hit the back
			{
				m_nSideHit = 6;	
			}

			if (m_hLastDamager)
				pServerDE->BreakInterObjectLink(m_hObject, m_hLastDamager);

			m_hLastDamager = hWhoHit;

			if(m_hLastDamager)
				pServerDE->CreateInterObjectLink(m_hObject, m_hLastDamager);

			if(m_nNodeHit == NODE_NECK)
			{
				AI_Mgr* pAI = (AI_Mgr*)pServerDE->HandleToObject(m_hObject);

				if(pAI->m_bCabal || pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("SoulDrudge")))
					m_fHitPoints = 0;
				
				fDamage *= 1.5f;
			}
			else if(m_nNodeHit == NODE_TORSO)
			{
				fDamage *= 1.0f;
			}
			else
			{
				fDamage *= 0.5f;
			}
		}

		if (IsBaseCharacter(m_hObject))
		{
			CBaseCharacter *pOwner = (CBaseCharacter*)pServerDE->HandleToObject(m_hObject);

//			if (pOwner->IsItemActive(SPELL_STONE))
//				return;

			// If Nigh-invulnerability powerup in effect..
			if (m_bNighInvulnerable)
				fDamage = fDamage * 0.05f;

			// Shield absorbs the damage as Focus ammo use
/*			if (nDamageType != DAMAGE_TYPE_DEATH && pOwner->IsItemActive(SPELL_SHIELD))
			{
				DFLOAT fFocusAmmo = pOwner->GetInventoryMgr()->GetAmmoCount(AMMO_FOCUS);
		
				fFocusAmmo -= fDamage;

				if (fFocusAmmo < 0.0f)
				{
					fDamage = -fFocusAmmo;
					fFocusAmmo = 0.0f;
				}
				else
				{
					fDamage = 0.0f;
				}

				pOwner->GetInventoryMgr()->SetAmmoCount(AMMO_FOCUS, fFocusAmmo);
			}
*/
			// Reflection reflects damage back to the sender, and absorbs 
			// twice the damage in focus ammo
/*			if (pOwner->IsItemActive(SPELL_REFLECTION) && !(nDamageType & DAMAGE_FLAG_AREAEFFECT))
			{
				DFLOAT fFocusAmmo = pOwner->GetInventoryMgr()->GetAmmoCount(AMMO_FOCUS);
		
				fFocusAmmo -= fDamage * 2.0f;

				if (fFocusAmmo < 0.0f)
				{
					fDamage = -fFocusAmmo / 2.0f;
					fFocusAmmo = 0.0f;
				}
				else
				{
					fDamage = 0.0f;
				}

				pOwner->GetInventoryMgr()->SetAmmoCount(AMMO_FOCUS, fFocusAmmo);
			}
*/
		}

		// If single player, don't let the player apply damage to himself.
		if (m_bApplyDamagePhysics && !(g_pBloodServerShell->GetGameType() == GAMETYPE_SINGLE && (m_hObject == hWhoHit) && IsPlayer(m_hObject)))
			ApplyDamagePhysics(fDamage, &vDir);
		
		// Can't damage if already dead...

		if( m_bDestructable && m_bDead )
			return;

		if( m_bDestructable && m_fArmorPoints > 0.0 && nDamageType != DAMAGE_TYPE_SUFFOCATE )
		{
			DFLOAT fAbsorb = 0.0f;

			if (m_fArmorPoints <= 25.0f)
				fAbsorb = fDamage * 0.3f;
			else if (m_fArmorPoints <= 50.0f)
				fAbsorb = fDamage * 0.5f;
			else if (m_fArmorPoints <= 100.0f)
				fAbsorb = fDamage * 0.7f;
			else if (m_fArmorPoints <= 150.0f)
				fAbsorb = fDamage * 0.8f;
			else 
				fAbsorb = fDamage * 0.9f;

			if (!m_bGodMode)
			{
				m_fArmorPoints -= fAbsorb;
				if (m_fArmorPoints < 0.0f) 
				{
					fAbsorb += m_fArmorPoints;
					m_fArmorPoints = 0.0f;
				}
        
				fDamage -= fAbsorb;
       		}
		}

		if (fDamage < 0.0f) fDamage = 0.0f;	// just to be sure :)

		// Save damage type so entity will know how to react
		nDamageType &= 0x0f;	// Mask off the damage type flags
		if (fDamage) m_nLastDamageType = nDamageType;

		if( m_bDestructable )
		{
			m_fHitPoints -= fDamage;
			m_fDeathHitPoints -= fDamage;
		}
	}
	// 01/13/98  How much damage was done (percentage of max hit points)
	m_fLastDamagePercent += (DFLOAT)fDamage/(DFLOAT)GetMaxHitPoints();
	m_fLastDamageAmount += fDamage;
	VEC_COPY(m_vLastDamageDirection, vDir);

	// Set pSender if sender is a player
	CPlayerObj* pSender = DNULL;

	if( m_bDestructable )
	{
		if(hWhoHit)
			if(pServerDE->IsKindOf(pServerDE->GetObjectClass(hWhoHit), pServerDE->GetClass("CPlayerObj")))
				pSender = (CPlayerObj*)pServerDE->HandleToObject(hWhoHit);

		// If it was hurt with a leech weapon, then add the damage done back to playerobj
		if(pSender && pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("CBaseCharacter")))
		{
			if(nDamageType == DAMAGE_TYPE_LEECH)
			{
				if (!pSender->IsDead() && !pSender->IsInSlowDeath())
				{
					pSender->GetDestructable()->Heal(fDamage / 10.0f);
				}
			}
		}
	}

//	m_fHitPoints = 1;
	if( m_bDestructable && m_fHitPoints <= 0 )
	{
		m_bDead = DTRUE;
		m_fHitPoints = 0;
		HandleDestruction();

		m_hWhoKilledMeLast = hWhoHit;

        // If its a PlayerObj then Increase the Kills 
/*		if(pSender && pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("CBaseCharacter"))) 
		{
            // If it was killed with a melee weapon, then add the damage done back to playerobj
        	if(nDamageType == DAMAGE_TYPE_LEECH)
            {
				pSender->GetDestructable()->Heal(fDamage / 5.0f);
				pSender->AddMeleeKill();

				DFLOAT fIncrease = 0.0f;
				int nKills = pSender->GetMeleeKills();
        
				if (nKills > 0)
				{
                    // Increase Damage by 5% for every kill
                    fIncrease = (DFLOAT)nKills * .05f;
                    // Max Increase 200%
                    if (fIncrease > 2.0f)   fIncrease = 2.0f;
                }            
                
                // If the Increase is greater than 50% then add back some of the damage to player
                if (fIncrease > 0.5f)
                {
                    // Add back damage to playerobj
                    DFLOAT fAddHits = fDamage * (fIncrease/2.0f);
                    
    				pSender->GetDestructable()->Heal(fAddHits);
                    
                    // Need to Glow the player Sword...
                    // Set Glow on the Melee Weapon
                    
                }
            }
        }*/
	}


	// If this is supposed to send a damage trigger, send it now..

	if( m_bDestructable && m_hstrDamageTriggerTarget && m_hstrDamageTriggerMessage )
	{
		LPBASECLASS pD = pServerDE->HandleToObject(m_hObject);
		SendTriggerMsgToObjects(pD, m_hstrDamageTriggerTarget, m_hstrDamageTriggerMessage);
	}

	// If player did this damage and has soul stealing binding..
	if( m_bDestructable && fOldHitPoints != m_fHitPoints && m_hObject != hWhoHit)
	{
		// Make sure it's a player
		if(pSender) 
		{
			DFLOAT fHeal;
			if (pSender->HasSoulStealingBinding() && (fHeal = (fOldHitPoints - m_fHitPoints) / 10.0f))
			{
				pSender->GetDestructable()->Heal(fHeal);
			}
		}
	}
}