關於最近網上謠言傳的很凶的 “太吾繪卷” 遊戲原始碼的問題。
這兩天吵的挺厲害的,我本人覺得喜歡這類題材的人們也可以去支援一下這個遊戲,但是有一點惡意的抨擊別人的程式碼寫得亂,我感到真的沒必要,先想想你自己寫的怎麼樣再來說吧。
當然我這不是為 “太吾繪卷” 洗白,這跟我沒關係(不是一起的),但是我說過我很厭惡裝逼俠,它們都令我都有一點點語言歧視,我可以說我把 “太吾繪卷” 的 .net dlllib 提取出來了(相當於程式碼出來了)但是本人想說,雖然 “太吾” 的程式碼寫得很一般,一些地方也有不少設計不合理的地方,當然這個在不同專案裡面都無法避免,只能說會逐步的進行修復程式碼重構調整,但不至於被網路上瘋傳的那麼差勁,我覺得我們是不是應該尊重一個客觀的事實。
國內能把程式碼到一般水平的人也需要好好碼幾年沉澱一下,追求程式碼 “行雲流水”、“一氣呵成” 那是玩程式碼藝術(質量 >= 90分,>= 95分很難寫,一行程式碼扣腦袋得扣半天),都是一幫牛魔王的人才寫的出來,一般人想想就好了,
當然本人貼出的一部分東西,真偽你們可以找 “太吾繪卷” 的技術團隊論證程式碼的真偽,我覺得這個沒有什麼好裝逼的,雖然搞掉這個東西也沒花到太久的時間,但是這也說明了 “太吾繪卷” 在這塊做的安全性不是很好,當然提高安全的辦法有不少,但這不是我在本人要談到的,我說過跟我一點關係沒有。本人只是單純的看不慣裝逼犯,要裝逼去 java 那邊去,你們一起裝,可勁的裝不要停,停了是罪,停了是惡!
另外本人不會提供程式碼,也不會破解這個遊戲,它跟我沒有任何衝突,另外我本人實在找不到破解這遊戲的一個理由在哪裡,秀技術?算了這東西又不難,對於比我 “高或同層次” 的工程師來說,我這可能是要自己打自己的打臉的節奏~呀(裝逼,秀技術不是這麼秀的);第二我現在一直又氪又肝 “楚留香” 這個遊戲,第三我現在是混 “醫療千秋行業” 的。。。當然玩一個幾十塊錢的單機還想著破解,弄外掛,你們真的也是夠了,有啥意思,除了自慰。。。(發自肺腑)。。。
上面用C/C++寫的程式碼是用於從加密的 “偽dll” 中提取真正的 “.net dlllib”,u3d-csharp 是基於 mono 的體系,而 mono 只支援到 .net 3.5(所以這個dll 工程師是 .net 2.0 的也不足為奇)當然你可以利用 mono 對你 .net dlllib 加密,但是這個東西真的很脆弱,雖然它在不同版本中可能會不一致,但是大體函式的簽名是沒有變的,破掉的方法有幾種,一種是呼叫 XXX【打黑碼,本人不是教你們來玩破解的】 庫載入到程序的模組空間,然後在把它 dump 出來(無論你是通過emit組建,還是直接從模組表中提出)還有就是破解密函式(這個比較省事,需要分析寫的程式碼都會少很多),.... ,另外我想,你們能把 mono 內鏈靜態編譯的話,幾乎就把目前 99% 人砍掉,剩下這批也沒多大心情會去搞你這個玩意,浪費的時間與回報簡直不成正比,當然辦法還有很多增加別人成本,到它不能忍受你就贏了,要想根治是不可能的。。。
本人隨便從 “太吾繪卷” 中摘要一些程式碼吧,它們噴別人的程式碼中帶有 “MonoBehaviour” 我就貼幾個與此相關的程式碼,各位看官自行判斷吧。
BoneFollower:
// Spine.Unity.BoneFollower
using Spine;
using Spine.Unity;
using System;
using UnityEngine;
using UnityEngine.Serialization;
[ExecuteInEditMode]
[AddComponentMenu("Spine/BoneFollower")]
public class BoneFollower : MonoBehaviour
{
public SkeletonRenderer skeletonRenderer;
[SpineBone("", "skeletonRenderer", true, false)]
[SerializeField]
public string boneName;
public bool followZPosition = true;
public bool followBoneRotation = true;
[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
public bool followSkeletonFlip = true;
[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
public bool followLocalScale = false;
[FormerlySerializedAs("resetOnAwake")]
public bool initializeOnAwake = true;
[NonSerialized]
public bool valid;
[NonSerialized]
public Bone bone;
private Transform skeletonTransform;
private bool skeletonTransformIsParent;
public SkeletonRenderer SkeletonRenderer
{
get
{
return skeletonRenderer;
}
set
{
skeletonRenderer = value;
Initialize();
}
}
public bool SetBone(string name)
{
bone = skeletonRenderer.skeleton.FindBone(name);
if (bone != null)
{
boneName = name;
return true;
}
Debug.LogError("Bone not found: " + name, this);
return false;
}
public void Awake()
{
if (initializeOnAwake)
{
Initialize();
}
}
public void HandleRebuildRenderer(SkeletonRenderer skeletonRenderer)
{
Initialize();
}
public void Initialize()
{
bone = null;
valid = ((UnityEngine.Object)skeletonRenderer != (UnityEngine.Object)null && skeletonRenderer.valid);
if (valid)
{
skeletonTransform = skeletonRenderer.transform;
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
skeletonRenderer.OnRebuild += HandleRebuildRenderer;
skeletonTransformIsParent = object.ReferenceEquals(skeletonTransform, base.transform.parent);
if (!string.IsNullOrEmpty(boneName))
{
bone = skeletonRenderer.skeleton.FindBone(boneName);
}
}
}
private void OnDestroy()
{
if ((UnityEngine.Object)skeletonRenderer != (UnityEngine.Object)null)
{
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
}
}
public void LateUpdate()
{
if (!valid)
{
Initialize();
}
else
{
if (bone == null)
{
if (string.IsNullOrEmpty(boneName))
{
return;
}
bone = skeletonRenderer.skeleton.FindBone(boneName);
if (!SetBone(boneName))
{
return;
}
}
Transform transform = base.transform;
Quaternion quaternion;
if (skeletonTransformIsParent)
{
Transform transform2 = transform;
float worldX = bone.worldX;
float worldY = bone.worldY;
float z;
if (followZPosition)
{
z = 0f;
}
else
{
Vector3 localPosition = transform.localPosition;
z = localPosition.z;
}
transform2.localPosition = new Vector3(worldX, worldY, z);
if (followBoneRotation)
{
float num = Mathf.Atan2(bone.c, bone.a) * 0.5f;
if (followLocalScale && bone.scaleX < 0f)
{
num += 1.57079637f;
}
quaternion = default(Quaternion);
Quaternion localRotation = quaternion;
localRotation.z = Mathf.Sin(num);
localRotation.w = Mathf.Cos(num);
transform.localRotation = localRotation;
}
}
else
{
Vector3 position = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
if (!followZPosition)
{
Vector3 position2 = transform.position;
position.z = position2.z;
}
float num2 = bone.WorldRotationX;
Transform parent = transform.parent;
if ((UnityEngine.Object)parent != (UnityEngine.Object)null)
{
Matrix4x4 localToWorldMatrix = parent.localToWorldMatrix;
if (localToWorldMatrix.m00 * localToWorldMatrix.m11 - localToWorldMatrix.m01 * localToWorldMatrix.m10 < 0f)
{
num2 = 0f - num2;
}
}
if (followBoneRotation)
{
quaternion = skeletonTransform.rotation;
Vector3 eulerAngles = quaternion.eulerAngles;
if (followLocalScale && bone.scaleX < 0f)
{
num2 += 180f;
}
transform.SetPositionAndRotation(position, Quaternion.Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z + num2));
}
else
{
transform.position = position;
}
}
Vector3 localScale = (!followLocalScale) ? new Vector3(1f, 1f, 1f) : new Vector3(bone.scaleX, bone.scaleY, 1f);
if (followSkeletonFlip)
{
localScale.y *= ((!(bone.skeleton.flipX ^ bone.skeleton.flipY)) ? 1f : (-1f));
}
transform.localScale = localScale;
}
}
}
SkeletonUtility:
// Spine.Unity.SkeletonUtility
using Spine;
using Spine.Unity;
using System;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(ISkeletonAnimation))]
[ExecuteInEditMode]
public class SkeletonUtility : MonoBehaviour
{
public delegate void SkeletonUtilityDelegate();
public Transform boneRoot;
[HideInInspector]
public SkeletonRenderer skeletonRenderer;
[HideInInspector]
public ISkeletonAnimation skeletonAnimation;
[NonSerialized]
public List<SkeletonUtilityBone> utilityBones = new List<SkeletonUtilityBone>();
[NonSerialized]
public List<SkeletonUtilityConstraint> utilityConstraints = new List<SkeletonUtilityConstraint>();
protected bool hasTransformBones;
protected bool hasUtilityConstraints;
protected bool needToReprocessBones;
public event SkeletonUtilityDelegate OnReset;
public static PolygonCollider2D AddBoundingBoxGameObject(Skeleton skeleton, string skinName, string slotName, string attachmentName, Transform parent, bool isTrigger = true)
{
Skin skin = (!string.IsNullOrEmpty(skinName)) ? skeleton.data.FindSkin(skinName) : skeleton.data.defaultSkin;
if (skin != null)
{
Attachment attachment = skin.GetAttachment(skeleton.FindSlotIndex(slotName), attachmentName);
if (attachment != null)
{
BoundingBoxAttachment boundingBoxAttachment = attachment as BoundingBoxAttachment;
if (boundingBoxAttachment == null)
{
Debug.LogFormat("Attachment '{0}' was not a Bounding Box.", attachmentName);
return null;
}
Slot slot = skeleton.FindSlot(slotName);
return AddBoundingBoxGameObject(boundingBoxAttachment.Name, boundingBoxAttachment, slot, parent, isTrigger);
}
Debug.LogFormat("Attachment in slot '{0}' named '{1}' not found in skin '{2}'.", slotName, attachmentName, skin.name);
return null;
}
Debug.LogError("Skin " + skinName + " not found!");
return null;
}
public static PolygonCollider2D AddBoundingBoxGameObject(string name, BoundingBoxAttachment box, Slot slot, Transform parent, bool isTrigger = true)
{
GameObject gameObject = new GameObject("[BoundingBox]" + ((!string.IsNullOrEmpty(name)) ? name : box.Name));
Transform transform = gameObject.transform;
transform.parent = parent;
transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.identity;
transform.localScale = Vector3.one;
return AddBoundingBoxAsComponent(box, slot, gameObject, isTrigger, true, 0f);
}
public static PolygonCollider2D AddBoundingBoxAsComponent(BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true, bool isKinematic = true, float gravityScale = 0f)
{
if (box != null)
{
if (slot.bone != slot.Skeleton.RootBone)
{
Rigidbody2D component = gameObject.GetComponent<Rigidbody2D>();
if ((UnityEngine.Object)component == (UnityEngine.Object)null)
{
component = gameObject.AddComponent<Rigidbody2D>();
component.isKinematic = isKinematic;
component.gravityScale = gravityScale;
}
}
PolygonCollider2D polygonCollider2D = gameObject.AddComponent<PolygonCollider2D>();
polygonCollider2D.isTrigger = isTrigger;
SetColliderPointsLocal(polygonCollider2D, slot, box);
return polygonCollider2D;
}
return null;
}
public static void SetColliderPointsLocal(PolygonCollider2D collider, Slot slot, BoundingBoxAttachment box)
{
if (box != null)
{
if (box.IsWeighted())
{
Debug.LogWarning("UnityEngine.PolygonCollider2D does not support weighted or animated points. Collider points will not be animated and may have incorrect orientation. If you want to use it as a collider, please remove weights and animations from the bounding box in Spine editor.");
}
Vector2[] localVertices = box.GetLocalVertices(slot, null);
collider.SetPath(0, localVertices);
}
}
public static Bounds GetBoundingBoxBounds(BoundingBoxAttachment boundingBox, float depth = 0f)
{
float[] vertices = boundingBox.Vertices;
int num = vertices.Length;
Bounds result = default(Bounds);
result.center = new Vector3(vertices[0], vertices[1], 0f);
for (int i = 2; i < num; i += 2)
{
result.Encapsulate(new Vector3(vertices[i], vertices[i + 1], 0f));
}
Vector3 size = result.size;
size.z = depth;
result.size = size;
return result;
}
private void Update()
{
Skeleton skeleton = skeletonRenderer.skeleton;
if ((UnityEngine.Object)boneRoot != (UnityEngine.Object)null && skeleton != null)
{
Vector3 one = Vector3.one;
if (skeleton.FlipX)
{
one.x = -1f;
}
if (skeleton.FlipY)
{
one.y = -1f;
}
boneRoot.localScale = one;
}
}
private void OnEnable()
{
if ((UnityEngine.Object)skeletonRenderer == (UnityEngine.Object)null)
{
skeletonRenderer = GetComponent<SkeletonRenderer>();
}
if (skeletonAnimation == null)
{
skeletonAnimation = GetComponent<SkeletonAnimation>();
if (skeletonAnimation == null)
{
skeletonAnimation = GetComponent<SkeletonAnimator>();
}
}
skeletonRenderer.OnRebuild -= HandleRendererReset;
skeletonRenderer.OnRebuild += HandleRendererReset;
if (skeletonAnimation != null)
{
skeletonAnimation.UpdateLocal -= UpdateLocal;
skeletonAnimation.UpdateLocal += UpdateLocal;
}
CollectBones();
}
private void Start()
{
CollectBones();
}
private void OnDisable()
{
skeletonRenderer.OnRebuild -= HandleRendererReset;
if (skeletonAnimation != null)
{
skeletonAnimation.UpdateLocal -= UpdateLocal;
skeletonAnimation.UpdateWorld -= UpdateWorld;
skeletonAnimation.UpdateComplete -= UpdateComplete;
}
}
private void HandleRendererReset(SkeletonRenderer r)
{
if (this.OnReset != null)
{
this.OnReset();
}
CollectBones();
}
public void RegisterBone(SkeletonUtilityBone bone)
{
if (!utilityBones.Contains(bone))
{
utilityBones.Add(bone);
needToReprocessBones = true;
}
}
public void UnregisterBone(SkeletonUtilityBone bone)
{
utilityBones.Remove(bone);
}
public void RegisterConstraint(SkeletonUtilityConstraint constraint)
{
if (!utilityConstraints.Contains(constraint))
{
utilityConstraints.Add(constraint);
needToReprocessBones = true;
}
}
public void UnregisterConstraint(SkeletonUtilityConstraint constraint)
{
utilityConstraints.Remove(constraint);
}
public void CollectBones()
{
Skeleton skeleton = skeletonRenderer.skeleton;
if (skeleton != null)
{
if ((UnityEngine.Object)boneRoot != (UnityEngine.Object)null)
{
List<object> list = new List<object>();
ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
int i = 0;
for (int count = ikConstraints.Count; i < count; i++)
{
list.Add(ikConstraints.Items[i].target);
}
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
int j = 0;
for (int count2 = transformConstraints.Count; j < count2; j++)
{
list.Add(transformConstraints.Items[j].target);
}
List<SkeletonUtilityBone> list2 = utilityBones;
int k = 0;
for (int count3 = list2.Count; k < count3; k++)
{
SkeletonUtilityBone skeletonUtilityBone = list2[k];
if (skeletonUtilityBone.bone != null)
{
hasTransformBones |= (skeletonUtilityBone.mode == SkeletonUtilityBone.Mode.Override);
hasUtilityConstraints |= list.Contains(skeletonUtilityBone.bone);
}
}
hasUtilityConstraints |= (utilityConstraints.Count > 0);
if (skeletonAnimation != null)
{
skeletonAnimation.UpdateWorld -= UpdateWorld;
skeletonAnimation.UpdateComplete -= UpdateComplete;
if (hasTransformBones || hasUtilityConstraints)
{
skeletonAnimation.UpdateWorld += UpdateWorld;
}
if (hasUtilityConstraints)
{
skeletonAnimation.UpdateComplete += UpdateComplete;
}
}
needToReprocessBones = false;
}
else
{
utilityBones.Clear();
utilityConstraints.Clear();
}
}
}
private void UpdateLocal(ISkeletonAnimation anim)
{
if (needToReprocessBones)
{
CollectBones();
}
List<SkeletonUtilityBone> list = utilityBones;
if (list != null)
{
int i = 0;
for (int count = list.Count; i < count; i++)
{
list[i].transformLerpComplete = false;
}
UpdateAllBones(SkeletonUtilityBone.UpdatePhase.Local);
}
}
private void UpdateWorld(ISkeletonAnimation anim)
{
UpdateAllBones(SkeletonUtilityBone.UpdatePhase.World);
int i = 0;
for (int count = utilityConstraints.Count; i < count; i++)
{
utilityConstraints[i].DoUpdate();
}
}
private void UpdateComplete(ISkeletonAnimation anim)
{
UpdateAllBones(SkeletonUtilityBone.UpdatePhase.Complete);
}
private void UpdateAllBones(SkeletonUtilityBone.UpdatePhase phase)
{
if ((UnityEngine.Object)boneRoot == (UnityEngine.Object)null)
{
CollectBones();
}
List<SkeletonUtilityBone> list = utilityBones;
if (list != null)
{
int i = 0;
for (int count = list.Count; i < count; i++)
{
list[i].DoUpdate(phase);
}
}
}
public Transform GetBoneRoot()
{
if (!((UnityEngine.Object)boneRoot != (UnityEngine.Object)null))
{
boneRoot = new GameObject("SkeletonUtility-Root").transform;
boneRoot.parent = base.transform;
boneRoot.localPosition = Vector3.zero;
boneRoot.localRotation = Quaternion.identity;
boneRoot.localScale = Vector3.one;
return boneRoot;
}
return boneRoot;
}
public GameObject SpawnRoot(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
{
GetBoneRoot();
Skeleton skeleton = skeletonRenderer.skeleton;
GameObject result = SpawnBone(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
CollectBones();
return result;
}
public GameObject SpawnHierarchy(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
{
GetBoneRoot();
Skeleton skeleton = skeletonRenderer.skeleton;
GameObject result = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
CollectBones();
return result;
}
public GameObject SpawnBoneRecursively(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
{
GameObject gameObject = SpawnBone(bone, parent, mode, pos, rot, sca);
ExposedList<Bone> children = bone.Children;
int i = 0;
for (int count = children.Count; i < count; i++)
{
Bone bone2 = children.Items[i];
SpawnBoneRecursively(bone2, gameObject.transform, mode, pos, rot, sca);
}
return gameObject;
}
public GameObject SpawnBone(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
{
GameObject gameObject = new GameObject(bone.Data.Name);
gameObject.transform.parent = parent;
SkeletonUtilityBone skeletonUtilityBone = gameObject.AddComponent<SkeletonUtilityBone>();
skeletonUtilityBone.skeletonUtility = this;
skeletonUtilityBone.position = pos;
skeletonUtilityBone.rotation = rot;
skeletonUtilityBone.scale = sca;
skeletonUtilityBone.mode = mode;
skeletonUtilityBone.zPosition = true;
skeletonUtilityBone.Reset();
skeletonUtilityBone.bone = bone;
skeletonUtilityBone.boneName = bone.Data.Name;
skeletonUtilityBone.valid = true;
if (mode == SkeletonUtilityBone.Mode.Override)
{
if (rot)
{
gameObject.transform.localRotation = Quaternion.Euler(0f, 0f, skeletonUtilityBone.bone.AppliedRotation);
}
if (pos)
{
gameObject.transform.localPosition = new Vector3(skeletonUtilityBone.bone.X, skeletonUtilityBone.bone.Y, 0f);
}
gameObject.transform.localScale = new Vector3(skeletonUtilityBone.bone.scaleX, skeletonUtilityBone.bone.scaleY, 0f);
}
return gameObject;
}
}
PointFollower:
// Spine.Unity.PointFollower
using Spine;
using Spine.Unity;
using UnityEngine;
[ExecuteInEditMode]
[AddComponentMenu("Spine/Point Follower")]
public class PointFollower : MonoBehaviour, IHasSkeletonRenderer, IHasSkeletonComponent
{
[SerializeField]
public SkeletonRenderer skeletonRenderer;
[SpineSlot("", "skeletonRenderer", false, true, false)]
public string slotName;
[SpineAttachment(true, false, false, "slotName", "skeletonRenderer", "", true, true)]
public string pointAttachmentName;
public bool followRotation = true;
public bool followSkeletonFlip = true;
public bool followSkeletonZPosition = false;
private Transform skeletonTransform;
private bool skeletonTransformIsParent;
private PointAttachment point;
private Bone bone;
private bool valid;
public SkeletonRenderer SkeletonRenderer
{
get
{
return skeletonRenderer;
}
}
public ISkeletonComponent SkeletonComponent
{
get
{
return skeletonRenderer;
}
}
public bool IsValid
{
get
{
return valid;
}
}
public void Initialize()
{
valid = ((Object)skeletonRenderer != (Object)null && skeletonRenderer.valid);
if (valid)
{
UpdateReferences();
}
}
private void HandleRebuildRenderer(SkeletonRenderer skeletonRenderer)
{
Initialize();
}
private void UpdateReferences()
{
skeletonTransform = skeletonRenderer.transform;
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
skeletonRenderer.OnRebuild += HandleRebuildRenderer;
skeletonTransformIsParent = object.ReferenceEquals(skeletonTransform, base.transform.parent);
bone = null;
point = null;
if (!string.IsNullOrEmpty(pointAttachmentName))
{
Skeleton skeleton = skeletonRenderer.skeleton;
int num = skeleton.FindSlotIndex(slotName);
if (num >= 0)
{
Slot slot = skeleton.slots.Items[num];
bone = slot.bone;
point = (skeleton.GetAttachment(num, pointAttachmentName) as PointAttachment);
}
}
}
public void LateUpdate()
{
if (point == null)
{
if (string.IsNullOrEmpty(pointAttachmentName))
{
return;
}
UpdateReferences();
if (point == null)
{
return;
}
}
Vector2 vector = default(Vector2);
point.ComputeWorldPosition(bone, out vector.x, out vector.y);
float num = point.ComputeWorldRotation(bone);
Transform transform = base.transform;
Quaternion quaternion;
if (skeletonTransformIsParent)
{
Transform transform2 = transform;
float x = vector.x;
float y = vector.y;
float z;
if (followSkeletonZPosition)
{
z = 0f;
}
else
{
Vector3 localPosition = transform.localPosition;
z = localPosition.z;
}
transform2.localPosition = new Vector3(x, y, z);
if (followRotation)
{
float f = num * 0.5f * 0.0174532924f;
quaternion = default(Quaternion);
Quaternion localRotation = quaternion;
localRotation.z = Mathf.Sin(f);
localRotation.w = Mathf.Cos(f);
transform.localRotation = localRotation;
}
}
else
{
Vector3 position = skeletonTransform.TransformPoint(new Vector3(vector.x, vector.y, 0f));
if (!followSkeletonZPosition)
{
Vector3 position2 = transform.position;
position.z = position2.z;
}
Transform parent = transform.parent;
if ((Object)parent != (Object)null)
{
Matrix4x4 localToWorldMatrix = parent.localToWorldMatrix;
if (localToWorldMatrix.m00 * localToWorldMatrix.m11 - localToWorldMatrix.m01 * localToWorldMatrix.m10 < 0f)
{
num = 0f - num;
}
}
if (followRotation)
{
quaternion = skeletonTransform.rotation;
Vector3 eulerAngles = quaternion.eulerAngles;
transform.SetPositionAndRotation(position, Quaternion.Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z + num));
}
else
{
transform.position = position;
}
}
if (followSkeletonFlip)
{
Vector3 localScale = transform.localScale;
localScale.y = Mathf.Abs(localScale.y) * ((!(bone.skeleton.flipX ^ bone.skeleton.flipY)) ? 1f : (-1f));
transform.localScale = localScale;
}
}
}