123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- /*!
- Base native class of all vehicles in game.
- */
- #ifdef FEATURE_NETWORK_RECONCILIATION
- class TransportOwnerState : PawnOwnerState
- {
- proto native void SetWorldTransform(vector transform[4]);
- proto native void GetWorldTransform(out vector transform[4]);
- proto native void SetLinearVelocity(vector value);
- proto native void GetLinearVelocity(out vector value);
- proto native void SetAngularVelocity(vector value);
- proto native void GetAngularVelocity(out vector value);
-
- proto native void SetBuoyancySubmerged(float value);
- proto native float GetBuoyancySubmerged();
- #ifdef DIAG_DEVELOPER
- override event void GetTransform(inout vector transform[4])
- {
- GetWorldTransform(transform);
- }
- #endif
- };
- class TransportMove : PawnMove
- {
- proto native void SetWorldTransform(vector transform[4]);
- proto native void GetWorldTransform(out vector transform[4]);
- proto native void SetLinearVelocity(vector value);
- proto native void GetLinearVelocity(out vector value);
- proto native void SetAngularVelocity(vector value);
- proto native void GetAngularVelocity(out vector value);
-
- #ifdef DIAG_DEVELOPER
- override event void GetTransform(inout vector transform[4])
- {
- GetWorldTransform(transform);
- }
- #endif
- };
- //! Uses NetworkMoveStrategy.NONE
- class Transport extends Pawn
- #else
- class Transport extends EntityAI
- #endif
- {
- //! Shared context across all vehicles for flipping
- private static ref VehicleFlippedContext m_FlippedContext;
-
- ref TIntArray m_SingleUseActions;
- ref TIntArray m_ContinuousActions;
- ref TIntArray m_InteractActions;
-
- protected bool m_EngineZoneReceivedHit;
- protected vector m_fuelPos;
-
- protected ref set<int> m_UnconsciousCrewMemberIndices;
- protected ref set<int> m_DeadCrewMemberIndices;
-
- void Transport()
- {
- RegisterNetSyncVariableBool("m_EngineZoneReceivedHit");
-
- if ( MemoryPointExists("refill") )
- m_fuelPos = GetMemoryPointPos("refill");
- else
- m_fuelPos = "0 0 0";
-
- m_UnconsciousCrewMemberIndices = new set<int>();
- m_DeadCrewMemberIndices = new set<int>();
- }
-
- override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
- {
- super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
- SetEngineZoneReceivedHit(dmgZone == "Engine");
- }
- override int GetMeleeTargetType()
- {
- return EMeleeTargetType.NONALIGNABLE;
- }
- //!
- protected override event typename GetOwnerStateType()
- {
- return TransportOwnerState;
- }
- //!
- protected override event typename GetMoveType()
- {
- return TransportMove;
- }
- //! Synchronizes car's state in case the simulation is not running.
- proto native void Synchronize();
- //! Returns crew capacity of this vehicle.
- proto native int CrewSize();
- //! Returns crew member index based on action component index.
- //! -1 is returned when no crew position corresponds to given component index.
- proto native int CrewPositionIndex( int componentIdx );
- //! Returns crew member index based on player's instance.
- //! -1 is returned when the player is not isnide.
- proto native int CrewMemberIndex( Human player );
- //! Returns crew member based on position index.
- //! Null can be returned if no Human is present on the given position.
- proto native Human CrewMember( int posIdx );
- //! Returns the driver
- //! Null can be returned if no Human is present.
- proto native Human CrewDriver();
- //! Reads entry point and direction into vehicle on given position in model space.
- proto void CrewEntry( int posIdx, out vector pos, out vector dir );
- //! Reads entry point and direction into vehicle on given position in world space.
- proto void CrewEntryWS( int posIdx, out vector pos, out vector dir );
- //! Returns crew transformation indside vehicle in model space
- proto void CrewTransform( int posIdx, out vector mat[4] );
- //! Returns crew transformation indside vehicle in world space
- proto void CrewTransformWS( int posIdx, out vector mat[4] );
- //! Performs transfer of player from world into vehicle on given position.
- proto native void CrewGetIn( Human player, int posIdx );
- //! Performs transfer of player from vehicle into world from given position.
- proto native Human CrewGetOut( int posIdx );
-
- //! Handles death of player in vehicle and awakes its physics if needed
- proto native void CrewDeath( int posIdx );
-
- override bool IsTransport()
- {
- return true;
- }
-
- override bool IsIgnoredByConstruction()
- {
- return false;
- }
-
- override bool IsHealthVisible()
- {
- return true;
- }
- override bool ShowZonesHealth()
- {
- return true;
- }
- override int GetHideIconMask()
- {
- return EInventoryIconVisibility.HIDE_VICINITY;
- }
-
- float GetMomentum()
- {
- return GetVelocity(this).Length() * dBodyGetMass(this);
- }
-
- bool IsVitalSparkPlug()
- {
- return true;
- }
-
- string GetVehicleType()
- {
- return "VehicleTypeUndefined";
- }
-
- string GetActionCompNameFuel()
- {
- return "refill";
- }
-
- float GetActionDistanceFuel()
- {
- return 1.5;
- }
-
- vector GetRefillPointPosWS()
- {
- return ModelToWorld( m_fuelPos );
- }
-
- protected /*sealed*/ VehicleFlippedContext GetFlipContext()
- {
- if (!m_FlippedContext)
- {
- m_FlippedContext = new VehicleFlippedContext();
- }
- #ifdef DIAG_DEVELOPER
- m_FlippedContext.Reset(DiagMenu.GetBool(DiagMenuIDs.VEHICLE_DRAW_FLIP_CONTEXT));
- #endif
-
- return m_FlippedContext;
- }
-
- protected bool DetectFlippedUsingSurface(VehicleFlippedContext ctx, float angleTolerance)
- {
- vector corners[4];
- GetTightlyPackedCorners(ETransformationAxis.BOTTOM, corners);
-
- // compute the average position to find the lowest "center-most" position
- vector avgPosition = vector.Zero;
- for (int i = 0; i < 4; i++)
- {
- avgPosition = avgPosition + corners[i];
- }
-
- avgPosition = avgPosition * 0.25;
-
- // get depth of the water to determine if we should use the roadway surface normal or just up vector
- float depth = GetGame().GetWaterDepth(avgPosition);
-
- vector normal = vector.Up;
- vector dirUp = GetDirectionUp();
-
- bool testLand = depth < -1.0;
-
- // iterate over the corners to find the average normal
- if (testLand)
- {
- // trace roadway, incase the vehicle is on a rock, or bridge
- ctx.m_SurfaceParams.type = SurfaceDetectionType.Roadway;
-
- // ignore expensive water computation, we already know we are above land
- ctx.m_SurfaceParams.includeWater = false;
-
- // ignore this vehicle, it may have a roadway LOD
- ctx.m_SurfaceParams.ignore = this;
-
- // detect closest to the given point
- ctx.m_SurfaceParams.rsd = RoadSurfaceDetection.CLOSEST;
-
- for (i = 0; i < 4; i++)
- {
- ctx.m_SurfaceParams.position = corners[i];
-
- GetGame().GetSurface(ctx.m_SurfaceParams, ctx.m_SurfaceResult);
-
- corners[i][1] = ctx.m_SurfaceResult.height;
- }
-
- vector d0 = vector.Direction(corners[0], corners[1]);
- vector d1 = vector.Direction(corners[0], corners[2]);
-
- d0.Normalize();
- d1.Normalize();
-
- // cross product the two directions to get the normal vector of the land
- normal = d0 * d1;
- }
-
- bool isFlipped = vector.Dot(normal, dirUp) < Math.Cos(angleTolerance * Math.DEG2RAD);
-
- #ifdef DIAG_DEVELOPER
- if (ctx.IsDebug())
- {
- int color = 0xFF00FF00;
- if (isFlipped)
- color = 0xFFFF0000;
-
- ctx.AddShape(Shape.Create(ShapeType.LINE, color, ShapeFlags.NOZBUFFER, corners[0], corners[0] + normal));
- ctx.AddShape(Shape.Create(ShapeType.LINE, color, ShapeFlags.NOZBUFFER, corners[1], corners[1] + normal));
- ctx.AddShape(Shape.Create(ShapeType.LINE, color, ShapeFlags.NOZBUFFER, corners[2], corners[2] + normal));
- ctx.AddShape(Shape.Create(ShapeType.LINE, color, ShapeFlags.NOZBUFFER, corners[3], corners[3] + normal));
- }
- #endif
-
- return isFlipped;
- }
-
- //! Override based on vehicle implementation (Car, Boat, modded, etc.)
- protected bool DetectFlipped(VehicleFlippedContext ctx)
- {
- return false;
- }
-
- //! Don't override, may change to native for caching 'DetectFlipped' in the future based on active-ness (i.e. only updated when vehicle changes active state)
- /*sealed*/ bool IsFlipped()
- {
- VehicleFlippedContext ctx = GetFlipContext();
- ctx.m_bIsAction = false;
- ctx.m_ActionPlayer = null;
- return DetectFlipped(ctx);
- }
-
- //! Don't override, may change to native for caching 'DetectFlipped' in the future based on active-ness (i.e. only updated when vehicle changes active state)
- /*sealed*/ bool IsActionFlipped(Man player)
- {
- VehicleFlippedContext ctx = GetFlipContext();
- ctx.m_bIsAction = true;
- ctx.m_ActionPlayer = player;
- return DetectFlipped(ctx);
- }
-
- bool IsAnyCrewPresent()
- {
- for (int index = 0; index < CrewSize(); ++index)
- {
- if (CrewMember(index) != null)
- return true;
- }
-
- return false;
- }
-
- float GetTransportCameraDistance()
- {
- return 4.0;
- }
-
- void MarkCrewMemberUnconscious(int crewMemberIndex)
- {
- set<int> crewMemberIndicesCopy = new set<int>();
- crewMemberIndicesCopy.Copy(m_UnconsciousCrewMemberIndices);
- crewMemberIndicesCopy.Insert(crewMemberIndex);
- m_UnconsciousCrewMemberIndices = crewMemberIndicesCopy;
- }
-
- void MarkCrewMemberDead(int crewMemberIndex)
- {
- set<int> crewMemberIndicesCopy = new set<int>();
- crewMemberIndicesCopy.Copy(m_DeadCrewMemberIndices);
- crewMemberIndicesCopy.Insert(crewMemberIndex);
- m_DeadCrewMemberIndices = crewMemberIndicesCopy;
- }
- protected void HandleByCrewMemberState(ECrewMemberState state);
- vector GetTransportCameraOffset()
- {
- return "0 1.3 0";
- }
-
- int GetAnimInstance()
- {
- #ifndef CFGMODS_DEFINE_TEST
- Error("GetAnimInstance() not implemented");
- return 0;
- #else
- return 2;
- #endif
- }
- int GetSeatAnimationType( int posIdx )
- {
- #ifndef CFGMODS_DEFINE_TEST
- Error("GetSeatAnimationType() not implemented");
- #endif
- return 0;
- }
- int Get3rdPersonCameraType()
- {
- #ifndef CFGMODS_DEFINE_TEST
- Error("Get3rdPersonCameraType() not implemented");
- return 0;
- #else
- return 31;
- #endif
- }
-
- bool CrewCanGetThrough( int posIdx )
- {
- #ifndef CFGMODS_DEFINE_TEST
- return false;
- #else
- return true;
- #endif
- }
-
- bool CanReachSeatFromSeat( int currentSeat, int nextSeat )
- {
- #ifndef CFGMODS_DEFINE_TEST
- return false;
- #else
- return true;
- #endif
- }
-
- bool CanReachSeatFromDoors( string pSeatSelection, vector pFromPos, float pDistance = 1.0 )
- {
- #ifndef CFGMODS_DEFINE_TEST
- return false;
- #else
- return true;
- #endif
- }
- bool CanReachDoorsFromSeat( string pDoorsSelection, int pCurrentSeat )
- {
- #ifndef CFGMODS_DEFINE_TEST
- return false;
- #else
- return true;
- #endif
- }
-
- int GetSeatIndexFromDoor( string pDoorSelection )
- {
- //Potientially could be fixed some other way, currently follows the unfortunate pattern that CanReachDoorsFromSeat has created
- switch (pDoorSelection)
- {
- case "DoorsDriver":
- return 0;
- break;
- case "DoorsCoDriver":
- return 1;
- break;
- case "DoorsCargo1":
- return 2;
- break;
- case "DoorsCargo2":
- return 3;
- break;
- }
- return -1;
- }
-
- bool IsIgnoredObject( Object o )
- {
- if (!o)
- return false;
- //! If the player can't interact (hint: collide) with the object, then it is ignored
- int layer = dBodyGetInteractionLayer(o);
- bool interacts = dGetInteractionLayer(this, PhxInteractionLayers.CHARACTER, layer);
- if (!interacts)
- {
- return true;
- }
- DayZPlayer player;
- if (Class.CastTo(player, o))
- {
- //! Ignore any player that is currently in this vehicle
- HumanCommandVehicle hcv = player.GetCommand_Vehicle();
- if (hcv && hcv.GetTransport() == this)
- {
- return true;
- }
- }
- EntityAI e = EntityAI.Cast(o);
- // CanBeSkinned means it is a dead entity which should not block the door
- return ( ( e && (e.IsZombie() || e.IsHologram()) ) || o.CanBeSkinned() || o.IsBush() || o.IsTree() );
- }
-
- void SetEngineZoneReceivedHit(bool pState)
- {
- m_EngineZoneReceivedHit = pState;
- SetSynchDirty();
- }
-
- bool HasEngineZoneReceivedHit()
- {
- return m_EngineZoneReceivedHit;
- }
-
- bool IsAreaAtDoorFree( int currentSeat, float maxAllowedObjHeight, inout vector extents, out vector transform[4] )
- {
- GetTransform(transform);
-
- vector crewPos;
- vector crewDir;
- CrewEntry( currentSeat, crewPos, crewDir );
-
- vector entry[4];
- entry[2] = crewDir;
- entry[0] = vector.Up * crewDir;
- entry[1] = entry[2] * entry[0];
- entry[3] = crewPos;
-
- Math3D.MatrixMultiply4( transform, entry, transform );
-
- vector position = transform[3];
- vector orientation = Math3D.MatrixToAngles(transform);
-
- position[1] = position[1] + maxAllowedObjHeight + (extents[1] * 0.5);
-
- array<Object> excluded = new array<Object>;
- array<Object> collided = new array<Object>;
-
- excluded.Insert(this);
-
- GetGame().IsBoxColliding(position, orientation, extents, excluded, collided);
-
- orientation.RotationMatrixFromAngles(transform);
- transform[3] = position;
-
- foreach (Object o : collided)
- {
- EntityAI e = EntityAI.Cast(o);
- if (IsIgnoredObject(o))
- continue;
-
- vector minmax[2];
- if (o.GetCollisionBox(minmax))
- return false;
- }
- return true;
- }
- bool IsAreaAtDoorFree( int currentSeat, float maxAllowedObjHeight = 0.5, float horizontalExtents = 0.5, float playerHeight = 1.7 )
- {
- vector transform[4];
- vector extents;
-
- extents[0] = horizontalExtents;
- extents[1] = playerHeight;
- extents[2] = horizontalExtents;
-
- return IsAreaAtDoorFree( currentSeat, maxAllowedObjHeight, extents, transform );
- }
-
- Shape DebugFreeAreaAtDoor( int currentSeat, float maxAllowedObjHeight = 0.5, float horizontalExtents = 0.5, float playerHeight = 1.7 )
- {
- int color = ARGB(20, 0, 255, 0);
-
- vector transform[4];
- vector extents;
-
- extents[0] = horizontalExtents;
- extents[1] = playerHeight;
- extents[2] = horizontalExtents;
-
- if (!IsAreaAtDoorFree( currentSeat, maxAllowedObjHeight, extents, transform ))
- {
- color = ARGB(20, 255, 0, 0);
- }
-
- Shape shape = Debug.DrawBox(-extents * 0.5, extents * 0.5, color);
- shape.SetMatrix(transform);
- return shape;
- }
- };
- class VehicleContactData
- {
- vector m_LocalPos;
- IEntity m_Other;
- float m_Impulse;
-
- void SetData(vector localPos, IEntity other, float impulse)
- {
- m_LocalPos = localPos;
- m_Other = other;
- m_Impulse = impulse;
- }
- };
- class VehicleFlippedContext
- {
- bool m_bIsAction = false;
- Man m_ActionPlayer;
-
- ref SurfaceDetectionParameters m_SurfaceParams = new SurfaceDetectionParameters();
- ref SurfaceDetectionResult m_SurfaceResult = new SurfaceDetectionResult();
-
- #ifdef DIAG_DEVELOPER
- private ref array<Shape> m_DebugShapes;
- private bool m_bIsDebug;
- void VehicleFlippedContext()
- {
- m_DebugShapes = new array<Shape>();
- }
-
- void ~VehicleFlippedContext()
- {
- Reset();
- }
-
- void Reset(bool isDebug = false)
- {
- foreach (Shape shape : m_DebugShapes)
- {
- shape.Destroy();
- }
-
- m_DebugShapes.Clear();
-
- m_bIsDebug = isDebug;
- }
-
- void AddShape(Shape shape)
- {
- m_DebugShapes.Insert(shape);
- }
-
- bool IsDebug()
- {
- return m_bIsDebug;
- }
- #endif
- };
|