private Camera CreateNewCamera(bool isAi, ShipRefs r) { // create empty gameobject GameObject newCamera = new GameObject("Ship Camera"); newCamera.transform.parent = transform; // attach all components needed for cameras Camera c = newCamera.AddComponent<Camera>(); newCamera.AddComponent<GUILayer>(); newCamera.AddComponent<FlareLayer>(); newCamera.AddComponent<AudioListener>(); // render planes c.nearClipPlane = 0.05f; c.farClipPlane = 1500.0f; // ai switch if (isAi) { newCamera.SetActive(false); } else { RaceSettings.currentCamera = c; StartCamera sc = newCamera.AddComponent<StartCamera>(); sc.r = r; } return c; }
private Camera CreateNewCamera(bool isAi, ShipRefs r) { // create empty gameobject GameObject newCamera = new GameObject("Ship Camera"); newCamera.transform.parent = transform; // attach all components needed for cameras Camera c = newCamera.AddComponent <Camera>(); newCamera.AddComponent <GUILayer>(); newCamera.AddComponent <FlareLayer>(); newCamera.AddComponent <AudioListener>(); // render planes c.nearClipPlane = 0.05f; c.farClipPlane = 1500.0f; // ai switch if (isAi) { newCamera.SetActive(false); } else { RaceSettings.currentCamera = c; StartCamera sc = newCamera.AddComponent <StartCamera>(); sc.r = r; } return(c); }
/*------------------------------------------------------------------------------------------------------------------------- * Called per Ai physics tick. * * holdTimer is the time that the AI has been holding the weapon, including timer modifications from gamemodes. * unscaledHoldTimer is the time that the AI has been holding the weapon, not including their modifications from gamemodes. * --------------------------------------------------------------------------------------------------------------------------*/ public override void AiUpdate(float holdTimer, float unscaledHoldTimer) { // if the total hold time is over the usage time then drop the pickup if (unscaledHoldTimer > AiUsageDelay) { OnDrop(); } // check if there a ship in front of the ai bool canSeeShip = Physics.Raycast(R.RBody.position, R.Forward, out RaycastHit hit, 15.0f, Layers.ShipToShip); // cast against the ship to ship layer, which are the bounding box colliders of each ship if (!canSeeShip) { return; } // figure out which ship is at the hit point. If the AI is passive towards the ship, do nothing ShipRefs targetShip = Ships.GetClosestShipToPoint(hit.point); if (R.IsPassiveTowards(targetShip)) { canSeeShip = false; } if (canSeeShip) { OnUse(); } }
public override void OnInit(float dmg, ShipRefs r, E_WEAPONS wClass) { base.OnInit(dmg, r, wClass); // get current track section currentSection = r.initialSection; }
/* This is called everytime a ship reaches 0% shield energy. What you do here is up to you, the base behaviour calls EliminateShip(r). */ public override void OnShipExploded(ShipRefs r) { base.OnShipExploded(r); // if this is the player who has died then open the eliminated interface after a short delay. if (r.IsPlayer) { _eliminatedInterface.OpenDelayed(1.0f); } }
/*---Creates a new grenade object---*/ public static GrenadeObject CreateNew(Vector3 position, Quaternion rotation, ShipRefs owner) { // create object CustomPrefab grenadePrefab = Instantiate(GrenadeMod.GrenadePrefab); GrenadeObject grenade = grenadePrefab.gameObject.AddComponent <GrenadeObject>(); grenade.Owner = owner; // setup the grenades transform grenade.transform.position = position; grenade.transform.rotation = rotation; // get the components from the custom prefab and apply them to the grenade MeshRenderer grenadeRenderer = grenadePrefab.GetComponent <MeshRenderer>("Mesh"); BoxCollider shipCollider = grenadePrefab.GetComponent <BoxCollider>("ShipCollider"); BoxCollider environmentCollider = grenadePrefab.GetComponent <BoxCollider>("EnvCollider"); // setup Components environmentCollider.gameObject.layer = LayerMask.NameToLayer("Weapon"); // the weapon layer only collides with scenery // setup speed float velBasedSpeed = owner.InverseTransformDirection(owner.RBody.velocity).z *ConfigSpeed * 0.06f; grenade.StatSpeed = Mathf.Max(ConfigSpeed, velBasedSpeed); // setup other stats grenade.ImpactSettings = ConfigImpactSettings; grenade.StatLifetime = ConfigLifetime; grenade.StatGravity = ConfigGravity; grenade.StatBounceForce = ConfigBounceForce; grenade.StatMaxBounces = ConfigMaxBounces; // setup Colliders grenade.ShipCollider = shipCollider; grenade.EnvironmentCollider = environmentCollider; grenade.ProjectileMeshRenderer = grenadeRenderer; // cache transform of the grenade mesh object. grenade.GrenadeMeshT = grenadeRenderer.transform; // assign explosion prefab grenade.PrefabExplosion = GrenadeMod.ExposionPrefab; grenade.ConfigureProjectile(owner.CollisionMeshObject, grenade.StatSpeed, owner); // check if there is environment between the ship and grenade spawn position and destroy the grenade if there is bool envBlockingGrenade = Physics.Linecast(owner.RBody.position, position, Layers.FloorMask | Layers.TrackWall); if (envBlockingGrenade) { grenade.DestroyProjectile(null); } return(grenade); }
/// <summary> /// Called whenever a ship has just been spawned. /// </summary> /// <param name="ship"></param> private void OnShipSpawned(ShipRefs ship) { /*---Do nothing if the mod isn't activated---*/ if (!CustomShieldActive) { return; } /*---Apply the custom color---*/ ship.Effects.TargetShieldColor = UseTeamColor ? ship.Settings.REF_ENGINECOL_BRIGHT : CustomShieldColor; }
static void ApplyModernGfx(ShipRefs ship, UnityScene unityScene) { using (var p = new TimerUtil()) { ApplyUnityLightingToScene(unityScene); ApplyStandardShaderToScenery(unityScene); ApplyStandardShaderToShip(ship); ApplyDynamicShadows(ship); ApplyNewCamera(unityScene); } }
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ * Spawns a new set of grenades. networkSpawn allows us to determine if the server is spawning the grenades and if it's a local spawn, we'll tell the server we've fired grenades * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ public static void CreateGrenade(ShipRefs ship) { // if we're a player then play a 2D deployment sound if (ship.IsPlayer) { AudioHelpers.PlayOneShot(AudioHelpers.GetAudioClip(AudioHelpers.Weapons_MineDrop), AudioHelpers.E_AUDIOCHANNEL.SFX, 1.0f, 1.0f); } // create the grenades GrenadeObject.CreateNew(ship.transform.TransformPoint(-GrenadeSpawnSpread, 0.0f, ship.MeshBoundsFront.z), ship.RBody.rotation, ship); GrenadeObject.CreateNew(ship.transform.TransformPoint(0.0f, 0.0f, 1.0f), ship.RBody.rotation, ship); GrenadeObject.CreateNew(ship.transform.TransformPoint(GrenadeSpawnSpread, 0.0f, ship.MeshBoundsFront.z), ship.RBody.rotation, ship); }
/// <summary> /// Call to set variables. /// </summary> /// <param name="dmg"></param> /// <param name="r"></param> public virtual void OnInit(float dmg, ShipRefs r, E_WEAPONS wClass) { PU_DMG = dmg; PU_SHIP = r; PU_SHIP.weaponClass = wClass; // play pickup sound if (!PU_SHIP.isAI) { AudioClip clip = Resources.Load("Audio/Ships/WEAPON") as AudioClip; OneShot.CreateOneShot(clip, 1.0f, Random.Range(0.9f, 1.1f)); } }
/// <summary> /// Tries to apply modern Unity graphics to the current BallsiticNG track scene. /// </summary> /// <param name="ship">A BallisticNG ShipRef object</param> /// <param name="unityScene">An object specifying certain GameObject names in your Unity scene</param> /// <returns>False if the unityScene argument is invalid, otherwise true.</returns> public static async Task <bool> TryApplyModernGfx(ShipRefs ship, UnityScene unityScene) { if (CanApplyModernGfx(unityScene)) { ApplyModernGfx(ship, unityScene); return(true); } else { await LogUtil.Log("Cant apply modern graphics (is your unityScene parameter correct?)"); return(false); } }
public async override void OnShipTriggerStartLine(ShipRefs ship) { if (ship.IsPlayer) { await ModernBngCore.TryApplyModernGfx(ship, new UnityScene { SceneNameWithUnityLighting = "TestStdShader", SunObject = "main-sun", ModernSceneryObject = "modern-scenery", SkyMaterialObject = "sky-material-ref", PostProcessingObject = "post-processing-ref" }); } }
/* This is called every time a ship passes the mid line. r is the reference to the ship that has passed. */ public override void OnShipTriggerMidLine(ShipRefs r) { // validate the lap so it can be updated next time the player triggers the start line r.LapValidated = true; r.MiddleSection = r.CurrentSection; if (r.IsPlayer && !r.PassedValidationGate) { AudioHelpers.PlayOneShot(AudioHelpers.UI_Checkpoint, AudioHelpers.E_AUDIOCHANNEL.INTERFACE, 1.0f, 1.0f); CalculateAndDisplayRelativeTime(r); r.PassedValidationGate = true; } }
/// <summary> /// Writes the current cockpit settings to the ini /// </summary> public void SaveCockpitSettings(ShipRefs r) { INIParser ini = new INIParser(); ini.Open(settingsPath); ini.WriteValue("Options", "Enable Lean", leanEnabled); ini.WriteValue("Options", "Lean Scale", leanScaler); var shipName = r.name; ini.WriteValue(shipName, "Cockpit Offset", JsonUtility.ToJson(cockpitOffset)); ini.WriteValue(shipName, "Cockpit Scale", JsonUtility.ToJson(cockpitScale)); ini.Close(); }
/// <summary> /// Loads the current cockpit settings from the ini /// </summary> public void LoadCockpitSettings(ShipRefs r) { INIParser ini = new INIParser(); ini.Open(settingsPath); leanEnabled = ini.ReadValue("Options", "Enable Lean", leanEnabled); leanScaler = (float)ini.ReadValue("Options", "Lean Scale", leanScaler); var shipName = r.name; cockpitOffset = JsonUtility.FromJson <Vector3>(ini.ReadValue(shipName, "Cockpit Offset", JsonUtility.ToJson(cockpitOffset))); cockpitScale = JsonUtility.FromJson <Vector3>(ini.ReadValue(shipName, "Cockpit Scale", JsonUtility.ToJson(cockpitScale))); ini.Close(); }
/*---Called to init the AI control for this pickup--*/ public override void OnAiInit() { // specify some delay before the AI will think about using the pickup. For this grenade we're using a random time between 10 and 25 seconds AiUsageDelay = Random.Range(10, 25); // warn the player that the ai has picked the grenade up if it's within 30 sections of the player ShipRefs player = Ships.PlayerOneShip; if (!player || !player.IsPlayer || R.IsPassiveTowards(player)) { return; } if (Ships.SectionOffsetBetween(Ships.PlayerOneShip, R) < 30) { R.CurrentPickupRegister.WarnPlayer(); } }
public override void OnUpdate(ShipRefs r) { // Run default cockpit update behavior base.OnUpdate(r); HandleInput(r); // Update camera position with our new offset T.localPosition += settings.cockpitOffset; // Update cockpit mesh with our new scale value r.VrCockpitParent.localScale = settings.cockpitScale; // DCS-esque camera lean logic if (!Settings.Gameplay.NoInternalCameraTilt && settings.leanEnabled) { var rotationDot = Vector3.Dot(T.right, Vector3.up); T.localRotation *= Quaternion.Euler(Vector3.forward * -settings.leanScaler * rotationDot); } }
/*---------------------------------------------------------------------------------------------------------------------- * Assuming the prefab is setup correctly with the environment collider being solid and the ship collider being a trigger, * this will trigger when the ship collider starts to collide with something. * ----------------------------------------------------------------------------------------------------------------------*/ public override void OnTriggerEnter(Collider other) { base.OnTriggerEnter(other); // don't do anything against the object that owns the projectile or trigger behaviours if (other.gameObject == Origin || other.GetComponent <NgTriggerBehaviour>()) { return; } // destroy Mines if (other.CompareTag("Explosive")) { DestroyExplosive(other.GetComponent <Explosive>()); StatHelpers.MinesweeperStatAndAchievementHandler(Owner); } // do nothing if the rocket doesn't collide with a track or ship int layer = other.gameObject.layer; if (layer != LayerIDs.Ship) { return; } // get the other ship from the hit objects root transform Transform shipT = other.gameObject.transform.root; ShipRefs hitRef = shipT.GetComponent <ShipRefs>(); bool hitShip = ShipImpact(hitRef); // if we can increase the score from the impact (team race), increase the ships score if (hitShip && Owner && Owner.CanIncreaseScoreFrom(hitRef)) { Owner.IncreaseScore(WeaponConstants.EliminatorSettings.Mines); } // finally destroy the grenade DestroyProjectile(shipT); }
public void SpawnShip(bool isAI) { // load ship prefab and get settings from it GameObject prefab = LoadShip(RaceSettings.playerShip); ShipSettings settings = prefab.GetComponent <ShipSettings>(); if (settings == null) { Debug.LogError("The loaded prefab does not contain a settings class!"); return; } // create axis containers GameObject axis = new GameObject("_axis"); GameObject anim = new GameObject("_anim"); anim.transform.parent = transform; anim.transform.localPosition = Vector3.zero; anim.transform.localRotation = Quaternion.identity; axis.transform.parent = anim.transform; axis.transform.localPosition = Vector3.zero; axis.transform.localRotation = Quaternion.identity; // parent prefab to axis prefab.transform.parent = axis.transform; prefab.transform.localPosition = Vector3.zero; prefab.transform.localRotation = Quaternion.identity; // create rigibody Rigidbody body = gameObject.AddComponent <Rigidbody>(); body.useGravity = false; body.constraints = RigidbodyConstraints.FreezeRotation; body.drag = 1; // create classses ShipRefs r = gameObject.AddComponent <ShipRefs>(); r.settings = settings; r.position = gameObject.AddComponent <ShipPosition>(); r.position.r = r; r.effects = gameObject.AddComponent <ShipEffects>(); r.effects.r = r; r.input = gameObject.AddComponent <ShipInput>(); r.input.r = r; r.sim = gameObject.AddComponent <ShipSim>(); r.sim.r = r; r.body = body; r.mesh = settings.REF_MESH; r.cam = CreateNewCamera(isAI, r); r.shield = settings.DAMAGE_SHIELD; r.axis = axis; r.anim = anim; // attach mesh collider to mesh MeshCollider mc = r.mesh.AddComponent <MeshCollider>(); mc.convex = true; // add frictionless physics manterial to collider PhysicMaterial shipMat = new PhysicMaterial(); shipMat.bounceCombine = PhysicMaterialCombine.Minimum; shipMat.frictionCombine = PhysicMaterialCombine.Minimum; shipMat.bounciness = 0; shipMat.dynamicFriction = 0; shipMat.staticFriction = 0; mc.material = shipMat; r.isAI = isAI; // destroy this class (it's no longer needed) Destroy(this); }
/// <summary> /// User input handling logic /// </summary> private void HandleInput(ShipRefs r) { // Ignore movement input if the VR interface shift key is pressed if (!Input.GetKey(KeyCode.Keypad0)) { // Calculate our per-frame offset var offsetDelta = 0.05f * Time.unscaledDeltaTime; var scaleDelta = 1.0f * Time.unscaledDeltaTime; // Handle y axis input if (Input.GetKey("[8]")) { settings.cockpitOffset.y += offsetDelta; } else if (Input.GetKey("[2]")) { settings.cockpitOffset.y -= offsetDelta; } // Handle x axis input if (Input.GetKey("[4]")) { settings.cockpitOffset.x -= offsetDelta; } else if (Input.GetKey("[6]")) { settings.cockpitOffset.x += offsetDelta; } // Handle z axis input if (Input.GetKey("[+]")) { settings.cockpitOffset.z += offsetDelta; } else if (Input.GetKey("[-]")) { settings.cockpitOffset.z -= offsetDelta; } // Handle cockpit scale input if (Input.GetKey("[7]")) { settings.cockpitScale += Vector3.one * -scaleDelta; } else if (Input.GetKey("[9]")) { settings.cockpitScale += Vector3.one * scaleDelta; } // Handle reset input if (Input.GetKeyDown("[5]")) { settings.cockpitOffset = new Vector3(); settings.cockpitScale = new Vector3(1.0f, 1.0f, 1.0f); } // Handle save key press if (Input.GetKeyDown(KeyCode.KeypadMultiply)) { settings.SaveCockpitSettings(r); } // Handle load key press if (Input.GetKeyDown(KeyCode.KeypadDivide)) { settings.LoadCockpitSettings(r); } } }
public override void OnChangedTo(ShipRefs ship) { base.OnChangedTo(ship); UpdateVrHudPosition(); }
public VrCockpitCamera(ShipRefs ship, ref VrHudModSettings settings) : base(ship.CamSim) { this.settings = settings; settings.LoadCockpitSettings(ship); UpdateVrHudPosition(); }
/* Call this to load the time for this track. Default behaviour loads the file that is saved to disk by SaveTime(r). */ public override void LoadTime(ShipRefs r) { base.LoadTime(r); }
/* This is called every time a ship passes the start line, r is the reference to the ship that has passed. */ public override void OnShipTriggerStartLine(ShipRefs r) { /* If this lap has been validated or the ship hasn't done any laps yet, then we want to do some stuff. */ if (r.LapValidated || r.CurrentLap == 0) { // invalidate the lap again r.LapValidated = false; /* If the ship has finished a lap and is not on the last lap then we want to store and display some information. */ if (r.CurrentLap > 0 && r.CurrentLap <= Race.MaxLaps) { if (r.IsPlayer) { /* Update best time */ if ((r.CurrentLapTime < r.BestLapTime || !r.HasBestLapTime) && !r.LoadedBestLapTime) { r.BestLapTime = r.CurrentLapTime; r.HasBestLapTime = true; } /* Perfect lap notification */ if (r.IsPerfectLap) { // this triggers an onscreen message to appear. You can provide a color or you can write it using richtext in the string. BallisticEvents.Ui.CallOnTriggerMessage("PERFECT LAP", r, ScriptableHud.BnGAccent); // this plays a voice, you can feed this any sound you want (if you load your own you can also use that). AudioHelpers.PlayVoice(AudioHelpers.Voice_PerfectLap); } /* Interface sounds */ if (r.CurrentLap == Race.MaxLaps - 1) { BallisticEvents.Ui.CallOnTriggerMessage("FINAL LAP", r, ScriptableHud.BnGAccent); AudioHelpers.PlayVoice(AudioHelpers.Voice_FinalLap); } AudioHelpers.PlayOneShot(AudioHelpers.UI_Checkpoint, AudioHelpers.E_AUDIOCHANNEL.INTERFACE, 1.0f, 1.0f); } // set values for current lap r.LapTimes[r.CurrentLap - 1] = r.CurrentLapTime; r.PerfectLaps[r.CurrentLap - 1] = r.IsPerfectLap; } /* Tasks for when the ship has completed the race */ if (r.CurrentLap >= Race.MaxLaps && !r.FinishedEvent && !r.Eliminated) { r.FinishedEvent = true; // calling this does some needed config to mark the ship as having finished RaceHelpers.FinishRace(r); // if this is a player ship then set the ship as an AI ship and then save the time if (r.IsPlayer) { // destroy the ship camera and replace it with the finished camera Object.Destroy(r.ShipCamera.GetComponent <ShipCamera>()); ShipFCam finishCam = r.ShipCamera.gameObject.AddComponent <ShipFCam>(); finishCam.r = r; r.IsAi = true; SaveTime(r); } } /* Reset timers and states */ // this resets the current laps time to zero r.CurrentLapTime = 0.0f; r.IsPerfectLap = true; ++r.CurrentLap; r.PassedValidationGate = false; // this clears the hit weapon pads so ships can use them again r.ClearHitPads(); BallisticEvents.Race.CallOnShipLapUpdate(r); // this calculates the time between this ship and another (depending on the ships position) if (r.IsPlayer) { CalculateAndDisplayRelativeTime(r); } // give the ship a turbo PickupRegistry.GivePickupToShip(r, PickupRegistry.FindPickupByName("turbo")); } }
/* This is called everytime a ship starts a new lap. */ public override void OnShipLapUpdate(ShipRefs r) { base.OnShipLapUpdate(r); }
/* This is called everytime a ship finishes the race. */ public override void OnShipFinished(ShipRefs r) { base.OnShipFinished(r); }
public GrenadePickup(ShipRefs r) : base(r) { }
/* This is called every time a ship is spawned. */ public override void OnShipSpawn(ShipRefs r) { base.OnShipSpawn(r); }
/* This is called every time a ship passes the mid line reset gate, setup just behind the mid line gate. */ public override void OnShipTriggerMidLineReset(ShipRefs r) { // invalidate this lap r.LapValidated = false; }
/*---Called whenever the game recieves a code mod packet---*/ private void OnRecievedCustomPacketData(NgNetworkBase network, byte subheader, NgPacket packet) { // we're using 0 as a base to identify packets for this mod if (subheader != 0) { return; } // open the packet packet.Open(); { /*--------------------------------------------------------------------------------------------------------------------------------------------------------------- * Check for ID that confirms this packet is for this mod. This allows us to prevent conflicts if another mod is also using 0 as the value for its subheader * * We've wrapped the byte reading in a try/catch block because NgPacket will throw an exception if it tries to read data past its data length, so we can use this * to log the exception to the log file and not break code execution. * --------------------------------------------------------------------------------------------------------------------------------------------------------------*/ byte[] packetIdRaw = new byte[7]; try { for (int i = 0; i < 7; ++i) { packetIdRaw[i] = packet.ReadByte(); } } catch (Exception e) { // note: if you want to write to the ingame console instead of the unity log, replace Debug with DebugConsole Debug.LogError(e); packet.Close(); return; } // verify packet string packetId = Encoding.UTF8.GetString(packetIdRaw, 0, 7); if (packetId != "XPL_GRN") { packet.Close(); return; } // we've validated that this is an example mod grenade packet. Let's spawn the grenade // all we need to do this is figure out who fired the grenade. For other weapons, you might need to send more information then just who fired it. NgPeer peer = NgNetworkBase.CurrentNetwork.GetPeerById(packet.ReadNetworkConnection()); if (peer == null) { return; } // get the ship from the peer that fired the grenades ShipRefs peerShip = peer.LinkedShip; if (!peerShip) { return; } // now spawn the grenades GrenadePickup.CreateGrenade(peerShip); // if we're the server then also relay this packet to the other peers using the weapon spawn channel if (NgNetworkBase.IsServer) { NgNetworkBase.CurrentNetwork.SendToAllPeers(packet.ToBytes(), NgNetworkBase.CurrentNetwork.WeaponSpawnChannel); } } // close the packet. This disposes the resources needed for reading the packet packet.Close(); }
internal static MeshRenderer ShipMeshRenderer(ShipRefs ship) { return(ship.ShipRenderer); }
internal static Projector ShipShadowProjector(ShipRefs ship) { return(ship.ShadowProjector); }
/* Call this to save the time for this track. Default behaviour saves the ships total time to disk. */ public override void SaveTime(ShipRefs r) { base.SaveTime(r); }