Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /****************************************************************************
- * VEHICLE HANDLER ENTITY DEFINITION
- *
- * Description: Vehicle handler entity. Stores information about
- * the vehicle's parts and so on. It is the main body of the vehicle.
- ***************************************************************************/
- class Vehicle_Controller;
- Vehicle_Handler CurrentGameVehicle; // Pointer to the current game vehicle
- // Radial Menu Action definitions
- #include "scripts/Entities/RadialActionDefs.h"
- vector VSunPos; // Sunlight position and distance vector (for use in power generation) [0] = Azimuth, [1] = Zenith, [2] = Distance in AU
- vector VWeather; // Weather vector (for use in power generation etc) [0] = Weather value, [1] = Wind direction, [2] = Wind speed
- string VSkyPreset; // The currently set sky preset (for switching between NV and normal)
- Controller CallCtrlerOnCancel; // Linked to in the cancel function in CCGame.c
- class Controller
- {
- /* Vehicle_Controller owner;
- void SetOwner(Vehicle_Controller own)
- {
- owner = own;
- }
- */
- void ~Controller()
- {
- if (CallCtrlerOnCancel == this)
- CallCtrlerOnCancel = NULL;
- }
- bool Controller_OnCancel()
- {
- return true;
- }
- void Controller_OnSelect(Vehicle_Controller controller)
- {
- }
- void Controller_OnUnselect(Vehicle_Controller controller)
- {
- }
- void Controller_Init(Vehicle_Controller controller)
- {
- }
- void Controller_PostInit(Vehicle_Controller controller)
- {
- }
- void Controller_Exit(Vehicle_Controller controller)
- {
- }
- void Controller_OnFrm(Vehicle_Controller controller)
- {
- }
- void Controller_OnPFrm(Vehicle_Controller controller)
- {
- }
- void Controller_OnDeleteWidgets(Vehicle_Controller controller)
- {
- }
- void Controller_OnPreSim(Vehicle_Controller controller)
- {
- }
- void Controller_OnSim(Vehicle_Controller controller)
- {
- }
- void Controller_OnAfterSim(Vehicle_Controller controller)
- {
- }
- void Controller_OnTeleport(Vehicle_Controller controller)
- {
- }
- void Controller_OnSetVelocity(Vehicle_Controller controller)
- {
- }
- string Controller_GetStringForVar(string varName)
- {
- return "";
- }
- int Controller_GetIntForVar(string varName)
- {
- return 0;
- }
- float Controller_GetFloatForVar(string varName)
- {
- return 0;
- }
- bool Controller_GetBoolForVar(string varName)
- {
- return false;
- }
- vector Controller_GetVectorForVar(string varName)
- {
- return ZeroVec;
- }
- bool Controller_GetVehicleBroken()
- {
- return false;
- }
- float Controller_GetListenerVolume()
- {
- return 1;
- }
- float Controller_GetListenerSFXLerp()
- {
- return 0;
- }
- string Controller_GetListenerSFXPath()
- {
- return "";
- }
- bool Controller_GetOutOfFuel()
- {
- return false;
- }
- bool Controller_Editor_GetCanSpawnFuel()
- {
- return false;
- }
- void Controller_Editor_SpawnFuel()
- {
- }
- void Controller_OnFullyInitialized()
- {
- }
- void Controller_OnPartDamagedBy(Vehicle_Controller controller, Vehicle_Part part, float damage, int damagedByID)
- {
- }
- void Controller_OnPartHandleDamage(Vehicle_Controller controller, Vehicle_Part part, float damage)
- {
- }
- void Controller_OnBreakJoint(Vehicle_Controller controller, int jNum, bool breakFX, bool logLoss)
- {
- }
- void Controller_OnDeletePart(Vehicle_Controller controller, Vehicle_Part part, int pNum)
- {
- }
- void Controller_OnPress(Vehicle_Controller controller, Vehicle_Part part, bool end)
- {
- }
- void Controller_OnUnPress(Vehicle_Controller controller, Vehicle_Part part, bool end)
- {
- }
- void Controller_OnEvent(Vehicle_Controller controller, string eventName)
- {
- }
- void Controller_OnEventWithForce(Vehicle_Controller controller, string eventName, vector pos, vector force)
- {
- }
- void Controller_OnEventWithEntity(Vehicle_Controller controller, string eventName, _entity ent)
- {
- }
- void Controller_OnEventWithUnit(Vehicle_Controller controller, string eventName, Vehicle_Handler unit)
- {
- }
- void Controller_OnEventWithPart(Vehicle_Controller controller, string eventName, Vehicle_Part part)
- {
- }
- void Controller_OnEventWithSoundParams(Vehicle_Controller controller, string eventName, SoundShader sndShdr, vector sndPos, float sndVol, int ownerID)
- {
- }
- void Controller_OnEventWithInt(Vehicle_Controller controller, string eventName, int input)
- {
- }
- void Controller_OnEventWithFloat(Vehicle_Controller controller, string eventName, float input)
- {
- }
- void Controller_OnEventWithMatrix(Vehicle_Controller controller, string eventName, vector mat[])
- {
- }
- void Controller_OnContact(Vehicle_Controller controller, Vehicle_Part contactPart, _entity other, Contact extra)
- {
- }
- void Controller_SetCustomAnimation(string animPath, float tgtAnimSpeed, float tgtAnimFadeSpeed, bool noMove, bool mustComplete, bool lockView, float tgtFrame)
- {
- }
- void Controller_OnCompleteCustomAnimation(string animPath)
- {
- }
- void Controller_OnInventoryChanged(Vehicle_Controller controller)
- {
- }
- void Controller_OnInventoryAccessing(Vehicle_Controller controller, Vehicle_Part part, widget rootWidget, float timeSlice)
- {
- }
- // Called from a Ragdoll_Part entity if associated with this unit
- void Controller_OnRagdollContact(Vehicle_Controller controller, Ragdoll_Part contactPart, _entity other, Contact extra)
- {
- }
- bool Controller_OnClick(Vehicle_Controller controller, widget w, int x, int y, int button)
- {
- return false;
- }
- void OnEnterCar()
- {
- }
- void OnEnterBBlockSeat()
- {
- }
- // Called when fuel handler values should be stored (deletion of stored values handled automatically)
- void StoreFuelHandlerValues()
- {
- }
- //! MULTIPLAYER: See comment in GameEntity class
- void OnNetObjectInitSend( PacketOutputAdapter output )
- {
- }
- //! MULTIPLAYER: See comment in GameEntity class
- void OnNetObjectInitReceived( PacketInputAdapter input )
- {
- }
- //! MULTIPLAYER: See comment in GameEntity class
- int NeedNetUpdate()
- {
- return 0; //no update
- }
- //! MULTIPLAYER: See comment in GameEntity class
- void OnNetUpdate( PacketOutputAdapter output )
- {
- }
- //! MULTIPLAYER: See comment in GameEntity class
- bool OnNetMessage( PacketInputAdapter input )
- {
- return true;
- }
- //! MULTIPLAYER: See comment in GameEntity class
- bool OnRPC( int proc, PacketInputAdapter input )
- {
- return true;
- }
- bool IsServer()
- {
- return g_Game.IsServer();
- }
- bool IsClient()
- {
- return g_Game.IsClient();
- }
- Vehicle_Part GetPartByCustomTitle(Vehicle_Controller controller, string customTitle)
- {
- return NULL;
- }
- _entity GetEntityByCustomTitle(Vehicle_Controller controller, string customTitle)
- {
- return NULL;
- }
- // Radiation
- float GetPartRadiationShieldingScale(Vehicle_Part part, int partNum)
- {
- return 1;
- }
- // Communications
- vector GetPartCommsRange_Pos(Vehicle_Part part, int partNum)
- {
- return ZeroVec;
- }
- float GetPartCommsRange_Near(Vehicle_Part part, int partNum)
- {
- return 0;
- }
- float GetPartCommsRange_Far(Vehicle_Part part, int partNum)
- {
- return 0;
- }
- bool GetCommsAlwaysVisibleOnMap()
- {
- return false;
- }
- // Dynamic Atmo zone created - client only
- void OnDynamicAtmoZoneCreated(DynamicAtmoZone dynAtmoZone, int customID)
- {
- }
- // Dynamic Atmo zone deleted - client only
- void OnDynamicAtmoZoneDeleted(DynamicAtmoZone dynAtmoZone, int customID)
- {
- }
- float GetObjectViewPct(_entity ent)
- {
- return 0;
- }
- AtmoZone GetAtmoZoneByName(string atmoZoneName)
- {
- return NULL;
- }
- };
- class Vehicle_Controller
- {
- Vehicle_Handler ownerVehicle;
- ScriptModule scriptModule[CONTROL_VEHICLEMAX];
- Controller scriptController[CONTROL_VEHICLEMAX];
- int netUpdateFlags;
- int numScript;
- float VInput_mX;
- float VInput_mY;
- float VInput_mW;
- float VInput_aF;
- float VInput_aB;
- float VInput_aL;
- float VInput_aR;
- float VInput_aU;
- float VInput_aD;
- float VInput_sF;
- float VInput_sB;
- float VInput_sL;
- float VInput_sR;
- float VInput_sU;
- float VInput_sD;
- float VInput_actJump;
- float VInput_actElev;
- float VInput_actRele;
- void InitScripts();
- void PostInitScripts();
- void ProcessOnSelect();
- void ProcessOnUnselect();
- void ProcessOnFrm();
- void ProcessOnPFrm();
- void ProcessOnDeleteWidgets();
- void ProcessOnPreSim();
- void ProcessOnSim();
- void ProcessOnAfterSim();
- void ProcessOnTeleport();
- void ProcessOnSetVelocity();
- void ProcessOnPartDamagedBy(Vehicle_Part part, float damage, int damagedByID);
- void ProcessOnPartHandleDamage(Vehicle_Part part, float damage);
- void ProcessOnBreakJoint(int jNum, bool breakFX, bool logLoss);
- void ProcessOnDeletePart(Vehicle_Part part, int pNum);
- void ProcessOnPress(Vehicle_Part part, bool end);
- void ProcessOnUnPress(Vehicle_Part part, bool end);
- void ProcessOnEvent(string eventName);
- void ProcessOnEventWithForce(string eventName, vector pos, vector force);
- void ProcessOnEventWithEntity(string eventName, _entity ent);
- void ProcessOnEventWithUnit(string eventName, Vehicle_Handler unit);
- void ProcessOnEventWithPart(string eventName, Vehicle_Part part);
- void ProcessOnEventWithSoundParams(string eventName, SoundShader sndShdr, vector sndPos, float sndVol, int ownerID);
- void ProcessOnEventWithInt(string eventName, int input);
- void ProcessOnEventWithFloat(string eventName, float input);
- void ProcessOnEventWithMatrix(string eventName, vector mat[]);
- void ProcessOnContact(Vehicle_Part contactPart, _entity other, Contact extra);
- void ProcessSetCustomAnimation(string animPath, float tgtAnimSpeed, float tgtAnimFadeSpeed, bool noMove, bool mustComplete, bool lockView, float tgtFrame);
- void ProcessOnCompleteCustomAnimation(string animPath);
- void ProcessInventoryChanged();
- void ProcessInventoryAccessing(Vehicle_Part part, widget rootWidget, float timeSlice);
- void ProcessOnRagdollContact(Ragdoll_Part contactPart, _entity other, Contact extra);
- void ProcessOnClick(widget w, int x, int y, int button);
- Vehicle_Part GetPartByCustomTitle(string customTitle);
- _entity GetEntityByCustomTitle(string customTitle);
- // Radiation
- float GetPartRadiationShieldingScale(Vehicle_Part part, int partNum);
- // Communications
- vector GetPartCommsRange_Pos(Vehicle_Part part, int partNum);
- float GetPartCommsRange_Near(Vehicle_Part part, int partNum);
- float GetPartCommsRange_Far(Vehicle_Part part, int partNum);
- bool GetCommsAlwaysVisibleOnMap();
- // Dynamic Atmo zones - client only
- void ProcessOnDynamicAtmoZone(DynamicAtmoZone dynAtmoZone, int customID);
- void ProcessDeleteDynamicAtmoZone(DynamicAtmoZone dynAtmoZone, int customID);
- float GetObjectViewPct(_entity ent);
- AtmoZone GetAtmoZoneByName(string atmoZoneName);
- void AddScript(string scriptStr);
- void ExitScripts();
- void OnEnterCar();
- void OnEnterBBlockSeat();
- //! MULTIPLAYER: See comment in GameEntity class
- bool IsServer();
- bool IsClient();
- void OnNetObjectInitSend( PacketOutputAdapter output );
- void OnNetObjectInitReceived( PacketInputAdapter input );
- int NeedNetUpdate();
- void OnNetUpdate( PacketOutputAdapter output );
- bool OnNetMessage( PacketInputAdapter input );
- bool OnRPC( int proc, PacketInputAdapter input );
- string GetStringForVar(string varName)
- {
- string result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetStringForVar(varName);
- if (result != "")
- return result;
- }
- }
- return "";
- }
- int GetIntForVar(string varName)
- {
- int result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetIntForVar(varName);
- if (result != 0)
- return result;
- }
- }
- return 0;
- }
- float GetFloatForVar(string varName)
- {
- float result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetFloatForVar(varName);
- if (result != 0)
- return result;
- }
- }
- return 0;
- }
- bool GetBoolForVar(string varName)
- {
- bool result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetBoolForVar(varName);
- if (result)
- return result;
- }
- }
- return false;
- }
- vector GetVectorForVar(string varName)
- {
- vector result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetVectorForVar(varName);
- if (result != ZeroVec)
- return result;
- }
- }
- return ZeroVec;
- }
- bool GetVehicleBroken()
- {
- bool result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetVehicleBroken();
- if (result)
- return result;
- }
- }
- return false;
- }
- float GetListenerVolume()
- {
- float result = 1;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetListenerVolume();
- if (result != 1)
- return result;
- }
- }
- return 1;
- }
- float GetListenerSFXLerp()
- {
- float result = 0;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetListenerSFXLerp();
- if (result != 0)
- return result;
- }
- }
- return 0;
- }
- string GetListenerSFXPath()
- {
- string result = "";
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetListenerSFXPath();
- if (result != "")
- return result;
- }
- }
- return "";
- }
- bool GetOutOfFuel()
- {
- bool result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_GetOutOfFuel();
- if (result)
- return result;
- }
- }
- return false;
- }
- bool Editor_GetCanSpawnFuel()
- {
- bool result;
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- {
- result = ctrl.Controller_Editor_GetCanSpawnFuel();
- if (result)
- return result;
- }
- }
- return false;
- }
- void Editor_SpawnFuel()
- {
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- ctrl.Controller_Editor_SpawnFuel();
- }
- }
- void CallOnFullyInitialized()
- {
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- ctrl.Controller_OnFullyInitialized();
- }
- }
- void StoreFuelHandlerValues()
- {
- for (int i = 0; i < numScript; i++)
- {
- Controller ctrl = scriptController[i];
- if (ctrl)
- ctrl.StoreFuelHandlerValues();
- }
- }
- void Vehicle_Controller()
- {
- ownerVehicle = NULL;
- numScript = 0;
- for (int i = 0; i < CONTROL_VEHICLEMAX; i++)
- {
- scriptModule[i] = NULL;
- scriptController[i] = NULL;
- }
- }
- void ~Vehicle_Controller()
- {
- ownerVehicle = NULL;
- numScript = 0;
- ScriptModule smodule;
- Controller controller;
- for (int i = 0; i < CONTROL_VEHICLEMAX; i++)
- {
- if (scriptModule[i])
- {
- controller = scriptController[i];
- smodule = scriptModule[i];
- if(controller)
- delete controller; //destroy before destroing module!
- if (smodule)
- smodule.Release();
- scriptModule[i] = NULL;
- }
- }
- }
- }
- class Vehicle_Handler extends Vehicle_Part
- {
- World GetCurrentWorld(); // Returns the current world
- NetPlayerTKOM netPlayer; //player which controls this vehicle
- VehicleObject storage; //vehicle object storage. exist always and is serializable. all vehicle/mission data that need be serialized, store to this!!!
- TraceContact VehicleTrcCon; // Pointer to the vehicle's TraceContact entity
- _entity VehicleTrcEnt; // Pointer to the traced entity (NOT SERIALIZED SO ENSURE RESET!)
- Vehicle_WidgetHandler widgetHandler; // The vehicle's widget handler
- Vehicle_Controller vehicleController; // The vehicle's controller
- widget widgetList[WIDGETS_VEHICLEMAX] // A list of widgets created on the vehicle
- // Variables that should not be serialized
- // =============================================================================================
- bool delayDelete; // If true, the vehicle will delete itself the next frame
- bool isSelected; // True when the vehicle is selected
- bool lastSelected; // Stores the last selected state (for optimization)
- bool EnvData; // True if environmental data should be displayed
- bool EmergencyMode; // True if the vehicle is in emergency mode (for HUD)
- bool HasMovementInput; // True if the unit has some form of input
- bool HasTurboInput; // True if the unit has turbo input
- vector MovementInput; // Amount of input in units
- float PriPartSwitchTime; // Delay time for keyboard and analog controls for primary parts
- float SecPartSwitchTime; // Delay time for keyboard and analog controls for secondary parts
- float GodModeTime; // If above 0, the vehicle cannot get damaged and joints can't break. Decrements with time
- float PowerGenRate; // Stores the amount of power the vehicle is generating per hour
- float PowerDrainRate; // Stores the amount of power the vehicle is draining per hour
- float PowerStorageMax; // Stores the amount of power the vehicle can store
- float ChemBattLevel; // Stores the amount of power available in backup chemical batteries (for HUD)
- bool ChemBattUse; // Stores whether the chemical batteries are being actively used
- vector PowerTraces; // Stores the number of traces performed for solar panel simulation
- string CommandsHelpList[MAX_VEHICLES_COMMANDS_TYPES][MAX_VEHICLES_COMMANDS_TYPESMAX]; // Stores a list of commands that are available for the vehicle
- int CommandsHelpListNum;
- bool CommandsHelpListUpdated; // If false, tells the controllers to update the list
- bool NoHierarchyGripImpulseBreak; // If true, then impulses to gripped parts will not break the grip of other gripped parts
- void QueueDelete();
- // On fully initialized
- void OnFullyInitialized()
- {
- if( HasNetworkObject() ) //in multiplayer on server
- InitNetworkObject(); //we have to notify c++ side that entity is completely initialized!
- if (vehicleController)
- vehicleController.CallOnFullyInitialized();
- }
- // Radiation
- float GetPartRadiationShieldingScale(Vehicle_Part part, int partNum)
- {
- if (vehicleController)
- return vehicleController.GetPartRadiationShieldingScale(part, partNum);
- return 1;
- }
- // Communications
- vector GetPartCommsRange_Pos(Vehicle_Part part, int partNum)
- {
- if (vehicleController)
- return vehicleController.GetPartCommsRange_Pos(part, partNum);
- return ZeroVec;
- }
- float GetPartCommsRange_Near(Vehicle_Part part, int partNum)
- {
- if (vehicleController)
- return vehicleController.GetPartCommsRange_Near(part, partNum);
- return 0;
- }
- float GetPartCommsRange_Far(Vehicle_Part part, int partNum)
- {
- if (vehicleController)
- return vehicleController.GetPartCommsRange_Far(part, partNum);
- return 0;
- }
- bool GetCommsAlwaysVisibleOnMap()
- {
- if (vehicleController)
- return vehicleController.GetCommsAlwaysVisibleOnMap();
- return false;
- }
- // Object in view screen percent checking
- float GetObjectViewPct(_entity ent)
- {
- if (vehicleController)
- return vehicleController.GetObjectViewPct(ent);
- return 0;
- }
- // Get an atmospheric zone by name
- AtmoZone GetAtmoZoneByName(string atmoZoneName)
- {
- if (vehicleController)
- return vehicleController.GetAtmoZoneByName(atmoZoneName);
- return NULL;
- }
- // Joint pointers, block pointers etc
- dJoint joints_ents[VEHICLE_MAXJOINTS]; // Stores a pointer to each joint
- dBlock blocks_ents[VEHICLE_MAXBLOCKS]; // Stores a pointer to each collision blocker
- Vehicle_Part parts_ents[VEHICLE_MAXPARTS]; // Stores an entity pointer to each part
- int parts_interactionLayer[VEHICLE_MAXPARTS]; // Stores the physics interaction layer of each part for disabling collisions
- GUI3DWidgetHandler gui3dWidgetHandler[VEHICLE_MAXPARTS]; // Stores pointer to 3D GUI widget handler pointer
- #ifdef DEVELOPER
- float parts_lastGripTime[VEHICLE_MAXPARTS]; // Stores the last time the part gripped in MP
- #endif
- // List of 3D GUI widget handlers for multiplayer synch
- GUI3DWidgetHandler MP_gui3dWidgetHandlerList[VEHICLE_MAXPARTS];
- int MP_gui3dWidgetHandlerListNum;
- int Get3DGUIWidgetHandlerListPartNum(GUI3DWidgetHandler w3dguih)
- {
- for (int p = 0; p < MP_gui3dWidgetHandlerListNum; p++)
- {
- if (gui3dWidgetHandler[p] == w3dguih)
- return p;
- }
- return -1;
- }
- void Assign3DGUIWidgetHandlerToPart(int partNum, GUI3DWidgetHandler w3dguih)
- {
- if (gui3dWidgetHandler[partNum])
- {
- Print(String("VEHICLE_HANDLER::ASSIGN3DGUIWIDGETHANDLERTOPART() - Cannot assign 3D GUI widget handler to part " + itoa(partNum) + ", already one assigned!"));
- return;
- }
- w3dguih.owner = this;
- w3dguih.id = partNum;
- gui3dWidgetHandler[partNum] = w3dguih;
- MP_gui3dWidgetHandlerList[MP_gui3dWidgetHandlerListNum] = w3dguih;
- MP_gui3dWidgetHandlerListNum++;
- }
- void Unassign3DGUIWidgetHandlerFromPart(int partNum)
- {
- if (!gui3dWidgetHandler[partNum])
- return;
- GUI3DWidgetHandler w3dguih_del = gui3dWidgetHandler[partNum];
- gui3dWidgetHandler[partNum] = NULL;
- bool found = false;
- for (int gui = 0; gui < MP_gui3dWidgetHandlerListNum; gui++)
- {
- GUI3DWidgetHandler w3dguih = MP_gui3dWidgetHandlerList[gui];
- if (w3dguih == w3dguih_del)
- found = true;
- if (found)
- {
- if (MP_gui3dWidgetHandlerListNum <= gui + 1)
- MP_gui3dWidgetHandlerList[gui] = NULL;
- else
- MP_gui3dWidgetHandlerList[gui] = MP_gui3dWidgetHandlerList[gui + 1];
- }
- }
- MP_gui3dWidgetHandlerListNum--;
- }
- GUI3DHandler GetCurrent3DGUI();
- bool PlayerUsing3DGUI();
- // Returns the vehicle's current power drain
- float GetTotalPowerDrain()
- {
- float result = 0;
- for (int i = 0; i < storage.parts_num; i++)
- {
- result += storage.parts_pwrdrain[i];
- }
- return result;
- }
- // Updates power level from drain, charge, and max storage
- void UpdatePower();
- // Sends a popup message to the target player
- void SendPopupToOwner(bool noAlphaChange, bool clearPrevious, float time, string layout, string titStr, string descStr, string descStr2);
- //! MULTIPLAYER: See comment in GameEntity class
- void OnNetObjectInitSend( PacketOutputAdapter output );
- void OnNetObjectInitReceived( PacketInputAdapter input );
- void OnNetObjectAfterInitSend( PacketOutputAdapter output );
- void OnNetObjectAfterInitReceived( PacketInputAdapter input );
- int NeedNetUpdate();
- void OnNetUpdate( PacketOutputAdapter output );
- bool OnNetMessage( PacketInputAdapter input );
- bool OnRPC(int proc, PacketInputAdapter input);
- void RP_SynchTeam(int team, bool isRemoteCall = false);
- void RP_SelectCameraMainMode(int mode, bool isRemoteCall = false);
- bool EnterCar(Vehicle_Handler vehicle, int reachSeat);
- void RP_EnterCar(int vehicleID, int reachSeat, bool isRemoteCall = false);
- bool EnterBBlockSeat(_entity bblockBase, int reachSeat);
- void RP_EnterBBlockSeat(int bblockID, int reachSeat, bool isRemoteCall = false);
- void SelectCameraMainMode(int mode);
- void SetNetPlayer(NetPlayerTKOM player);
- NetPlayer GetNetPlayer();
- bool IsControlledByLocalPlayer();
- bool IsControlledByLocalDriver();
- bool IsControlledByRemoteDriver();
- bool IsControlledByRemotePlayer();
- bool IsControlledByAnyPlayer();
- bool IsControlledByAnyDriver();
- float GetControllerValue(int eEvent);
- bool IsControlsReceiver();
- bool PlayerHasMouseCursorEnabled();
- void SetInteractionLayer(int layer);
- Vehicle_Handler GetDriver();
- Vehicle_Handler GetPassenger(int iSeatNum);
- // Returns the display name for the input type name
- string GetTypeDisplayName(string typeStr)
- {
- for (int i = 0; i < storage.parts_num; i++) {
- if (storage.parts_types[i] == typeStr)
- return storage.parts_title[i];
- }
- return "";
- }
- // Returns the display name for the input sub-type name
- string GetSubTypeDisplayName(string subTypeStr)
- {
- for (int i = 0; i < storage.parts_num; i++) {
- if (storage.parts_subtypes[i] == subTypeStr)
- return storage.parts_title[i];
- }
- return "";
- }
- // Clear the commands help list
- void ClearCommandsHelpList()
- {
- CommandsHelpListUpdated = false;
- for (int i = 0; i < MAX_VEHICLES_COMMANDS_TYPES; i++) {
- for (int n = 0; n < MAX_VEHICLES_COMMANDS_TYPESMAX; n++) {
- CommandsHelpList[i][n] = "";
- }
- }
- CommandsHelpListNum = 0;
- }
- // Adds a command to the help list
- void AddCommandToHelpList(string cmdStr1, string cmdStr2, string cmdStr3, string cmdStr4, string cmdStr5, string descStr)
- {
- if (CommandsHelpListNum >= MAX_VEHICLES_COMMANDS_TYPES)
- return;
- CommandsHelpList[CommandsHelpListNum][0] = cmdStr1;
- CommandsHelpList[CommandsHelpListNum][1] = cmdStr2;
- CommandsHelpList[CommandsHelpListNum][2] = cmdStr3;
- CommandsHelpList[CommandsHelpListNum][3] = cmdStr4;
- CommandsHelpList[CommandsHelpListNum][4] = cmdStr5;
- CommandsHelpList[CommandsHelpListNum][5] = descStr;
- CommandsHelpListNum++;
- }
- // Arcade input
- float input_arc_pri0;
- float input_arc_pri1;
- float input_arc_pri2;
- bool input_arc_prigui;
- float input_arc_sec0;
- float input_arc_sec1;
- float input_arc_sec2;
- bool input_arc_secgui;
- float input_mouse_X;
- float input_mouse_Y;
- float input_mouse_Whl;
- // Vehicle switch tab variables
- bool tabs_update; // Read from the campaign to determine whether to update the tabs
- // Vehicle camera display variables
- const int CAMS_MAINCAMNUM = 4;
- const int CAMS_FIRSTCAMNUM = 5;
- int cams_alllist[VEHICLE_MAXPARTS];
- int cams_allistpos; // Stores the camera PIP the comprehensive list should be generated for
- bool cams_tookphoto; // If true will take photo from the main camera
- bool cams_mainModeSwitch; // True when switch button pressed
- int cams_switchsel; // 0 is null, 1-6 correspond to cams 1-6
- vector cams_photoOffset; // Used for tracing to the camera taking the picture
- bool cams_photoColor; // Used to determine if the correct camera is being used in photo framing
- int cams_photoPart; // Used to determine which vehicle part took the photo, for disabling collision in traces
- // Vehicle instrument display variables
- int inst_alllist[VEHICLE_MAXPARTS]; //list of instruments indexes
- int inst_alllistex[VEHICLE_MAXPARTS]; //list of instruments indexes including passive
- float inst_invalidtime; // Stores how long the invalid target hint is shown for
- int inst_invalidtype; // Stores the type of invalid target to show, 0 = null, 1 = out of range, 2 = wrong target type
- bool inst_inrange; // Set from instruments, if true, a valid target is in range
- string inst_hilite; // Set from instruments, text to display in the instrument HUD when mousing over use instrument
- string inst_sample; // Set from instruments, text to display in the instrument HUD when the instrument is sampling
- string inst_analyze; // Set from instruments, text to display in the instrument HUD when the instrument is analyzing
- // Vehicle Radial Menu variables
- bool radm_closed; // Read from controllers to determine whether the radial menu is closed
- bool radm_disabled; // Read from controllers to determine whether the radial menu is disabled
- bool radm_lastcursor; // Stores the state of the cursor prior to opening the radial menu
- bool radm_reloadimg; // Set to true when the icons on the radial menu need to be reloaded
- float radm_alpha; // Stores the alpha value (0 - 1) of the window
- string radm_act[RADM_NUMSLOTS]; // Store the actions to be executed when the appropriate radial menu icon is selected
- bool radm_used[RADM_NUMSLOTS]; // True when the assigned action should be executed
- //Camera matrix in entity format
- vector cameraMat[4];
- vector cameraForcedMat[4];
- // Camera Mode HUD variables
- float camHUD_zoom; // Zoom level (-1 - 1)
- // Vehicle part HUD status indicators
- const int STAT_MAX = 10;
- int stat_state[STAT_MAX]; // Used in controllers to indicate the status of important parts
- // Returns the first free radial menu slot
- int RadialMenuGetFreeSlot()
- {
- if (radm_act[RADM_UP] == "")
- return RADM_UP;
- if (radm_act[RADM_RT] == "")
- return RADM_RT;
- if (radm_act[RADM_DN] == "")
- return RADM_DN;
- if (radm_act[RADM_LT] == "")
- return RADM_LT;
- return RADM_NULL;
- }
- // Returns the radial menu position the action has been assigned to
- int RadialMenuGetActionAssigned(string action)
- {
- if (radm_act[RADM_UP] == action)
- return RADM_UP;
- if (radm_act[RADM_DN] == action)
- return RADM_DN;
- if (radm_act[RADM_LT] == action)
- return RADM_LT;
- if (radm_act[RADM_RT] == action)
- return RADM_RT;
- return RADM_NULL;
- }
- // Associates an action to the desired icon, assigning the appropriate icon as well
- void RadialMenuSetAction(int pos, string action, string image, string imageHi, string actionTitle)
- {
- widget wP = FindWidget(NULL, "HUDRoot_RadialMenu");
- if (wP) {
- string txt2 = "";
- if (pos == RADM_UP && radm_act[RADM_UP] != action) {
- radm_act[RADM_UP] = action;
- radm_used[RADM_UP] = false;
- txt2 = "up";
- }
- if (pos == RADM_DN && radm_act[RADM_DN] != action) {
- radm_act[RADM_DN] = action;
- radm_used[RADM_DN] = false;
- txt2 = "down";
- }
- if (pos == RADM_LT && radm_act[RADM_LT] != action) {
- radm_act[RADM_LT] = action;
- radm_used[RADM_LT] = false;
- txt2 = "left";
- }
- if (pos == RADM_RT && radm_act[RADM_RT] != action) {
- radm_act[RADM_RT] = action;
- radm_used[RADM_RT] = false;
- txt2 = "right";
- }
- if (image != "" && imageHi != "") {
- widget wIco = FindAnyWidget(wP, "icon_" + txt2 + "0");
- widget wIcoHi = FindAnyWidget(wP, "icon_" + txt2 + "0_hi");
- widget wTxt = FindAnyWidget(wP, "icon_" + txt2 + "1_hi");
- if (wIco) {
- if (action == "") {
- if (widgetHandler) {
- int id = widgetHandler.FindInList("icon_" + txt2 + "0");
- if (id != -1)
- SetWidgetColor(wIco, ARGBF(widgetHandler.HUDBtn_Color[id][0], widgetHandler.HUDBtn_Color[id][1], widgetHandler.HUDBtn_Color[id][2], widgetHandler.HUDBtn_Color[id][3]));
- }
- }
- LoadWidgetImage(wIco, 1, image);
- SetWidgetImage(wIco, 1);
- }
- if (wIcoHi) {
- if (action == "")
- SetWidgetColor(wIcoHi, ARGBF(0, 0, 0, 0));
- else {
- LoadWidgetImage(wIcoHi, 1, imageHi);
- SetWidgetImage(wIcoHi, 1);
- }
- }
- if (wTxt) {
- if (action == "")
- SetWidgetColor(wTxt, ARGBF(0, 0, 0, 0));
- else
- SetWidgetTextEx(wTxt, 0, 1, actionTitle);
- }
- }
- }
- }
- // Tries to assign an action to the radial menu, if succeeds returns the slot
- int RadialMenuAttemptAssignAction(string action, string image, string imageHi, string actionTitle)
- {
- int result = RadialMenuGetActionAssigned(action);
- if (result == RADM_NULL) {
- result = RadialMenuGetFreeSlot();
- if (result != RADM_NULL)
- RadialMenuSetAction(result, action, image, imageHi, actionTitle);
- }
- return result;
- }
- // Tries to reset a single radial menu action to none
- void RadialMenuResetAction(int pos)
- {
- if (pos != RADM_NULL)
- RadialMenuSetAction(pos, "", "gui/textures/radmenu/icon_none", "gui/textures/radmenu/icon_none", "#tkom_rdmac_none");
- }
- // Resets all radial menu actions to none
- void RadialMenuResetActions()
- {
- radm_act[RADM_UP] = "RESET";
- radm_act[RADM_DN] = "RESET";
- radm_act[RADM_LT] = "RESET";
- radm_act[RADM_RT] = "RESET";
- RadialMenuSetAction(RADM_UP, "", "gui/textures/radmenu/icon_none", "gui/textures/radmenu/icon_none", "#tkom_rdmac_none");
- RadialMenuSetAction(RADM_DN, "", "gui/textures/radmenu/icon_none", "gui/textures/radmenu/icon_none", "#tkom_rdmac_none");
- RadialMenuSetAction(RADM_LT, "", "gui/textures/radmenu/icon_none", "gui/textures/radmenu/icon_none", "#tkom_rdmac_none");
- RadialMenuSetAction(RADM_RT, "", "gui/textures/radmenu/icon_none", "gui/textures/radmenu/icon_none", "#tkom_rdmac_none");
- }
- // Enables/disables impact damage on parts (does not disable joint breaking!!)
- void EnableImpactDamage(bool enable)
- {
- for (int i = 0; i < storage.parts_num; i++)
- {
- Vehicle_Part pEnt = parts_ents[i];
- if (pEnt)
- pEnt.ImpactDamageEnabled = enable;
- }
- }
- // Checks whether a part is connected to the target part
- bool CheckPartConnect(int partNum, int partParent)
- {
- if (partNum <= -1 || partParent <= -1)
- return false;
- Vehicle_Part pEnt = parts_ents[partNum];
- if (pEnt) {
- int pNum = partNum;
- if (storage.parts_models[partNum] == "INTERNAL") // If internal part, then automatically assume its parent can only be part 0
- pNum = 0;
- else {
- int numIterations = 0;
- while(pNum != partParent && pNum != -1 && numIterations < VEHICLE_MAXPARTS) {
- pEnt = parts_ents[pNum];
- if (pEnt)
- pNum = pEnt.ParentPartNum;
- numIterations++;
- }
- if (numIterations == VEHICLE_MAXPARTS) {
- pNum = -1;
- Print(String("CHECKPARTCONNECT(): Vehicle '" + storage.name + "' got stuck in an infinite loop while checking connection from parent " + itoa(partParent) + " to child " + itoa(partNum) + "!"));
- }
- }
- if (pNum == partParent)
- return true;
- }
- return false;
- }
- // Checks whether a part is connected to a base part
- bool CheckPartBaseConnect(int partNum)
- {
- if (partNum <= -1)
- return false;
- if (CheckPartConnect(partNum, 0)) // Part 0 is always a base
- return true;
- for (int i = 0; i < storage.ctrlbase_num; i++)
- {
- if (storage.ctrlbase_parts[i] > 0 && CheckPartConnect(partNum, storage.ctrlbase_parts[i]))
- return true;
- }
- return false;
- }
- float GetSpringScale()
- {
- float sscale = 1 / phys_FixedTick - 60 / 60;
- clamp sscale<0, 1>;
- sscale = 1 - sscale * 1 + 1;
- return sscale;
- }
- float GetSpringLinDampScale()
- {
- return 0.0001;
- }
- float GetSpringAngDampScale()
- {
- return 0.0001;
- }
- // Returns joint index that is connected to part. Careful, returns only first joint it finds!
- int GetJointToPart(int partNum)
- {
- if (partNum <= -1)
- return -1;
- for (int i = 0; i < storage.joints_num; i++)
- {
- if (storage.joints_part2[i] == partNum)
- return i;
- }
- return -1;
- }
- // Returns joint index that is connected between parts. Careful, returns only first joint it finds!
- int GetJointBetweenParts(int parentPartNum, int partNum)
- {
- if (partNum <= -1)
- return -1;
- if (parentPartNum <= -1)
- return -1;
- for (int i = 0; i < storage.joints_num; i++)
- {
- if (storage.joints_part1[i] == parentPartNum && storage.joints_part2[i] == partNum)
- return i;
- }
- return -1;
- }
- // Returns whether to use a lower LOD for the joint
- bool GetUseLODJoint(int jointNum)
- {
- if (!IsClient() && storage.joints_isLODed[jointNum] && fsum(1 / phys_FixedTick) < 100)
- return true;
- else
- return false;
- }
- // Returns the joint's type, taking into account joint LODs
- int GetJointType(int jointNum)
- {
- int jointType = storage.joints_type[jointNum];
- if (GetUseLODJoint(jointNum))
- jointType = JOINT_FIXED;
- return jointType;
- }
- // Returns the number of the target part type
- int PartTypeGetNum(int pNum, string pType)
- {
- int result = 0;
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i]) {
- if (storage.parts_types[i] == pType)
- result++;
- }
- if (i >= pNum)
- break;
- }
- return result;
- }
- // Returns the number of the target part subtype
- int PartSubTypeGetNum(int pNum, string pType)
- {
- int result = 0;
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i]) {
- if (storage.parts_subtypes[i] == pType)
- result++;
- }
- if (i >= pNum)
- break;
- }
- return result;
- }
- // Returns first part of set type
- Vehicle_Part GetPartByType(string pType)
- {
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i] && storage.parts_types[i] == pType)
- return parts_ents[i];
- }
- }
- // Checks if a camera part is in the camera list
- int CameraGetInList(int pNum)
- {
- int result = -1;
- for (int i = 0; i < CAMS_MAX; i++) {
- if (storage.cams_list[i] == pNum) {
- result = i;
- break;
- }
- }
- return result;
- }
- // Adds a camera part to the camera list
- void CameraAddToList(int pNum)
- {
- if (CameraGetInList(pNum) == -1) {
- for (int i = 0; i < CAMS_MAX; i++) {
- if (storage.cams_list[i] == -1) {
- storage.cams_list[i] = pNum;
- storage.cams_online[i] = true;
- break;
- }
- }
- }
- }
- // Removes a camera part from the camera list
- void CameraRemoveFromList(int pNum)
- {
- bool removed = false;
- for (int i = 0; i < CAMS_MAX; i++) {
- if (storage.cams_list[i] == pNum) {
- storage.cams_list[i] = -1;
- storage.cams_online[i] = false;
- removed = true;
- }
- }
- if (removed) {
- int cams_tmplist[CAMS_MAX];
- bool cams_tmponline[CAMS_MAX];
- int tmpNum = 0;
- for (i = 0; i < CAMS_MAX; i++) {
- if (storage.cams_list[i] != -1) {
- cams_tmplist[tmpNum] = storage.cams_list[i];
- cams_tmponline[tmpNum] = storage.cams_online[i];
- tmpNum++;
- }
- }
- for (i = 0; i < CAMS_MAX; i++) {
- if (i < tmpNum) {
- storage.cams_list[i] = cams_tmplist[i];
- storage.cams_online[i] = cams_tmponline[i];
- } else {
- storage.cams_list[i] = -1;
- storage.cams_online[i] = false;
- }
- }
- }
- }
- // Clear Cams
- void CameraClearList()
- {
- for (int i = 0; i < CAMS_MAX; i++) {
- storage.cams_list[i] = -1;
- }
- }
- // Clears the comprehensive list of cameras attached to the vehicle
- void CameraClearFullList()
- {
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- cams_alllist[i] = -1;
- }
- }
- // Generates the comprehensive list of cameras attached to the vehicle, but not being displayed currently
- int CameraCreateFullList()
- {
- bool isCam;
- CameraClearFullList();
- // First generate a list of available camera types on the vehicle
- string camTypeList[VEHICLE_MAXPARTS];
- int numCTypes = 0;
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- camTypeList[i] = "";
- isCam = false;
- if (storage.parts_types[i] == "Camera" || storage.parts_types[i] == "CameraBW")
- isCam = true;
- if (isCam && storage.parts_subtypes[i] != "")
- {
- bool subtypeKnown = false;
- for (int t = 0; t < numCTypes; t++)
- {
- if (storage.parts_subtypes[i] == camTypeList[t]) {
- subtypeKnown = true;
- t = numCTypes;
- }
- }
- if (!subtypeKnown) {
- camTypeList[numCTypes] = storage.parts_subtypes[i];
- numCTypes++;
- }
- }
- }
- int result = 0;
- for (t = 0; t < numCTypes; t++)
- {
- for (i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i]) {
- if (result >= storage.parts_num) {
- i = storage.parts_num;
- t = numCTypes;
- } else {
- isCam = false;
- if (storage.parts_types[i] == "Camera" || storage.parts_types[i] == "CameraBW")
- isCam = true;
- if (CheckPartBaseConnect(i) && isCam && storage.parts_subtypes[i] == camTypeList[t] && CameraGetInList(i) == -1) {
- cams_alllist[result] = i;
- result++;
- }
- }
- }
- }
- }
- return result;
- }
- // Generates the comprehensive list of all cameras attached to the vehicle
- int GetTotalCameraCount()
- {
- int result = 0;
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- if (storage.parts_types[i] == "Camera" || storage.parts_types[i] == "CameraBW")
- result++
- }
- return result;
- }
- // Searches through all Science Targets and checks to see whether they are visible
- void CameraTakePhoto(Vehicle_Part ignorePart, int camNum, vector camPos, bool color);
- // Clears the comprehensive list of instruments attached to the vehicle
- void InstrumentClearFullList()
- {
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- inst_alllist[i] = -1;
- }
- }
- // Generates the comprehensive list of instruments attached to the vehicle
- int InstrumentCreateFullList()
- {
- InstrumentClearFullList();
- // First generate a list of available camera types on the vehicle
- string instTypeList[VEHICLE_MAXPARTS];
- int numCTypes = 0;
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- instTypeList[i] = "";
- if (storage.parts_types[i] == "Instrument" && storage.parts_subtypes[i] != "") {
- bool subtypeKnown = false;
- for (int t = 0; t < numCTypes; t++)
- {
- if (storage.parts_subtypes[i] == instTypeList[t]) {
- subtypeKnown = true;
- t = numCTypes;
- }
- }
- if (!subtypeKnown) {
- instTypeList[numCTypes] = storage.parts_subtypes[i];
- numCTypes++;
- }
- }
- }
- int result = 0;
- for (t = 0; t < numCTypes; t++)
- {
- for (i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i]) {
- if (result >= storage.parts_num) {
- i = storage.parts_num;
- t = numCTypes;
- } else {
- if (CheckPartBaseConnect(i) && storage.parts_types[i] == "Instrument" && storage.parts_subtypes[i] == instTypeList[t]) {
- inst_alllist[result] = i;
- result++;
- }
- }
- }
- }
- }
- return result;
- }
- // Clears the comprehensive list of instruments (inc. passive) attached to the vehicle
- void InstrumentClearFullListEx()
- {
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- inst_alllistex[i] = -1;
- }
- }
- // Generates the comprehensive list of instruments (inc. passive) attached to the vehicle
- int InstrumentCreateFullListEx()
- {
- InstrumentClearFullList();
- int i;
- int index;
- // First generate a list of available camera types on the vehicle
- string instTypeList[VEHICLE_MAXPARTS];
- int numCTypes = 0;
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- instTypeList[i] = "";
- if (storage.parts_types[i] == "Instrument" || storage.parts_types[i] == "InstrumentPassive")
- {
- if (storage.parts_subtypes[i] != "")
- {
- bool subtypeKnown = false;
- for (int t = 0; t < numCTypes; t++)
- {
- if (storage.parts_subtypes[i] == instTypeList[t])
- {
- subtypeKnown = true;
- t = numCTypes;
- }
- }
- if (!subtypeKnown)
- {
- instTypeList[numCTypes] = storage.parts_subtypes[i];
- numCTypes++;
- }
- }
- }
- }
- int result = 0;
- for (t = 0; t < numCTypes; t++)
- {
- for (i = 0; i < storage.parts_num; i++)
- {
- if (parts_ents[i])
- {
- if (result >= storage.parts_num)
- {
- i = storage.parts_num;
- t = numCTypes;
- }
- else
- {
- if (storage.parts_types[i] == "Instrument" || storage.parts_types[i] == "InstrumentPassive")
- {
- if (CheckPartBaseConnect(i) && storage.parts_subtypes[i] == instTypeList[t])
- {
- inst_alllistex[result] = i;
- result++;
- }
- }
- }
- }
- }
- }
- //Sort non passive instruments first
- for (i = 0; i < result; i++)
- {
- if (storage.parts_types[inst_alllistex[i]] == "InstrumentPassive")
- {
- for (index = i; index < result; index++)
- {
- if (storage.parts_types[inst_alllistex[index]] == "Instrument")
- {
- int id = inst_alllistex[i] ;
- inst_alllistex[i] = inst_alllistex[index]
- inst_alllistex[index] = id;
- break
- }
- }
- }
- }
- return result;
- }
- // Searches through all Science Targets and determine's if they should be completed
- void InstrumentAnalyze(Vehicle_Part ignorePart, string instSubType, int physMat, string specMat, vector pos);
- // Vehicle part data clearing
- void ClearData()
- {
- for (int i = 0; i < VEHICLE_MAXJOINTS; i++)
- {
- joints_ents[i] = NULL;
- }
- for (i = 0; i < VEHICLE_MAXBLOCKS; i++)
- {
- blocks_ents[i] = NULL;
- }
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- parts_ents[i] = NULL;
- gui3dWidgetHandler[i] = NULL;
- #ifdef DEVELOPER
- parts_lastGripTime[i] = 0;
- #endif
- MP_gui3dWidgetHandlerList[i] = NULL;
- }
- MP_gui3dWidgetHandlerListNum = 0;
- }
- // In multiplayer must be client vehicle without joints, but must have blockers of these joints
- void AppendBlocksForAllJoints()
- {
- int i;
- //find first free block index
- int lastFreeBlockIndex = -1;
- for (i = VEHICLE_MAXBLOCKS - 1; i >= 0; i--)
- {
- if(storage.blocks_part1[i] != -1 && storage.blocks_part2[i] != -1)
- {
- lastFreeBlockIndex = i + 1;
- break;
- }
- }
- if(lastFreeBlockIndex == -1)
- lastFreeBlockIndex = 0;
- if(lastFreeBlockIndex >= VEHICLE_MAXBLOCKS)
- return; //cannot add next blockers
- for (i = 0; i < VEHICLE_MAXJOINTS; i++)
- {
- int part1 = storage.joints_part1[i];
- int part2 = storage.joints_part2[i];
- if (storage.joints_type[i] == -1 || part1 == -1 || part2 == -1)
- continue;
- storage.blocks_part1[lastFreeBlockIndex] = part1;
- storage.blocks_part2[lastFreeBlockIndex] = part2;
- lastFreeBlockIndex++;
- }
- }
- // Returns a vehicle part by input custom title
- Vehicle_Part GetPartByCustomTitle(string customTitle)
- {
- if (vehicleController)
- return vehicleController.GetPartByCustomTitle(customTitle);
- return NULL;
- }
- // Returns an entity by input custom title
- _entity GetEntityByCustomTitle(string customTitle)
- {
- if (vehicleController)
- return vehicleController.GetEntityByCustomTitle(customTitle);
- return NULL;
- }
- // Deletes a widgets created for the vehicle
- void DeleteRootWidget(string rootwidget)
- {
- widget w = FindWidget(NULL, rootwidget);
- if (w) {
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- if (widgetList[i] == w) {
- DestroyWidget(widgetList[i]);
- widgetList[i] = NULL;
- }
- }
- }
- }
- // Deletes widgets created for the vehicle (HUD etc)
- void DeleteWidgets()
- {
- if (vehicleController)
- vehicleController.ProcessOnDeleteWidgets();
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- if (widgetList[i])
- {
- DestroyWidget(widgetList[i]);
- widgetList[i] = NULL;
- }
- if (widgetHandler)
- widgetHandler.ClearHUDButtons();
- }
- radm_closed = true;
- RadialMenuResetActions();
- }
- // Checks if the specified root widget exists in the widget list
- widget FindVehWidget(string rootwidget)
- {
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- widget w = widgetList[i];
- if (w && w.GetName() == rootwidget)
- return w;
- }
- return NULL;
- }
- // Creates a new layout for the vehicle and puts its main root into the widget list
- bool CreateVehWidgetsFromFile(string layoutFile, string rootwidget)
- {
- if (FindVehWidget(rootwidget))
- return false;
- else
- {
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- if (!widgetList[i])
- {
- widget w = CreateWidgets(String(layoutFile), NULL);
- if (!w)
- {
- Print(String("CREATEVEHWIDGETSFROMFILE: Could not create widgets from layout '" + layoutFile + "'!!!"));
- return false;
- }
- widgetList[i] = w;
- if (widgetHandler)
- SetWidgetEventHandler(w, widgetHandler);
- return true;
- }
- }
- }
- return false;
- }
- // Creates a new layout (without using the suffix) for the vehicle and puts its main root into the widget list
- bool CreateVehWidgetsNoSuffix(string layout, string rootwidget)
- {
- if (FindVehWidget(rootwidget))
- return false;
- else
- {
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- if (!widgetList[i])
- {
- widget w = CreateWidgets(String(layout + ".layout"), NULL);
- if (!w)
- {
- Print(String("CREATEVEHWIDGETSNOSUFFIX: Could not create widgets from layout '" + layout + ".layout'!!!"));
- return false;
- }
- widgetList[i] = w;
- if (widgetHandler)
- SetWidgetEventHandler(w, widgetHandler);
- return true;
- }
- }
- }
- return false;
- }
- // Creates a new layout for the vehicle and puts its main root into the widget list
- bool CreateVehWidgets(string layout, string rootwidget)
- {
- if (FindVehWidget(rootwidget))
- return false;
- else
- {
- for (int i = 0; i < WIDGETS_VEHICLEMAX; i++)
- {
- if (!widgetList[i])
- {
- widget w = CreateWidgets(String(layout + ".layout"), NULL);
- if (!w)
- {
- Print(String("CREATEVEHWIDGETS: Could not create widgets from layout '" + layout + ".layout'!!!"));
- return false;
- }
- widgetList[i] = w;
- if (widgetHandler)
- SetWidgetEventHandler(w, widgetHandler);
- return true;
- }
- }
- }
- return false;
- }
- // Returns the quantized world mins and maxs for the whole vehicle
- void Vehicle_GetWorldBounds(vector fullBounds[])
- {
- vector mins, maxs;
- GetCBoundBox(this, mins, maxs);
- for (int n = 0; n < storage.parts_num; n++) {
- Vehicle_Part vehPart = parts_ents[n];
- if (vehPart) {
- vector mins2, maxs2;
- GetCBoundBox(vehPart, mins2, maxs2);
- for (int a = 0; a < 3; a++) {
- if (mins2[a] < mins[a])
- mins[a] = mins2[a];
- if (maxs2[a] > maxs[a])
- maxs[a] = maxs2[a];
- }
- }
- }
- fullBounds[0] = mins;
- fullBounds[1] = maxs;
- }
- // Returns the mins and maxs for the whole vehicle
- void Vehicle_GetFullBounds(vector fullBounds[])
- {
- vector mins, maxs;
- GetBoundBox(this, mins, maxs);
- for (int n = 0; n < storage.parts_num; n++) {
- Vehicle_Part vehPart = parts_ents[n];
- if (vehPart) {
- vector rotBounds[2], mins2, maxs2;
- GetBoundBox(vehPart, mins2, maxs2);
- GetRotatedBounds(storage.parts_pos[n], storage.parts_ang[n], mins2, maxs2, rotBounds);
- mins2 = rotBounds[0];
- maxs2 = rotBounds[1];
- for (int a = 0; a < 3; a++) {
- if (mins2[a] < mins[a])
- mins[a] = mins2[a];
- if (maxs2[a] > maxs[a])
- maxs[a] = maxs2[a];
- }
- }
- }
- fullBounds[0] = mins;
- fullBounds[1] = maxs;
- }
- // Returns the mins and maxs for the whole vehicle, limited to parts with physics
- void Vehicle_GetFullPhysicsBounds(vector fullBounds[])
- {
- vector mins, maxs;
- GetBoundBox(this, mins, maxs);
- for (int n = 0; n < storage.parts_num; n++) {
- Vehicle_Part vehPart = parts_ents[n];
- if (vehPart && dBodyIsDynamic(vehPart)) {
- vector rotBounds[2], mins2, maxs2;
- GetBoundBox(vehPart, mins2, maxs2);
- GetRotatedBounds(storage.parts_pos[n], storage.parts_ang[n], mins2, maxs2, rotBounds);
- mins2 = rotBounds[0];
- maxs2 = rotBounds[1];
- for (int a = 0; a < 3; a++) {
- if (mins2[a] < mins[a])
- mins[a] = mins2[a];
- if (maxs2[a] > maxs[a])
- maxs[a] = maxs2[a];
- }
- }
- }
- fullBounds[0] = mins;
- fullBounds[1] = maxs;
- }
- // Returns collective center of mass, can be set to return only for attached parts to the vehicle hull, and can be set to return in local coords
- vector Vehicle_GetCollectiveCOM(bool onlyAttached, bool localCoords)
- {
- vector mat[4];
- GetMatrix4(this, mat);
- int numCounted = 0;
- float totalMass = 0;
- // First get the highest mass
- for (int n = 0; n < storage.parts_num; n++) {
- if (onlyAttached && !CheckPartConnect(n, 0))
- continue;
- Vehicle_Part vehPart = parts_ents[n];
- if (vehPart) {
- if (!dBodyIsDynamic(vehPart))
- continue;
- float mass = GetObjectMass(vehPart);
- totalMass += mass;
- }
- }
- if (totalMass == 0)
- totalMass = 1;
- vector result = ZeroVec;
- for (n = 0; n < storage.parts_num; n++) {
- if (onlyAttached && !CheckPartConnect(n, 0))
- continue;
- vehPart = parts_ents[n];
- if (vehPart) {
- if (!dBodyIsDynamic(vehPart))
- continue;
- GetMatrix4(vehPart, mat);
- vector comPos = VectorMatrixMultiply4(mat, dBodyGetCenterOfMass(vehPart));
- mass = GetObjectMass(vehPart);
- float massScale = mass / totalMass;
- result = comPos * massScale + result;
- numCounted++;
- }
- }
- if (localCoords)
- result = CoordToLocal(result);
- return result;
- }
- // Teleports the entire vehicle to the desired location
- void TeleportVehicle(vector pos, vector ang, bool ignoreDetachedParts)
- {
- if (GodModeTime < TELEPORT_GODMODETIME)
- GodModeTime = TELEPORT_GODMODETIME;
- SetOrigin(this, pos);
- SetAngles(this, ang);
- for (int i = 0; i < storage.parts_num; i++)
- {
- bool isStatic = false;
- for (int i2 = 0; i2 < storage.statcons_num; i2++)
- {
- int p2 = storage.statcons_part2[i2];
- if (p2 == i) {
- isStatic = true;
- break;
- }
- }
- bool ignorePart = false;
- if (i > 0 && ignoreDetachedParts && !CheckPartBaseConnect(i))
- ignorePart = true;
- Vehicle_Part vPart = parts_ents[i];
- if (vPart && storage.parts_models[i] != "INTERNAL" && !isStatic && !ignorePart) {
- vector mat[4];
- GetEntOffsetMatrix(this, storage.parts_pos[i], storage.parts_ang[i], mat);
- SetMatrix(vPart, mat);
- }
- }
- if (vehicleController)
- vehicleController.ProcessOnTeleport();
- }
- // Teleports the entire vehicle to the desired location
- void TeleportVehicleMat4(vector mat[], bool ignoreDetachedParts)
- {
- if (GodModeTime < TELEPORT_GODMODETIME)
- GodModeTime = TELEPORT_GODMODETIME;
- SetMatrix(this, mat);
- for (int i = 0; i < storage.parts_num; i++)
- {
- bool isStatic = false;
- for (int i2 = 0; i2 < storage.statcons_num; i2++)
- {
- int p2 = storage.statcons_part2[i2];
- if (p2 == i) {
- isStatic = true;
- break;
- }
- }
- bool ignorePart = false;
- if (i > 0 && ignoreDetachedParts && !CheckPartBaseConnect(i))
- ignorePart = true;
- Vehicle_Part vPart = parts_ents[i];
- if (vPart && storage.parts_models[i] != "INTERNAL" && !isStatic && !ignorePart) {
- GetEntOffsetMatrix(this, storage.parts_pos[i], storage.parts_ang[i], mat);
- SetMatrix(vPart, mat);
- }
- }
- if (vehicleController)
- vehicleController.ProcessOnTeleport();
- }
- // Sets linear velocity on all parts
- void SetVehicleLinVelocity(vector linvel, bool ignoreDetachedParts)
- {
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (i > 0 && ignoreDetachedParts && !CheckPartBaseConnect(i))
- continue;
- Vehicle_Part vPart = parts_ents[i];
- if (vPart && dBodyIsDynamic(vPart))
- SetVelocity(vPart, linvel);
- }
- if (vehicleController)
- vehicleController.ProcessOnSetVelocity();
- }
- // Sets angular velocity on all parts
- void SetVehicleAngVelocity(vector angvel, bool ignoreDetachedParts)
- {
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (i > 0 && ignoreDetachedParts && !CheckPartBaseConnect(i))
- continue;
- Vehicle_Part vPart = parts_ents[i];
- if (vPart && dBodyIsDynamic(vPart))
- dBodySetAngularVelocity(vPart, angvel);
- }
- if (vehicleController)
- vehicleController.ProcessOnSetVelocity();
- }
- // Returns false if the part is internal, or a static connection
- bool GetCanCreatePhysicsForPart(int pNum)
- {
- if (storage.parts_models[pNum] == "INTERNAL")
- return false;
- for (int p = 0; p < VEHICLE_MAXPARTS; p++)
- {
- int pNum2 = storage.statcons_part2[p];
- if (pNum == pNum2)
- return false;
- }
- return true;
- }
- // Spawns a vehicle part and sets its parameters
- Vehicle_Part Vehicle_SpawnPart(int partNum)
- {
- vector mat[4];
- GetEntOffsetMatrix(this, storage.parts_pos[partNum], storage.parts_ang[partNum], mat);
- vobject model;
- if (storage.parts_models[partNum] != "INTERNAL")
- model = GetObject(storage.parts_models[partNum]);
- Vehicle_Part ent = this;
- if (partNum != 0) {
- ent = new Vehicle_Part(false);
- //ent.SetSceneID(TKOMHighestEntID + 1);
- }
- ent.PartNum = partNum;
- if (storage.parts_models[partNum] != "INTERNAL") {
- SetFlags(ent, TFL_VISIBLE|TFL_ACTIVE|TFL_SOLID);
- ent.SetObject(model, "");
- SetMatrix(ent, mat);
- }
- if (storage.parts_conPtcSnd[partNum] != "")
- ent.FXIndex = CreateFXType(storage.parts_conPtcSnd[partNum]);
- ent.GenVec = storage.parts_genVec[partNum];
- ent.GenVec2 = storage.parts_genVec2[partNum];
- ent.GenVec3 = storage.parts_genVec3[partNum];
- ent.GenVec4 = storage.parts_genVec4[partNum];
- ent.GenVec5 = storage.parts_genVec5[partNum];
- ent.GenVec6 = storage.parts_genVec6[partNum];
- ent.Toughness = storage.parts_tough[partNum];
- ent.ParentVehicle = this;
- if (GetCanCreatePhysicsForPart(partNum))
- {
- dBodyCreateDynamic(ent, ZeroVec, 0xffffffff);
- UpdateDampingOnEnt(ent, NULL, 1);
- float sleepThreshold = GetGlobalizedSleepThreshold();
- dBodySetSleepingTreshold(ent, sleepThreshold, sleepThreshold);
- dBodySetMass(ent, storage.parts_mass[partNum]);
- ent.UpdatePhysicalParams();
- CreateNamedGeomBox(ent, GEOMNAME_AABB, COLLIDERLAYER_DYNAMIC_AABB);
- dBodyInteractionLayerEx(ent, storage.interactionLayer);
- }
- if (storage.parts_models[partNum] != "INTERNAL" && model)
- ReleaseObject(model, false);
- /*if( IsClient() && storage.isCharacter )
- ent.EnableGravity( false );//disable gravity for all dynamic objects on clients!!! this keeps movement prediction, but removes jumping
- */
- return ent;
- }
- // Constructs the vehicle from the part and joint data
- void ConstructVehicle(vector pos, vector ang)
- {
- storage.joints_num = 0;
- storage.blocks_num = 0;
- storage.parts_num = 0;
- storage.statcons_num = 0;
- local int part1, part2;
- vector rndVel = storage.ReentryVelocity;
- storage.ReentryVelocity = ZeroVec;
- if (storage.ReentryZone != ZeroVec) {
- storage.LandingZone = storage.ReentryZone;
- storage.LandingZone[2] = GetTerrainHeight(storage.LandingZone);
- storage.ReentryZone[2] = storage.ReentryOffsetPos[2];
- pos[0] = storage.ReentryZone[0] + storage.ReentryOffsetPos[0];
- pos[1] = storage.ReentryZone[1] + storage.ReentryOffsetPos[1];
- storage.ReentryZone[0] = pos[0];
- storage.ReentryZone[1] = pos[1];
- ang = storage.ReentryOffsetAng;
- rndVel[0] = rndVel[0] * frand(0.95, 1.05);
- rndVel[1] = rndVel[1] * frand(0.95, 1.05);
- rndVel[2] = rndVel[2] * frand(0.95, 1.05);
- }
- SetOrigin(this, pos);
- SetAngles(this, ZeroVec);
- inst_inrange = false;
- inst_hilite = "";
- inst_sample = "";
- inst_analyze = "";
- PriPartSwitchTime = 0;
- SecPartSwitchTime = 0;
- // First create the static vehicle parts
- for (local int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- if (storage.parts_models[i] == "")
- continue;
- if (GetCanCreatePhysicsForPart(i))
- continue;
- parts_ents[i] = Vehicle_SpawnPart(i);
- if (storage.parts_num < i + 1)
- storage.parts_num = i + 1;
- }
- // Now create the dynamic vehicle parts
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- if (storage.parts_models[i] == "")
- continue;
- if (!GetCanCreatePhysicsForPart(i))
- continue;
- parts_ents[i] = Vehicle_SpawnPart(i);
- if (storage.parts_num < i + 1)
- storage.parts_num = i + 1;
- }
- // Create the vehicle joints
- for (i = 0; i < VEHICLE_MAXJOINTS; i++)
- {
- int jointType = GetJointType(i); // Get joint type taking into account LODed joints and physics tick
- if (jointType != -1) {
- if (storage.joints_num < i + 1)
- storage.joints_num = i + 1;
- vector jmat1[4], jmat2[4];
- part1 = storage.joints_part1[i];
- part2 = storage.joints_part2[i];
- if (part1 == -1 || part2 == -1)
- continue;
- Vehicle_Part p1Ent = parts_ents[part1];
- Vehicle_Part p2Ent = parts_ents[part2];
- if (p1Ent && p2Ent)
- {
- // Create the joint's vehicle FX ent, if it doesn't exist
- if (storage.joints_breakPtcSnd[i] != "")
- storage.joints_FXIndex[i] = CreateFXType(storage.joints_breakPtcSnd[i]);
- // Create joint connection matrix 1 from the joint angles, part2 position, subtracted part 1 and 2 angles and part 1 center of mass
- /*RollPitchYawMatrix(storage.joints_angles[i] + storage.parts_ang[part2] - storage.parts_ang[part1], jmat1);
- jmat1[3] = p1Ent.CoordToLocal(CoordToParent(storage.parts_pos[part2])) - dBodyGetCenterOfMass(p1Ent);
- // Create joint connection matrix 2 from the joint angles, and part 2 center of mass
- RollPitchYawMatrix(storage.joints_angles[i], jmat2);
- jmat2[3] = ZeroVec - dBodyGetCenterOfMass(p2Ent);*/
- p2Ent.ParentPartNum = part1; // Store in each part its parent
- p1Ent.AddChildPart(part2); // Store each child
- vector p1Mat[4], p2Mat[4];
- /*if( IsClient() && storage.isCharacter ) //do not create joints in multiplayer on clients
- joints_ents[i] = NULL;
- else
- {*/
- GetMatrix4(p1Ent, p1Mat);
- GetMatrix4(p2Ent, p2Mat);
- // Get joint rotation matrices
- vector jaMat1[3], jaMat2[3];
- RollPitchYawMatrix(storage.joints_angles[i], jaMat1);
- MatrixMultiply3(p2Mat, jaMat1, jaMat2);
- MatrixInvMultiply3(p1Mat, jaMat2, jmat1);
- MatrixInvMultiply3(p2Mat, jaMat2, jmat2);
- if (jointType == JOINT_360MOTOR)
- {
- vector jaMat3601[3], jaMat3602[3];
- RollPitchYawMatrix("180 -180 0", jaMat3601);
- jaMat3602[0] = jmat2[0];
- jaMat3602[1] = jmat2[1];
- jaMat3602[2] = jmat2[2];
- MatrixInvMultiply3(jaMat3602, jaMat3601, jmat2);
- }
- // Get joint positions
- jmat1[3] = p1Ent.CoordToLocal(CoordToParent(storage.parts_pos[part2])) - dBodyGetCenterOfMass(p1Ent);
- jmat2[3] = ZeroVec - dBodyGetCenterOfMass(p2Ent);
- // Fixed joint - keeps the parts firmly locked together.
- if (jointType == JOINT_FIXED)
- {
- //joints_ents[i] = dJointCreateFixed(p1Ent, p2Ent, jmat1[3], jmat2[3], true, -1);
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSetAngularLimits(joints_ents[i], ZeroVec, ZeroVec);
- continue;
- }
- // Hinge joint - rotates about a single axis. Ideal for suspension, for example.
- if (jointType == JOINT_HINGE)
- {
- //joints_ents[i] = dJointCreateHinge2(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Hinge Limits:
- storage.joints_limits_lo[i][0] = Lower limit in degrees - the joint won't turn below this amount (eg. -90)
- storage.joints_limits_hi[i][0] = Upper limit in degrees - the joint won't turn above this amount (eg. 90)
- Note: If the Lower limit is higher than the Upper Limit, the axis is free to turn 360 Degrees
- storage.joints_limits_lo[i][1] = Softness - % of limits where movement is free, above this the limit is gradually enforced (eg. 0.5)
- storage.joints_limits_lo[i][2] = Bias Factor - the strength with which the constraint resists limit violations (eg. 0.3)
- storage.joints_limits_hi[i][1] = Relaxation Factor - The lower the values, the less the constraint will fight velocities which
- violate the angular limits (eg. 1)
- **/
- /*if (storage.joints_limits_lo[i][0] != 0 && storage.joints_limits_hi[i][0] != 0)
- dJointHingeSetLimits(joints_ents[i], storage.joints_limits_lo[i][0] * DEG2RAD, storage.joints_limits_hi[i][0] * DEG2RAD, storage.joints_limits_lo[i][1], storage.joints_limits_lo[i][2], storage.joints_limits_hi[i][1]);*/
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- vector hingeang_min = Vector(0, 0, storage.joints_limits_lo[i][0] * -DEG2RAD);
- vector hingeang_max = Vector(0, 0, storage.joints_limits_hi[i][0] * -DEG2RAD);
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSetAngularLimits(joints_ents[i], hingeang_min, hingeang_max);
- continue;
- }
- // Motor joint (slider joint with motor forces) - rotates about one axis, useful for wheels.
- if (jointType == JOINT_MOTOR) {
- joints_ents[i] = dJointCreateSlider(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Motor Limits:
- storage.joints_limits_lo[i][0] = Lower limit in degrees - the joint won't turn below this amount (eg. -90)
- storage.joints_limits_hi[i][0] = Upper limit in degrees - the joint won't turn above this amount (eg. 90)
- Note: If the Lower limit is higher than the Upper Limit, the axis is free to turn 360 Degrees
- storage.joints_limits_hi[i][1] = Motor spin-up/down speed (used in controllers)
- storage.joints_limits_lo[i][1] = Maximum motor velocity - the maximum speed the motor can turn at
- storage.joints_limits_lo[i][2] = Maximum motor torque - the maximum force used to turn the motor with
- **/
- dJointSliderSetLinearLimits(joints_ents[i], 0, 0);
- dJointSliderSetAngularLimits(joints_ents[i], storage.joints_limits_lo[i][0] * DEG2RAD, storage.joints_limits_hi[i][0] * DEG2RAD);
- continue;
- }
- // Twist Motor joint (hinge2 joint with twist motor setting) - rotates about one axis, can be instructed to twist to a certain angle, useful for steering.
- if (jointType == JOINT_TMOTOR) {
- //joints_ents[i] = dJointCreateHinge2(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Hinge Limits:
- storage.joints_limits_lo[i][0] = Half limit in degrees - the joint won't turn beyond this amount in any direction (eg. 90)
- Note: If the Lower limit is higher than the Upper Limit, the axis is free to turn 360 Degrees
- storage.joints_limits_lo[i][1] = Maximum motor turn - the time it takes the motor to turn to the desired angle
- storage.joints_limits_lo[i][2] = Maximum motor torque - the maximum force used to turn the motor with
- storage.joints_limits_hi[i][0] = Softness - % of limits where movement is free, above this the limit is gradually enforced (eg. 0.5)
- storage.joints_limits_hi[i][1] = Bias Factor - the strength with which the constraint resists limit violations (eg. 0.3)
- storage.joints_limits_hi[i][2] = Relaxation Factor - The lower the values, the less the constraint will fight velocities which
- violate the angular limits (eg. 1)
- **/
- /*if (storage.joints_limits_lo[i][0] != 0 && storage.joints_limits_hi[i][0] != 0)
- dJointHingeSetLimits(joints_ents[i], storage.joints_limits_lo[i][0] * -DEG2RAD, storage.joints_limits_lo[i][0] * DEG2RAD, storage.joints_limits_hi[i][0], storage.joints_limits_hi[i][1], storage.joints_limits_hi[i][2]);*/
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- TKOMJoint180_SetAngle(joints_ents[i], 0);
- continue;
- }
- // 360 Motor joint (hinge2 joint with rotational motor setting) - rotates about one axis, can be instructed to twist to a certain angle, useful for steering.
- if (jointType == JOINT_360MOTOR) {
- joints_ents[i] = dJointCreateHinge2(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Hinge Limits:
- storage.joints_limits_lo[i][0] = Forward limit in degrees - can be used to prevent the joint from turning beyond this amount (eg. 270)
- storage.joints_limits_lo[i][1] = Maximum motor turn - the maximum speed the motor can turn at
- storage.joints_limits_lo[i][2] = Maximum motor torque - the maximum force used to turn the motor with
- storage.joints_limits_hi[i][0] = Softness - % of limits where movement is free, above this the limit is gradually enforced (eg. 0.5)
- storage.joints_limits_hi[i][1] = Bias Factor - the strength with which the constraint resists limit violations (eg. 0.3)
- storage.joints_limits_hi[i][2] = Relaxation Factor - The lower the values, the less the constraint will fight velocities which
- violate the angular limits (eg. 1)
- **/
- if (storage.joints_limits_lo[i][0] != 0 && storage.joints_limits_hi[i][0] != 0)
- dJointHingeSetLimits(joints_ents[i], -180 * DEG2RAD, 180 * DEG2RAD, 0.5, 0.7, 0.7);
- //dJointHingeSetLimits(joints_ents[i], -180 * DEG2RAD, 180 * DEG2RAD, storage.joints_limits_hi[i][0], storage.joints_limits_hi[i][1], storage.joints_limits_hi[i][2]);
- /*joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);*/
- TKOMJoint360_SetAngle(joints_ents[i], 0);
- continue;
- }
- // 6 Degrees Of Freedom joint - allows movement in all axes
- if (jointType == JOINT_6DOF) {
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** 6DOF Limits:
- storage.joints_limits_lo[i] = Linear limits in units (eg. "0 20 0")
- storage.joints_limits_hi[i] = Angular limits in degrees (eg. "0 100 0")
- **/
- vector lim_lin = storage.joints_limits_lo[i];
- vector lim_ang = storage.joints_limits_hi[i] * DEG2RAD;
- dJoint6DOFSetLinearLimits(joints_ents[i], -lim_lin, lim_lin);
- dJoint6DOFSetAngularLimits(joints_ents[i], -lim_ang, lim_ang);
- continue;
- }
- // Piston joint (slider joint with linear motor forces) - extends/retracts along an axis, useful for pistons.
- if (jointType == JOINT_PISTON) {
- //joints_ents[i] = dJointCreateSlider(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Motor Limits:
- storage.joints_limits_lo[i][0] = Lower limit - the joint won't move below this amount in meters (eg. -1)
- storage.joints_limits_hi[i][0] = Upper limit - the joint won't move above this amount in meters (eg. 1)
- Note: If the Lower limit is higher than the Upper Limit, the axis is free to move
- storage.joints_limits_lo[i][1] = Maximum motor velocity - the maximum speed the piston can move at
- storage.joints_limits_lo[i][2] = Maximum motor force - the maximum force used to extend/retract the piston with
- **/
- /*dJointSliderSetLinearLimits(joints_ents[i], storage.joints_limits_lo[i][0], storage.joints_limits_hi[i][0]);
- dJointSliderSetAngularLimits(joints_ents[i], 0, 0);*/
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSetAngularLimits(joints_ents[i], ZeroVec, ZeroVec);
- continue;
- }
- // Spring joint - allows movement in all axes
- if (jointType == JOINT_SPRING) {
- joints_ents[i] = dJointCreate6DOFSpring(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Spring Limits:
- storage.joints_limits_lo[i] = Linear limits in units (eg. "0 20 0")
- storage.joints_limits_hi[i][0] = Stiffness of the spring (eg. 2000)
- storage.joints_limits_hi[i][1] = Damping of the spring, lower values means more damping (eg. 0.5)
- **/
- vector sprlim_lin = storage.joints_limits_lo[i];
- dJoint6DOFSetLinearLimits(joints_ents[i], -sprlim_lin, sprlim_lin);
- dJoint6DOFSetAngularLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSpringSetSpring(joints_ents[i], 0, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 1, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 2, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- continue;
- }
- // Angular Spring joint - allows rotation in all axes
- if (jointType == JOINT_ANGSPRING) {
- joints_ents[i] = dJointCreate6DOFSpring(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Spring Limits:
- storage.joints_limits_lo[i] = Angular limits in degrees (eg. "0 20 0")
- storage.joints_limits_hi[i][0] = Stiffness of the spring (eg. 2000)
- storage.joints_limits_hi[i][1] = Damping of the spring, lower values means more damping (eg. 0.5)
- **/
- vector sprlim_ang = storage.joints_limits_lo[i];
- sprlim_ang[0] = sprlim_ang[0] * DEG2RAD;
- sprlim_ang[1] = sprlim_ang[1] * DEG2RAD;
- sprlim_ang[2] = sprlim_ang[2] * DEG2RAD;
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSetAngularLimits(joints_ents[i], -sprlim_ang, sprlim_ang);
- dJoint6DOFSpringSetSpring(joints_ents[i], 3, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 4, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 5, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- continue;
- }
- // Sphere Spring joint - allows movement in all axes, including rotation
- if (jointType == JOINT_SPHERESPRING) {
- joints_ents[i] = dJointCreate6DOFSpring(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** Spring Limits:
- storage.joints_limits_lo[i][0] = Linear limits in units (eg. 20)
- storage.joints_limits_lo[i][1] = Angular limits in degrees (eg. 10)
- storage.joints_limits_hi[i][0] = Stiffness of the spring (eg. 2000)
- storage.joints_limits_hi[i][1] = Damping of the spring, lower values means more damping (eg. 0.5)
- **/
- vector sphsprlim_lin = Vector(storage.joints_limits_lo[i][0], storage.joints_limits_lo[i][0], storage.joints_limits_lo[i][0]);
- vector sphsprlim_ang = Vector(storage.joints_limits_lo[i][1] * DEG2RAD, storage.joints_limits_lo[i][1] * DEG2RAD, storage.joints_limits_lo[i][1] * DEG2RAD);
- dJoint6DOFSetLinearLimits(joints_ents[i], -sphsprlim_lin, sphsprlim_lin);
- dJoint6DOFSetAngularLimits(joints_ents[i], -sphsprlim_ang, sphsprlim_ang);
- dJoint6DOFSpringSetSpring(joints_ents[i], 0, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 1, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 2, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringLinDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 3, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 4, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- dJoint6DOFSpringSetSpring(joints_ents[i], 5, storage.joints_limits_hi[i][0] * GetSpringScale(), storage.joints_limits_hi[i][1] * GetSpringAngDampScale());
- continue;
- }
- // 6 Degrees Of Freedom Hinge joint - allows rotation in all axes
- if (jointType == JOINT_6DOFHINGE) {
- joints_ents[i] = dJointCreate6DOF(p1Ent, p2Ent, jmat1, jmat2, true, -1);
- /** 6DOF Hinge Limits:
- storage.joints_limits_lo[i] = Minimum angular limits in units (eg. "0 20 0")
- storage.joints_limits_hi[i] = Maximum angular limits in degrees (eg. "0 100 0")
- **/
- vector lim_ang_min = storage.joints_limits_lo[i] * DEG2RAD;
- vector lim_ang_max = storage.joints_limits_hi[i] * DEG2RAD;
- dJoint6DOFSetLinearLimits(joints_ents[i], ZeroVec, ZeroVec);
- dJoint6DOFSetAngularLimits(joints_ents[i], lim_ang_min, lim_ang_max);
- continue;
- }
- //}
- } else {
- string printStr = "VEHICLEHANDLER: Constructing vehicle joint but part";
- if (p1Ent || p2Ent) {
- if (!p1Ent)
- printStr += " " + itoa(part1) + " does not exist!";
- if (!p2Ent)
- printStr += " " + itoa(part2) + " does not exist!";
- } else
- printStr += "s " + itoa(part1) + " and " + itoa(part2) + " do not exist!";
- Print(String(printStr));
- }
- }
- }
- // Create the collision blockers
- for (i = 0; i < VEHICLE_MAXBLOCKS; i++)
- {
- if (storage.blocks_part1[i] != -1 && storage.blocks_part2[i] != -1) {
- if (storage.blocks_num < i + 1)
- storage.blocks_num = i + 1;
- part1 = storage.blocks_part1[i];
- part2 = storage.blocks_part2[i];
- p1Ent = parts_ents[part1];
- p2Ent = parts_ents[part2];
- if (p1Ent && p2Ent && dBodyIsSet(p1Ent) && dBodyIsSet(p2Ent))
- blocks_ents[i] = dBodyCollisionBlock(p1Ent, p2Ent);
- else {
- if (!p1Ent || !p2Ent)
- {
- printStr = "VEHICLEHANDLER: Constructing vehicle collision blocker " + itoa(i) + " but part";
- if (p1Ent || p2Ent) {
- if (!p1Ent)
- printStr += " " + itoa(part1) + " does not exist!";
- if (!p2Ent)
- printStr += " " + itoa(part2) + " does not exist!";
- } else
- printStr += "s " + itoa(part1) + " and " + itoa(part2) + " do not exist!";
- Print(String(printStr));
- if (p1Ent || p2Ent) {
- if (!p1Ent)
- Print(String("Model: '" + storage.parts_models[part1] + "'"));
- if (!p2Ent)
- Print(String("Model: '" + storage.parts_models[part2] + "'"));
- } else {
- Print(String("Model 1: '" + storage.parts_models[part1] + "'"));
- Print(String("Model 2: '" + storage.parts_models[part2] + "'"));
- }
- }
- else
- {
- printStr = "VEHICLEHANDLER: Constructing vehicle collision blocker " + itoa(i) + " but part";
- if (dBodyIsSet(p1Ent) || dBodyIsSet(p2Ent)) {
- if (!dBodyIsSet(p1Ent))
- printStr += " " + itoa(part1) + " does not have physics set (static connection?)!";
- if (!dBodyIsSet(p2Ent))
- printStr += " " + itoa(part2) + " does not have physics set (static connection?)!";
- } else
- printStr += "s " + itoa(part1) + " and " + itoa(part2) + " do not have physics set (static connection?)!";
- Print(String(printStr));
- if (dBodyIsSet(p1Ent) || dBodyIsSet(p2Ent)) {
- if (!dBodyIsSet(p1Ent))
- Print(String("Model: '" + storage.parts_models[part1] + "'"));
- if (!dBodyIsSet(p2Ent))
- Print(String("Model: '" + storage.parts_models[part2] + "'"));
- } else {
- Print(String("Model 1: '" + storage.parts_models[part1] + "'"));
- Print(String("Model 2: '" + storage.parts_models[part2] + "'"));
- }
- }
- }
- }
- }
- if (storage.ReentryZone != ZeroVec) {
- TeleportVehicle(storage.ReentryZone, ang, false);
- storage.ReentryZone = ZeroVec;
- } else
- TeleportVehicle(pos, ang, false);
- // Move parts to world coordinates, if defined, and set previous parents
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- vector checkVec = storage.parts_wmat3[i];
- if (parts_ents[i])
- {
- Vehicle_Part pEnt = parts_ents[i];
- // if( IsClient() )
- // dBodyInteractionLayer(pEnt, COLLIDERLAYER_NONE);
- if (checkVec != ZeroVec)
- {
- vector mat[4];
- mat[0] = storage.parts_wmat0[i];
- mat[1] = storage.parts_wmat1[i];
- mat[2] = storage.parts_wmat2[i];
- mat[3] = storage.parts_wmat3[i];
- SetMatrix(parts_ents[i], mat);
- }
- if (rndVel != ZeroVec)
- SetVelocity(parts_ents[i], rndVel);
- else
- {
- SetVelocity(parts_ents[i], storage.parts_velLin[i]);
- dBodySetAngularVelocity(parts_ents[i], storage.parts_velAng[i]);
- }
- if (storage.parts_storedParent[i] >= -1) // If there is a stored parent data, use it
- pEnt.ParentPartNum = storage.parts_storedParent[i];
- }
- }
- // Create static connections
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- int p1 = storage.statcons_part1[i];
- int p2 = storage.statcons_part2[i];
- if (p1 > -1 && p2 > -1 && parts_ents[p1] && parts_ents[p2]) {
- if (storage.statcons_num < i + 1)
- storage.statcons_num = i + 1;
- Vehicle_Part sp1Ent = parts_ents[p1];
- Vehicle_Part sp2Ent = parts_ents[p2];
- vector sp1Mat[4], sp2Mat[4], smodMat[4];
- RollPitchYawMatrix(storage.parts_ang[p1], sp1Mat);
- RollPitchYawMatrix(storage.parts_ang[p2], smodMat);
- sp1Mat[3] = storage.parts_pos[p1];
- smodMat[3] = storage.parts_pos[p2];
- MatrixInvMultiply4(sp1Mat, smodMat, sp2Mat);
- dBodyInteractionLayer(sp2Ent, COLLIDERLAYER_NONE);
- AddChild(sp1Ent, sp2Ent, -1);
- SetMatrix(sp2Ent, sp2Mat);
- sp2Ent.ParentPartNum = p1;
- sp1Ent.AddChildPart(p2); // Store each child
- }
- }
- // Activate the vehicle handler's simulation
- SetEventMask(this, EV_SIMULATE|EV_FRAME|EV_POSTFRAME);
- // Create the vehicle's widget handler
- if (!widgetHandler)
- widgetHandler = new Vehicle_WidgetHandler(this);
- // Create the vehicle's controller
- if (!vehicleController)
- vehicleController = new Vehicle_Controller();
- if (vehicleController)
- {
- vehicleController.ownerVehicle = this;
- for (i = 0; i < CONTROL_VEHICLEMAX; i++)
- {
- vehicleController.AddScript(storage.script_Path[i]);
- }
- vehicleController.InitScripts();
- }
- vector compatSpawnPos = storage.CompatibilitySpawnMat[3];
- if (compatSpawnPos != ZeroVec)
- TeleportVehicleMat4(storage.CompatibilitySpawnMat, false);
- MatrixIdentity(storage.CompatibilitySpawnMat);
- }
- void UnitScriptsPostInit()
- {
- if (vehicleController)
- vehicleController.PostInitScripts();
- }
- void DestroyController()
- {
- if(vehicleController)
- {
- vehicleController.ExitScripts();
- delete vehicleController;
- vehicleController = NULL;
- }
- }
- void RemoveJointsBlockers()
- {
- World curWorld = GetCurrentWorld();
- for (int i = 0; i < VEHICLE_MAXJOINTS; i++) {
- dJoint killJoint = joints_ents[i];
- if (killJoint)
- {
- dJointDestroy(killJoint);
- joints_ents[i] = NULL;
- }
- }
- for (i = 0; i < VEHICLE_MAXBLOCKS; i++) {
- dBlock killBlock = blocks_ents[i];
- if (killBlock && curWorld)
- {
- dBodyRemoveBlock(curWorld, killBlock);
- blocks_ents[i] = NULL;
- }
- }
- }
- void RemoveStaticConnections()
- {
- if (storage) {
- for (int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- int p1 = storage.statcons_part1[i];
- int p2 = storage.statcons_part2[i];
- if (p1 > -1 && p2 > -1 && parts_ents[p1] && parts_ents[p2])
- RemoveChild(parts_ents[p1], parts_ents[p2]);
- }
- }
- }
- // Update world matrix for parts
- void UpdatePartsWorldData()
- {
- for (int i = 0; i < storage.parts_num; i++)
- {
- Vehicle_Part partEnt = parts_ents[i];
- if (partEnt) {
- vector mat[4];
- GetMatrix4(partEnt, mat);
- storage.parts_wmat0[i] = mat[0];
- storage.parts_wmat1[i] = mat[1];
- storage.parts_wmat2[i] = mat[2];
- storage.parts_wmat3[i] = mat[3];
- if (noUpdate) {
- storage.parts_velLin[i] = partEnt.noUpdate_velLin;
- storage.parts_velAng[i] = partEnt.noUpdate_velAng;
- } else {
- storage.parts_velLin[i] = GetVelocity(partEnt);
- storage.parts_velAng[i] = dBodyGetAngularVelocity(partEnt);
- }
- storage.parts_genVec[i] = partEnt.GenVec;
- storage.parts_genVec2[i] = partEnt.GenVec2;
- storage.parts_genVec3[i] = partEnt.GenVec3;
- storage.parts_genVec4[i] = partEnt.GenVec4;
- storage.parts_genVec5[i] = partEnt.GenVec5;
- storage.parts_genVec6[i] = partEnt.GenVec6;
- storage.parts_storedParent[i] = partEnt.ParentPartNum;
- }
- }
- }
- // Called when fuel handler values should be stored
- void StoreFuelHandlerValues()
- {
- if(vehicleController)
- vehicleController.StoreFuelHandlerValues();
- }
- void BrokeVehiclePart(string partType);
- // Goes through attached children to the parent part and adds log entries of losses
- void LogLosses(int parentPart)
- {
- if (storage.parts_title[parentPart] != "") {
- if (storage.parts_subtypes[parentPart] != "")
- storage.AddLogEntry("#tkom_log_malfloss " + storage.parts_title[parentPart] + " " + itoa(PartSubTypeGetNum(parentPart, storage.parts_subtypes[parentPart])));
- else {
- if (storage.parts_types[parentPart] != "")
- storage.AddLogEntry("#tkom_log_malfloss " + storage.parts_title[parentPart] + " " + itoa(PartTypeGetNum(parentPart, storage.parts_types[parentPart])));
- }
- }
- if (storage.parts_types[parentPart] != "")
- BrokeVehiclePart(storage.parts_types[parentPart]);
- for (int i = 0; i < storage.parts_num; i++)
- {
- if (i != parentPart && CheckPartConnect(i, parentPart)) {
- if (storage.parts_title[i] != "") {
- if (storage.parts_subtypes[i] != "")
- storage.AddLogEntry("#tkom_log_malfloss " + storage.parts_title[i] + " " + itoa(PartSubTypeGetNum(i, storage.parts_subtypes[i])));
- else {
- if (storage.parts_types[i] != "")
- storage.AddLogEntry("#tkom_log_malfloss " + storage.parts_title[i] + " " + itoa(PartTypeGetNum(i, storage.parts_types[i])));
- }
- }
- if (storage.parts_types[i] != "")
- BrokeVehiclePart(storage.parts_types[i]);
- }
- }
- }
- void OnInventoryChanged() // Called from inventories when items within them have changed
- {
- if (vehicleController)
- vehicleController.ProcessInventoryChanged();
- }
- void CallCustomEvent(string eventName)
- {
- if (vehicleController)
- vehicleController.ProcessOnEvent(eventName);
- storage.InventoriesOnEvent(eventName);
- }
- void CallCustomEventWithEntity(string eventName, _entity ent)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithEntity(eventName, ent);
- storage.InventoriesOnEventWithEntity(eventName, ent);
- }
- void CallCustomEventWithUnit(string eventName, Vehicle_Handler unit)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithUnit(eventName, unit);
- storage.InventoriesOnEventWithUnit(eventName, unit);
- }
- void CallCustomEventWithPart(string eventName, Vehicle_Handler part)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithPart(eventName, part);
- storage.InventoriesOnEventWithPart(eventName, part);
- }
- void CallCustomEventWithSoundParams(string eventName, SoundShader sndShdr, vector sndPos, float sndVol, int ownerID)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithSoundParams(eventName, sndShdr, sndPos, sndVol, ownerID);
- storage.InventoriesOnEventWithSoundParams(eventName, sndShdr, sndPos, sndVol, ownerID);
- }
- void CallCustomEventWithInt(string eventName, int input)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithInt(eventName, input);
- storage.InventoriesOnEventWithInt(eventName, input);
- }
- void CallCustomEventWithFloat(string eventName, float input)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithFloat(eventName, input);
- storage.InventoriesOnEventWithFloat(eventName, input);
- }
- void CallCustomEventWithMatrix(string eventName, vector mat[])
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithMatrix(eventName, mat);
- storage.InventoriesOnEventWithMatrix(eventName, mat);
- }
- void CallCustomEventWithForce(string eventName, vector pos, vector force)
- {
- if (vehicleController)
- vehicleController.ProcessOnEventWithForce(eventName, pos, force);
- storage.InventoriesOnEventWithForce(eventName, pos, force);
- }
- bool GetVehicleBroken()
- {
- if (vehicleController)
- return vehicleController.GetVehicleBroken();
- }
- bool GetOutOfFuel()
- {
- if (vehicleController)
- return vehicleController.GetOutOfFuel();
- }
- bool Editor_GetCanSpawnFuel()
- {
- if (vehicleController)
- return vehicleController.Editor_GetCanSpawnFuel();
- }
- void Editor_SpawnFuel()
- {
- if (vehicleController)
- vehicleController.Editor_SpawnFuel();
- }
- bool GetOutOfPower()
- {
- float genVsDrain = PowerGenRate - PowerDrainRate;
- if (genVsDrain > 0)
- return false;
- if (storage.LowPowerShutdown)
- return true;
- else
- return false;
- }
- float GetListenerVolume()
- {
- if (vehicleController)
- return vehicleController.GetListenerVolume();
- }
- float GetListenerSFXLerp()
- {
- if (vehicleController)
- return vehicleController.GetListenerSFXLerp();
- }
- string GetListenerSFXPath()
- {
- if (vehicleController)
- return vehicleController.GetListenerSFXPath();
- }
- // Enables custom gravity simulation
- bool CustomGravityEnabled;
- vector CustomGravity;
- void EnableCustomGravity(bool enable, vector gravity)
- {
- CustomGravityEnabled = enable;
- if (enable)
- CustomGravity = gravity;
- else
- CustomGravity = ZeroVec;
- for (int i = 0; i < storage.parts_num; i++)
- {
- Vehicle_Part partEnt = parts_ents[i];
- if (partEnt && dBodyIsDynamic(partEnt))
- {
- if (enable)
- dBodyEnableGravity(partEnt, false);
- else
- dBodyEnableGravity(partEnt, true);
- }
- }
- CallCustomEvent("CHANGED_CUSTOMGRAVITY");
- }
- // Simulate custom gravity
- void SimulateCustomGravity(float timeslice)
- {
- if (!CustomGravityEnabled)
- return;
- if (CustomGravity == ZeroVec)
- return;
- for (int i = 0; i < storage.parts_num; i++)
- {
- Vehicle_Part partEnt = parts_ents[i];
- if (partEnt && dBodyIsDynamic(partEnt) && dBodyIsActive(partEnt)) {
- float mass = dBodyGetMass(partEnt);
- dBodyApplyImpulse(partEnt, CustomGravity * 32 * mass * timeslice);
- }
- }
- }
- // Dynamic atmo zone created - client only
- void MP_CallCreated(GameEntity dynAtmoZoneBase, int customID)
- {
- if (!IsClient())
- return;
- if (!vehicleController)
- return;
- DynamicAtmoZone dynAtmoZone = (DynamicAtmoZone)dynAtmoZoneBase;
- if (!dynAtmoZone)
- return;
- vehicleController.ProcessOnDynamicAtmoZone(dynAtmoZone, customID);
- }
- // Dynamic atmo zone deleted - client only
- void MP_CallDeleted(GameEntity dynAtmoZoneBase, int customID)
- {
- if (!IsClient())
- return;
- if (!vehicleController)
- return;
- DynamicAtmoZone dynAtmoZone = (DynamicAtmoZone)dynAtmoZoneBase;
- if (!dynAtmoZone)
- return;
- vehicleController.ProcessDeleteDynamicAtmoZone(dynAtmoZone, customID);
- }
- // Docking
- void MPSafe_Dock(int dockNum, int otherID, int otherDockNum);
- void Dock(int dockNum, int otherID, int otherDockNum);
- void RP_Dock(int dockNum, int otherID, int otherDockNum, bool isRemoteCall);
- // Undocking
- void MPSafe_Undock(int dockNum, bool applyUndockForce);
- void Undock(int dockNum, bool applyUndockForce);
- void RP_Undock(int dockNum, bool applyUndockForce, bool isRemoteCall);
- // Event to controller that a part was damaged by something else
- void PartDamagedBy(Vehicle_Part part, float damage, int damagedByID)
- {
- if (vehicleController)
- vehicleController.ProcessOnPartDamagedBy(part, damage, damagedByID);
- }
- // Event to controller that a part was damaged
- void PartHandleDamage(Vehicle_Part part, float damage)
- {
- if (vehicleController)
- vehicleController.ProcessOnPartHandleDamage(part, damage);
- }
- // Deletes a specific joint and spawns its particle effect
- void MPSafe_BreakJoint(int jNum, bool breakFX, bool logLoss);
- void RP_BreakJoint(int jNum, bool breakFX, bool logLoss, bool isRemoteCall);
- void BreakJoint(int jNum, bool breakFX, bool logLoss);
- // Deletes joints connecting to the specified part
- void MPSafe_DeleteJointsToPart(int pNum, bool breakFX, bool logLoss, bool forceDelete);
- void RP_DeleteJointsToPart(int pNum, bool breakFX, bool logLoss, bool forceDelete, bool isRemoteCall);
- void DeleteJointsToPart(int pNum, bool breakFX, bool logLoss, bool forceDelete)
- {
- bool deleteBlockers = true;
- World curWorld = GetCurrentWorld();
- for (int i = 0; i < storage.joints_num; i++)
- {
- if (storage.joints_part1[i] == pNum || storage.joints_part2[i] == pNum) {
- /*if (storage.joints_noDelete[i])
- Print(String("Joint " + itoa(i) + " is set to no delete!"));
- else
- Print(String("Deleting joint " + itoa(i)));*/
- if (forceDelete || !storage.joints_noDelete[i])
- BreakJoint(i, breakFX, logLoss);
- else
- deleteBlockers = false;
- }
- }
- if (!deleteBlockers)
- return;
- for (i = 0; i < storage.blocks_num; i++)
- {
- if (storage.blocks_part1[i] == pNum || storage.blocks_part2[i] == pNum) {
- storage.blocks_part1[i] = -1; // Part 1 number
- storage.blocks_part2[i] = -1; // Part 2 number
- if (blocks_ents[i] && curWorld)
- {
- if (forceDelete || !storage.blocks_noDelete[i])
- dBodyRemoveBlock(curWorld, blocks_ents[i]);
- }
- blocks_ents[i] = NULL;
- }
- }
- }
- // Deletes joints connecting the specified parts
- void MPSafe_DeleteJointsBetweenParts(int pNum1, int pNum2, bool breakFX, bool logLoss, bool forceDelete);
- void RP_DeleteJointsBetweenParts(int pNum1, int pNum2, bool breakFX, bool logLoss, bool forceDelete, bool isRemoteCall);
- void DeleteJointsBetweenParts(int pNum1, int pNum2, bool breakFX, bool logLoss, bool forceDelete)
- {
- bool deleteBlockers = true;
- bool del = false;
- for (int i = 0; i < storage.joints_num; i++)
- {
- del = false;
- if (storage.joints_part1[i] == pNum1 || storage.joints_part1[i] == pNum2) {
- if (storage.joints_part2[i] == pNum1 || storage.joints_part2[i] == pNum2)
- del = true;
- }
- if (del) {
- if (forceDelete || !storage.joints_noDelete[i])
- BreakJoint(i, breakFX, logLoss);
- else
- deleteBlockers = false;
- }
- }
- if (!deleteBlockers)
- return;
- for (i = 0; i < storage.blocks_num; i++)
- {
- del = false;
- if (storage.blocks_part1[i] == pNum1 || storage.blocks_part1[i] == pNum2) {
- if (storage.blocks_part2[i] == pNum1 || storage.blocks_part2[i] == pNum2)
- del = true;
- }
- if (del) {
- World curWorld = GetCurrentWorld();
- storage.blocks_part1[i] = -1; // Part 1 number
- storage.blocks_part2[i] = -1; // Part 2 number
- if (blocks_ents[i] && curWorld)
- {
- if (forceDelete || !storage.blocks_noDelete[i])
- dBodyRemoveBlock(curWorld, blocks_ents[i]);
- }
- blocks_ents[i] = NULL;
- }
- }
- }
- // Docking stuff
- void GetDockingPortMat(int dockPortIndex, vector mat[4]);
- bool GetVehicleDockToDockStressOk(int dockNum, Vehicle_Part myDockPart, Vehicle_Handler otherVehicle, int otherVehicleDockNum, Vehicle_Part otherDockPart);
- bool GetDocksAligned(vector myDockPortMat[4], vector otherDockPortMat[4]);
- bool GetCanDockToVehicle(int dockNum, Vehicle_Handler otherVehicle, int otherVehicleDockNum);
- void Update_TryDocking();
- void ApplyUndockForce(int dockPortIndex);
- void Update_DockPortForce();
- void Update_DockPortStress();
- // Permanently deletes a part
- void DeletePart(local int pNum)
- {
- if (pNum == 0) // No deleting the main piece!
- return;
- DeleteJointsToPart(pNum, false, false, true);
- // First check if it is a statically connected part
- for (local int i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- local int p1 = storage.statcons_part1[i];
- local int p2 = storage.statcons_part2[i];
- if (p1 > -1 && p2 > -1 && parts_ents[p1] && parts_ents[p2] && pNum == p2) {
- RemoveChild(parts_ents[p1], parts_ents[p2]);
- storage.statcons_part1[i] = -1;
- storage.statcons_part2[i] = -1;
- }
- }
- // Now check if it has a static part connected to it
- for (i = 0; i < VEHICLE_MAXPARTS; i++)
- {
- p1 = storage.statcons_part1[i];
- p2 = storage.statcons_part2[i];
- if (p1 > -1 && p2 > -1 && parts_ents[p1] && parts_ents[p2] && pNum == p1)
- DeletePart(p2);
- }
- // Now remove it and clear its data
- storage.parts_pwrdrain[pNum] = 0;
- storage.parts_damage[pNum] = -1;
- storage.parts_tough[pNum] = 0;
- storage.parts_mass[pNum] = -1;
- storage.parts_models[pNum] = "";
- storage.parts_types[pNum] = "";
- storage.parts_subtypes[pNum] = "";
- storage.parts_title[pNum] = "";
- storage.parts_pos[pNum] = ZeroVec;
- storage.parts_ang[pNum] = ZeroVec;
- storage.parts_wmat0[pNum] = ZeroVec;
- storage.parts_wmat1[pNum] = ZeroVec;
- storage.parts_wmat2[pNum] = ZeroVec;
- storage.parts_wmat3[pNum] = ZeroVec;
- storage.parts_velLin[pNum] = ZeroVec;
- storage.parts_velAng[pNum] = ZeroVec;
- storage.parts_genVec[pNum] = ZeroVec;
- storage.parts_genVec2[pNum] = ZeroVec;
- storage.parts_genVec3[pNum] = ZeroVec;
- storage.parts_genVec4[pNum] = ZeroVec;
- storage.parts_genVec5[pNum] = ZeroVec;
- storage.parts_genVec6[pNum] = ZeroVec;
- storage.parts_conPtcSnd[pNum] = "";
- storage.parts_storedParent[pNum] = -2;
- if (vehicleController)
- vehicleController.ProcessOnDeletePart(parts_ents[pNum], pNum);
- if (parts_ents[pNum])
- delete parts_ents[pNum];
- parts_ents[pNum] = NULL;
- }
- // Delete part queue (to delete outside physics tick)
- int DeletePartQueue[VEHICLE_MAXPARTS];
- int DeletePartQueueNum;
- bool GetPartDeleteQueueIndex(int p)
- {
- return IsInArray(DeletePartQueue, DeletePartQueueNum, p);
- }
- void AddPartToDeleteQueue(int p)
- {
- if (p <= -1)
- return;
- if (GetPartDeleteQueueIndex(p) != -1)
- return;
- Vehicle_Part pEnt = parts_ents[p];
- if (!pEnt)
- return;
- parts_interactionLayer[p] = COLLIDERLAYER_NONE;
- dBodyInteractionLayer(pEnt, COLLIDERLAYER_NONE);
- ClearFlags(pEnt, TFL_VISIBLE);
- DeletePartQueue[DeletePartQueueNum] = p;
- DeletePartQueueNum++;
- }
- void ProcessDeletePartQueue()
- {
- for (local int p = 0; p < DeletePartQueueNum; p++)
- {
- local int pNum = DeletePartQueue[p];
- DeletePart(pNum);
- }
- DeletePartQueueNum = 0;
- }
- // Queues a part for permanent deletion
- void MPSafe_DeletePart(local int pNum);
- void RP_DeletePart(local int pNum, bool isRemoteCall);
- void QueueDeletePart(local int pNum)
- {
- if (pNum == 0) // No deleting the main piece!
- return;
- AddPartToDeleteQueue(pNum);
- }
- void Update_JointStress()
- {
- if (GodModeTime > 0)
- return;
- // Adjust for unreliable stress values in lower physics settings
- float physTickScale = 1 / phys_FixedTick - 60 / 60;
- clamp physTickScale<0, 1>;
- physTickScale = 1 - physTickScale * 0.25 + 1;
- for (int i = 0; i < storage.joints_num; i++)
- {
- if (!joints_ents[i])
- continue;
- if (storage.joints_noDelete[i])
- continue;
- int p1 = storage.joints_part1[i];
- int p2 = storage.joints_part2[i];
- Vehicle_Part vehPart1 = parts_ents[p1];
- if (!vehPart1)
- continue;
- Vehicle_Part vehPart2 = parts_ents[p2];
- if (!vehPart2)
- continue;
- float lStressMax = storage.joints_Lstress[i] * physTickScale;
- float aStressMax = storage.joints_Astress[i] * physTickScale;
- if (lStressMax < 0 && aStressMax < 0)
- continue;
- vector lv_p1, lv_p2, av_p1, av_p2;
- lv_p1 = GetVelocity(vehPart1);
- av_p1 = dBodyGetAngularVelocity(vehPart1);
- lv_p2 = GetVelocity(vehPart2);
- av_p2 = dBodyGetAngularVelocity(vehPart2);
- lv_p1 = lv_p1 - lv_p2;
- av_p1 = av_p1 - av_p2;
- float lStress = VectorLength(lv_p1);
- float aStress = VectorLength(av_p1);
- if (lStress >= lStressMax && lStressMax >= 0)
- MPSafe_BreakJoint(i, true, true);
- else
- {
- if (aStress >= aStressMax && aStressMax >= 0)
- MPSafe_BreakJoint(i, true, true);
- }
- }
- }
- // Updates the status text (failure etc)
- /*void Update_PartStatus(int partNum, float damage)
- {
- storage.parts_detailsStatus[i]
- }*/
- // Checks parts for any AddDamage value and adds it to the part's total damage value, breaking joints to the part if it is 1.0
- void Update_PartDamage()
- {
- for (int i = 0; i < storage.parts_num; i++) {
- Vehicle_Part pEnt = parts_ents[i];
- if (pEnt) {
- if (GodModeTime == 0) {
- float dmg = storage.parts_damage[i] + pEnt.AddDamage;
- bool doBreak = false;
- if (dmg >= 1 && storage.parts_damage[i] < 1)
- doBreak = true;
- clamp dmg<0, 1>;
- storage.parts_damage[i] = dmg;
- //if (dmg > 0)
- //Print(String("Part " + itoa(i) + " damaged, total: " + ftoa(dmg) + ", Toughness: " + itoa(storage.parts_tough[i])));
- // Destroyed, break off
- if (doBreak) {
- MPSafe_DeleteJointsToPart(i, true, true, false);
- //Print(String("Part " + itoa(i) + " is destroyed, breaking joints..."));
- }
- }
- pEnt.AddDamage = 0;
- }
- //Update_PartStatus(i);
- }
- }
- // Checks if any part has the bool GripImpulse set to true, if so, then any gripped parts are ungripped unless NoHierarchyGripImpulseBreak set to true
- void Update_PartGrip()
- {
- int i;
- Vehicle_Part pEnt;
- if (NoHierarchyGripImpulseBreak) {
- for (i = 0; i < storage.parts_num; i++) {
- pEnt = parts_ents[i];
- if (pEnt && pEnt.GripImpulse)
- pEnt.GripImpulse = false;
- }
- return;
- }
- bool breakGrips = false;
- // First run through the list and pass any grip impulses to the highest parent
- for (i = 0; i < storage.parts_num; i++) {
- pEnt = parts_ents[i];
- if (pEnt && pEnt.GripImpulse) {
- breakGrips = true;
- pEnt.GripImpulse = false;
- int pNum = pEnt.ParentPartNum;
- if (pNum == -1)
- pEnt.GripImpulse = true;
- else {
- int numIterations = 0;
- while(pNum != -1 && numIterations < VEHICLE_MAXPARTS) {
- pEnt = parts_ents[pNum];
- if (pEnt) {
- pEnt.GripImpulse = false;
- pNum = pEnt.ParentPartNum;
- if (pNum == -1)
- pEnt.GripImpulse = true;
- }
- numIterations++;
- }
- if (numIterations == VEHICLE_MAXPARTS)
- Print(String("UPDATE_PARTSGRIP(): Vehicle '" + storage.name + "' got stuck in an infinite loop while checking connection!"));
- }
- }
- }
- // Now, if there were any grip impulses, run through each part and check up to its highest parent for grip impulses
- if (breakGrips) {
- for (i = 0; i < storage.parts_num; i++) {
- pEnt = parts_ents[i];
- if (pEnt) {
- pNum = pEnt.ParentPartNum;
- if (pNum != -1) {
- numIterations = 0;
- while(pNum != -1 && numIterations < VEHICLE_MAXPARTS) {
- Vehicle_Part pEnt2 = parts_ents[pNum];
- if (pEnt2) {
- if (pEnt2.GripImpulse)
- pEnt.GripImpulse = true;
- pNum = pEnt2.ParentPartNum;
- }
- numIterations++;
- }
- if (numIterations == VEHICLE_MAXPARTS)
- Print(String("UPDATE_PARTSGRIP(): Vehicle '" + storage.name + "' got stuck in an infinite loop while checking connection!"));
- }
- if (pEnt.GripImpulse && pEnt.Gripped)
- pEnt.MPSafe_Grip(false);
- }
- }
- // Finally, run through again and remove any grip impulses
- for (i = 0; i < storage.parts_num; i++) {
- pEnt = parts_ents[i];
- if (pEnt && pEnt.GripImpulse)
- pEnt.GripImpulse = false;
- }
- }
- }
- // Returns the total mass of the objects connected to the target part
- float GetPayloadMass(int payloadParent)
- {
- float result = 0;
- for (int i = 0; i < storage.parts_num; i++) {
- if (CheckPartConnect(i, payloadParent))
- result += storage.parts_mass[i];
- }
- return result;
- }
- // Returns number of a type of part attached to the vehicle
- int GetNumPartType(string partType)
- {
- int result = 0;
- for (int i = 0; i < storage.parts_num; i++) {
- if (storage.parts_types[i] == partType && CheckPartBaseConnect(i))
- result++;
- }
- return result;
- }
- void ClearInput(bool secondary)
- {
- if( !IsControlsReceiver() )
- {
- if (!secondary) {
- input_arc_pri0 = 0;
- input_arc_pri1 = 0;
- input_arc_pri2 = 0;
- input_arc_prigui = false;
- } else {
- input_arc_sec0 = 0;
- input_arc_sec1 = 0;
- input_arc_sec2 = 0;
- input_arc_secgui = false;
- }
- }
- }
- void SelectNextPart(bool previous, bool secondary, bool force)
- {
- int curPart;
- int result;
- bool switchPart = false;
- if (!secondary) {
- curPart = storage.CurrentPriPart;
- result = storage.CurrentPriPart;
- if (GetMissionTime(1) > PriPartSwitchTime || PriPartSwitchTime < GetMissionTime(1) || force) {
- PriPartSwitchTime = GetMissionTime(1) + 0.25;
- switchPart = true;
- }
- } else {
- curPart = storage.CurrentSecPart;
- result = storage.CurrentSecPart;
- if (GetMissionTime(1) > SecPartSwitchTime || SecPartSwitchTime < GetMissionTime(1) || force) {
- SecPartSwitchTime = GetMissionTime(1) + 0.25;
- switchPart = true;
- }
- }
- if (switchPart) {
- ClearInput(secondary);
- int numChecks = 0;
- while (result == curPart && numChecks < storage.parts_num) {
- if (previous)
- result--;
- else
- result++;
- if (result >= storage.parts_num)
- result = 0;
- if (result < 0)
- result = storage.parts_num - 1;
- bool isControlable = false;
- for (int i = 0; i < storage.ctrl_num; i++) {
- if (storage.parts_types[result] == storage.ctrl_types[i])
- isControlable = true;
- }
- if (isControlable && CheckPartBaseConnect(result))
- curPart = -1;
- else
- curPart = result;
- numChecks++;
- }
- if (!secondary)
- storage.CurrentPriPart = result;
- else
- storage.CurrentSecPart = result;
- }
- }
- void SelectPart(int num, bool secondary)
- {
- bool isControlable = false;
- for (int i = 0; i < storage.ctrl_num; i++) {
- if (storage.parts_types[num] == storage.ctrl_types[i])
- isControlable = true;
- }
- if (isControlable) {
- if (secondary)
- storage.CurrentPriPart = num;
- else
- storage.CurrentSecPart = num;
- }
- ClearInput(secondary);
- }
- // Sets/resets physics interaction layer of the vehicle for collision sweep tests
- void EnablePhysicsInteraction(bool enable)
- {
- for (int i = 0; i < storage.parts_num; i++) {
- Vehicle_Part vPart = parts_ents[i];
- if (vPart) {
- int intLayer = parts_interactionLayer[i];
- if (enable)
- {
- if (intLayer > 0)
- dBodyInteractionLayerEx(vPart, intLayer);
- parts_interactionLayer[i] = 0;
- }
- else
- {
- if (intLayer <= 0)
- parts_interactionLayer[i] = dBodyGetGeomInteractionLayer(vPart, 0);
- dBodyInteractionLayer(vPart, COLLIDERLAYER_NONE);
- }
- }
- }
- }
- // Enables/disables solidity of the vehicle for traces
- void EnableSolidity(bool enable)
- {
- for (int i = 0; i < storage.parts_num; i++) {
- Vehicle_Part vPart = parts_ents[i];
- if (vPart) {
- if (enable)
- SetFlags(vPart, TFL_SOLID);
- else
- ClearFlags(vPart, TFL_SOLID);
- }
- }
- }
- // Enables/disables solidity of the vehicle's passengers for traces
- bool EnablePassengersSolidity(bool enable)
- {
- for (int i = 0; i < storage.passengerSeat_num; i++)
- {
- CharacterObject passenger = storage.passengers[i];
- if (passenger) {
- Vehicle_Handler passengerHandler = passenger.vehicleHandler;
- if (passengerHandler)
- passengerHandler.EnableSolidity(enable);
- }
- }
- }
- // Traces forward from the part and returns the distance
- float TracePart(vector mat[4], float minDist, float maxDist, Vehicle_Part ignorePart)
- {
- VehicleTrcEnt = NULL;
- _entity t_ent = NULL;
- float t_plane[4];
- int t_surfparm;
- vector start = mat[0] * minDist + mat[3];
- vector end = mat[0] * maxDist + mat[3];
- if (ignorePart)
- ClearFlags(ignorePart, TFL_SOLID);
- float result = TraceLineExEx(start, end, ZeroVec, ZeroVec, t_ent, t_plane, 0, t_surfparm, TRACE_WORLD|TRACE_ENTS|TRACE_LINE|TRACE_ONLY_PHYSICS|TRACE_RAGDOLLS, NULL, COLLIDERLAYER_DYNAMIC);
- if (VehicleTrcCon) {
- VehicleTrcCon.Shader = "";
- VehicleTrcCon.Surfparm = -1;
- }
- /*const vector TRCVEC = "0.5 0.5 0.5";
- AddDShape(SHAPE_DIAMOND, COLOR_GREEN, SS_ONCE, end - TRCVEC, end + TRCVEC);*/
- vector t_ent_mins = ZeroVec;
- vector t_ent_maxs = ZeroVec;
- float size = 0;
- if (t_ent) {
- GetBoundBox(t_ent, t_ent_mins, t_ent_maxs);
- size = VectorLength(t_ent_maxs - t_ent_mins);
- }
- if (result < 1 && t_ent && t_ent != GetCurrentWorld() && VehicleTrcCon && size != 0) {
- VehicleTrcEnt = t_ent;
- start = mat[0] * minDist + mat[3];
- end = mat[0] * maxDist + mat[3];
- bool traced = TraceLineToEntity(t_ent, start, end, VehicleTrcCon);
- }
- if (VehicleTrcCon && result < 1)
- VehicleTrcCon.Surfparm = t_surfparm;
- if (ignorePart)
- SetFlags(ignorePart, TFL_SOLID);
- return result;
- }
- // Traces forward from the part and returns the distance, ignoring tracing faces
- float TracePartNoFaces(vector mat[4], float minDist, float maxDist, Vehicle_Part ignorePart)
- {
- _entity t_ent = NULL;
- float t_plane[4];
- int t_surfparm;
- vector start = mat[0] * minDist + mat[3];
- vector end = mat[0] * maxDist + mat[3];
- if (ignorePart)
- ClearFlags(ignorePart, TFL_SOLID);
- float result = TraceLineExEx(start, end, ZeroVec, ZeroVec, t_ent, t_plane, 0, t_surfparm, TRACE_WORLD|TRACE_ENTS|TRACE_LINE|TRACE_ONLY_PHYSICS|TRACE_RAGDOLLS, NULL, COLLIDERLAYER_DYNAMIC);
- /*const vector TRCVEC = "0.5 0.5 0.5";
- AddDShape(SHAPE_DIAMOND, COLOR_GREEN, SS_ONCE, end - TRCVEC, end + TRCVEC);*/
- if (ignorePart)
- SetFlags(ignorePart, TFL_SOLID);
- return result;
- }
- bool getSolidGround_worldBoundsClamp;
- float getSolidGround_worldBoundsOffset;
- float GetSolidGroundHeight(_entity optEnt);
- float GetSolidGroundHeightEx(_entity optEnt, vector offset, vector dir, float dist);
- float GetSolidGroundDist(_entity optEnt, vector dir);
- float GetTotalHeatVolume()
- {
- float result = 0;
- for (int i = 0; i < storage.parts_num; i++)
- {
- Vehicle_Part vehPart = parts_ents[i];
- if (vehPart)
- result += vehPart.heatValue * vehPart.PartMass;
- }
- return result;
- }
- vector Trace3rdCam_normal;
- // Traces forward from the 3rd persp. cam and returns the distance
- float Trace3rdCam(vector mat[4], float minDist, float maxDist, int layerMask)
- {
- _entity t_ent = NULL;
- float t_plane[4];
- int t_surfparm;
- vector start = mat[0] * minDist + mat[3];
- vector end = mat[0] * maxDist + mat[3];
- EnableSolidity(false);
- float result = TraceLineExEx(start, end, ZeroVec, ZeroVec, t_ent, t_plane, 0, t_surfparm, TRACE_WORLD|TRACE_ENTS|TRACE_LINE|TRACE_ONLY_PHYSICS|TRACE_RAGDOLLS, NULL, layerMask);
- EnableSolidity(true);
- Trace3rdCam_normal = Vector(t_plane[0], t_plane[1], t_plane[2]);
- return result;
- }
- // Selects the next valid base part (or a specified part) for the 3rd person cam
- void Select3rdTargetPart(int optPart)
- {
- int cP, cPIndex;
- int lastPart = storage.cams_3rdPart;
- if (optPart != -1)
- storage.cams_3rdPart = optPart;
- else {
- if (storage.cams_3rdPart == 0) { // Part 0 selected, so cycle through valid base parts and select a valid one
- for (cP = 0; cP < storage.ctrlbase_num; cP++) {
- cPIndex = storage.ctrlbase_parts[cP];
- if (cPIndex != -1 && parts_ents[cPIndex]) {
- storage.cams_3rdPart = cPIndex;
- break;
- }
- }
- } else {
- int curBasePartNum = -1;
- for (cP = 0; cP < storage.ctrlbase_num; cP++) { // Find which base part we are using
- cPIndex = storage.ctrlbase_parts[cP];
- if (cPIndex != -1 && parts_ents[cPIndex] && storage.cams_3rdPart == cPIndex) {
- curBasePartNum = cP + 1;
- break;
- }
- }
- if (curBasePartNum != -1 && curBasePartNum < storage.ctrlbase_num)
- storage.cams_3rdPart = storage.ctrlbase_parts[curBasePartNum];
- else
- storage.cams_3rdPart = 0;
- }
- }
- int curPart = storage.cams_3rdPart;
- if (lastPart != curPart) {
- Vehicle_Part lastPEnt = parts_ents[lastPart];
- Vehicle_Part curPEnt = parts_ents[curPart];
- if (storage.cams_mainMode == 1)
- storage.cams_3rdPosition = GetOrigin(lastPEnt) - GetOrigin(curPEnt) + storage.cams_3rdPosition;
- if (storage.cams_mainMode == 2)
- storage.cams_3rdPosition2 = GetOrigin(lastPEnt) - GetOrigin(curPEnt) + storage.cams_3rdPosition2;
- }
- }
- //assign location storage object. exist always, and is serializable
- void SetStorage(VehicleObject vehicle)
- {
- if (!vehicle)
- return;
- storage = vehicle;
- storage.vehicleHandler = this;
- }
- //create default storage object
- void CreateDefaultStorage();
- void CreateDefaultCharacterStorage();
- // Delete storage, if exists
- void DeleteStorage();
- bool NewFrame; // For use in OnSimulate to determine whether we have a new frame
- float LastFrameTime;
- float FrameTimeDiff;
- void OnPreSimulate()
- {
- if (!noUpdate)
- {
- if (!IsClient())
- {
- Update_JointStress();
- Update_DockPortStress();
- Update_PartDamage();
- Update_PartGrip();
- }
- if (vehicleController)
- vehicleController.ProcessOnPreSim();
- }
- }
- private void EOnSimulate(_entity other, float dt)
- {
- if (!noUpdate) {
- Update_DockPortForce();
- if (!IsClient() || IsLagging())
- SimulateCustomGravity(phys_FixedTick);
- if (vehicleController)
- vehicleController.ProcessOnSim();
- storage.InventoriesOnSimulate();
- GodModeTime -= phys_FixedTick;
- if (GodModeTime < 0)
- GodModeTime = 0;
- storage.UpdateCommandSequence(phys_FixedTick);
- }
- NewFrame = false;
- if (delayDelete)
- SetInteractionLayer(COLLIDERLAYER_NONE);
- }
- void OnAfterSimulate()
- {
- if (!noUpdate)
- {
- if (vehicleController)
- vehicleController.ProcessOnAfterSim();
- }
- }
- int lastTeam;
- event private void EOnFrame(_entity other, int extra)
- {
- Update_TryDocking();
- UpdatePower();
- // Send view/body matrix to storage UnitMapMatrix, used for map icons
- if (storage)
- {
- if (storage.isCharacter)
- {
- vector camPos = cameraMat[3];
- if (camPos == ZeroVec)
- GetMatrix4(this, storage.UnitMapMatrix);
- else
- {
- storage.UnitMapMatrix[0] = cameraMat[0];
- storage.UnitMapMatrix[1] = cameraMat[1];
- storage.UnitMapMatrix[2] = cameraMat[2];
- storage.UnitMapMatrix[3] = cameraMat[3];
- }
- }
- else
- GetMatrix4(this, storage.UnitMapMatrix);
- }
- if (IsServer() && !delayDelete && storage && storage.Team != lastTeam)
- {
- lastTeam = storage.Team;
- RP_SynchTeam(storage.Team, false);
- }
- if (!delayDelete && !noUpdate && vehicleController)
- {
- vehicleController.ProcessOnFrm();
- storage.InventoriesOnFrame();
- }
- if (delayDelete)
- {
- DeleteStorage();
- delete this;
- }
- }
- vector threeFrame_mX;
- vector threeFrame_mY;
- int threeFrameNum;
- event private void EOnPostFrame(_entity other, int extra)
- {
- ProcessDeletePartQueue();
- if (delayDelete)
- return;
- NewFrame = true;
- float CurFrameTime = GetMissionTime(1);
- if (LastFrameTime == 0 || CurFrameTime < LastFrameTime)
- LastFrameTime = CurFrameTime;
- FrameTimeDiff = CurFrameTime - LastFrameTime;
- if (!noUpdate && vehicleController)
- {
- storage.UpdateGeneratedMission(FrameTimeDiff, GetOrigin(this)); // Update the vehicle's generated mission
- if (widgetHandler) {
- if (widgetHandler.wUpdateTime > CurFrameTime || widgetHandler.wUpdateTime < CurFrameTime - 1)
- widgetHandler.wUpdateTime = CurFrameTime;
- widgetHandler.UpdateHUDButtons(CurFrameTime - widgetHandler.wUpdateTime);
- widgetHandler.wUpdateTime = CurFrameTime;
- }
- if (!isSelected)
- {
- if (lastSelected)
- {
- DeleteWidgets();
- if( !IsControlsReceiver() )
- {
- input_mouse_X = 0;
- input_mouse_Y = 0;
- input_mouse_Whl = 0;
- }
- lastSelected = false;
- }
- }
- else
- {
- lastSelected = true;
- if( !IsControlsReceiver() && !g_Game.IsMainMenuVisible() )
- {
- // Handle mouse-controls
- if (!Cursor_Enable)
- {
- float scaleDown = FrameTimeDiff * 10;
- if (!Options_FluidFreeFly)
- scaleDown = FrameTimeDiff * 30;
- clamp scaleDown<0, 1>;
- input_mouse_X *= 1 - scaleDown;
- input_mouse_Y *= 1 - scaleDown;
- vehicleController.VInput_mX = g_Controller.GetDeltaHorizontal();
- vehicleController.VInput_mY = g_Controller.GetDeltaVertical();
- clamp vehicleController.VInput_mX<-600, 600>;
- clamp vehicleController.VInput_mY<-600, 600>;
- if (!Options_FluidFreeFly) {
- vehicleController.VInput_mX *= 5;
- vehicleController.VInput_mY *= 5;
- }
- input_mouse_X += vehicleController.VInput_mX * fabs(1/200);
- input_mouse_Y += vehicleController.VInput_mY * fabs(1/200);
- if (input_mouse_X < 0.001 && input_mouse_X > -0.001)
- input_mouse_X = 0;
- if (input_mouse_Y < 0.001 && input_mouse_Y > -0.001)
- input_mouse_Y = 0;
- /*threeFrameNum++;
- if (threeFrameNum > 2)
- threeFrameNum = 0;
- if (Options_FluidFreeFly) {
- float scaleDown = FrameTimeDiff * 10;
- clamp scaleDown<0, 1>;
- input_mouse_X *= 1 - scaleDown;
- input_mouse_Y *= 1 - scaleDown;
- }
- vehicleController.VInput_mX = g_Controller.GetDeltaHorizontal();
- vehicleController.VInput_mY = g_Controller.GetDeltaVertical();
- clamp vehicleController.VInput_mX<-600, 600>;
- clamp vehicleController.VInput_mY<-600, 600>;
- if (Options_FluidFreeFly) {
- input_mouse_X += vehicleController.VInput_mX * fabs(1/200);
- input_mouse_Y += vehicleController.VInput_mY * fabs(1/200);
- if (input_mouse_X < 0.001 && input_mouse_X > -0.001)
- input_mouse_X = 0;
- if (input_mouse_Y < 0.001 && input_mouse_Y > -0.001)
- input_mouse_Y = 0;
- } else {
- threeFrame_mX[threeFrameNum] = vehicleController.VInput_mX * fabs(1/20);
- threeFrame_mY[threeFrameNum] = vehicleController.VInput_mY * fabs(1/20);
- int fnum = threeFrameNum + 1;
- if (fnum > 2)
- fnum = 0;
- if (fabs(threeFrame_mX[threeFrameNum]) < fabs(threeFrame_mX[fnum])
- input_mouse_X = threeFrame_mX[0] + threeFrame_mX[1] + threeFrame_mX[2] + threeFrame_mX[fnum] + threeFrame_mX[fnum] / 5;
- else
- input_mouse_X = threeFrame_mX[0] + threeFrame_mX[1] + threeFrame_mX[2] + threeFrame_mX[threeFrameNum] + threeFrame_mX[threeFrameNum] / 5;
- if (fabs(threeFrame_mY[threeFrameNum]) < fabs(threeFrame_mY[fnum])
- input_mouse_Y = threeFrame_mY[0] + threeFrame_mY[1] + threeFrame_mY[2] + threeFrame_mY[fnum] + threeFrame_mY[fnum] / 5;
- else
- input_mouse_Y = threeFrame_mY[0] + threeFrame_mY[1] + threeFrame_mY[2] + threeFrame_mY[threeFrameNum] + threeFrame_mY[threeFrameNum] / 5;
- }*/
- if (!storage.isCharacter && storage.cams_mainMode == 0) {
- clamp input_mouse_X<-2, 2>;
- clamp input_mouse_Y<-2, 2>;
- }
- vehicleController.VInput_mW = UniversalGetControllerValue(AC_WHEEL_UP);
- vehicleController.VInput_mW -= UniversalGetControllerValue(AC_WHEEL_DOWN);
- input_mouse_Whl += vehicleController.VInput_mW * 0.25;
- if (vehicleController.VInput_mW == 0)
- input_mouse_Whl *= 1 - fabs(FrameTimeDiff * 4);
- if (input_mouse_Whl < 0.001 && input_mouse_Whl > -0.001)
- input_mouse_Whl = 0;
- clamp input_mouse_Whl<-10, 10>;
- }
- else
- {
- input_mouse_X = 0;
- input_mouse_Y = 0;
- input_mouse_Whl = 0;
- }
- // Update input controls
- vehicleController.VInput_aF = UniversalGetControllerValue(AC_FORWARD);
- vehicleController.VInput_aB = UniversalGetControllerValue(AC_BACKWARD);
- vehicleController.VInput_aL = UniversalGetControllerValue(AC_LEFT);
- vehicleController.VInput_aR = UniversalGetControllerValue(AC_RIGHT);
- vehicleController.VInput_aU = UniversalGetControllerValue(AC_UP);
- vehicleController.VInput_aD = UniversalGetControllerValue(AC_DOWN);
- vehicleController.VInput_sF = UniversalGetControllerValue(AC_SEC_FORWARD);
- vehicleController.VInput_sB = UniversalGetControllerValue(AC_SEC_BACKWARD);
- vehicleController.VInput_sL = UniversalGetControllerValue(AC_SEC_LEFT);
- vehicleController.VInput_sR = UniversalGetControllerValue(AC_SEC_RIGHT);
- vehicleController.VInput_sU = UniversalGetControllerValue(AC_SEC_UP);
- vehicleController.VInput_sD = UniversalGetControllerValue(AC_SEC_DOWN);
- vehicleController.VInput_actJump = UniversalGetControllerValue(AC_HUMAN_JUMP);
- vehicleController.VInput_actElev = UniversalGetControllerValue(AC_ELEVATE);
- vehicleController.VInput_actRele = UniversalGetControllerValue(AC_RELEGATE);
- input_arc_pri0 = vehicleController.VInput_aF - vehicleController.VInput_aB;
- input_arc_pri1 = vehicleController.VInput_aR - vehicleController.VInput_aL;
- input_arc_pri2 = vehicleController.VInput_aU - vehicleController.VInput_aD;
- input_arc_sec0 = vehicleController.VInput_sF - vehicleController.VInput_sB;
- input_arc_sec1 = vehicleController.VInput_sR - vehicleController.VInput_sL;
- input_arc_sec2 = vehicleController.VInput_sU - vehicleController.VInput_sD;
- }
- }
- if (!CommandsHelpListUpdated) {
- AddCommandToHelpList("CLEAR", "", "", "", "", "#tkom_vehcmddesc_clear");
- AddCommandToHelpList("", "", "", "", "", "");
- AddCommandToHelpList("WAIT", "(num)", "H/M/S", "", "", "#tkom_vehcmddesc_wait");
- AddCommandToHelpList("", "", "", "", "", "");
- }
- vehicleController.ProcessOnPFrm();
- storage.InventoriesOnPostFrame();
- if (!CommandsHelpListUpdated)
- CommandsHelpListUpdated = true;
- }
- LastFrameTime = CurFrameTime;
- }
- // Called when unit is unselected
- void OnUnselect()
- {
- isSelected = false;
- if (vehicleController)
- vehicleController.ProcessOnUnselect();
- DeleteWidgets();
- }
- // Called when unit is selected
- void OnSelect()
- {
- isSelected = true;
- if (vehicleController)
- vehicleController.ProcessOnSelect();
- }
- //send and receive message to construct vehicle on server/clients
- // void SendConstructMessage();
- // void OnReceiveConstructMessage( PacketInputAdapter input );
- // Creates static objects at the position of the vehicle parts
- void CreateStaticsFromParts();
- //----------------------------------------------------------
- void SetSceneID(int id)
- {
- SetID( id ); //set unique ID for fast finding using FindEntityByID
- storage.Store_ID = id;
- if (id > TKOMHighestEntID)
- TKOMHighestEntID = id;
- }
- void Vehicle_Handler(bool character, bool netEnt);
- void ~Vehicle_Handler();
- }
- /****************************************************************************
- ***************************************************************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement