Advertisement
Guest User

BlockScript Example

a guest
Feb 20th, 2016
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.00 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using TheGuysYouDespise;
  5.  
  6. public class HornBlock : BlockScript
  7. {
  8.     //BlockSettings
  9.     protected MKey activateKey;
  10.     protected MSlider pitchSlider;
  11.     protected MSlider volumeSlider;
  12.     protected MToggle semitoneToggle;
  13.  
  14.     //other stuff
  15.     protected AudioSource audioSource;
  16.     protected bool hasSound = false;
  17.     protected float HornsWithMyKeyCoefficient = 0f;
  18.     protected bool flipped = false;
  19.     protected Vector3 orgScale = Vector3.one;
  20.     protected bool steamPowered = false;
  21.     protected float steamPoweredTimer = 10f;
  22.     protected float lastSoundTimer = 10f;
  23.  
  24.     //for the semitone toggle we'll be using we want to know a list of intervals we can use for that
  25.     protected float[] musicIntervals = new float[] {1/1f, 16/15f, 9/8f, 6/5f, 5/4f, 4/3f, 64/45f, 3/2f, 8/5f, 5/3f, 16/9f, 15/8f, 2/1f};
  26.     protected bool waitAFrame = true;
  27.  
  28.     //BlockLoader Specific method: is called right after the script is made - usually,
  29.     //this is done for all blocks of this type and is safe as it waits for stuff like
  30.     //colliders, visuals, resources and so on
  31.     public override void SafeAwake()
  32.     {
  33.         //Set the blocks original scale
  34.         orgScale = transform.localScale;
  35.  
  36.         activateKey = AddKey("Sound The Horn", //Display text
  37.                              "play",           //save name
  38.                              KeyCode.H);       //Keyboard button
  39.  
  40.         pitchSlider = AddSlider("Pitch",       //Display Text
  41.                                 "pitch",       //save name
  42.                                 1f,            //default value
  43.                                 0.5f,          //minimum value
  44.                                 2f);           //maximum value
  45.  
  46.         volumeSlider = AddSlider("Volume",       //Display Text
  47.                                  "volume",       //save name
  48.                                  1f,             //default value
  49.                                  0.1f,           //minimum value
  50.                                  1f);            //maximum value
  51.  
  52.         semitoneToggle = AddToggle("Semitone Snap",   //Display Text
  53.                                    "semitones",       //save name
  54.                                    true);             //default value
  55.  
  56.         //Call HandleSemiToneSnap() when the slider value changes
  57.         pitchSlider.ValueChanged += HandleSemitoneSnap;
  58.     }
  59.  
  60.     //BlockLoader Specific method: Is the safe 1 time called method for the prefab - that's the master gameobject, or template so to speek
  61.     //if you need to make alterations to the block you couldn't do with the standard framework, do it here.
  62.     public override void OnPrefabCreation()
  63.     {
  64.     }
  65.  
  66.     //BlockLoader Specific method: When the player presses spacebar or the simulate/play button in the upper left corner
  67.     protected override void OnSimulateStart()
  68.     {
  69.         //if the sound file we loaded in the LoadExampleBlock
  70.         if (resources.ContainsKey("warHorn.ogg"))
  71.         {
  72.             hasSound = true;
  73.             //set the audio source we'll be using to the respective component, but if we don't find one, add one.
  74.             audioSource = gameObject.GetComponent<AudioSource>() ?? gameObject.AddComponent<AudioSource>();
  75.             //set the clip the audio source will be playing to the one we loaded.
  76.             audioSource.clip = resources["warHorn.ogg"].audioClip;
  77.         }
  78.         //This is mostly flair:
  79.         //For all blocks in the machine we have during simulation
  80.         foreach (Transform t in Machine.Active().SimulationMachine)
  81.         {
  82.             //get the ones that are a HornBlock
  83.             if (t.GetComponent<HornBlock>())
  84.             {
  85.                 //and if they use the save keyboard button to play their sound
  86.                 if (t.GetComponent<HornBlock>().activateKey.KeyCode[0] == activateKey.KeyCode[0])
  87.                 {
  88.                     //Add their volume to a coefficient we need for later
  89.                     HornsWithMyKeyCoefficient += t.GetComponent<HornBlock>().volumeSlider.Value;
  90.                 }
  91.             }
  92.         }
  93.     }
  94.  
  95.     //BlockLoader Specific method: When the player is simulating instead of building
  96.     protected override void OnSimulateUpdate()
  97.     {
  98.         //as long as our block isn't destroyed
  99.         if (!HasBurnedOut() && !Destroyed())
  100.         {
  101.             //when we press the key
  102.             if (activateKey.IsPressed)
  103.             {
  104.                 //Play the horn sound
  105.                 SoundTheHorn();
  106.             }
  107.             //Or when steam powers the horn
  108.             else if(steamPowered)
  109.             {
  110.                 //We check all this stuff to stop spamming of powering the horn
  111.                 if (!audioSource.isPlaying || steamPoweredTimer > 0.1f || lastSoundTimer > 1f)
  112.                 {
  113.                     //Play the horn sound
  114.                     lastSoundTimer = 0f;
  115.                     SoundTheHorn();
  116.                 }
  117.             }
  118.             lastSoundTimer += Time.deltaTime;
  119.             steamPoweredTimer += Time.deltaTime;
  120.             steamPowered = false;
  121.         }
  122.     }
  123.    
  124.     //Checking Steam powering
  125.     protected virtual void OnParticleCollision(GameObject other)
  126.     {
  127.         //ignore if we are already steam powered
  128.         if (!steamPowered)
  129.         {
  130.             //if collison is with steam
  131.             if (other.name == "SteamParticle")
  132.                 //if it's entering from the top-ish
  133.                 if (Vector3.Angle(-other.transform.forward, transform.forward) < 55f)
  134.                 {
  135.                     steamPoweredTimer = 0f;
  136.                     steamPowered = true;
  137.                 }
  138.         }
  139.     }
  140.  
  141.     //HornBlock defined method: We have made this method to play the sound we want
  142.     public void SoundTheHorn()
  143.     {
  144.         StopCoroutine(ShakeScale(transform.FindChild("Vis").gameObject, 0.025f, 0.25f / pitchSlider.Value));
  145.         StartCoroutine(ShakeScale(transform.FindChild("Vis").gameObject, 0.025f, 0.25f / pitchSlider.Value));
  146.  
  147.         if (hasSound)
  148.         {
  149.             //Set a couple of frames of random delay (we don't use Time.deltaTime, because if we have low fps we don't want to wait longer for the sounds to play)
  150.             audioSource.PlayDelayed(Random.Range(0f, 0.0165f * 3f));
  151.             //Set the pitch - the brightness - of the sound to be dependent on the timescale and the slider we have for it
  152.             audioSource.pitch = Time.timeScale * pitchSlider.Value;
  153.             //This is the flair coefficient, this basically helps the sounds to be dimmed when a lot of blocks play at the same time
  154.             float Coefficient = 0.6f / (HornsWithMyKeyCoefficient < 4.5f ? 1f : HornsWithMyKeyCoefficient / 3f);
  155.             //Set the volume - the loudness - of the sound to be dependent on the slider and coefficient
  156.             audioSource.volume = volumeSlider.Value * Coefficient;
  157.         }
  158.     }
  159.  
  160.     //BlockLoader Specific method: When we are done simulating, usually you don't need to do anything here,
  161.     //as the block in simulation mode is deleted, but if you have static variables or similar you might want to update it here.
  162.     protected override void OnSimulateExit()
  163.     {
  164.         //reset this flair thing for good meassure
  165.         HornsWithMyKeyCoefficient = 0f;
  166.     }
  167.    
  168.     //Flip the block on F, this method needs to be called "Flip"
  169.     public void Flip()
  170.     {
  171.         //play the flipping sound - BlockScript predefined
  172.         PlayFlipSound();
  173.         //Do the flipping we need:
  174.         FlipNoSound();
  175.     }
  176.  
  177.     //Setting the flip needed for copying, loading and such.
  178.     public void SetFlipNoSound(bool flip)
  179.     {
  180.         //we don't want to do the flip if the flipping matches
  181.         if (flipped == flip)
  182.             return;
  183.         //Do the flipping we need:
  184.         FlipNoSound();
  185.     }
  186.  
  187.     //HornBlock defined method: We flip the block litterally
  188.     public void FlipNoSound()
  189.     {
  190.         //reverse the flipping bool
  191.         flipped = !flipped;
  192.         //mirror the visuals of the block to be... well... mirrored
  193.         foreach(var vis in Visuals)
  194.             MirrorVisual(vis); //BlockScript defined method
  195.         //mirror the colliders in a different way where we make sure to rotate the colliders to achieve the correct stuff
  196.         foreach (var col in Colliders)
  197.             MirrorCollider(col); //BlockScript defined method
  198.     }
  199.  
  200.     //HornBlock defined method:
  201.     //Animates a shake in the scale of a gameobject
  202.     protected IEnumerator ShakeScale(GameObject go, float magnitude, float duration)
  203.     {
  204.         float elapsed = Time.deltaTime;
  205.         duration += Time.deltaTime;
  206.  
  207.         Vector3 orgScale = go.transform.localScale;
  208.         Vector3 fromScale = orgScale;
  209.         Vector3 targetScale = orgScale;
  210.         float previousCoef = 10f;
  211.  
  212.         while (elapsed < duration)
  213.         {
  214.             elapsed += Time.deltaTime;
  215.            
  216.             //this if statement deals with time scale,
  217.             //for >100% time scale it's run every frame
  218.             //but as the time scale is lower we don't want the shaking to appear much faster than fitting for the time
  219.             //in that scenario we will sample the shaking every now and then
  220.             //we then smoothly lerp between the samples
  221.             if (Time.timeScale >= 0.9f || (elapsed % 0.01666f) / 0.01666f < previousCoef)
  222.             {
  223.                 go.transform.localScale = targetScale;
  224.                 //dampen based on the tails of the animation
  225.                 float percentComplete = elapsed / duration;
  226.                 float damper = 1.0f - Mathf.Clamp(5.0f * percentComplete - 4.0f, 0.0f, 1.0f);
  227.  
  228.                 // map value to [-1, 1]
  229.                 float x = Random.value * 2.0f - 1.0f;
  230.                 float y = Random.value * 2.0f - 1.0f;
  231.                 // dampen
  232.                 x *= magnitude * damper;
  233.                 y *= magnitude * damper;
  234.  
  235.                 //Set the two points to lerp between
  236.                 fromScale = go.transform.localScale;
  237.                 targetScale = new Vector3(orgScale.x + x, orgScale.y + y, orgScale.z);
  238.             }
  239.             previousCoef = (elapsed % 0.01666f) / 0.01666f;
  240.             go.transform.localScale = Vector3.Lerp(fromScale, targetScale, (elapsed % 0.01666f) / 0.01666f);
  241.  
  242.             yield return null;
  243.         }
  244.         go.transform.localScale = orgScale;
  245.         yield break;
  246.     }
  247.  
  248.     //HornBlock defined method: make sure that the pitch only can fit a musical interval when toggled
  249.     protected virtual void HandleSemitoneSnap(float value)
  250.     {
  251.         //we have to wait a frame not to create a feedback loop where when we change the value to snap to a semi tone it will then call this function again
  252.         if (waitAFrame)
  253.         {
  254.             waitAFrame = false;
  255.             float lower, upper;
  256.             if (semitoneToggle.IsActive)
  257.             {
  258.                 //we go through all of the semitones
  259.                 for (int i = 0; i < musicIntervals.Length - 1; i++)
  260.                 {
  261.                     lower = musicIntervals[i];
  262.                     upper = musicIntervals[i + 1];
  263.                     //for 2 octaves, below and above the
  264.                     for (int octave = 1; octave <= 2; octave++)
  265.                     {
  266.                         //we are inversing the intervals to get the intervals below 1.0 and above
  267.                         lower = 1f / lower;
  268.                         upper = 1f / upper;
  269.  
  270.                         //see whether the value is between the lower and upper (lower and upper can be inverse, due to we inversing the fraction)
  271.                         if ((value >= lower && value <= upper)
  272.                          || (value >= upper && value <= lower))
  273.                         {
  274.                             //find the closer of the values
  275.                             if (Mathf.Abs(lower - value)
  276.                               < Mathf.Abs(upper - value))
  277.                             {
  278.                                 pitchSlider.Value = lower;
  279.                                 goto ReturnAndUpdate;
  280.                             }
  281.                             else
  282.                             {
  283.                                 pitchSlider.Value = upper;
  284.                                 goto ReturnAndUpdate;
  285.                             }
  286.                         }
  287.                     }
  288.                 }
  289.                 //we were outside the range of the intervals
  290.                 //clamp the value to the absolute lower and upper
  291.                 lower = 1f / musicIntervals[musicIntervals.Length - 1];
  292.                 upper = musicIntervals[musicIntervals.Length - 1];
  293.                 pitchSlider.Value = Mathf.Clamp(value, lower, upper);
  294.  
  295.                 ReturnAndUpdate:
  296.                 StopAllCoroutines();
  297.                 StartCoroutine(UpdateMapper());
  298.             }
  299.         }
  300.         else waitAFrame = true;
  301.     }
  302.  
  303.     //HornBlock defined method
  304.     protected virtual IEnumerator UpdateMapper()
  305.     {
  306.         if (BlockMapper.CurrentInstance == null)
  307.             yield break;
  308.         while (Input.GetMouseButton(0))
  309.             yield return null;
  310.         BlockMapper.CurrentInstance.Copy();
  311.         BlockMapper.CurrentInstance.Paste();
  312.         yield break;
  313.     }
  314.  
  315.     //The following functions are for saving, loading, copying and pasting the values
  316.  
  317.     //Besiege Specific method
  318.     public override void OnSave(BlockXDataHolder data)
  319.     {
  320.         SaveMapperValues(data);
  321.  
  322.         data.Write("flipped", flipped);
  323.     }
  324.  
  325.     //Besiege Specific method
  326.     public override void OnLoad(BlockXDataHolder data)
  327.     {
  328.         LoadMapperValues(data);
  329.  
  330.         // If the simulation just started we do not want to load
  331.         // our flip state from the data holder.
  332.         // The flip variable is automatically copied
  333.         // over by Unity when the simulation starts.
  334.         if (data.WasSimulationStarted) return;
  335.        
  336.         if (data.HasKey("flipped"))
  337.         {
  338.             SetFlipNoSound(data.ReadBool("flipped"));
  339.         }
  340.     }
  341. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement