Author Topic: Burster for NPC unit master/slave movements. Requires PHOTON  (Read 1417 times)

Offline Colonizer

  • Administrator
  • Newbie
  • *****
  • Posts: 45
    • View Profile
Burster for NPC unit master/slave movements. Requires PHOTON
« on: November 08, 2016, 05:06:35 pm »
Master part of code...

Extended version. Updated 23.11.2016

Code: [Select]
///
///
/// Code by Jari Kaija (2016)
///
/// You can use this code freely, but I would like, if you will add my name
/// to your game "Greetings/Coders" list. That's enough for me.
///
/// Usage:
///
/// Create a new C# monobehaviour file and copy paste this code to it.
/// Add this script to a new empty gameobject OR your other root main
/// GamObject, what will be available at the beginning on your game.
///
///
/// Code is self explained. Very easy to understand and modify.
/// This part, what I published are stripped version of my own
/// game version, what have possibilities to add any kind of
/// variables for transferring required data from Master NPC to Slave NPCs.
/// And all of this ON ONE WORKING stream.
///
/// The main reason, why I made this:
///
/// I have a huge legion of soldiers under several troop leaders in my game +
/// lott of workers to carry things and other habitats.
///
/// Photon's (and unity's) streaming SUCKED TOTALLY. My clients
/// incoming buffer were filled and ruined totally and game stopped on all
/// clients. And only one leader and his 35 soldiers. Pathetic....
///
/// So. I made some research and this is conclusion. Totally rewritten
/// "delta stream" style code.
///
/// Enjoy...
///
///


using UnityEngine;
using System;
using System.Linq;
using System.Collections.Generic;


[HelpURL("http://www.thecolonizers.com")]
[RequireComponent(typeof(PhotonView))]
public class BurstMaster : Photon.MonoBehaviour
{
    /// <summary>
    ///
    /// </summary>
    [Serializable]
    public class _BurstClients
    {
        public int photonId;
//        [HideInInspector]
        public bool newPosition = false;
//        [HideInInspector]
        public bool newRotation = false;
//        [HideInInspector]
        public bool newScale = false;
//        [HideInInspector]
        public bool newRigidBits = false;
//        [HideInInspector]
        public bool newAnimation = false;
        //        [HideInInspector]
        public bool newOnOff = false;

        public Vector3 position;
        public Vector3 rotation;
        public Vector3 scale;
        public byte rigidBits;
        public string animation = "";
        public uint onOff;

        [HideInInspector]
        public bool dataReceived = false;
    }

    [Tooltip("With this switch you can turn on/off sending & receiving")]
    public bool active;

    [Header("Send packets / s (max)")]
    [Range(1, 20)]
    public float MaxSendRate = 3;

    float waitTimerVal;
    [Header("Clients list with data")]
    public List<_BurstClients> BurstClients = new List<_BurstClients>();

    public bool newBurstToSendWaiting = false;
    bool newBurstArrived = false;

    [Header("Current unformatted raw data size in structure")]
    [Header("With this info you can compare byte array/raw sizes")]
    [Tooltip("Only for informational use!")]
    public int bufferSize;
    [Header("Current byte array size for transmit")]
    [Tooltip("Only for informational use!")]
    public int bytesSize;

    [HideInInspector]
    public int count = 0;
    [Header("Packets sent / s")]
    [Tooltip("Only for informational use!")]
    public int counter = 0;
    [HideInInspector]
    public int amount = 0;
    [Header("Bytes sent / s")]
    [Tooltip("Only for informational use!")]
    public int bytes = 0;

    [Header("Packets sent")]
    [Tooltip("Only for informational use!")]
    public int sent = 0;
    [Header("Packets received")]
    [Tooltip("Only for informational use!")]
    public int received = 0;
    [Header("Be aware, IT IS SLOW to write log window!")]
    public bool debug = false;
    float seconder;
    string burstString = string.Empty;
    string receivedBurstString = string.Empty;

    int partsinpacket = 0;

    string outserializedata = "";

public void OnEventRaised(byte eventCode, object content, int senderID)
    {
        //Debug.Log(string.Format("OnEventRaised: {0}, {1}, {2}", eventCode, content, senderID));
        handleIncomingData((byte[]) content);
    }
    void handleIncomingData(byte[] bytedata)
    {
        bytesSize = bytedata.Length;
        string data = getString(bytedata);
        if (debug) Debug.Log("Data in: " + data);
        PhotonView pv = PhotonView.Get(this);
        //        if (!pv.isMine)
        //        {
        // Receive and parse all "masters"
        string[] masters = data.Split('&');
        foreach (string master in masters)
        {
            // Receive and parse "master" string to "class"...
            // First split every class parts from data
            string[] dataParts = master.Split('/');
            int clientId;
            // First get photonID and verify it.
            if (int.TryParse(dataParts[0], out clientId))
            {
                if (debug) Debug.Log("Data in from id: " + clientId);
                _BurstClients burstClient = BurstClients.FirstOrDefault(i => i.photonId == clientId);
                if (burstClient != null)
                {
                    // Variables for possible incomings...
                    Vector3 position = burstClient.position;
                    Vector3 rotation = burstClient.rotation;
                    Vector3 scaling = burstClient.scale;
                    byte rigidBits = burstClient.rigidBits;
                    string animation = burstClient.animation;
                    uint wordBits = burstClient.onOff;


                    foreach (string dp in dataParts)
                    {
                        string[] dataSmall = dp.Split(':');
                        if (dataSmall[0] == "P")
                        {
                            position = new Vector3(float.Parse(dataSmall[1]), float.Parse(dataSmall[2]), float.Parse(dataSmall[3]));
                            burstClient.position = position;
                            burstClient.dataReceived = true;
                        }
                        else
                        if (dataSmall[0] == "R")
                        {
                            rotation = new Vector3(float.Parse(dataSmall[1]), float.Parse(dataSmall[2]), float.Parse(dataSmall[3]));
                            burstClient.rotation = rotation;
                            burstClient.dataReceived = true;
                        }
                        else
                        if (dataSmall[0] == "S")
                        {
                            scaling = new Vector3(float.Parse(dataSmall[1]), float.Parse(dataSmall[2]), float.Parse(dataSmall[3]));
                            burstClient.scale = scaling;
                            burstClient.dataReceived = true;
                        }
                        else
                        if (dataSmall[0] == "A")
                        {
                            animation = dataSmall[1];
                            burstClient.animation = animation;
                            burstClient.dataReceived = true;
                        }
                        else
                        if (dataSmall[0] == "B")
                        {
                            rigidBits = byte.Parse(dataSmall[1]);
                            burstClient.rigidBits = rigidBits;
                            burstClient.dataReceived = true;
                        }
                        else
                        if (dataSmall[0] == "F")
                        {
                            wordBits = byte.Parse(dataSmall[1]);
                            burstClient.onOff = wordBits;
                            burstClient.dataReceived = true;
                        }
                    }
                }
            }

            ++received;
        }

    }
    /// <summary>
    /// Send data to clients
    /// </summary>
    /// <param name="data"> Formatted string</param>
    void SendBurst(string data)
    {
        if (debug) Debug.Log("Data out: " + data);

        byte TestEvent = 10;
        PhotonNetwork.RaiseEvent((byte)TestEvent, getBytes(data), true, RaiseEventOptions.Default);
        newBurstToSendWaiting = false;
        ++sent;
    }

    // Use this for initialization
    void Start()
    {
        waitTimerVal = Time.time;
        PhotonNetwork.OnEventCall += this.OnEventRaised;
    }


    // Update is called once per frame
    void Update()
    {
        if (!active) return;
        if (!PhotonNetwork.isMasterClient && !PhotonNetwork.isNonMasterClientInRoom) return;

        PhotonNetwork.sendRate = (int)MaxSendRate + 5;
        PhotonNetwork.sendRateOnSerialize = (int)MaxSendRate + 5;
        // Read the Burstclients list, check if any data updated. If so,
        // add data to pool...
        if (Time.time > seconder + 1)
        {
            counter = count;
            bytes = amount;
            count = 0;
            amount = 0;
            seconder = Time.time;
        }
        if (Time.time > waitTimerVal)
        {

            bool anyBurst = false;
            burstString = string.Empty;
            bufferSize = 0;
            if (!newBurstToSendWaiting)
            {
               
                foreach (_BurstClients bursted in BurstClients)
                {
                    partsinpacket = 0;
                    bool addremainer = false;
                    // First, add a ID to beginning of stream part if any bursted found...
                    if (bursted.newPosition || bursted.newRotation || bursted.newScale || bursted.newRigidBits || bursted.newAnimation || bursted.newOnOff)
                    {
                        ++partsinpacket;
                        burstString += bursted.photonId.ToString();
                        addremainer = true;
                    }
                    if (bursted.newPosition)
                    {
                       
                        burstString += string.Format("/P:{0:0.##}:{1:0.##}:{2:0.##}", bursted.position.x, bursted.position.y, bursted.position.z);
                        bursted.newPosition = false;
                        anyBurst = true;
                        bufferSize += 12;
                    }
                    if (bursted.newRotation)
                    {
                       
                        burstString += string.Format("/R:{0:0.##}:{1:0.##}:{2:0.##}", bursted.rotation.x, bursted.rotation.y, bursted.rotation.z);
                        bursted.newRotation = false;
                        anyBurst = true;
                        bufferSize += 16;
                    }
                    if (bursted.newScale)
                    {
                       
                        burstString += string.Format("/S:{0:0.##}:{1:0.##}:{2:0.##}", bursted.scale.x, bursted.scale.y, bursted.scale.z);
                        bursted.newScale = false;
                        anyBurst = true;
                        bufferSize += 12;
                    }
                    if (bursted.newRigidBits)
                    {
                       
                        burstString += string.Format("/B:{0}", bursted.rigidBits);
                        bursted.newRigidBits = false;
                        anyBurst = true;
                        bufferSize += 1;
                    }
                    if (bursted.newAnimation)
                    {
                       
                        burstString += ("/A:" + bursted.animation);
                        bursted.newAnimation = false;
                        anyBurst = true;
                        bufferSize += bursted.animation.Length * 2;
                    }
                    if (bursted.newOnOff)
                    {
                        burstString += string.Format("/F:{0}", bursted.onOff);
                        bursted.newOnOff = false;
                        anyBurst = true;
                        bufferSize += 2;
                    }
                    if (addremainer)
                    {
                        burstString += "&";
                    }
                }
                if (anyBurst)
                {
                    if (debug) Debug.Log("Parts in big packet: " + partsinpacket);
                    anyBurst = false;

                    outserializedata = burstString;

                    newBurstToSendWaiting = true;
                    ++count;
                    amount = amount + bytesSize;
                    SendBurst(burstString);
                   
                }

            }

            waitTimerVal = (1 / MaxSendRate) + Time.time;
        }

    }

    /// <summary>
    /// Add your master/slave object to burst  list
    /// </summary>
    /// <param name="clientId">PhotonView viewId for bursting</param>
    public void addToBursted(int clientId)
    {
        if (BurstClients.FirstOrDefault(i => i.photonId == clientId) == null)
        {
            _BurstClients newBurst = new _BurstClients();
            newBurst.photonId = clientId;
            newBurst.newPosition = false;
            newBurst.newRotation = false;
            newBurst.newScale = false;
            newBurst.newAnimation = false;
            newBurst.position = Vector3.zero;
            newBurst.rotation = Vector3.zero;
            newBurst.scale = Vector3.zero;
            newBurst.animation = "";
            BurstClients.Add(newBurst);
        }
    }

    /// <summary>
    /// Add your master/slave object to burst list with default values
    /// </summary>
    /// <param name="clientId">PhotonView viewId for bursting</param>
    /// <param name="transform">Object transform script</param>
    /// <param name="animation">Object current animation clip on play</param>
    public void addToBursted(int clientId, Transform transform, Rigidbody rigidbody, string animation, uint wordBits)
    {
        if (BurstClients.FirstOrDefault(i => i.photonId == clientId) == null)
        {
            _BurstClients newBurst = new _BurstClients();
            newBurst.photonId = clientId;
            newBurst.newPosition = true;
            newBurst.newRotation = true;
            newBurst.newScale = true;
            if (animation.Length > 0)
            {
                newBurst.newAnimation = true;
            }
            else
            {
                newBurst.newAnimation = false;
            }
            if (transform != null)
            {
                newBurst.position = transform.position;
                newBurst.newPosition = true;
                newBurst.rotation = transform.rotation.eulerAngles;
                newBurst.newRotation = true;
                newBurst.scale = transform.localScale;
                newBurst.newScale = true;
                BurstClients.Add(newBurst);
            }
            else
            {
                newBurst.position = Vector3.zero;
                newBurst.rotation = Vector3.zero;
                newBurst.scale = Vector3.zero;
                BurstClients.Add(newBurst);
            }
            if (rigidbody != null)
            {
                bool changed = false;
                byte bits = newBurst.rigidBits;
                bits = (byte)rigidbody.constraints;
                Set(ref bits, 0, rigidbody.useGravity);
                Set(ref bits, 7, rigidbody.isKinematic);
                newBurst.rigidBits = bits;
                newBurst.newRigidBits = true;
            }
            newBurst.newOnOff = true;
            newBurst.onOff = wordBits;
        }
    }

    /// <summary>
    /// Get only animation.
    /// </summary>
    /// <param name="clientId">Slave object photonView viewId for bursting</param>
    /// <param name="animation">Requires local string variable for return</param>
    /// <returns>False = No new animation, True = New animation received</returns>
    public bool getBurstData(int clientId, out string animation)
    {
        animation = "";
        string newanimation;
        Vector3 position;
        Vector3 rotation;
        Vector3 localscale;
        byte rigidBits;
        uint wordBits;
        if (getBurstData(clientId, out newanimation, out position, out rotation, out localscale, out rigidBits, out wordBits))
        {
            newanimation = animation;
            return true;
        }
        return false;
    }
    /// <summary>
    ///
    /// </summary>
    /// <param name="clientId">Slave object photonView viewId for bursting</param>
    /// <param name="animation">Requires local string variable for return</param>
    /// <param name="position">Requires local Vector3 variable for return</param>
    /// <param name="rotation">Requires local Quaternion variable for return</param>
    /// <param name="localscale">Requires local Vector3 variable for return</param>
    /// <returns></returns>
    public bool getBurstData(int clientId, out string animation, out Vector3 position, out Vector3 rotation, out Vector3 localscale, out byte rigidBits, out uint wordBits)
    {
        animation = "";
        position = Vector3.zero;
        rotation = Vector3.zero;
        localscale = Vector3.zero;
        rigidBits = 0;
        wordBits = 0;
        _BurstClients bursting = BurstClients.FirstOrDefault(i => i.photonId == clientId);
        if (bursting != null)
        {
            if (bursting.dataReceived)
            {
                animation = bursting.animation;
                position = bursting.position;
                rotation = bursting.rotation;
                localscale = bursting.scale;
                rigidBits = bursting.rigidBits;
                wordBits = bursting.onOff;
                bursting.dataReceived = false;
                return true;
            }
        }

        return false;
    }
    /// <summary>
    /// Adding animation change for client objects.
    /// </summary>
    /// <param name="clientId">Master object photonView viewId for bursting</param>
    /// <param name="animation">Master object current animation clip on play</param>
    public void addBurstData(int clientId, string animation)
    {
        addBurstData(clientId, null, null, 0, animation, false, false, false, false, true, false);
    }
    /// <summary>
    /// Adding selectable transform variables and animation string for client objects
    /// </summary>
    /// <param name="clientId">Master object photonView viewId for bursting</param>
    /// <param name="transform">Master object transform script</param>
    /// <param name="animation">Master object current animation clip on play</param>
    /// <param name="setposition">Update position switch</param>
    /// <param name="setrotation">Update rotation switch</param>
    /// <param name="setscale">Update size switch</param>
    /// <param name="setanimation">Update animation switch</param>
    public void addBurstData(int clientId, Transform transform, Rigidbody rigidbody, uint wordbits, string animation, bool setposition, bool setrotation, bool setscale, bool setrigidbody, bool setanimation, bool setWordBits)
    {
       
        // First check, if we are in list, if not, add automatically.
        if (BurstClients.FirstOrDefault(i => i.photonId == clientId) == null) addToBursted(clientId);
        _BurstClients bursting = BurstClients.FirstOrDefault(i => i.photonId == clientId);
        if (transform != null)
        {
           
            if (setposition && string.Format("{0:0.##}",bursting.position) != string.Format("{0:0.##}", transform.position))
            {
                bursting.position = transform.position;
                bursting.newPosition = true;
            }
            if (setrotation && string.Format("{0:0.##}",bursting.rotation) != string.Format("{0:0.##}", transform.rotation.eulerAngles))
            {
                bursting.rotation = transform.rotation.eulerAngles;
                bursting.newRotation = true;
            }
            if (setscale && string.Format("{0:0.##}", bursting.scale) != string.Format("{0:0.##}", transform.localScale))
            {
                bursting.scale = transform.localScale;
                bursting.newScale = true;
            }
        }

        if (rigidbody != null)
        {
            if (setrigidbody)
            {
                bool changed = false;
                byte bits = bursting.rigidBits;
                // bits 0 & 7 taken for gravity and kinematics...
                if (rigidbody.useGravity != Get(bits, 0)) changed = true;
                if (rigidbody.isKinematic != Get(bits, 7)) changed = true;

                // reset 0 & 7 to get real constraints value
                Set(ref bits, 0, false);
                Set(ref bits, 7, false);

                if (bits != (byte)rigidbody.constraints) changed = true;
                if (changed)
                {
                    bits = (byte)rigidbody.constraints;
                    Set(ref bits, 0, rigidbody.useGravity);
                    Set(ref bits, 7, rigidbody.isKinematic);
                    bursting.rigidBits = bits;
                    bursting.newRigidBits = true;
                }
            }
        }

        if (setanimation && bursting.animation.CompareTo(animation) != 0)
        {
            bursting.animation = animation;
            bursting.newAnimation = true;
        }
        if (setWordBits && bursting.onOff != wordbits)
        {
            bursting.onOff = wordbits;
            bursting.newOnOff = true;
        }
    }

    //*****************************************************************
    //**** Helpers...                                              ****
    //*****************************************************************
    byte[] getBytes(string s)
    {
        if (s != null)
        {
            List<byte> bytes = new List<byte>();
            foreach (char ch in s.ToCharArray())
            {
                bytes.Add(Convert.ToByte(ch));
            }
            return bytes.ToArray();
        }
        return null;
    }
    string getString(byte[] bytes)
    {
        if (bytes != null)
        {
            string ret = string.Empty;
            foreach (byte b in bytes)
            {
                ret += (char)b;
            }
            return ret;
        }
        return ("");
    }


    public static void Set(ref byte aByte, int pos, bool value)
    {
        if (value)
        {
            //left-shift 1, then bitwise OR
            aByte = (byte)(aByte | (1 << pos));
        }
        else
        {
            //left-shift 1, then take complement, then bitwise AND
            aByte = (byte)(aByte & ~(1 << pos));
        }
    }

    public static bool Get(byte aByte, int pos)
    {
        //left-shift 1, then bitwise AND, then check for non-zero
        return ((aByte & (1 << pos)) != 0);
    }

    public static void SetWord(ref uint aByte, int pos, bool value)
    {
        if (value)
        {
            //left-shift 1, then bitwise OR
            aByte = (uint)(aByte | (1 << pos));
        }
        else
        {
            //left-shift 1, then take complement, then bitwise AND
            aByte = (uint)(aByte & ~(1 << pos));
        }
    }

    public static bool GetWord(uint aByte, int pos)
    {
        //left-shift 1, then bitwise AND, then check for non-zero
        return ((aByte & (1 << pos)) != 0);
    }

}

« Last Edit: November 25, 2016, 08:51:06 am by Colonizer »

Offline Colonizer

  • Administrator
  • Newbie
  • *****
  • Posts: 45
    • View Profile
Re: Burster for NPC unit master/slave movements. Requires PHOTON
« Reply #1 on: November 08, 2016, 05:07:36 pm »
Slave part of code:

Extended version. Updated 23.11.2016

Moved lerp routines under FixedUpdate for smooth movements...

Code: [Select]
using System;
using System.Collections.Generic;
///
///
/// Code by Jari Kaija (2016)
///
/// You can use this code freely, but I would like, if you will add my name
/// to your game "Greetings/Coders" list. That's enough for me.
///
/// Usage:
///
/// Add this script to your NPC GameObject. Drag all necessary scripts
/// from your GameObject to this script inspector.
///
/// Remove ALL transform, whatever movement scripts from PhotonView inspector.
/// YOU DON*T NEED THEM ANYMORE. EVER!
///
/// Use ForceAsOwner together with Software master/slave selection. Example in your NPC code:
/// if (isMine)
/// {
///     gameObject.GetComponent<BurstClient>().ForceAsOwner = true;
/// }
///
/// That's all. No more headache.
///
/// Code is self explained. Very easy to understand and modify.
/// This part, what I published are stripped version of my own
/// game version, what have possibilities to add any kind of
/// variables for transferring required data from Master NPC to Slave NPCs.
/// And all of this ON ONE WORKING stream.
///
/// The main reason, why I made this:
///
/// I have a huge legion of soldiers under several troop leaders in my game +
/// lott of workers to carry things and other habitats.
///
/// Photon's (and unity's) streaming SUCKED TOTALLY. My clients
/// incoming buffer were filled and ruined totally and game stopped on all
/// clients. And only one leader and his 35 soldiers. Pathetic....
///
/// So. I made some research and this is conclusion. Totally rewritten
/// "delta stream" style code.
///
/// Enjoy...
///
///
using UnityEngine;

[HelpURL("http://www.thecolonizers.com")]
[RequireComponent(typeof(PhotonView))]

public class BurstClient : MonoBehaviour
{
    public enum _ownerShip
    {
        Auto,
        Software,
        ItsMine,
        ImSlave
    }
    public enum _movements
    {
        None,
        Step,
        Lerp
    }
    public enum _rotations
    {
        None,
        Step,
        Lerp
    }
    public enum _scalings
    {
        None,
        Step,
        Lerp
    }

    public BurstMaster burstMaster;
    public PhotonView photonView;
    public Transform transform;
    public Rigidbody rigidbody;
    public Animation animation;

    public List<GameObject> onOffObjects = new List<GameObject>();
   

    [Tooltip("Force your NPC to Master/Slave with code...")]
    public bool ForceAsOwner;

    [Tooltip("Only for informational use...")]
    public string Whos;

    [Tooltip("Decide, what is this NPC role on your world")]
    public _ownerShip ownerShip;

    [Header("Transferrable data settings for NPC")]
    public _movements movements;
    public _rotations rotations;
    public _scalings scalings;
    [Tooltip("Movement and rotation freezes & UseGravity & isKinematic")]
    public bool sendRigidbody;
    public bool sendAnimation;
    public bool sendActiveOnOff;

    [Tooltip("Speed for movement lerping")]
    [Range(0.1f,10)]
    public float positionSpeed = 1;
    [Tooltip("Speed for rotation lerping")]
    [Range(0.1f, 10)]
    public float rotationSpeed = 1;
    [Tooltip("Speed for local scaling lerping")]
    [Range(0.1f, 10)]
    public float scalingSpeed = 1;

    // Variables for inner use...
    bool imSlave;
    byte rigidBits;
    Vector3 position;
    Vector3 newposition;
    Vector3 rotation;
    Vector3 newrotation;
    Vector3 localScale;
    Vector3 newlocalScale;
    string animation_name = "";
    float lightning;
    uint onOffBits;
    uint tempu;
   

    // Use this for initialization
    void Start()
    {
       
        if (burstMaster == null)
        {
            burstMaster = FindObjectOfType<BurstMaster>(); //  Find("BurstMaster").GetComponent<BurstMaster>();
            if (burstMaster == null)  // Still missing???
            {
                Debug.LogError("BurstMaster gameobject missing. Or haven't BurstMaster script in it!!!");
                return;
            }   
        }
        photonView = gameObject.GetComponentInChildren<PhotonView>(true);
        if (animation != null)
        {
            animation_name = animation.clip.name;
        }
        if (ForceAsOwner)
        {
            photonView.ownershipTransfer = OwnershipOption.Takeover;
            photonView.RequestOwnership();
        }
        burstMaster.addToBursted(photonView.viewID, transform, rigidbody, animation_name, onOffBits);
        lightning = Time.time;
        tempu = checkActives();
        newposition = transform.position;
        newrotation = transform.rotation.eulerAngles;
        newlocalScale = transform.localScale;

    }


    public uint checkActives()
    {
        int count = 0;
        uint result = 0;
       
        foreach (GameObject go in onOffObjects)
        {
            if (go.activeInHierarchy)
            {
                SetWord(ref result, count, true);
            }
            else
            {
                SetWord(ref result, count, false);
            }
            ++count;
        }
        return result;
    }

    public void setActives(uint word)
    {
        int count = 0;
        foreach (GameObject go in onOffObjects)
        {
            if (GetWord(word, count))
            {
                go.gameObject.SetActive(true);
            }
            else
            {
                go.gameObject.SetActive(false);
            }
            ++count;
        }
    }

    void FixedUpdate()
    {
        if (imSlave)
        {
            if (movements == _movements.Lerp)
            {
                transform.position = Vector3.Lerp(transform.position, newposition, Time.deltaTime * this.positionSpeed);
            }
            if (rotations == _rotations.Lerp)
            {
                transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(newrotation.x, newrotation.y, newrotation.z), Time.deltaTime * this.rotationSpeed);
            }
            if (scalings == _scalings.Lerp)
            {
                transform.localScale = Vector3.Lerp(transform.localScale, newlocalScale, Time.deltaTime * this.scalingSpeed);
            }
        }
    }
    // Update is called once per frame
    void Update()
    {

        if (Time.time > lightning + 0.1f)
        {
            if (ownerShip == _ownerShip.Auto)
            {
                if (photonView.isMine)
                {
                    Whos = "It is mine";
                    imSlave = false;
                }
                else
                {
                    Whos = "I'm a slave";
                    imSlave = true;
                }
            }
            else
            if (ownerShip == _ownerShip.Software)
            {
                if (ForceAsOwner)
                {
                    imSlave = false;
                    Whos = "It is mine";
                }
                else
                {
                    imSlave = true;
                    Whos = "I'm a slave";
                }
            }
            else
            if (ownerShip == _ownerShip.ImSlave)
            {
                Whos = "I'm a slave";
                imSlave = true;
            }
            else
            if (ownerShip == _ownerShip.ItsMine)
            {
                Whos = "It is mine";
                imSlave = false;
            }
            if (!imSlave)
            {
                // I'm the king, I'm the master. Slaves obey me!!!
                {
                    if (animation != null) animation_name = GetCurrentPlayingAnimationClip();
                    burstMaster.addBurstData(photonView.viewID, transform, rigidbody, checkActives(), animation_name, movements != _movements.None, rotations != _rotations.None, scalings != _scalings.None, sendRigidbody, sendAnimation, sendActiveOnOff);
                }
            }
            lightning = Time.time;
        }
       
        // I'm a master, so I do things what master normally have...
        if (imSlave)
        {
           
            if (burstMaster.getBurstData(photonView.viewID, out animation_name, out position, out rotation, out localScale, out rigidBits, out onOffBits))
            {
                if (transform != null)
                {
                   
                    if (movements == _movements.Step)
                    {
                        transform.position = position;
                    }
                    if (rotations == _rotations.Step)
                    {
                        transform.rotation = Quaternion.Euler(rotation.x, rotation.y, rotation.z);
                    }
                    if (movements == _movements.Lerp)
                    {
                        newposition = position;
                    }
                    if (rotations == _rotations.Lerp)
                    {
                        newrotation = rotation;
                    }
                    if (scalings == _scalings.Step)
                    {
                        transform.localScale = localScale;
                    }
                    if (scalings == _scalings.Lerp)
                    {
                        newlocalScale = localScale;
                    }
                   
                }

                if (rigidbody != null && sendRigidbody)
                {
                    byte bits = rigidBits;
                    rigidbody.useGravity = Get(bits, 0);
                    rigidbody.isKinematic = Get(bits, 7);
                    Set(ref bits, 0, false);
                    Set(ref bits, 7, false);
                    rigidbody.constraints = RigidbodyConstraints.None + bits;

                    //Constraints as BIT : ENUM - Name
                    // 1 : 2 - FreezePositionX
                    // 2 : 4 - FreezePositionY
                    // 3 : 8 - FreezePositionZ
                    // 4 : 16 - FreezeRotationX
                    // 5 : 32 - FreezeRotationY
                    // 6 : 64 - FreezeRotationZ
                }


                if (animation != null)
                {
                    string animname = GetCurrentPlayingAnimationClip();
                    if (animation_name.CompareTo(animname) != 0)
                    {
                        if (animation_name.Length > 0)
                        {
                            animation.Play(animation_name);
                        }
                    }
                }

                if (sendActiveOnOff)
                {
                    if (tempu != onOffBits)
                    {
                        setActives(onOffBits);
                        tempu = onOffBits;
                    }
                }
               
            }
        }
    }
    /// <summary>
    /// Get currenlty playing animation clip name
    /// </summary>
    /// <returns>Currently playing animation</returns>
    public string GetCurrentPlayingAnimationClip()
    {
        foreach (AnimationState anim in animation)
        {
            if (animation.IsPlaying(anim.name))
            {
                return anim.name;
            }
        }
        return string.Empty;
    }

    //*****************************************************************
    //**** Helpers...                                              ****
    //*****************************************************************

    public static void Set(ref byte aByte, int pos, bool value)
    {
        if (value)
        {
            //left-shift 1, then bitwise OR
            aByte = (byte)(aByte | (1 << pos));
        }
        else
        {
            //left-shift 1, then take complement, then bitwise AND
            aByte = (byte)(aByte & ~(1 << pos));
        }
    }

    public static bool Get(byte aByte, int pos)
    {
        //left-shift 1, then bitwise AND, then check for non-zero
        return ((aByte & (1 << pos)) != 0);
    }

    public static void SetWord(ref uint aByte, int pos, bool value)
    {
        if (value)
        {
            //left-shift 1, then bitwise OR
            aByte = (uint)(aByte | (1 << pos));
        }
        else
        {
            //left-shift 1, then take complement, then bitwise AND
            aByte = (uint)(aByte & ~(1 << pos));
        }
    }

    public static bool GetWord(uint aByte, int pos)
    {
        //left-shift 1, then bitwise AND, then check for non-zero
        return ((aByte & (1 << pos)) != 0);
    }
}

« Last Edit: November 23, 2016, 10:19:17 pm by Colonizer »

Offline Colonizer

  • Administrator
  • Newbie
  • *****
  • Posts: 45
    • View Profile
Re: Burster for NPC unit master/slave movements. Requires PHOTON
« Reply #2 on: November 09, 2016, 05:31:42 pm »
Remember!

"""Add "BurstData" string to your Photon Server Settings RPC list!"""

Above, NOT Required anymore. I switched to event system. A little bit faster
than RPC call.
« Last Edit: November 23, 2016, 12:11:01 am by Colonizer »