示例#1
0
bool CPickup::CanUse ( CPlayer& Player, bool bOnfootCheck )
{
    // Is the player on foot?
    if ( !bOnfootCheck || !Player.GetOccupiedVehicle () )
    {
        // Check if he can pick it up depending on the type
        switch ( m_ucType )
        {
            case CPickup::HEALTH:
                // TODO: calc max health from max_health stat
                return ( Player.GetHealth () < 200.0f );

            case CPickup::ARMOR:
                return ( Player.GetArmor () < 100.0f );

            case CPickup::WEAPON:
                return true;

            case CPickup::CUSTOM:
                return true;
        }
    }

    return false;
}
示例#2
0
bool CLightsyncPacket::Write(NetBitStreamInterface& BitStream) const
{
    bool bSyncPosition;

    if (Count() == 0)
        return false;

    for (std::vector<CPlayer*>::const_iterator iter = m_players.begin(); iter != m_players.end(); ++iter)
    {
        CPlayer*                       pPlayer = *iter;
        CPlayer::SLightweightSyncData& data = pPlayer->GetLightweightSyncData();
        CVehicle*                      pVehicle = pPlayer->GetOccupiedVehicle();

        // Find the difference between now and the time the position last changed for the player
        long long llTicksDifference = GetTickCount64_() - pPlayer->GetPositionLastChanged();

        // Right we need to sync the position if there is no vehicle or he's in a vehicle and the difference between setPosition is less than or equal to the
        // slow sync rate i.e. make sure his position has been updated more than 0.001f in the last 1500ms plus a small margin for error (probably not needed).
        // This will ensure we only send positions when the position has changed.
        bSyncPosition = (!pVehicle || pPlayer->GetOccupiedVehicleSeat() == 0) && llTicksDifference <= g_TickRateSettings.iLightSync + 100;

        BitStream.Write(pPlayer->GetID());
        BitStream.Write((unsigned char)pPlayer->GetSyncTimeContext());

        unsigned short usLatency = pPlayer->GetPing();
        BitStream.WriteCompressed(usLatency);

        BitStream.WriteBit(data.health.bSync);
        if (data.health.bSync)
        {
            SPlayerHealthSync health;
            health.data.fValue = pPlayer->GetHealth();
            BitStream.Write(&health);

            SPlayerArmorSync armor;
            armor.data.fValue = pPlayer->GetArmor();
            BitStream.Write(&armor);
        }

        BitStream.WriteBit(bSyncPosition);
        if (bSyncPosition)
        {
            SLowPrecisionPositionSync pos;
            pos.data.vecPosition = pPlayer->GetPosition();
            BitStream.Write(&pos);

            bool bSyncVehicleHealth = data.vehicleHealth.bSync && pVehicle;
            BitStream.WriteBit(bSyncVehicleHealth);
            if (bSyncVehicleHealth)
            {
                SLowPrecisionVehicleHealthSync health;
                health.data.fValue = pVehicle->GetHealth();
                BitStream.Write(&health);
            }
        }
    }

    return true;
}
void CLightsyncManager::DoPulse ()
{
    // The point of this method is to get all players that should receive right now the lightweight
    // sync from all the other players. To make this efficient, we are using a queue in what the
    // players at the front have are more inminent to receive this sync. As all players have the same
    // far sync rate, just taking the players from the front, processing them  and pushing them to the
    // back will keep the order of priority to be processed.
    //
    // We also want to perform delta sync on stuff like the health, but it would require to know the last
    // value synced from every player to every player, because we are getting players from the front and
    // sending them all the other players data. This would be crazily inefficient and would require a lot
    // of mainteinance, so we will leave special entries in the queue to mark in what moment a player
    // health changed. This way, we will force the health sync for that player until the queue cycle
    // reaches that special entry again. As there might be multiple changes in a complete queue cycle, we
    // are also storing the delta context in what it happened, so we only consider the health unchanged
    // when we find the marker with the same context value.

    if ( g_pBandwidthSettings->bLightSyncEnabled == false )
        return;

    // For counting stats
    long iPacketsSent = 0;
    long iBitsSent = 0;

    // For limiting light sync processing
    long iLimitCounter = Max < uint > ( 10, g_pGame->GetPlayerManager ()->Count () / 25 );
    int iLightsyncRate = g_TickRateSettings.iLightSync;
    long long llTickCountNow = GetTickCount64_ ();
    while ( m_Queue.size() > 0 && m_Queue.front().ullTime + iLightsyncRate <= llTickCountNow && iLimitCounter > 0 )
    {
        SEntry entry = m_Queue.front ();
        m_Queue.pop_front ();

        CPlayer* pPlayer = entry.pPlayer;
        CPlayer::SLightweightSyncData& data = pPlayer->GetLightweightSyncData ();

        switch ( entry.eType )
        {
            case SYNC_PLAYER:
            {
                CLightsyncPacket packet;

                // Use this players far list
                const SViewerMapType& farList = pPlayer->GetFarPlayerList ();

                // For each far player
                for ( SViewerMapType ::const_iterator it = farList.begin (); it != farList.end (); ++it )
                {
                    CPlayer* pCurrent = it->first;
                    dassert ( pPlayer != pCurrent );

                    // Only send if he isn't network troubled.
                    if ( pCurrent->UhOhNetworkTrouble ( ) == false )
                    {
                        CPlayer::SLightweightSyncData& currentData = pCurrent->GetLightweightSyncData ();
                        packet.AddPlayer ( pCurrent );

                        // Calculate the delta sync
                        if ( fabs(currentData.health.fLastHealth - pCurrent->GetHealth()) > LIGHTSYNC_HEALTH_THRESHOLD ||
                             fabs(currentData.health.fLastArmor - pCurrent->GetArmor()) > LIGHTSYNC_HEALTH_THRESHOLD )
                        {
                            currentData.health.fLastHealth = pCurrent->GetHealth ();
                            currentData.health.fLastArmor = pCurrent->GetArmor ();
                            currentData.health.bSync = true;
                            currentData.health.uiContext++;

                            // Generate the health marker
                            SEntry marker;
                            marker.ullTime = 0;
                            marker.pPlayer = pCurrent;
                            marker.eType = DELTA_MARKER_HEALTH;
                            marker.uiContext = currentData.health.uiContext;
                            m_Queue.push_back ( marker );
                        }

                        CVehicle* pVehicle = pCurrent->GetOccupiedVehicle ();
                        if ( pVehicle && pCurrent->GetOccupiedVehicleSeat() == 0 )
                        {
                            if ( currentData.vehicleHealth.lastVehicle != pVehicle ||
                                 fabs(currentData.vehicleHealth.fLastHealth - pVehicle->GetHealth ()) > LIGHTSYNC_VEHICLE_HEALTH_THRESHOLD )
                            {
                                currentData.vehicleHealth.fLastHealth = pVehicle->GetHealth ();
                                currentData.vehicleHealth.lastVehicle = pVehicle;
                                currentData.vehicleHealth.bSync = true;
                                currentData.vehicleHealth.uiContext++;

                                // Generate the vehicle health marker
                                SEntry marker;
                                marker.ullTime = 0;
                                marker.pPlayer = pCurrent;
                                marker.eType = DELTA_MARKER_VEHICLE_HEALTH;
                                marker.uiContext = currentData.vehicleHealth.uiContext;
                                m_Queue.push_back ( marker );
                            }
                        }

                        if ( packet.Count () == LIGHTSYNC_MAX_PLAYERS )
                        {
                            iBitsSent += pPlayer->Send ( packet );
                            iPacketsSent++;
                            packet.Reset ();
                        }
                    }
                }

                if ( packet.Count () > 0 )
                {
                    iBitsSent += pPlayer->Send ( packet );
                    iPacketsSent++;
                }

                RegisterPlayer ( pPlayer );
                iLimitCounter--;
                break;
            }

            case DELTA_MARKER_HEALTH:
            {
                if ( data.health.uiContext == entry.uiContext )
                    data.health.bSync = false;

                break;
            }

            case DELTA_MARKER_VEHICLE_HEALTH:
            {
                if ( data.vehicleHealth.uiContext == entry.uiContext )
                    data.vehicleHealth.bSync = false;

                break;
            }
        }
    }

    // Update stats
    g_pStats->lightsync.llLightSyncPacketsSent += iPacketsSent;
    g_pStats->lightsync.llLightSyncBytesSent += iBitsSent / 8;

    // Subtract lightsync usage from skipped accumulators
    g_pStats->lightsync.llSyncPacketsSkipped -= iPacketsSent;
    g_pStats->lightsync.llSyncBytesSkipped -= iBitsSent / 8;
}
bool CVehiclePuresyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Got a player to send?
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );

        // Player is in a vehicle and is the driver?
        CVehicle* pVehicle = pSourcePlayer->GetOccupiedVehicle ();
        if ( pVehicle )
        {
            // Player ID
            ElementID PlayerID = pSourcePlayer->GetID ();
            BitStream.Write ( PlayerID );

            // Write the time context of that player
            BitStream.Write ( pSourcePlayer->GetSyncTimeContext () );

            // Write his ping divided with 2 plus a small number so the client can find out when this packet was sent
            unsigned short usLatency = pSourcePlayer->GetPing ();
            BitStream.WriteCompressed ( usLatency );

            // Write the keysync data
            CControllerState ControllerState = pSourcePlayer->GetPad ()->GetCurrentControllerState ();
            WriteFullKeysync ( ControllerState, BitStream );

            // Write the vehicle matrix only if he's the driver
            CVector vecTemp;
            unsigned int uiSeat = pSourcePlayer->GetOccupiedVehicleSeat ();
            if ( uiSeat == 0 )
            {
                // Vehicle position
                SPositionSync position ( false );
                position.data.vecPosition = pVehicle->GetPosition ();
                BitStream.Write ( &position );

                // Vehicle rotation
                SRotationDegreesSync rotation;
                pVehicle->GetRotationDegrees ( rotation.data.vecRotation );
                BitStream.Write ( &rotation );

                // Move speed vector
                SVelocitySync velocity;
                velocity.data.vecVelocity = pVehicle->GetVelocity ();
                BitStream.Write ( &velocity );

                // Turn speed vector
                SVelocitySync turnSpeed;
                turnSpeed.data.vecVelocity = pVehicle->GetTurnSpeed ();
                BitStream.Write ( &turnSpeed );

                // Health
                SVehicleHealthSync health;
                health.data.fValue = pVehicle->GetHealth ();
                BitStream.Write ( &health );
            }

            // Player health and armor
            SPlayerHealthSync health;
            health.data.fValue = pSourcePlayer->GetHealth ();
            BitStream.Write ( &health );

            SPlayerArmorSync armor;
            armor.data.fValue = pSourcePlayer->GetArmor ();
            BitStream.Write ( &armor );

            // Weapon
            unsigned char ucWeaponType = pSourcePlayer->GetWeaponType ();

            // Flags
            SVehiclePuresyncFlags flags;
            flags.data.bIsWearingGoggles     = pSourcePlayer->IsWearingGoggles ();
            flags.data.bIsDoingGangDriveby   = pSourcePlayer->IsDoingGangDriveby ();
            flags.data.bIsSirenOrAlarmActive = pVehicle->IsSirenActive ();
            flags.data.bIsSmokeTrailEnabled  = pVehicle->IsSmokeTrailEnabled ();
            flags.data.bIsLandingGearDown    = pVehicle->IsLandingGearDown ();
            flags.data.bIsOnGround           = pVehicle->IsOnGround ();
            flags.data.bIsInWater            = pVehicle->IsInWater ();
            flags.data.bIsDerailed           = pVehicle->IsDerailed ();
            flags.data.bIsAircraft           = ( pVehicle->GetVehicleType () == VEHICLE_PLANE ||
                                                 pVehicle->GetVehicleType () == VEHICLE_HELI );
            flags.data.bHasAWeapon           = ( ucWeaponType != 0 );
            flags.data.bIsHeliSearchLightVisible = pVehicle->IsHeliSearchLightVisible ();
            BitStream.Write ( &flags );

            // Write the weapon stuff
            if ( flags.data.bHasAWeapon )
            {
                // Write the weapon slot
                SWeaponSlotSync slot;
                slot.data.uiSlot = pSourcePlayer->GetWeaponSlot ();
                BitStream.Write ( &slot );

                if ( flags.data.bIsDoingGangDriveby && CWeaponNames::DoesSlotHaveAmmo ( slot.data.uiSlot ) )
                {
                    // Write the ammo states
                    SWeaponAmmoSync ammo ( ucWeaponType, false, true );
                    ammo.data.usAmmoInClip = pSourcePlayer->GetWeaponAmmoInClip ();
                    BitStream.Write ( &ammo );

                    // Sync aim data
                    SWeaponAimSync aim ( 0.0f, true );
                    aim.data.vecOrigin = pSourcePlayer->GetSniperSourceVector ();
                    pSourcePlayer->GetTargettingVector ( aim.data.vecTarget );
                    aim.data.fArm = pSourcePlayer->GetAimDirection ();
                    BitStream.Write ( &aim );

                    // Sync driveby direction
                    SDrivebyDirectionSync driveby;
                    driveby.data.ucDirection = pSourcePlayer->GetDriveByDirection ();
                    BitStream.Write ( &driveby );
                }
            }

            // Vehicle specific data only if he's the driver
            if ( uiSeat == 0 )
            {
                WriteVehicleSpecific ( pVehicle, BitStream );
            }

            // Write vehicle_look_left and vehicle_look_right control states when
            // it's an aircraft.
            if ( flags.data.bIsAircraft )
            {
                BitStream.WriteBit ( ControllerState.LeftShoulder2 != 0 );
                BitStream.WriteBit ( ControllerState.RightShoulder2 != 0 );
            }

            // Success
            return true;
        }
    }

    return false;
}
bool CVehiclePuresyncPacket::Read ( NetBitStreamInterface& BitStream )
{
    // Got a player to read?
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );

        // Player is in a vehicle?
        CVehicle* pVehicle = pSourcePlayer->GetOccupiedVehicle ();
        if ( pVehicle )
        {
            // Read out the time context
            unsigned char ucTimeContext = 0;
            if ( !BitStream.Read ( ucTimeContext ) )
                return false;

            // Only read this packet if it matches the current time context that
            // player is in.
            if ( !pSourcePlayer->CanUpdateSync ( ucTimeContext ) )
            {
                return false;
            }

            // Read out the keysync data
            CControllerState ControllerState;
            if ( !ReadFullKeysync ( ControllerState, BitStream ) )
                return false;

            // Read out its position
            SPositionSync position ( false );
            if ( !BitStream.Read ( &position ) )
                return false;
            pSourcePlayer->SetPosition ( position.data.vecPosition );

            // Jax: don't allow any outdated packets through
            unsigned char ucSeat;
            if ( !BitStream.Read ( ucSeat ) )
                return false;
            if ( ucSeat != pSourcePlayer->GetOccupiedVehicleSeat () )
            {
                // Mis-matching seats can happen when we warp into a different one,
                // which will screw up the whole packet
                return false;
            }

            // Read out the vehicle matrix only if he's the driver
            unsigned int uiSeat = pSourcePlayer->GetOccupiedVehicleSeat ();
            if ( uiSeat == 0 )
            {
                // Read out the vehicle rotation in degrees
                SRotationDegreesSync rotation;
                if( !BitStream.Read ( &rotation ) )
                    return false;

                // Set it
                pVehicle->SetPosition ( position.data.vecPosition );
                pVehicle->SetRotationDegrees ( rotation.data.vecRotation );

                // Move speed vector
                SVelocitySync velocity;
                if ( !BitStream.Read ( &velocity ) )
                    return false;

                pVehicle->SetVelocity ( velocity.data.vecVelocity );
                pSourcePlayer->SetVelocity ( velocity.data.vecVelocity );

                // Turn speed vector
                SVelocitySync turnSpeed;
                if ( !BitStream.Read ( &turnSpeed ) )
                    return false;

                pVehicle->SetTurnSpeed ( turnSpeed.data.vecVelocity );

                // Health
                SVehicleHealthSync health;
                if ( !BitStream.Read ( &health ) )
                    return false;
                float fPreviousHealth = pVehicle->GetHealth ();                
                float fHealth = health.data.fValue;

                // Less than last time?
                if ( fHealth < fPreviousHealth )
                {                 
                    // Grab the delta health
                    float fDeltaHealth = fPreviousHealth - fHealth;

					if ( fDeltaHealth > 0.0f )
					{
						// Call the onVehicleDamage event
						CLuaArguments Arguments;
						Arguments.PushNumber ( fDeltaHealth );
						pVehicle->CallEvent ( "onVehicleDamage", Arguments );
					}
                }
                pVehicle->SetHealth ( fHealth );

                // Trailer chain
                CVehicle* pTowedByVehicle = pVehicle;
                CVehicle* pTrailer = NULL;
                ElementID TrailerID;
                bool bHasTrailer;
                if ( !BitStream.ReadBit ( bHasTrailer ) )
                    return false;

                while ( bHasTrailer )
                {
                    BitStream.ReadCompressed ( TrailerID );
                    CElement* pElement = CElementIDs::GetElement ( TrailerID );
                    if ( pElement )
                        pTrailer = static_cast < CVehicle* > ( pElement );
                    
                    // Read out the trailer position and rotation
                    SPositionSync trailerPosition ( false );
                    if ( !BitStream.Read ( &trailerPosition ) )
                        return false;

                    SRotationDegreesSync trailerRotation;
                    if ( !BitStream.Read ( &trailerRotation ) )
                        return false;

                    // If we found the trailer
                    if ( pTrailer )
                    {
                        // Set its position and rotation
                        pTrailer->SetPosition ( trailerPosition.data.vecPosition );
                        pTrailer->SetRotationDegrees ( trailerRotation.data.vecRotation );
    
                        // Is this a new trailer, attached?
                        CVehicle* pCurrentTrailer = pTowedByVehicle->GetTowedVehicle ();
                        if ( pCurrentTrailer != pTrailer )
                        {
                            // If theres a trailer already attached
                            if ( pCurrentTrailer )
                            {
                                pTowedByVehicle->SetTowedVehicle ( NULL );
                                pCurrentTrailer->SetTowedByVehicle ( NULL );

                                // Tell everyone to detach them
                                CVehicleTrailerPacket AttachPacket ( pTowedByVehicle, pCurrentTrailer, false );
                                g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket );

                                // Execute the attach trailer script function
                                CLuaArguments Arguments;
                                Arguments.PushElement ( pTowedByVehicle );
                                pCurrentTrailer->CallEvent ( "onTrailerDetach", Arguments );
                            }

                            // If something else is towing this trailer
                            CVehicle* pCurrentVehicle = pTrailer->GetTowedByVehicle ();
                            if ( pCurrentVehicle )
                            {
                                pCurrentVehicle->SetTowedVehicle ( NULL );
                                pTrailer->SetTowedByVehicle ( NULL );

                                // Tell everyone to detach them
                                CVehicleTrailerPacket AttachPacket ( pCurrentVehicle, pTrailer, false );
                                g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket );

                                // Execute the attach trailer script function
                                CLuaArguments Arguments;
                                Arguments.PushElement ( pCurrentVehicle );
                                pTrailer->CallEvent ( "onTrailerDetach", Arguments );
                            }

                            pTowedByVehicle->SetTowedVehicle ( pTrailer );
                            pTrailer->SetTowedByVehicle ( pTowedByVehicle );

                            // Execute the attach trailer script function
                            CLuaArguments Arguments;
                            Arguments.PushElement ( pTowedByVehicle );
                            bool bContinue = pTrailer->CallEvent ( "onTrailerAttach", Arguments );

                            // Attach or detach trailers depending on the event outcome
                            CVehicleTrailerPacket TrailerPacket ( pTowedByVehicle, pTrailer, bContinue );
                            g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( TrailerPacket );
                        }
                    }
                    else
                        break;

                    pTowedByVehicle = pTrailer;

                    if ( BitStream.ReadBit ( bHasTrailer ) == false )
                        return false;
                }

                // If there was a trailer before
                CVehicle* pCurrentTrailer = pTowedByVehicle->GetTowedVehicle ();
                if ( pCurrentTrailer )
                {
                    pTowedByVehicle->SetTowedVehicle ( NULL );
                    pCurrentTrailer->SetTowedByVehicle ( NULL );

                    // Tell everyone else to detach them
                    CVehicleTrailerPacket AttachPacket ( pTowedByVehicle, pCurrentTrailer, false );
                    g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket );

                    // Execute the detach trailer script function
                    CLuaArguments Arguments;
                    Arguments.PushElement ( pTowedByVehicle );
                    pCurrentTrailer->CallEvent ( "onTrailerDetach", Arguments );                    
                }
            }

            // Player health
            SPlayerHealthSync health;
            if ( !BitStream.Read ( &health ) )
                return false;
            float fHealth = health.data.fValue;

            float fOldHealth = pSourcePlayer->GetHealth ();
			float fHealthLoss = fOldHealth - fHealth;

            // Less than last packet's frame?
            if ( fHealth < fOldHealth && fHealthLoss > 0 )
            {
                // Call the onPlayerDamage event
                CLuaArguments Arguments;
                Arguments.PushNil ();
                Arguments.PushNumber ( false );
                Arguments.PushNumber ( false );
                Arguments.PushNumber ( fHealthLoss );
                pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments );
            }
            pSourcePlayer->SetHealth ( fHealth );

			// Armor
            SPlayerArmorSync armor;
            if ( !BitStream.Read ( &armor ) )
                return false;
            float fArmor = armor.data.fValue;

			float fOldArmor = pSourcePlayer->GetArmor ();
			float fArmorLoss = fOldArmor - fArmor;

			// Less than last packet's frame?
			if ( fArmor < fOldArmor && fArmorLoss > 0 )
			{
				// Call the onPlayerDamage event
				CLuaArguments Arguments;
                Arguments.PushNil ();
                Arguments.PushNumber ( false );
                Arguments.PushNumber ( false );
				Arguments.PushNumber ( fArmorLoss );

				pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments );					
			}
            pSourcePlayer->SetArmor ( fArmor );

            // Flags
            SVehiclePuresyncFlags flags;
            if ( !BitStream.Read ( &flags ) )
                return false;

            pSourcePlayer->SetWearingGoggles ( flags.data.bIsWearingGoggles );
            pSourcePlayer->SetDoingGangDriveby ( flags.data.bIsDoingGangDriveby );            

            // Weapon sync
            if ( flags.data.bHasAWeapon )
            {
                SWeaponSlotSync slot;
                if ( !BitStream.Read ( &slot ) )
                    return false;

                pSourcePlayer->SetWeaponSlot ( slot.data.uiSlot );

                if ( flags.data.bIsDoingGangDriveby && CWeaponNames::DoesSlotHaveAmmo ( slot.data.uiSlot ) )
                {
                    // Read the ammo states
                    SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), false, true );
                    if ( !BitStream.Read ( &ammo ) )
                        return false;
                    pSourcePlayer->SetWeaponAmmoInClip ( ammo.data.usAmmoInClip );

                    // Read aim data
                    SWeaponAimSync aim ( pSourcePlayer->GetWeaponRange (), true );
                    if ( !BitStream.Read ( &aim ) )
                        return false;
                    pSourcePlayer->SetAimDirection ( aim.data.fArm );
                    pSourcePlayer->SetSniperSourceVector ( aim.data.vecOrigin );
                    pSourcePlayer->SetTargettingVector ( aim.data.vecTarget );

                    // Read the driveby direction
                    SDrivebyDirectionSync driveby;
                    if ( !BitStream.Read ( &driveby ) )
                        return false;
                    pSourcePlayer->SetDriveByDirection ( driveby.data.ucDirection );
                }
            }
            else
                pSourcePlayer->SetWeaponSlot ( 0 );


            // Vehicle specific data if he's the driver
            if ( uiSeat == 0 )
            {
                ReadVehicleSpecific ( pVehicle, BitStream );

                // Set vehicle specific stuff if he's the driver
                pVehicle->SetSirenActive ( flags.data.bIsSirenOrAlarmActive );
                pVehicle->SetSmokeTrailEnabled ( flags.data.bIsSmokeTrailEnabled );
                pVehicle->SetLandingGearDown ( flags.data.bIsLandingGearDown );
                pVehicle->SetOnGround ( flags.data.bIsOnGround );
                pVehicle->SetInWater ( flags.data.bIsInWater );
                pVehicle->SetDerailed ( flags.data.bIsDerailed );
                pVehicle->SetHeliSearchLightVisible ( flags.data.bIsHeliSearchLightVisible );
            }

            // Read the vehicle_look_left and vehicle_look_right control states
            // if it's an aircraft.
            if ( flags.data.bIsAircraft )
            {
                ControllerState.LeftShoulder2 = BitStream.ReadBit () * 255;
                ControllerState.RightShoulder2 = BitStream.ReadBit () * 255;
            }

            pSourcePlayer->GetPad ()->NewControllerState ( ControllerState );

            // Success
            return true;
        }
    }

    return false;
}
示例#6
0
bool CPlayerPuresyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );

        ElementID PlayerID = pSourcePlayer->GetID ();
        unsigned short usLatency = pSourcePlayer->GetPing ();
        const CControllerState& ControllerState = pSourcePlayer->GetPad ()->GetCurrentControllerState ();
        CElement* pContactElement = pSourcePlayer->GetContactElement ();

        // Get current weapon slot
        unsigned char ucWeaponSlot = pSourcePlayer->GetWeaponSlot ();

        // Flags
        SPlayerPuresyncFlags flags;
        flags.data.bIsInWater       = ( pSourcePlayer->IsInWater () == true );
        flags.data.bIsOnGround      = ( pSourcePlayer->IsOnGround () == true );
        flags.data.bHasJetPack      = ( pSourcePlayer->HasJetPack () == true );
        flags.data.bIsDucked        = ( pSourcePlayer->IsDucked () == true );
        flags.data.bWearsGoogles    = ( pSourcePlayer->IsWearingGoggles () == true );
        flags.data.bHasContact      = ( pContactElement != NULL );
        flags.data.bIsChoking       = ( pSourcePlayer->IsChoking () == true );
        flags.data.bAkimboTargetUp  = ( pSourcePlayer->IsAkimboArmUp () == true );
        flags.data.bIsOnFire        = ( pSourcePlayer->IsOnFire () == true );
        flags.data.bHasAWeapon      = ( ucWeaponSlot != 0 );
        flags.data.bSyncingVelocity = ( !flags.data.bIsOnGround || pSourcePlayer->IsSyncingVelocity () );
        flags.data.bStealthAiming   = ( pSourcePlayer->IsStealthAiming () == true );

        CVector vecPosition = pSourcePlayer->GetPosition ();
        if ( pContactElement )
            pSourcePlayer->GetContactPosition ( vecPosition );
        float fCameraRotation = pSourcePlayer->GetCameraRotation ();

        BitStream.WriteCompressed ( PlayerID );

        // Write the time context
        BitStream.Write ( pSourcePlayer->GetSyncTimeContext () );

        BitStream.WriteCompressed ( usLatency );
        WriteFullKeysync ( ControllerState, BitStream );
/*
        // Figure out what to send
        SPlayerPuresyncSentHeader sent;
        sent.bFlags             = CompareAndSet ( usFlags,          pSourcePlayer->lastSent.usFlags );
        sent.bPosition          = CompareAndSet ( vecPosition,      pSourcePlayer->lastSent.vecPosition );
        sent.bRotation          = CompareAndSet ( fRotation,        pSourcePlayer->lastSent.fRotation );
        sent.bVelocity          = CompareAndSet ( vecVelocity,      pSourcePlayer->lastSent.vecVelocity );
        sent.bHealth            = CompareAndSet ( ucHealth,         pSourcePlayer->lastSent.ucHealth );
        sent.bArmor             = CompareAndSet ( ucArmor,          pSourcePlayer->lastSent.ucArmor );
        sent.bCameraRotation    = CompareAndSet ( fCameraRotation,  pSourcePlayer->lastSent.fCameraRotation );
        sent.bWeaponType        = CompareAndSet ( ucWeaponType,     pSourcePlayer->lastSent.ucWeaponType );
        sent.Write ( BitStream );

        if ( sent.bPosition )
        {
            BitStream.Write ( vecPosition.fX );
            BitStream.Write ( vecPosition.fY );
            BitStream.Write ( vecPosition.fZ );
        }

        if ( sent.bRotation )
            BitStream.Write ( fRotation );

        etc... Could also do a 'sent' header in WriteFullKeysync
*/
        BitStream.Write ( &flags );

        if ( pContactElement )
            BitStream.WriteCompressed ( pContactElement->GetID () );

        SPositionSync position ( false );
        position.data.vecPosition = vecPosition;
        BitStream.Write ( &position );

        SPedRotationSync rotation;
        rotation.data.fRotation = pSourcePlayer->GetRotation ();
        BitStream.Write ( &rotation );

        if ( flags.data.bSyncingVelocity )
        {
            SVelocitySync velocity;
            pSourcePlayer->GetVelocity ( velocity.data.vecVelocity );
            BitStream.Write ( &velocity );
        }

        // Player health and armor
        SPlayerHealthSync health;
        health.data.fValue = pSourcePlayer->GetHealth ();
        BitStream.Write ( &health );

        SPlayerArmorSync armor;
        armor.data.fValue = pSourcePlayer->GetArmor ();
        BitStream.Write ( &armor );

        BitStream.Write ( fCameraRotation );

        if ( flags.data.bHasAWeapon )
        {
            unsigned int uiSlot = ucWeaponSlot;
            SWeaponSlotSync slot;
            slot.data.uiSlot = uiSlot;
            BitStream.Write ( &slot );

            if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) )
            {
                unsigned short usWeaponAmmoInClip = pSourcePlayer->GetWeaponAmmoInClip ();
/*
            // Figure out what to send
            SPlayerPuresyncWeaponSentHeader sent;
            sent.bWeaponAmmoInClip      = CompareAndSet ( usWeaponAmmoInClip,   pSourcePlayer->lastSent.usWeaponAmmoInClip );
            sent.bAimDirectionX         = CompareAndSet ( fAimDirectionX,       pSourcePlayer->lastSent.fAimDirectionX );
            sent.bAimDirectionY         = CompareAndSet ( fAimDirectionY,       pSourcePlayer->lastSent.fAimDirectionY );
            sent.bSniperSource          = CompareAndSet ( vecSniperSource,      pSourcePlayer->lastSent.vecSniperSource );
            sent.bTargetting            = CompareAndSet ( vecTargetting,        pSourcePlayer->lastSent.vecTargetting );
            sent.Write ( BitStream );

            if ( sent.bWeaponAmmoInClip )
                BitStream.Write ( usWeaponAmmoInClip );

            if ( sent.bAimDirectionX )
                BitStream.Write ( fAimDirectionX );
            if ( sent.bAimDirectionY )
                BitStream.Write ( fAimDirectionY );

            etc...
*/

                SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), false, true );
                ammo.data.usAmmoInClip = usWeaponAmmoInClip;
                BitStream.Write ( &ammo );

                SWeaponAimSync aim ( 0.0f, ( ControllerState.RightShoulder1 || ControllerState.ButtonCircle ) );
                aim.data.fArm = pSourcePlayer->GetAimDirection ();

                // Write the aim data only if he's aiming or shooting
                if ( aim.isFull() )
                {
                    aim.data.vecOrigin = pSourcePlayer->GetSniperSourceVector ();
                    pSourcePlayer->GetTargettingVector ( aim.data.vecTarget );
                }
                BitStream.Write ( &aim );
            }
        }

        // Success
        return true;
    }

    return false;
}
示例#7
0
bool CPlayerPuresyncPacket::Read ( NetBitStreamInterface& BitStream )
{
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );

        // Read out the time context
        unsigned char ucTimeContext = 0;
        if ( !BitStream.Read ( ucTimeContext ) )
            return false;

        // Only read this packet if it matches the current time context that
        // player is in.
        if ( !pSourcePlayer->CanUpdateSync ( ucTimeContext ) )
        {
            return false;
        }

        // Read out keys
        CControllerState ControllerState;
        ReadFullKeysync ( ControllerState, BitStream );
        pSourcePlayer->GetPad ()->NewControllerState ( ControllerState );

        // Read the flags
        SPlayerPuresyncFlags flags;
        if ( !BitStream.Read ( &flags ) )
            return false;

        pSourcePlayer->SetInWater ( flags.data.bIsInWater );
        pSourcePlayer->SetOnGround ( flags.data.bIsOnGround );
        pSourcePlayer->SetHasJetPack ( flags.data.bHasJetPack );
        pSourcePlayer->SetDucked ( flags.data.bIsDucked );
        pSourcePlayer->SetWearingGoggles ( flags.data.bWearsGoogles );
        pSourcePlayer->SetChoking ( flags.data.bIsChoking );
        pSourcePlayer->SetAkimboArmUp ( flags.data.bAkimboTargetUp );
        pSourcePlayer->SetOnFire ( flags.data.bIsOnFire );
        pSourcePlayer->SetStealthAiming ( flags.data.bStealthAiming );

        // Contact element
        CElement* pContactElement = NULL;
        if ( flags.data.bHasContact )
        {
            ElementID Temp;
            if ( !BitStream.ReadCompressed ( Temp ) )
                return false;
            pContactElement = CElementIDs::GetElement ( Temp );
        }
        CElement * pPreviousContactElement = pSourcePlayer->GetContactElement ();
        pSourcePlayer->SetContactElement ( pContactElement );

        if ( pPreviousContactElement != pContactElement )
        {
            // Call our onPlayerContact event
            CLuaArguments Arguments;
            if ( pPreviousContactElement )
                Arguments.PushElement ( pPreviousContactElement );
            else
                Arguments.PushNil ();
            if ( pContactElement )
                Arguments.PushElement ( pContactElement );
            else
                Arguments.PushNil ();

            pSourcePlayer->CallEvent ( "onPlayerContact", Arguments );
        }

        // Player position
        SPositionSync position ( false );
        if ( !BitStream.Read ( &position ) )
            return false;

        if ( pContactElement )
        {
            pSourcePlayer->SetContactPosition ( position.data.vecPosition );

            // Get the true position
            CVector vecTempPos = pContactElement->GetPosition ();
            position.data.vecPosition += vecTempPos;
        }
        pSourcePlayer->SetPosition ( position.data.vecPosition );

        // Player rotation
        SPedRotationSync rotation;
        if ( !BitStream.Read ( &rotation ) )
            return false;
        pSourcePlayer->SetRotation ( rotation.data.fRotation );

        // Move speed vector
        if ( flags.data.bSyncingVelocity )
        {
            SVelocitySync velocity;
            if ( !BitStream.Read ( &velocity ) )
                return false;
            pSourcePlayer->SetVelocity ( velocity.data.vecVelocity );
        }

        // Health ( stored with damage )
        SPlayerHealthSync health;
        if ( !BitStream.Read ( &health ) )
            return false;
        float fHealth = health.data.fValue;

        // Armor
        SPlayerArmorSync armor;
        if ( !BitStream.Read ( &armor ) )
            return false;

        float fArmor = armor.data.fValue;
        float fOldArmor = pSourcePlayer->GetArmor ();
        float fArmorLoss = fOldArmor - fArmor;

        pSourcePlayer->SetArmor ( fArmor );

        // Read out and set the camera rotation
        float fCameraRotation;
        if ( !BitStream.Read ( fCameraRotation ) )
            return false;
        pSourcePlayer->SetCameraRotation ( fCameraRotation );

        if ( flags.data.bHasAWeapon )
        {
            if ( BitStream.Version () >= 0x0d )
            {
                // Check client has the weapon we think he has
                unsigned char ucWeaponType;
                if ( !BitStream.Read ( ucWeaponType ) )
                    return false;

                if ( pSourcePlayer->GetWeaponType () != ucWeaponType )
                    return false;
            }

            // Current weapon slot
            SWeaponSlotSync slot;
            if ( !BitStream.Read ( &slot ) )
                return false;
            unsigned int uiSlot = slot.data.uiSlot;

            pSourcePlayer->SetWeaponSlot ( uiSlot );

            if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) )
            {
                // Read out the ammo states
                SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), true, true );
                if ( !BitStream.Read ( &ammo ) )
                    return false;
                pSourcePlayer->SetWeaponAmmoInClip ( ammo.data.usAmmoInClip );
                pSourcePlayer->SetWeaponTotalAmmo ( ammo.data.usTotalAmmo );

                // Read out the aim data
                SWeaponAimSync sync ( pSourcePlayer->GetWeaponRange (), ( ControllerState.RightShoulder1 || ControllerState.ButtonCircle ) );
                if ( !BitStream.Read ( &sync ) )
                    return false;

                // Set the arm directions and whether or not arms are up
                pSourcePlayer->SetAimDirection ( sync.data.fArm );

                // Read the aim data only if he's shooting or aiming
                if ( sync.isFull() )
                {
                    pSourcePlayer->SetSniperSourceVector ( sync.data.vecOrigin );
                    pSourcePlayer->SetTargettingVector ( sync.data.vecTarget );
                }
            }
            else
            {
                pSourcePlayer->SetWeaponAmmoInClip ( 1 );
                pSourcePlayer->SetWeaponTotalAmmo ( 1 );
            }
        }
        else
        {
            pSourcePlayer->SetWeaponSlot ( 0 );
            pSourcePlayer->SetWeaponAmmoInClip ( 1 );
            pSourcePlayer->SetWeaponTotalAmmo ( 1 );
        }

        // Read out damage info if changed
        if ( BitStream.ReadBit () == true )
        {
            ElementID DamagerID;
            if ( !BitStream.ReadCompressed ( DamagerID ) )
                return false;

            SWeaponTypeSync weaponType;
            if ( !BitStream.Read ( &weaponType ) )
                return false;

            SBodypartSync bodyPart;
            if ( !BitStream.Read ( &bodyPart ) )
                return false;

            pSourcePlayer->SetDamageInfo ( DamagerID, weaponType.data.ucWeaponType, bodyPart.data.uiBodypart );
        }

        // If we know the player's dead, make sure the health we send on is 0
        if ( pSourcePlayer->IsDead () )
            fHealth = 0.0f;

        float fOldHealth = pSourcePlayer->GetHealth ();
        float fHealthLoss = fOldHealth - fHealth;
        pSourcePlayer->SetHealth ( fHealth );

        // Less than last packet's frame?
        if ( fHealthLoss > 0 || fArmorLoss > 0 )
        {
            float fDamage = 0.0f;
            if ( fHealthLoss > 0 ) fDamage += fHealthLoss;
            if ( fArmorLoss > 0 ) fDamage += fArmorLoss;

            // Call the onPlayerDamage event
            CLuaArguments Arguments;
            CElement* pKillerElement = CElementIDs::GetElement ( pSourcePlayer->GetPlayerAttacker () );
            if ( pKillerElement ) Arguments.PushElement ( pKillerElement );
            else Arguments.PushNil ();
            Arguments.PushNumber ( pSourcePlayer->GetAttackWeapon () );
            Arguments.PushNumber ( pSourcePlayer->GetAttackBodyPart () );
            Arguments.PushNumber ( fDamage );

            pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments );
        }

        // Success
        return true;
    }

    return false;
}
示例#8
0
void CPickup::Use ( CPlayer& Player )
{
    // Call the onPickupUse event
    CLuaArguments Arguments;
    Arguments.PushElement ( &Player );
    if ( !CallEvent ( "onPickupUse", Arguments ) )
    {
        CLuaArguments Arguments2;
        Arguments2.PushElement ( this );      // pickup
        Player.CallEvent ( "onPlayerPickupUse", Arguments2 );
    }
    else
    {
        CLuaArguments Arguments2;
        Arguments2.PushElement ( this );      // pickup
        if ( Player.CallEvent ( "onPlayerPickupUse", Arguments2 ) )
        {
            // Tell all the other players to hide it if the respawn intervals are bigger than 0
            if ( m_ulRespawnIntervals > 0 )
            {
                // Save our last used time
                m_ulLastUsedTime = GetTime ();
                // Mark us as not spawned
                m_bSpawned = false;
        
                // Mark us as hidden
                SetVisible ( false );
            }
        
            // Tell him to play the sound and hide/show it
            Player.Send ( CPickupHitConfirmPacket ( this, true ) );
        
            // Tell everyone else to hide/show it as neccessary
            g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( CPickupHitConfirmPacket ( this, false ), &Player );
        
            // Handle it depending on the type
            switch ( m_ucType )
            {
                // Health pickup?
                case CPickup::HEALTH:
                {
                    float fHealth = Player.GetHealth ();
                    float fNewHealth = fHealth + m_fAmount;
                    if ( fNewHealth > 200.0f )
                        fNewHealth = 200.0f;

                    CStaticFunctionDefinitions::SetElementHealth ( &Player, fNewHealth );

                    break;
                }

                // Armor pickup?
                case CPickup::ARMOR:
                {
                    float fArmor = Player.GetArmor ();
                    float fNewArmor = fArmor + m_fAmount;
                    if ( fNewArmor > 100.0f )
                        fNewArmor = 100.0f;

                    CStaticFunctionDefinitions::SetPedArmor ( &Player, fNewArmor );

                    break;
                }

                // Weapon pickup?
                case CPickup::WEAPON:
                {
                    // Give him the weapon
                    CStaticFunctionDefinitions::GiveWeapon ( &Player, m_ucWeaponType, m_usAmmo );
                    break;
                }
                default: break;
            }
        }
    }
}