1212#include < math.h>
1313#include " ../npcs_impl.hpp"
1414#include " ../utils.hpp"
15-
16- namespace utils
17- {
18- float getAngleOfLine (float x, float y)
19- {
20- float angle = atan2 (y, x) * (180 .0f / M_PI) + 270 .0f ;
21- if (angle >= 360 .0f )
22- {
23- angle -= 360 .0f ;
24- }
25- else if (angle < 0 .0f )
26- {
27- angle += 360 .0f ;
28- }
29- return angle;
30- }
31- }
15+ #include < Server/Components/Vehicles/vehicle_seats.hpp>
3216
3317NPC::NPC (NPCComponent* component, IPlayer* playerPtr)
3418 : skin_(0 )
@@ -65,6 +49,10 @@ NPC::NPC(NPCComponent* component, IPlayer* playerPtr)
6549 , hitType_(PlayerBulletHitType_None)
6650 , lastDamager_(nullptr )
6751 , lastDamagerWeapon_(PlayerWeapon_End)
52+ , vehicleToEnter_(nullptr )
53+ , vehicleSeatToEnter_(SEAT_NONE)
54+ , enteringVehicle_(false )
55+ , jackingVehicle_(false )
6856{
6957 // Fill weapon accuracy with 1.0f, let server devs change it with the desired values
7058 weaponAccuracy.fill (1 .0f );
@@ -243,7 +231,7 @@ bool NPC::move(Vector3 pos, NPCMoveType moveType, float moveSpeed)
243231 }
244232
245233 auto rotation = getRotation ().ToEuler ();
246- rotation.z = utils:: getAngleOfLine (front.x , front.y );
234+ rotation.z = getAngleOfLine (front.x , front.y );
247235 footSync_.Rotation = rotation; // Do this directly, if you use NPC::setRotation it's going to cause recursion
248236
249237 // Calculate velocity to use on tick
@@ -259,7 +247,6 @@ bool NPC::move(Vector3 pos, NPCMoveType moveType, float moveSpeed)
259247 }
260248
261249 // Set internal variables
262- moveSpeed_ = moveSpeed_;
263250 targetPosition_ = pos;
264251 moving_ = true ;
265252 moveType_ = moveType;
@@ -872,6 +859,100 @@ float NPC::getWeaponAccuracy(uint8_t weapon) const
872859 return ret;
873860}
874861
862+ void NPC::enterVehicle (IVehicle& vehicle, uint8_t seatId, NPCMoveType moveType)
863+ {
864+ if (player_->getState () != PlayerState_OnFoot)
865+ {
866+ return ;
867+ }
868+
869+ if (int (moveType) > int (NPCMoveType_Sprint) || int (moveType) < int (NPCMoveType_Walk))
870+ {
871+ moveType = NPCMoveType_Jog;
872+ }
873+
874+ int passengerSeats = Impl::getVehiclePassengerSeats (vehicle.getModel ());
875+ if (passengerSeats == 0xFF || seatId < 1 || seatId > passengerSeats)
876+ {
877+ return ;
878+ }
879+
880+ auto destination = getVehicleSeatPos (vehicle, seatId);
881+ float distance = glm::distance (getPosition (), destination);
882+ if (distance > MAX_DISTANCE_TO_ENTER_VEHICLE)
883+ {
884+ return ;
885+ }
886+
887+ // Save the entering stats
888+ vehicleToEnter_ = &vehicle;
889+ vehicleSeatToEnter_ = seatId;
890+
891+ // Check distance
892+ if (distance < MIN_VEHICLE_GO_TO_DISTANCE)
893+ {
894+ // Wait until the entry animation is finished
895+ vehicleEnterExitUpdateTime_ = lastUpdate_;
896+ enteringVehicle_ = true ;
897+
898+ // Check whether the player is jacking the vehicle or not
899+ if (seatId == 0 )
900+ {
901+ IPlayer* driver = vehicle.getDriver ();
902+ if (driver && driver->getID () != player_->getID ())
903+ {
904+ jackingVehicle_ = true ;
905+ }
906+ }
907+ else
908+ {
909+ const FlatHashSet<IPlayer*>& passengers = vehicle.getPassengers ();
910+ for (auto passenger : passengers)
911+ {
912+ if (passenger && passenger->getID () != player_->getID ())
913+ {
914+ IPlayerVehicleData* data = queryExtension<IPlayerVehicleData>(passenger);
915+ if (data && data->getSeat () == seatId)
916+ {
917+ jackingVehicle_ = true ;
918+ }
919+ }
920+ }
921+ }
922+
923+ // Call the SAMP enter vehicle function
924+ NetworkBitStream bs;
925+ bs.writeUINT16 (vehicle.getID ());
926+ bs.writeUINT8 (vehicleSeatToEnter_);
927+ npcComponent_->emulateRPCIn (*player_, NetCode::RPC::OnPlayerEnterVehicle::PacketID, bs);
928+ }
929+ else
930+ {
931+ // Go to the vehicle
932+ move (destination, moveType);
933+ }
934+ }
935+
936+ void NPC::exitVehicle ()
937+ {
938+ if (player_->getState () != PlayerState_Driver && player_->getState () != PlayerState_Passenger)
939+ {
940+ return ;
941+ }
942+
943+ IPlayerVehicleData* vehicleData = queryExtension<IPlayerVehicleData>(player_);
944+ if (!vehicleData || vehicleData->getVehicle () == nullptr )
945+ {
946+ return ;
947+ }
948+
949+ NetworkBitStream bs;
950+ bs.writeUINT16 (vehicleData->getVehicle ()->getID ());
951+ npcComponent_->emulateRPCIn (*player_, NetCode::RPC::OnPlayerExitVehicle::PacketID, bs);
952+
953+ vehicleEnterExitUpdateTime_ = lastUpdate_;
954+ }
955+
875956void NPC::setWeaponState (PlayerWeaponState state)
876957{
877958 if (state == PlayerWeaponState_Unknown)
0 commit comments