commit 90687b56a41e8d10e5c8a936069d16374a929e3e
Author: VirtuBrick <139835327+VirtuBrick@users.noreply.github.com>
Date: Thu Feb 22 12:15:30 2024 -0500
Initial commit
diff --git a/Client2014/AppSettings.xml b/Client2014/AppSettings.xml
new file mode 100644
index 0000000..f51afc2
--- /dev/null
+++ b/Client2014/AppSettings.xml
@@ -0,0 +1,5 @@
+
+
+ content
+ http://www.syntax.eco
+
diff --git a/Client2014/Log.dll b/Client2014/Log.dll
new file mode 100644
index 0000000..ec697f0
Binary files /dev/null and b/Client2014/Log.dll differ
diff --git a/Client2014/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest b/Client2014/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest
new file mode 100644
index 0000000..41623b1
--- /dev/null
+++ b/Client2014/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/Client2014/Microsoft.VC90.CRT/msvcm90.dll b/Client2014/Microsoft.VC90.CRT/msvcm90.dll
new file mode 100644
index 0000000..b9cb123
Binary files /dev/null and b/Client2014/Microsoft.VC90.CRT/msvcm90.dll differ
diff --git a/Client2014/Microsoft.VC90.CRT/msvcp90.dll b/Client2014/Microsoft.VC90.CRT/msvcp90.dll
new file mode 100644
index 0000000..6b07c75
Binary files /dev/null and b/Client2014/Microsoft.VC90.CRT/msvcp90.dll differ
diff --git a/Client2014/Microsoft.VC90.CRT/msvcr90.dll b/Client2014/Microsoft.VC90.CRT/msvcr90.dll
new file mode 100644
index 0000000..a68249a
Binary files /dev/null and b/Client2014/Microsoft.VC90.CRT/msvcr90.dll differ
diff --git a/Client2014/Microsoft.VC90.MFC/Microsoft.VC90.MFC.manifest b/Client2014/Microsoft.VC90.MFC/Microsoft.VC90.MFC.manifest
new file mode 100644
index 0000000..0184745
--- /dev/null
+++ b/Client2014/Microsoft.VC90.MFC/Microsoft.VC90.MFC.manifest
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/Client2014/Microsoft.VC90.MFC/mfc90.dll b/Client2014/Microsoft.VC90.MFC/mfc90.dll
new file mode 100644
index 0000000..31fb2b3
Binary files /dev/null and b/Client2014/Microsoft.VC90.MFC/mfc90.dll differ
diff --git a/Client2014/Microsoft.VC90.MFC/mfcm90.dll b/Client2014/Microsoft.VC90.MFC/mfcm90.dll
new file mode 100644
index 0000000..55b19e3
Binary files /dev/null and b/Client2014/Microsoft.VC90.MFC/mfcm90.dll differ
diff --git a/Client2014/Microsoft.VC90.OPENMP/Microsoft.VC90.OpenMP.manifest b/Client2014/Microsoft.VC90.OPENMP/Microsoft.VC90.OpenMP.manifest
new file mode 100644
index 0000000..213b1d7
--- /dev/null
+++ b/Client2014/Microsoft.VC90.OPENMP/Microsoft.VC90.OpenMP.manifest
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/Client2014/Microsoft.VC90.OPENMP/vcomp90.dll b/Client2014/Microsoft.VC90.OPENMP/vcomp90.dll
new file mode 100644
index 0000000..cf7c805
Binary files /dev/null and b/Client2014/Microsoft.VC90.OPENMP/vcomp90.dll differ
diff --git a/Client2014/NPRobloxProxy.dll b/Client2014/NPRobloxProxy.dll
new file mode 100644
index 0000000..811eb6c
Binary files /dev/null and b/Client2014/NPRobloxProxy.dll differ
diff --git a/Client2014/PlatformContent/pc/textures/aluminum/diffuse.dds b/Client2014/PlatformContent/pc/textures/aluminum/diffuse.dds
new file mode 100644
index 0000000..fee64f0
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/aluminum/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/aluminum/normal.dds b/Client2014/PlatformContent/pc/textures/aluminum/normal.dds
new file mode 100644
index 0000000..30614cd
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/aluminum/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/aluminum/normaldetail.dds b/Client2014/PlatformContent/pc/textures/aluminum/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/aluminum/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/aluminum/specular.dds b/Client2014/PlatformContent/pc/textures/aluminum/specular.dds
new file mode 100644
index 0000000..0473951
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/aluminum/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/brick/diffuse.dds b/Client2014/PlatformContent/pc/textures/brick/diffuse.dds
new file mode 100644
index 0000000..7115e54
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/brick/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/brick/normal.dds b/Client2014/PlatformContent/pc/textures/brick/normal.dds
new file mode 100644
index 0000000..f42c2e6
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/brick/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/brick/normaldetail.dds b/Client2014/PlatformContent/pc/textures/brick/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/brick/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/brick/specular.dds b/Client2014/PlatformContent/pc/textures/brick/specular.dds
new file mode 100644
index 0000000..b346190
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/brick/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/concrete/diffuse.dds b/Client2014/PlatformContent/pc/textures/concrete/diffuse.dds
new file mode 100644
index 0000000..2dd4e21
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/concrete/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/concrete/normal.dds b/Client2014/PlatformContent/pc/textures/concrete/normal.dds
new file mode 100644
index 0000000..72149f9
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/concrete/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/concrete/normaldetail.dds b/Client2014/PlatformContent/pc/textures/concrete/normaldetail.dds
new file mode 100644
index 0000000..03b0daa
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/concrete/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/concrete/specular.dds b/Client2014/PlatformContent/pc/textures/concrete/specular.dds
new file mode 100644
index 0000000..6b22d02
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/concrete/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/diamondplate/diffuse.dds b/Client2014/PlatformContent/pc/textures/diamondplate/diffuse.dds
new file mode 100644
index 0000000..2184b3f
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/diamondplate/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/diamondplate/normal.dds b/Client2014/PlatformContent/pc/textures/diamondplate/normal.dds
new file mode 100644
index 0000000..234aa72
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/diamondplate/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/diamondplate/normaldetail.dds b/Client2014/PlatformContent/pc/textures/diamondplate/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/diamondplate/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/diamondplate/specular.dds b/Client2014/PlatformContent/pc/textures/diamondplate/specular.dds
new file mode 100644
index 0000000..8646e2d
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/diamondplate/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/fabric/diffuse.dds b/Client2014/PlatformContent/pc/textures/fabric/diffuse.dds
new file mode 100644
index 0000000..101e832
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/fabric/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/fabric/normal.dds b/Client2014/PlatformContent/pc/textures/fabric/normal.dds
new file mode 100644
index 0000000..ffe776c
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/fabric/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/fabric/normaldetail.dds b/Client2014/PlatformContent/pc/textures/fabric/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/fabric/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/fabric/specular.dds b/Client2014/PlatformContent/pc/textures/fabric/specular.dds
new file mode 100644
index 0000000..20eb572
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/fabric/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/granite/diffuse.dds b/Client2014/PlatformContent/pc/textures/granite/diffuse.dds
new file mode 100644
index 0000000..5ed1b7a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/granite/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/granite/normal.dds b/Client2014/PlatformContent/pc/textures/granite/normal.dds
new file mode 100644
index 0000000..d3b818f
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/granite/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/granite/normaldetail.dds b/Client2014/PlatformContent/pc/textures/granite/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/granite/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/granite/specular.dds b/Client2014/PlatformContent/pc/textures/granite/specular.dds
new file mode 100644
index 0000000..cef4a01
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/granite/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/grass/diffuse.dds b/Client2014/PlatformContent/pc/textures/grass/diffuse.dds
new file mode 100644
index 0000000..2907e38
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/grass/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/grass/normal.dds b/Client2014/PlatformContent/pc/textures/grass/normal.dds
new file mode 100644
index 0000000..81720c5
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/grass/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/grass/normaldetail.dds b/Client2014/PlatformContent/pc/textures/grass/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/grass/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/grass/specular.dds b/Client2014/PlatformContent/pc/textures/grass/specular.dds
new file mode 100644
index 0000000..183463a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/grass/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/ice/diffuse.dds b/Client2014/PlatformContent/pc/textures/ice/diffuse.dds
new file mode 100644
index 0000000..fee64f0
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/ice/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/ice/normal.dds b/Client2014/PlatformContent/pc/textures/ice/normal.dds
new file mode 100644
index 0000000..87c01dd
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/ice/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/ice/normaldetail.dds b/Client2014/PlatformContent/pc/textures/ice/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/ice/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/ice/specular.dds b/Client2014/PlatformContent/pc/textures/ice/specular.dds
new file mode 100644
index 0000000..6d5c917
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/ice/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/marble/diffuse.dds b/Client2014/PlatformContent/pc/textures/marble/diffuse.dds
new file mode 100644
index 0000000..894dcc2
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/marble/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/marble/normal.dds b/Client2014/PlatformContent/pc/textures/marble/normal.dds
new file mode 100644
index 0000000..cba80e1
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/marble/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/marble/normaldetail.dds b/Client2014/PlatformContent/pc/textures/marble/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/marble/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/marble/specular.dds b/Client2014/PlatformContent/pc/textures/marble/specular.dds
new file mode 100644
index 0000000..085525a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/marble/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/pebble/diffuse.dds b/Client2014/PlatformContent/pc/textures/pebble/diffuse.dds
new file mode 100644
index 0000000..c5b849f
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/pebble/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/pebble/normal.dds b/Client2014/PlatformContent/pc/textures/pebble/normal.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/pebble/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/pebble/normaldetail.dds b/Client2014/PlatformContent/pc/textures/pebble/normaldetail.dds
new file mode 100644
index 0000000..03b0daa
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/pebble/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/pebble/specular.dds b/Client2014/PlatformContent/pc/textures/pebble/specular.dds
new file mode 100644
index 0000000..6b22d02
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/pebble/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/plastic/diffuse.dds b/Client2014/PlatformContent/pc/textures/plastic/diffuse.dds
new file mode 100644
index 0000000..f9a20d9
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/plastic/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/plastic/normal.dds b/Client2014/PlatformContent/pc/textures/plastic/normal.dds
new file mode 100644
index 0000000..ba5c24f
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/plastic/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/plastic/normaldetail.dds b/Client2014/PlatformContent/pc/textures/plastic/normaldetail.dds
new file mode 100644
index 0000000..79db22a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/plastic/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/reflection.dds b/Client2014/PlatformContent/pc/textures/reflection.dds
new file mode 100644
index 0000000..b5bff8e
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/reflection.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/rust/diffuse.dds b/Client2014/PlatformContent/pc/textures/rust/diffuse.dds
new file mode 100644
index 0000000..5c387f0
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/rust/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/rust/normal.dds b/Client2014/PlatformContent/pc/textures/rust/normal.dds
new file mode 100644
index 0000000..4a20383
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/rust/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/rust/normaldetail.dds b/Client2014/PlatformContent/pc/textures/rust/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/rust/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/rust/specular.dds b/Client2014/PlatformContent/pc/textures/rust/specular.dds
new file mode 100644
index 0000000..f148de9
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/rust/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/sand/diffuse.dds b/Client2014/PlatformContent/pc/textures/sand/diffuse.dds
new file mode 100644
index 0000000..20e8b6d
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sand/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/sand/normal.dds b/Client2014/PlatformContent/pc/textures/sand/normal.dds
new file mode 100644
index 0000000..fb5b3b4
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sand/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/sand/normaldetail.dds b/Client2014/PlatformContent/pc/textures/sand/normaldetail.dds
new file mode 100644
index 0000000..b878e92
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sand/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/sand/specular.dds b/Client2014/PlatformContent/pc/textures/sand/specular.dds
new file mode 100644
index 0000000..6efec1b
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sand/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_bk.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_bk.tex
new file mode 100644
index 0000000..fcdd232
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_bk.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_dn.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_dn.tex
new file mode 100644
index 0000000..d63e52d
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_dn.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_ft.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_ft.tex
new file mode 100644
index 0000000..215b51b
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_ft.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_lf.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_lf.tex
new file mode 100644
index 0000000..a096acf
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_lf.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_rt.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_rt.tex
new file mode 100644
index 0000000..6c0aaf1
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_rt.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/sky/sky512_up.tex b/Client2014/PlatformContent/pc/textures/sky/sky512_up.tex
new file mode 100644
index 0000000..a973654
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/sky/sky512_up.tex differ
diff --git a/Client2014/PlatformContent/pc/textures/slate/diffuse.dds b/Client2014/PlatformContent/pc/textures/slate/diffuse.dds
new file mode 100644
index 0000000..3ccb456
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/slate/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/slate/normal.dds b/Client2014/PlatformContent/pc/textures/slate/normal.dds
new file mode 100644
index 0000000..dc94035
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/slate/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/slate/normaldetail.dds b/Client2014/PlatformContent/pc/textures/slate/normaldetail.dds
new file mode 100644
index 0000000..e8faa22
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/slate/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/slate/specular.dds b/Client2014/PlatformContent/pc/textures/slate/specular.dds
new file mode 100644
index 0000000..0a44f39
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/slate/specular.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/studs.dds b/Client2014/PlatformContent/pc/textures/studs.dds
new file mode 100644
index 0000000..525b972
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/studs.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/terrain/diffuse.dds b/Client2014/PlatformContent/pc/textures/terrain/diffuse.dds
new file mode 100644
index 0000000..ba03a1d
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/terrain/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/terrain/diffusefar.dds b/Client2014/PlatformContent/pc/textures/terrain/diffusefar.dds
new file mode 100644
index 0000000..d8a7981
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/terrain/diffusefar.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0001.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0001.dds
new file mode 100644
index 0000000..2dec827
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0001.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0002.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0002.dds
new file mode 100644
index 0000000..82f8b8e
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0002.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0003.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0003.dds
new file mode 100644
index 0000000..aa094de
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0003.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0004.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0004.dds
new file mode 100644
index 0000000..0723462
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0004.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0005.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0005.dds
new file mode 100644
index 0000000..661dc6e
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0005.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0006.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0006.dds
new file mode 100644
index 0000000..d2ea2db
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0006.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0007.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0007.dds
new file mode 100644
index 0000000..8087f89
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0007.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0008.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0008.dds
new file mode 100644
index 0000000..4b38726
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0008.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0009.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0009.dds
new file mode 100644
index 0000000..cfe56b2
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0009.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0010.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0010.dds
new file mode 100644
index 0000000..97a1a36
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0010.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0011.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0011.dds
new file mode 100644
index 0000000..148697a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0011.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0012.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0012.dds
new file mode 100644
index 0000000..c86b5cf
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0012.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0013.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0013.dds
new file mode 100644
index 0000000..6feda1c
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0013.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0014.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0014.dds
new file mode 100644
index 0000000..ddc1586
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0014.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0015.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0015.dds
new file mode 100644
index 0000000..4c34f67
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0015.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0016.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0016.dds
new file mode 100644
index 0000000..e87c2d6
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0016.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0017.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0017.dds
new file mode 100644
index 0000000..c6ad2ec
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0017.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0018.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0018.dds
new file mode 100644
index 0000000..0c60ff4
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0018.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0019.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0019.dds
new file mode 100644
index 0000000..8a9848c
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0019.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0020.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0020.dds
new file mode 100644
index 0000000..b5e8d79
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0020.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0021.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0021.dds
new file mode 100644
index 0000000..750ad8a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0021.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0022.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0022.dds
new file mode 100644
index 0000000..7473007
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0022.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0023.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0023.dds
new file mode 100644
index 0000000..6acff51
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0023.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0024.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0024.dds
new file mode 100644
index 0000000..95d5fe5
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0024.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/water/a/RealWave_0025.dds b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0025.dds
new file mode 100644
index 0000000..f74a8ec
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/water/a/RealWave_0025.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/wood/diffuse.dds b/Client2014/PlatformContent/pc/textures/wood/diffuse.dds
new file mode 100644
index 0000000..db2c2fb
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/wood/diffuse.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/wood/normal.dds b/Client2014/PlatformContent/pc/textures/wood/normal.dds
new file mode 100644
index 0000000..e92f07a
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/wood/normal.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/wood/normaldetail.dds b/Client2014/PlatformContent/pc/textures/wood/normaldetail.dds
new file mode 100644
index 0000000..2d9f2bc
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/wood/normaldetail.dds differ
diff --git a/Client2014/PlatformContent/pc/textures/wood/specular.dds b/Client2014/PlatformContent/pc/textures/wood/specular.dds
new file mode 100644
index 0000000..9929b34
Binary files /dev/null and b/Client2014/PlatformContent/pc/textures/wood/specular.dds differ
diff --git a/Client2014/ReflectionMetadata.xml b/Client2014/ReflectionMetadata.xml
new file mode 100644
index 0000000..6410516
--- /dev/null
+++ b/Client2014/ReflectionMetadata.xml
@@ -0,0 +1,3752 @@
+
+ -
+
+
-
+
+ BindableFunction
+ Allow functions defined in one script to be called by another script
+ 4
+ 66
+
+
+
-
+
-
+
+ Invoke
+ Causes the function assigned to OnInvoke to be called. Arguments passed to this function get passed to OnInvoke function.
+
+
+
+ -
+
-
+
+ OnInvoke
+ Should be defined as a function. This function is called when Invoke() is called. Number of arguments is variable.
+
+
+
+
+ -
+
+ BindableEvent
+ Allow events defined in one script to be subscribed to by another script
+
+ 5
+ 67
+
+
-
+
-
+
+ Fire
+ Used to make the custom event fire (see Event for more info). Arguments can be variable length.
+
+
+
+ -
+
-
+
+ Event
+ This event fires when the Fire() method is used. Receives the variable length arguments from Fire().
+
+
+
+
+ -
+
+ TouchTransmitter
+ Used by networking and replication code to transmit touch events - no other purpose
+
+ false
+ 3
+ 37
+
+
+ -
+
+ ForceField
+ Prevents joint breakage from explosions, and stops Humanoids from taking damage
+ 3
+ 37
+
+
+ -
+
+ PluginManager
+
+
+
+ -
+
+ TeleportService
+ Allows players to seamlessly leave a game and join another
+
+
+ -
+
+ StudioTool
+
+
+
+ -
+
+ Plugin
+
+
+
+ -
+
+ PluginMouse
+
+
+
+ -
+
+ Glue
+
+
+ -
+
+ CollectionService
+
+
+ -
+
+ JointsService
+
+
+ -
+
+ BadgeService
+
+
+ -
+
+ LogService
+
+
+ -
+
+ AssetService
+ A service used to set and get information about assets stored on the Roblox website.
+
+
-
+
-
+
+ RevertAsset
+ Reverts a given place id to the version number provided. Returns true if successful on reverting, false otherwise.
+
+
+ -
+
+ SetPlacePermissions
+ Sets the permissions for a placeID to the place accessType. An optional table (inviteList) can be included that will set the accessType for only the player names provided. The table should be set up as an array of usernames (strings).
+
+
+ -
+
+ GetPlacePermissions
+ Given a placeID, this function will return a table with the permissions of the place. Useful for determining what kind of permissions a particular user may have for a place.
+
+
+ -
+
+ GetAssetVersions
+ Given a placeID, this function will return a table with the version info of the place. An optional arg of page number can be used to page through all revisions (a single page may hold about 50 revisions).
+
+
+ -
+
+ GetCreatorAssetID
+ Given a creationID, this function will return the asset that created the creationID. If no other asset created the given creationID, 0 is returned.
+
+
+
+
+ -
+
+ HttpService
+ 101
+
+
+
-
+
-
+
+ HttpEnabled
+ true
+ Enabling http requests from scripts
+
+
+
+
+ -
+
+ InsertService
+ A service used to insert objects stored on the website into the game.
+
+
-
+
-
+
+ GetCollection
+ Returns a table for the assets stored in the category. A category is an setId from www.roblox.com that links to a set. <a href="http://wiki.roblox.com/index.php/GetCollection_(Method)" target="_blank">More info on table format</a>. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ Insert
+ Inserts the Instance into the workspace. It is recommended to use Instance.Parent = game.Workspace instead, as this can cause issues currently.
+
+
+ -
+
+ ApproveAssetId
+ true
+ Deprecated
+
+
+ -
+
+ ApproveAssetVersionId
+ true
+ Deprecated
+
+
+
+
+ -
+
-
+
+ GetBaseSets
+ Returns a table containing a list of the various setIds that are ROBLOX approved. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetUserSets
+ Returns a table containing a list of the various setIds that correspond to argument 'userId'. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetBaseCategories
+ true
+ Deprecated. Use GetBaseSets() instead.
+
+
+ -
+
+ GetUserCategories
+ true
+ Deprecated. Use GetUserSets() instead.
+
+
+ -
+
+ LoadAsset
+ Returns a Model containing the Instance that resides at AssetId on the web. This call will also yield the script until the model is returned. Script execution can still continue, however, if you use a <a href="http://wiki.roblox.com/index.php/Function_Dump/Coroutine_Manipulationcoroutine" target="_blank">coroutine</a>.
+
+
+ -
+
+ LoadAssetVersion
+ Similar to LoadAsset, but instead an AssetVersionId is passed in, which refers to a particular version of the asset which is not neccessarily the latest version.
+
+
+
+
+ -
+
+ Hat
+ 3
+ 45
+
+
+ -
+
+ LocalBackpack
+
+
+ -
+
+ LocalBackpackItem
+
+
+ -
+
+ MotorFeature
+
+
+ -
+
+ Mouse
+ Used to receive input from the user. Actually tracks mouse events and keyboard events.
+
+
-
+
-
+
+ Hit
+ The CoordinateFrame of where the Mouse ray is currently hitting a 3D object in the Workspace. If the mouse is not over any 3D objects in the Workspace, this property is nil.
+
+
+ -
+
+ Icon
+ The current Texture of the Mouse Icon. Stored as a string, for more information on how to format the string <a href="http://wiki.roblox.com/index.php/Content" target="_blank">go here</a>
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking.
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking. This CoordinateFrame will be very close to the Camera.CoordinateFrame.
+
+
+ -
+
+ Target
+ The Part the mouse is currently over. If the mouse is not currently over any object (on the skybox, for example) this property is nil.
+
+
+ -
+
+ TargetFilter
+ A Part or Model that the Mouse will ignore when trying to find the Target, TargetSurface and Hit.
+
+
+ -
+
+ TargetSurface
+ The NormalId (Top, Left, Down, etc.) of the face of the part the Mouse is currently over.
+
+
+ -
+
+ UnitRay
+ The Unit Ray from where the mouse is (Origin) to the current Mouse.Target.
+
+
+ -
+
+ ViewSizeX
+ The viewport's (game window) width in pixels.
+
+
+ -
+
+ ViewSizeY
+ The viewport's (game window) height in pixels.
+
+
+ -
+
+ X
+ The absolute pixel position of the Mouse along the x-axis of the viewport (game window). Values start at 0 on the left hand side of the screen and increase to the right.
+
+
+ -
+
+ Y
+ The absolute pixel position of the Mouse along the y-axis of the viewport (game window). Values start at 0 on the stop of the screen and increase to the bottom.
+
+
+
+ -
+
-
+
+ Button1Down
+ Fired when the first button (usually the left, but could be another) on the mouse is depressed.
+
+
+ -
+
+ Button1Up
+ Fired when the first button (usually the left, but could be another) on the mouse is release.
+
+
+ -
+
+ Button2Down
+ This event is currently non-operational.
+
+
+ -
+
+ Button2Up
+ This event is currently non-operational.
+
+
+ -
+
+ Idle
+ Fired constantly when the mouse is not firing any other event (i.e. the mouse isn't moving, nor any buttons being pressed or depressed).
+
+
+ -
+
+ KeyDown
+ Fired when a user presses a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ KeyUp
+ Fired when a user releases a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ Move
+ Fired when the mouse X or Y member changes.
+
+
+ -
+
+ WheelBackward
+ This event is currently non-operational.
+
+
+ -
+
+ WheelForward
+ This event is currently non-operational.
+
+
+
+
+ -
+
+ ProfilingItem
+
+
+ -
+
+ ChangeHistoryService
+
+
+ -
+
+ RotateP
+
+
+ -
+
+ RotateV
+
+
+ -
+
+ ScriptContext
+
+
+ -
+
+ Selection
+
+
+ -
+
+ VelocityMotor
+
+
+ -
+
+ Weld
+ 20
+ 34
+
+
+ -
+
+ TaskScheduler
+
+
-
+
-
+
+ SetThreadShare
+ true
+ Deprecated
+
+
+
+
+ -
+
+ StatsItem
+
+
+ -
+
+ Snap
+
+
+ -
+
+ FileMesh
+
+
+
+ -
+
+ ClickDetector
+ Raises mouse events for parent object
+ 3
+ 41
+
+
-
+
-
+
+ MaxActivationDistance
+ The maximum distance a Player's character can be from the ClickDetector's parent Part that will allow the Player's mouse to fire events on this object.
+
+
+
+ -
+
-
+
+ MouseClick
+ Fired when a player clicks on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverEnter
+ Fired when a player's mouse enters on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverLeave
+ Fired when a player's mouse leaves the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+
+
+
+ -
+
+ Clothing
+ 0
+
+
+
+ -
+
+ Smoke
+ Makes the parent part or model object emit smoke
+ 3
+ 59
+
+
+ -
+
+ Sparkles
+ Makes the parent part or model object fantastic
+ 3
+ 42
+
+
+ -
+
+ Explosion
+ 3
+ 36
+ Creates an Explosion! This can be used as a purely graphical effect, or can be made to damage objects.
+
+
-
+
-
+
+ BlastPressure
+ How much force this Explosion exerts on objects within it's BlastRadius. Setting this to 0 creates a purely graphical effect. A larger number will cause Parts to fly away at higher velocities.
+
+
+ -
+
+ BlastRadius
+ How big the Explosion is. This is a circle starting from the center of the Explosion's Position, the larger this property the larger the circle of destruction.
+
+
+ -
+
+ Position
+ Where the Explosion occurs in absolute world coordinates.
+
+
+ -
+
+ ExplosionType
+ Defines the behavior of the Explosion. <a href="http://wiki.roblox.com/index.php/ExplosionType_(Enum)" target="_blank">More info</a>
+
+
+
+
+ -
+
+ Fire
+ Makes the parent part or model object emit fire
+ 3
+ 61
+
+
-
+
-
+
+ Color
+ The color of the base of the fire. See SecondaryColor for more.
+
+
+ -
+
+ Heat
+ How hot the fire appears to be. The flame moves quicker the higher this value is set.
+
+
+ -
+
+ SecondaryColor
+ The color the fire interpolates to from Color. The longer a particle exists in the fire, the close to this color it becomes.
+
+
+ -
+
+ Size
+ How large the fire appears to be.
+
+
+
+
+ -
+
+ Seat
+ 3
+ 35
+
+
+ -
+
+ Platform
+
+ Equivalent to a seat, except that the character stands up rather than sits down.
+ 3
+ 35
+
+
+ -
+
+ SkateboardPlatform
+
+ 3
+ 35
+
+
+ -
+
+ VehicleSeat
+ Automatically finds and powers hinge joints in an assembly. Ignores motors.
+ 3
+ 35
+
+
+ -
+
+ Tool
+ 3
+ 17
+
+
+ -
+
+ Flag
+ 3
+ 38
+
+
-
+
-
+
+ CanBeDropped
+ If someone is carrying this flag, this bool determines whether or not they can drop it and run.
+
+
+ -
+
+ TeamColor
+ The Team this flag is for. Corresponds with the TeamColors in the Teams service.
+
+
+
+
+ -
+
+ FlagStand
+ 3
+ 39
+
+
+ -
+
+ BackpackItem
+ 0
+
+
+ -
+
+ Decal
+ 4
+ 7
+ Descibes a texture that is placed on one of the sides of the Part it is parented to.
+
+
-
+
-
+
+ Face
+ Describes the face of the Part the decal will be applied to. <a href="http://wiki.roblox.com/index.php/NormalId_(Enum)" target="_blank">More info</a>
+
+
+ -
+
+ Shiny
+ How much light will appear to reflect off of the decal.
+
+
+ -
+
+ Specular
+ How light will react to the surface of the decal.
+
+
+ -
+
+ Transparency
+ How visible the decal is. 1 is completely invisible, while 0 is completely opaque
+
+
+
+
+ -
+
+ JointInstance
+ 20
+ 34
+
+
+ -
+
+ Message
+ 11
+ 33
+ StarterGui
+
+
+ -
+
+ Hint
+ true
+ 11
+ 33
+
+
+ -
+
+ IntValue
+ 3
+ 4
+ Stores a int value in it's Value member. Useful to share int information across multiple scripts.
+
+
+ -
+
+ RayValue
+ 3
+ 4
+ Stores a Ray value in it's Value member. Useful to share Ray information across multiple scripts.
+
+
+ -
+
+ IntConstrainedValue
+ 3
+ 4
+ Stores an int value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share int information across multiple scripts.
+
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+ -
+
+ DoubleConstrainedValue
+ 3
+ 4
+ Stores a double value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share double information across multiple scripts.
+
+
-
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+
+ -
+
+ BoolValue
+ 3
+ 4
+ Stores a boolean value in it's Value member. Useful to share boolean information across multiple scripts.
+
+
+ -
+
+ CustomEvent
+ 3
+ 4
+
+
+ -
+
+ CustomEventReceiver
+ 3
+ 4
+
+
+ -
+
+ TextureTrail
+ 3
+ 4
+
+
+ -
+
+ FloorWire
+ 3
+ 4
+ Renders a thin cylinder than can be adorned with textures that 'flow' from one object to the next. Has basic pathing abilities and attempts to to not intersect anything. <a href="http://wiki.roblox.com/index.php/FloorWire_Guide" target="_blank">More info</a>
+
+
-
+
-
+
+ CycleOffset
+ Controls how the decals are positioned along the wire. <a href="http://wiki.roblox.com/index.php/CycleOffset_(Property)" target="_blank">More info</a>
+
+
+ -
+
+ From
+ The object the FloorWire 'emits' from
+
+
+ -
+
+ StudsBetweenTextures
+ The space between two textures on the wire. Note: studs are relative depending on how far the camera is from the FloorWire.
+
+
+ -
+
+ Texture
+ The image we use to render the textures that flow from beginning to end of the FloorWire.
+
+
+ -
+
+ TextureSize
+ The size in studs of the Texture we use to flow from one object to the next.
+
+
+ -
+
+ To
+ The object the FloorWire 'emits' to
+
+
+ -
+
+ Velocity
+ The rate of travel that the textures flow along the wire.
+
+
+ -
+
+ WireRadius
+ How thick the wire is.
+
+
+
+
+ -
+
+ NumberValue
+ 3
+ 4
+
+
+ -
+
+ StringValue
+ 3
+ 4
+
+
+ -
+
+ Vector3Value
+ 3
+ 4
+
+
+ -
+
+ CFrameValue
+ 3
+ 4
+ Stores a CFrame value in it's Value member. Useful to share CFrame information across multiple scripts.
+
+
+ -
+
+ Color3Value
+ 3
+ 4
+ Stores a Color3 value in it's Value member. Useful to share Color3 information across multiple scripts.
+
+
+ -
+
+ BrickColorValue
+ 3
+ 4
+ Stores a BrickColor value in it's Value member. Useful to share BrickColor information across multiple scripts.
+
+
+ -
+
+ ObjectValue
+ 3
+ 4
+
+
+ -
+
+ SpecialMesh
+ 3
+ 8
+
+
+ -
+
+ BlockMesh
+ 3
+ 8
+
+
+
+ -
+
+ CylinderMesh
+ 3
+ 8
+
+
+
+ -
+
+ BevelMesh
+ false
+ true
+
+
+ -
+
+ DataModelMesh
+ false
+
+
+
+ -
+
+ Texture
+ 4
+ 10
+
+
+ -
+
+ Sound
+ 1
+ 11
+
+
-
+
-
+
+ play
+ true
+ Deprecated. Use Play() instead
+
+
+
+ -
+
-
+
+ PlayOnRemove
+ The sound will play when it is removed from the Workspace. Looped sounds don't play
+
+
+
+
+ -
+
+ StockSound
+ false
+ -1
+
+
+ -
+
+ SoundService
+ 50
+ 31
+
+
-
+
+
-
+
+ AmbientReverb
+
+ The ambient sound environment. May not work when using hardware sound
+
+
+ -
+
+ DopplerScale
+
+ The doppler scale is a general scaling factor for how much the pitch varies due to doppler shifting in 3D sound. Doppler is the pitch bending effect when a sound comes towards the listener or moves away from it, much like the effect you hear when a train goes past you with its horn sounding. With dopplerscale you can exaggerate or diminish the effect.
+
+
+ -
+
+ DistanceFactor
+
+ the relative distance factor, compared to 1.0 meters.
+
+
+ -
+
+ RolloffScale
+
+ Setting this value makes the sound drop off faster or slower. The higher the value, the faster volume will attenuate, and conversely the lower the value, the slower it will attenuate. For example a rolloff factor of 1 will simulate the real world, where as a value of 2 will make sounds attenuate 2 times quicker.
+
+
+
+
+ -
+
+ Backpack
+ 3
+ 20
+
+
+ -
+
+ StarterPack
+ 3
+ 20
+
+
+
+ -
+
+ StarterGear
+ 3
+ 20
+
+
+
+ -
+
+ StarterGui
+ 3
+ 46
+
+
+
-
+
-
+
+ SetCoreGuiEnabled
+ Will stop/begin certain core gui elements being rendered. See CoreGuiType for core guis that can be modified.
+
+
+ -
+
+ GetCoreGuiEnabled
+ Returns a boolean describing whether a CoreGuiType is currently being rendered.
+
+
+
+
+
+ -
+
+ CoreGui
+ false
+ 46
+
+
+
+ -
+
+ ContextActionService
+ A service used to bind input to various lua functions.
+
+
+
-
+
-
+
+ BindActionToInputTypes
+ Binds 'functionToBind' to fire when any 'inputTypes' happen. InputTypes can be variable in number and type. Types can be Enum.KeyCode, single strings corresponding to keys, or Enum.UserInputType. 'actionName' is a key used by many other ContextActionService functions to query state. 'createTouchButton' if true will create a button on screen on touch devices. This button will fire 'functionToBind'.
+
+
+ -
+
+ SetTitle
+ If 'actionName' key contains a bound action, then 'title' is set as the title of the touch button. Does nothing if a touch button was not created. No guarantees are made whether title will be set when button is manipulated.
+
+
+ -
+
+ SetDescription
+ If 'actionName' key contains a bound action, then 'description' is set as the description of the bound action. This description will appear for users in a listing of current actions availables.
+
+
+ -
+
+ SetImage
+ If 'actionName' key contains a bound action, then 'image' is set as the image of the touch button. Does nothing if a touch button was not created. No guarantees are made whether image will be set when button is manipulated.
+
+
+ -
+
+ SetPosition
+ If 'actionName' key contains a bound action, then 'position' is set as the position of the touch button. Does nothing if a touch button was not created. No guarantees are made whether position will be set when button is manipulated.
+
+
+ -
+
+ UnbindAction
+ If 'actionName' key contains a bound action, removes function from being called by all input that it was bound by (if function was also bound by a different action name as well, those bound input are still active). Will also remove any touch button created (if button was manipulated manually there is no guarantee it will be cleaned up).
+
+
+ -
+
+ UnbindAllActions
+ Removes all functions bound. No actionNames will remain. All touch buttons will be removed. If button was manipulated manually there is no guarantee it will be cleaned up.
+
+
+ -
+
+ GetBoundActionInfo
+ Returns a table with info regarding the function bound with 'actionName'. Table has the keys 'title' (current title that was set with SetTitle) 'image' (image set with SetImage) 'description' (description set with SetDescription) 'inputTypes' (tuple containing all input bound for this 'actionName') 'createTouchButton' (whether or not we created a touch button for this 'actionName').
+
+
+ -
+
+ GetAllBoundActionInfo
+ Returns a table with all bound action info. Each entry is a key with 'actionName' and value being the same table you would get from ContextActionService:GetBoundActionInfo('actionName').
+
+
+
+
+ -
+
-
+
+ GetButton
+ If 'actionName' key contains a bound action, then this will return the touch button (if was created). Returns nil if a touch button was not created. No guarantees are made whether button will be retrievable when button is manipulated.
+
+
+
+
+
+ -
+
+ PointsService
+ A service used to query and award points for Roblox users using the universal point system.
+
+
+
-
+
-
+
+ PointsAwarded
+ Fired when points are successfully awarded 'userId'. Also returns the updated balance of points for usedId in universe via 'userBalanceInUniverse', total points via 'userTotalBalance', and the amount points that were awarded via 'pointsAwarded'. This event fires on the server and also all clients in the game that awarded the points.
+
+
+
+
+ -
+
-
+
+ AwardPoints
+ Will attempt to award the 'amount' points to 'userId', returns 'userId' awarded to, the number of points awarded, the new point total the user has in the game, and the total number of points the user now has. Will also fire PointsService.PointsAwarded. Works with server scripts ONLY.
+
+
+ -
+
+ GetPointBalance
+ Returns the overall balance of points that player with userId has (the sum of all points across all games). Works with server scripts ONLY.
+
+
+ -
+
+ GetGamePointBalance
+ Returns the balance of points that player with userId has in the current game (all placeID points combined within the game). Works with server scripts ONLY.
+
+
+ -
+
+ GetAwardablePoints
+ Returns the number of points the current universe can award to players. Works with server scripts ONLY.
+
+
+
+
+
+ -
+
+ MarketplaceService
+ 46
+
+
-
+
-
+
+ PromptPurchase
+ Will prompt 'player' to purchase the item associated with 'assetId'. 'equipIfPurchased' is an optional argument that will give the item to the player immediately if they buy it (only applies to gear). 'currencyType' is also optional and will attempt to prompt the user with a specified currency if the product can be purchased with this currency, otherwise we use the default currency of the product.
+
+
+
+
+ -
+
-
+
+ GetProductInfo
+ Takes one argument "assetId" which should be a number of an asset on www.roblox.com. Returns a table containing the product information (if this process fails, returns an empty table).
+
+
+ -
+
+ PlayerOwnsAsset
+ Checks to see if 'Player' owns the product associated with 'assetId'. Returns true if the player owns it, false otherwise. This call will produce a warning if called on a guest player.
+
+
+
+ -
+
-
+
+ ProcessReceipt
+ Callback that is executed for pending Developer Product receipts.
+
+ If this function does not return Enum.ProductPurchaseDecision.PurchaseGranted, then you will not be granted the money for the purchase!
+
+ The callback will be invoked with a table, containing the following informational fields:
+ PlayerId - the id of the player making the purchase.
+ PlaceIdWherePurchased - the specific place where the purchase was made.
+ PurchaseId - a unique identifier for the purchase, should be used to prevent granting an item multiple times for one purchase.
+ ProductId - the id of the purchased product.
+ CurrencyType - the type of currency used (Tix, Robux).
+ CurrencySpent - the amount of currency spent on the product for this purchase.
+
+
+
+
+ -
+
-
+
+ PromptPurchaseFinished
+ Fired when a 'player' dismisses a purchase dialog for 'assetId'. If the player purchased the item 'isPurchased' will be true, otherwise it will be false. This call will produce a warning if called on a guest player.
+
+
+
+
+
+ -
+
+ UserInputService
+
+
-
+
-
+
+ TouchEnabled
+ Returns true if the local device accepts touch input, false otherwise.
+
+
+ -
+
+ KeyboardEnabled
+ Returns true if the local device accepts keyboard input, false otherwise.
+
+
+ -
+
+ MouseEnabled
+ Returns true if the local device accepts mouse input, false otherwise.
+
+
+
+
+ -
+
-
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ TouchStarted
+ Fired when a user places their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchMoved
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchEnded
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+
+
+
+ -
+
+ Sky
+ 0
+ 28
+
+
+ -
+
+ Motor
+
+ 0
+
+
+ -
+
+ Humanoid
+ 3
+ 9
+
+
-
+
+
-
+
+ MoveTo
+ Attempts to move the Humanoid and it's associated character to 'part'. 'location' is used as an offset from part's origin.
+
+
+ -
+
+ Jump
+
+
+ -
+
+ Sit
+
+
+ -
+
+ TakeDamage
+ Decreases health by the amount. Use this instead of changing health directly to make sure weapons are filtered for things such as ForceField(s).
+
+
+ -
+
+ UnequipTools
+
+ Takes any active gear/tools that the Humanoid is using and puts them into the backpack. This function only works on Humanoids with a corresponding Player.
+
+
+ -
+
+ EquipTool
+
+ Takes a specified tool and equips it to the Humanoid's Character. Tool argument should be of type 'Tool'.
+
+
+
+ -
+
-
+
+ NameOcclusion
+
+ Sets how to display other humanoid names to this humanoid's player. <a href="http://wiki.roblox.com/index.php/NameOcclusion_(Enum)" target="_blank">More info</a>
+
+
+ Health
+ How many hit points the Humanoid has. When this number reaches 0 or goes below 0, the Humanoid's character falls apart and will respawn.
+
+
+ MaxHealth
+ The maximum number of hit points a Humanoid's health can reach. If the Humanoid's health is set over this amount, the health gets set to this value.
+
+
+ TargetPoint
+ The location that the Humanoid is trying to walk to.
+
+
+
+
+ -
+
+ BodyColors
+
+ 0
+
+
+ -
+
+ Shirt
+ 0
+ 43
+
+
+ -
+
+ Pants
+ 0
+ 44
+
+
+ -
+
+ ShirtGraphic
+ 0
+ 40
+
+
+ -
+
+ Skin
+
+ 0
+
+
+ -
+
+ DebugSettings
+ false
+ 0
+
+
+ -
+
+ FaceInstance
+ false
+
+
+ -
+
+ GameSettings
+ false
+ 0
+
+
+ -
+
+ GlobalSettings
+ false
+ 0
+
+
+ -
+
+ Item
+ false
+ 0
+
+
+ -
+
+ NetworkPeer
+ false
+
+
+ -
+
+ NetworkSettings
+ false
+ 0
+
+
+ -
+
+ PVInstance
+ false
+
+
-
+
-
+
+ CoordinateFrame
+ true
+ Deprecated. Use CFrame instead
+
+
+
+
+ -
+
+ RenderSettings
+ false
+ 0
+
+
+ -
+
+ RootInstance
+ false
+
+
+ -
+
+ ServiceProvider
+ false
+
+
-
+
-
+
+ service
+ true
+ Use GetService() instead
+
+
+
+
+ -
+
+ ProfilingItem
+ false
+
+
+ -
+
+ NetworkMarker
+ false
+
+
+
+ -
+
+ Hopper
+ true
+ Use StarterPack instead
+ 0
+
+
+
+ -
+
+ Instance
+ false
+
+
+
-
+
-
+
+ Archivable
+ Determines whether or not an Instance can be saved when the game closes/attempts to save the game. Note: this only applies to games that use Data Persistence, or Personal Build Servers.
+
+
+ -
+
+ ClassName
+ The string name of this Instance's most derived class.
+
+
+ -
+
+ Parent
+ The Instance that is directly above this Instance in the tree.
+
+
+
+
+ -
+
+
-
+
+ GetDebugId
+ false
+ This function is for internal testing. Don't use in production code
+
+
+ -
+
+ Clone
+ Returns a copy of this Object and all its children. The copy's Parent is nil
+
+
+ -
+
+ clone
+ true
+ Use Clone() instead
+
+
+ -
+
+ isA
+ true
+ Use IsA() instead
+
+
+ -
+
+ IsA
+ Returns a boolean if this Instance is of type 'className' or a is a subclass of type 'className'. If 'className' is not a valid class type in ROBLOX, this function will always return false. <a href="http://wiki.roblox.com/index.php/IsA" target="_blank">More info</a>
+
+
+ -
+
+ FindFirstChild
+ Returns the first child of this Instance that matches the first argument 'name'. The second argument 'recursive' is an optional boolean (defaults to false) that will force the call to traverse down thru all of this Instance's descendants until it finds an object with a name that matches the 'name' argument. The function will return nil if no Instance is found.
+
+
+ -
+
+ GetFullName
+ Returns a string that shows the path from the root node (DataModel) to this Instance. This string does not include the root node (DataModel).
+
+
+ -
+
+ children
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ getChildren
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ GetChildren
+ Returns a read-only table of this Object's children
+
+
+ -
+
+ Remove
+ Deprecated. Use ClearAllChildren() to get rid of all child objects, or Destroy() to invalidate this object and its descendants
+ true
+
+
+ -
+
+ remove
+ true
+ Use Remove() instead
+
+
+ -
+
+ ClearAllChildren
+ Removes all children (but not this object) from the workspace.
+
+
+ -
+
+ Destroy
+ Removes object and all of its children from the workspace. Disconnects object and all children from open connections. Object and children may not be usable after calling Destroy.
+
+
+ -
+
+ findFirstChild
+ true
+ Use FindFirstChild() instead
+
+
+
+ -
+
+
-
+
+ AncestryChanged
+ Fired when any of this object's ancestors change. First argument 'child' is the object whose parent changed. Second argument 'parent' is the first argument's new parent.
+
+
+ -
+
+ DescendantAdded
+ Fired after an Instance is parented to this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ DescendantRemoving
+ Fired after an Instance is unparented from this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ Changed
+ Fired after a property changes value. The property argument is the name of the property
+
+
+
+
+
+ -
+
+ BodyGyro
+ Attempts to maintain a fixed orientation of its parent Part
+ 14
+ 14
+
+
-
+
+
-
+
+ maxTorque
+ The maximum torque that will be exerted on the Part
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power continually applied to this force
+
+
+ -
+
+ cframe
+ the cframe that this force is trying to orient its parent Part to. Note: this force only uses the rotation of the cframe, not the position.
+
+
+
+
+ -
+
+ BodyPosition
+ 14
+ 14
+
+
-
+
+
-
+
+ maxForce
+ The maximum force that will be exerted on the Part
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power factor continually applied to this force
+
+
+ -
+
+ position
+ The Vector3 that this force is trying to position its parent Part to.
+
+
+
+
+ -
+
+ RocketPropulsion
+
+ 14
+ 14
+ A propulsion system that mimics a rocket
+
+
+ -
+
+ BodyVelocity
+ 14
+ 14
+
+
-
+
-
+
+ maxForce
+ The maximum force that will be exerted on the Part in each axis
+
+
+ -
+
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+
+ -
+
+ velocity
+ The velocity this system tries to achieve. How quickly the system reaches this velocity (if ever) is defined by P.
+
+
+
+
+ -
+
+ BodyAngularVelocity
+ 14
+ 14
+
+
-
+
-
+ maxTorque
+ The maximum torque that will be exerted on the Part in each axis
+
+ -
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+ -
+ angularVelocity
+ The rotational velocity this system tries to achieve. How quickly the system reaches this velocity is defined by P.
+
+
+
+ -
+
+ BodyForce
+ 14
+ 14
+ When parented to a physical part, BodyForce will continually exert a force upon its parent object.
+
+
-
+
-
+ force
+ The continual force exerted on an object, defined in each axis.
+
+
+
+ -
+
+ BodyThrust
+ 14
+ 14
+
+
-
+
+
-
+
+ force
+ The power continually applied to this force
+
+
+ -
+
+ location
+ The Vector3 location of where to apply the force to.
+
+
+
+
+ -
+
+ Hole
+
+ 0
+
+
+ -
+
+ Feature
+ 0
+
+
+
+ -
+
+ Teams
+ This Service-level object is the container for all Team objects in a level. A map that supports team games must have a Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 14
+ 23
+
+
+
+ -
+
+ Team
+ The Team class is used to represent a faction in a team game. The only valid location for a Team object is under the Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 1
+ 24
+
+
+ -
+
+ SpawnLocation
+ 3
+ 25
+
+
+ -
+
+ NetworkClient
+ 3
+ 16
+
+
+ -
+
+ NetworkServer
+ 3
+ 15
+
+
+
+ -
+
+ Script
+ 3
+ 6
+
+
-
+
+
-
+
+ LinkedScript
+
+ This property is under development. Do not use
+
+
+
+
+
+ -
+
+ LocalScript
+ 4
+ 18
+ A script that runs on clients, NOT servers. LocalScripts can only run when parented under the PlayerGui currently.
+
+
+
+ -
+
+ NetworkReplicator
+ 3
+ 29
+
+
+
+ -
+
+ Model
+ 10
+ 2
+ A construct used to group Parts and other objects together, also allows manipulation of multiple objects.
+
+
-
+
-
+
+ BreakJoints
+ Breaks all surface joints contained within
+
+
+ -
+
+ GetModelCFrame
+ Returns a CFrame that has position of the centroid of all Parts in the Model. The rotation matrix is either the rotation matrix of the user-defined PrimaryPart, or if not specified then a part in the Model chosen by the engine.
+
+
+ -
+
+ GetModelSize
+ Returns a Vector3 that is union of the extents of all Parts in the model.
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints between all touching Parts contrained within the model. Technically, this function calls MakeJoints() on all Parts inside the model.
+
+
+ -
+
+ MoveTo
+ Moves the centroid of the Model to the specified location, respecting all relative distances between parts in the model.
+
+
+ -
+
+ ResetOrientationToIdentity
+ Rotates all parts in the model to the orientation that was set using SetIdentityOrientation(). If this function has never been called, rotation is reset to GetModelCFrame()'s rotation.
+
+
+ -
+
+ SetIdentityOrientation
+ Takes the current rotation matrix of the model and stores it as the model's identity matrix. The rotation is applied when ResetOrientationToIdentity() is called.
+
+
+ -
+
+ TranslateBy
+ Similar to MoveTo(), except instead of moving to an explicit location, we use the model's current CFrame location and offset it.
+
+
+ -
+
+ GetPrimaryPartCFrame
+ Returns the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error.
+
+
+ -
+
+ SetPrimaryPartCFrame
+ Sets the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error. This also sets the cframe of all descendant Parts relative to the cframe change to PrimaryPart.
+
+
+ -
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+ -
+
-
+
+ PrimaryPart
+ A Part that serves as a reference for the Model's CFrame. Used in conjunction with GetModelPrimaryPartCFrame and SetModelPrimaryPartCFrame. Use this to rotate/translate all Parts relative to the PrimaryPart.
+
+
+
+
+
+ -
+
+ Status
+ 10
+ 2
+
+
-
+
-
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+
+
+ -
+
+ DataModel
+
+
+
-
+
+
+
-
+
+ Workspace
+
+
+ -
+
+ workspace
+ true
+ Deprecated. Use Workspace
+
+
+ -
+
+ ShowMouse
+ true
+ Deprecated. Use Workspace.IsMouseCursorVisible
+
+
+ -
+
+ IsLoaded
+ Returns true if the game has finished loading, false otherwise. Check this before listening to the Loaded signal to ensure a script knows when a game finishes loading.
+
+
+
+
+ -
+
-
+
+ Loaded
+ Fires when the game finishes loading. Use this to know when to remove your custom loading gui. It is best to check IsLoaded() before connecting to this event, as the game may load before the event is connected to.
+
+
+
+
+ -
+
-
+
+ get
+ true
+ Use GetObjects() instead
+
+
+ -
+
+ SetPlaceID
+ true
+ Use SetPlaceId() instead
+
+
+ -
+
+ SetCreatorID
+ true
+ Use SetCreatorId() instead
+
+
+
+
+
+ -
+
+ HopperBin
+ 24
+ 22
+
+
+
+ -
+
+ Camera
+ 5
+ 5
+
+
-
+
-
+
+ CameraSubject
+ Where the Camera's focus is. Any rotation of the camera will be about this subject.
+
+
+ -
+
+ CameraType
+ Defines how the camera will behave. <a href="http://wiki.roblox.com/index.php/CameraType_(Enum)" target="_blank">More info</a>
+
+
+ -
+
+ CoordinateFrame
+ The current position and rotation of the Camera. For most CameraTypes, the rotation is set such that the CoordinateFrame lookVector is pointing at the Focus.
+
+
+ -
+
+ FieldOfView
+ The current angle, or width, of what the camera can see. Current acceptable values are from 20 degrees to 80.
+
+
+ -
+
+ Focus
+ The current CoordinateFrame that the camera is looking at. Note: it is not always guaranteed that the camera is always looking here.
+
+
+
+ -
+
-
+
+ GetRoll
+ Returns the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+ -
+
+ SetRoll
+ Sets the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+
+
+
+ -
+
+ Players
+ 2
+ 21
+
+
-
+
-
+
+ CharacterAutoLoads
+ true
+ Set to true, when a player joins a game, they get a character automatically, as well as when they die. When set to false, characters do not auto load and will only load in using Player:LoadCharacter().
+
+
+
+ -
+
-
+
+ players
+ true
+ Use GetPlayers() instead
+
+
+
+
+
+ -
+
+ ReplicatedStorage
+ 3
+ 70
+ A container whose contents are replicated to all clients and the server.
+
+
+
+ -
+
+ ReplicatedFirst
+ 3
+ 70
+ A container whose contents are replicated to all clients (but not back to the server) first before anything else. Useful for creating loading guis, tutorials, etc.
+
+
-
+
-
+
+ RemoveRobloxLoadingScreen
+ Removes the default Roblox loading screen from view. Call this when you are ready to either show your own loading gui, or when the game is ready to play.
+
+
+
+
+
+ -
+
+ ServerStorage
+ 3
+ 69
+ A container whose contents are only on the server.
+
+
+
+ -
+
+ ServerScriptService
+ 3
+ 71
+ A container whose contents should be scripts. Scripts that are added to the container are run on the server.
+
+
+
+ -
+
+ Lighting
+ 3
+ 13
+ Responsible for all lighting aspects of the world (affects how things are rendered).
+
+
-
+
-
+
+ GetMinutesAfterMidnight
+ The number of minutes that the current time is past midnight. If currently at midnight, returns 0. Will return decimal values if not at an exact minute.
+
+
+ -
+
+ GetMoonDirection
+ Returns the lookVector (Vector3) of the moon. If this lookVector was used in a CFrame, the Part would face the moon.
+
+
+ -
+
+ GetMoonPhase
+ Currently always returns 0.75. MoonPhase cannot be edited.
+
+
+ -
+
+ GetSunDirection
+ Returns the lookVector (Vector3) of the sun. If this lookVector was used in a CFrame, the Part would face the moon.
+
+
+ -
+
+ SetMinutesAfterMidnight
+ Sets the time to be a certain number of minutes after midnight. This works with integer and decimal values.
+
+
+
+ -
+
-
+
+ Ambient
+ The hue of the global lighting. Changing this changes the color tint of all objects in the Workspace.
+
+
+ -
+
+ Brightness
+ How much global light each Part in the Workspace receives. Standard range is 0 to 1 (0 being little light), but can be increased all the way to 5 (colors start to be appear very different at this value).
+
+
+ -
+
+ ColorShift_Bottom
+ The hue of global lighting on the bottom surfaces of an object.
+
+
+ -
+
+ ColorShift_Top
+ The hue of global lighting on the top surfaces of an object.
+
+
+ -
+
+ FogColor
+ A Color3 value that changes the hue of distance fog.
+
+
+ -
+
+ FogEnd
+ The distance at which fog completely blocks your vision. This distance is relative to the camera position. Units are in studs
+
+
+ -
+
+ FogStart
+ The distance at which the fog gradient begins. This distance is relative to the camera position. Units are in studs.
+
+
+ -
+
+ GeographicLatitude
+ The latitude position the level is placed at. This affects sun position. <a href="http://wiki.roblox.com/index.php/GeographicLatitude_(Property)" target="_blank">More info</a>
+
+
+ -
+
+ GlobalShadows
+ Flag enabling shadows from sun and moon in the place
+
+
+ -
+
+ OutdoorAmbient
+ Effective ambient value for outdoors, effectively shadow color outdoors (requires GlobalShadows enabled)
+
+
+ -
+
+ Outlines
+ Flag enabling or disabling outlines on parts and terrain
+
+
+ -
+
+ ShadowColor
+ Color the shadows appear as. Shadows are drawn mostly for characters, but depending on the lighting will also show for Parts in the Workspace. Rendering settings can also affect if shadows are drawn.
+
+
+ -
+
+ TimeOfDay
+ A string that represent the current time of day. Time is in 24-hour clock format "XX::YY:ZZ", where X is hour, Y is minute, and Z is seconds.
+
+
+
+ -
+
-
+
+ LightingChanged
+ Fired whenever a property of Lighting is changed, or a skybox is added or removed. Skyboxes are of type 'Sky' and should be parented directly to lighting.
+
+
+
+
+
+ -
+
+ TestService
+ 100
+ 68
+
+
+
+ -
+
+ DebuggerManager
+
+
+
+
+
+ -
+
+ ScriptDebugger
+
+
+
+
+
+ -
+
+ DebuggerBreakpoint
+
+
+
+
+
+ -
+
+ DebuggerWatch
+
+
+
+
+
+ -
+
+ Debris
+ 10
+ 30
+ A service that provides utility in cleaning up objects
+
+
-
+
-
+
+ addItem
+ true
+ Use AddItem() instead
+
+
+ -
+
+ AddItem
+ Adds an Instance into the debris service that will later be destroyed. Second argument 'lifetime' is optional and specifies how long (in seconds) to wait before destroying the item. If no time is specified then the item added will automatically be destroyed in 10 seconds.
+
+
+
+ -
+
-
+
+ MaxItems
+ true
+ Deprecated. No replacement
+
+
+
+
+
+ -
+
+ Accoutrement
+ 0
+ 32
+
+
+
+ -
+
+ Player
+ 1
+ 12
+
+
-
+
+
-
+
+ CharacterAppearance
+ false
+
+
+ -
+
+ CameraMode
+ An enum that describes how a Player's camera is allowed to behave. <a href="http://wiki.roblox.com/index.php/CameraMode_(Enum)" target="_blank">More info</a>.
+
+
+ -
+
+ DataReady
+ Read-only. If true, this Player's persistent data can be loaded, false otherwise. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+
+ -
+
+
-
+
+ LoadCharacter
+ true
+ Loads in a new character for this player. This will replace the player's current character, if they have one. This should be used in conjunction with Players.CharacterAutoLoads to control spawning of characters. This function only works from a server-side script (NOT a LocalScript).
+
+
+ -
+
+ playerFromCharacter
+ true
+ Use GetPlayerFromCharacter() instead
+
+
+ -
+
+ SetUnder13
+ true
+
+
+
+
+ -
+
-
+
+ WaitForDataReady
+ true
+ Yields until the persistent data for this Player is ready to be loaded. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+ -
+
+ GetWebPersonalServerRank
+ true
+
+
+
+
+ -
+
+
-
+
+ Idled
+ Fired periodically after the user has been AFK for a while. Currently this event is only fired for the *local* Player. "time" is the time in seconds that the user has been idle.
+
+
+
+
+
+ -
+
+ Workspace
+ 1
+ 19
+
+
-
+
-
+
+ FindPartsInRegion3
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartsInRegion3WithIgnoreList
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartOnRay
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+ -
+
+ FindPartOnRayWithIgnoreList
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+
+
+
+ -
+
+ BasePart
+ A structural class, not creatable
+ -1
+ false
+
+
+
-
+
-
+
+ Color
+ true
+ Deprecated. Use BrickColor instead
+
+
+ -
+
+ CFrame
+ Contains information regarding the Part's position and a matrix that defines the Part's rotation. Can read/write. <a href="http://wiki.roblox.com/index.php/Cframe" target="_blank">More info</a>
+
+
+ -
+
+ CanCollide
+ Determines whether physical interactions with other Parts are respected. If true, will collide and react with physics to other Parts. If false, other parts will pass thru instead of colliding
+
+
+ -
+
+ Anchored
+ Determines whether or not physics acts upon the Part. If true, part stays 'Anchored' in space, not moving regardless of any collision/forces acting upon it. If false, physics works normally on the part.
+
+
+ -
+
+ Elasticity
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will rebound against another. a value of 1 is like a superball, and 0 is like a lead block.
+
+
+ -
+
+ Friction
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will be able to slide. a value of 1 is no sliding, and 0 is no friction, so infinite sliding.
+
+
+ -
+
+ Locked
+ Determines whether building tools (in-game and studio) can manipulate this Part. If true, no editing allowed. If false, editing is allowed.
+
+
+ -
+
+ Material
+ Specifies the look and feel the Part should have. Note: this does not define the color the Part is, see BrickColor for that. <a href="http://wiki.roblox.com/index.php/Material_(Enum)" target="_blank">More info</a>
+
+
+ -
+
+ Reflectance
+ Specifies how shiny the Part is. A value of 1 is completely reflective (chrome), while a value of 0 is no reflectance (concrete wall)
+
+
+ -
+
+ ResizeIncrement
+ Sets the value for the smallest change in size allowable by the Resize(NormalId, int) function.
+
+
+ -
+
+ ResizeableFaces
+ Sets the value for the faces allowed to be resized by the Resize(NormalId, int) function.
+
+
+ -
+
+ Transparency
+ Sets how visible an object is. A value of 1 makes the object invisible, while a value of 0 makes the object opaque.
+
+
+ -
+
+ Velocity
+ How fast the Part is traveling in studs/second. This property is NOT recommended to be modified directly, unless there is good reason. Otherwise, try using a BodyForce to move a Part.
+
+
+
+
+ -
+
-
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model). This uses the SurfaceTypes defined on the surfaces of parts to create the appropriate welds. <a href="http://wiki.roblox.com/index.php/MakeJoints_(Method)" target="_blank">More info</a>
+
+
+ -
+
+ BreakJoints
+ Destroys SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model).
+
+
+ -
+
+ GetMass
+ Returns a number that is the mass of this Instance. Mass of a Part is immutable, and is changed only by the size of the Part.
+
+
+ -
+
+ Resize
+ Resizes a Part in the direction of the face defined by 'NormalId', by the amount specified by 'deltaAmount'. If the operation will expand the part to intersect another Instance, the part will not resize at all. Return true if the call is successful, false otherwise.
+
+
+ -
+
+ getMass
+ Use GetMass() instead
+ true
+
+
+
+ -
+
-
+
+ OutfitChanged
+ true
+
+
+ -
+
+ LocalSimulationTouched
+ true
+ Deprecated. Use Touched instead
+
+
+ -
+
+ StoppedTouching
+
+ Deprecated. Use TouchEnded instead
+
+
+ -
+
+ TouchEnded
+ Fired when the part stops touching another part
+
+
+
+
+ -
+
+ Part
+ A plastic building block - the fundamental component of ROBLOX
+ 11
+ 1
+
+
+ -
+
+ TrussPart
+ An extendable building truss
+ 12
+ 1
+
+
+ -
+
+ WedgePart
+ A Wedge Part
+ 12
+ 1
+
+
+ -
+
+ PrismPart
+ A Prism Part
+ false
+ 12
+ 1
+
+
+ -
+
+ PyramidPart
+ A Pyramid Part
+ false
+ 12
+ 1
+
+
+ -
+
+ ParallelRampPart
+ A ParallelRamp Part
+ false
+ 12
+ 1
+
+
+ -
+
+ RightAngleRampPart
+ A RightAngleRamp Part
+ false
+ 12
+ 1
+
+
+ -
+
+ CornerWedgePart
+ A CornerWedge Part
+ 12
+ 1
+
+
+ -
+
+ PlayerGui
+ A container instance that syncs data between a single player and the server. ScreenGui objects that are placed in this container will be shown to the Player parent only
+ 13
+ 46
+
+
+ -
+
+ GuiMain
+ Deprecated, please use ScreenGui
+ true
+ 14
+ 47
+
+
+
+ -
+
+ ScreenGui
+ The core GUI object on which tools are built. Add Frames/Labels/Buttons to this object to have them rendered as a 2D overlay
+ 14
+ 47
+ StarterGui
+
+
+ -
+
+ FunctionalTest
+ Deprecated. Use TestService instead
+ true
+ 1
+
+
+ -
+
+ BillboardGui
+ A GUI that adorns an object in the 3D world. Add Frames/Labels/Buttons to this object to have them rendered while attached to a 3D object
+ 14
+ 64
+ StarterGui
+
+
+
-
+
-
+
+ Adornee
+ The Object the billboard gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ AlwaysOnTop
+ If true, billboard gui does not get occluded by 3D objects, but always renders on the screen.
+
+
+ -
+
+ Enabled
+ If true, billboard gui will render, otherwise rendering will be skipped.
+
+
+ -
+
+ ExtentsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the extents of the 3d object it is rendering from.
+
+
+ -
+
+ PlayerToHideFrom
+ Specifies a Player that the BillboardGui will not render to.
+
+
+ -
+
+ StudsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the centroid of the 3d object it is rendering from
+
+
+ -
+
+ SizeOffset
+ A Vector2 (x,y) defined in studs that will offset the gui size from it's current size.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the BillboardGui. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>. Relative values are defined as one-to-one with studs.
+
+
+
+
+
+ -
+
+ SurfaceGui
+ tbd
+ 14
+ 64
+ StarterGui
+
+
+
-
+
-
+
+ Adornee
+ The Object the billboard gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ Enabled
+ If true, billboard gui will render, otherwise rendering will be skipped.
+
+
+
+
+
+
+
+ -
+
+ GuiBase2d
+ false
+
+
+
-
+
-
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+
+
+
+ -
+
+ InputObject
+ An object that describes a particular user input, such as mouse movement, touches, keyboard, and more.
+
+
-
+
-
+
+ UserInputType
+ An enum that describes what kind of input this object is describing (mousebutton, touch, etc.). See Enum.UserInputType for more info.
+
+
+ -
+
+ UserInputState
+ An enum that describes what state of a particular input (touch began, touch moved, touch ended, etc.). See Enum.UserInputState for more info.
+
+
+ -
+
+ Position
+ A Vector3 value that describes a positional value of this input. For mouse and touch input, this is the screen position of the mouse/touch, described in the x and y components. For mouse wheel input, the z component describes whether the wheel was moved forward or backward.
+
+
+ -
+
+ KeyCode
+ An enum that describes what kind of input is being pressed. For types of input like Keyboard, this describes what key was pressed. For input like mousebutton, this provides no additional information.
+
+
+
+
+
+ -
+
+ GuiObject
+ false
+
+
+
-
+
-
+
+ TweenPosition
+ Smoothly moves a GuiObject from its current position to 'endPosition'. The only required argument is 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenPosition_(Method)" target="_blank">More info</a>
+
+
+ -
+
+ TweenSize
+ Smoothly translates a GuiObject's current size to 'endSize'. The only required argument is 'endSize'. <a href="http://wiki.roblox.com/index.php/TweenSize_(Method)" target="_blank">More info</a>
+
+
+ -
+
+ TweenSizeAndPosition
+ Smoothly translates a GuiObject's current size to 'endSize', and also smoothly translates the GuiObject's current position to 'endPosition'. The only required arguments are 'endSize' and 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenSizeAndPosition_(Method)" target="_blank">More info</a>
+
+
+
+
+ -
+
-
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ BackgroundColor3
+ A Color3 value that specifies the background color for the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BackgroundTransparency
+ A number value that specifies how transparent the background of the GuiObject is. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BorderColor3
+ A Color3 value that specifies the color of the outline of the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BorderSizePixel
+ A number value that specifies the thickness (in pixels) of the outline of the GuiObject. Currently this value can only be set to either 0 or 1, any other number has no effect. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ ClipsDescendants
+ If set to true, any descendants of this GuiObject will only render if contained within it's borders. If set to false, all descendants will render regardless of position.
+
+
+ -
+
+ Draggable
+ If true, allows a GuiObject to be dragged by the user's mouse. The events 'DragBegin' and 'DragStopped' are fired when the appropriate action happens, and only will fire on Draggable=true GuiObjects.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the GuiObject on screen in both absolute and relative coordinates. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ Position
+ A UDim2 value describing the position of the top-left corner of the GuiObject on screen. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ SizeConstraint
+ The direction(s) that an object can be resized in. <a href="http://wiki.roblox.com/index.php/SizeConstraint_(Enum)" target="_blank">More info</a>.
+
+
+ -
+
+ ZIndex
+ Describes the ordering in which overlapping GuiObjects will be drawn. A value of 1 is drawn first, while higher values are drawn in ascending order (each value draws over the last).
+
+
+ -
+
+ BackgroundColor
+ true
+ Deprecated. Use BackgroundColor3 instead
+
+
+ -
+
+ BorderColor
+ true
+ Deprecated. Use BorderColor3 instead
+
+
+
+
+ -
+
-
+
+ DragBegin
+ Fired when a GuiObject with Draggable set to true starts to be dragged. 'InitialPosition' is a UDim2 value of the position of the GuiObject before any drag operation began.
+
+
+ -
+
+ DragStopped
+ Always fired after a DragBegin event, DragStopped is fired when the user releases the mouse button causing a drag operation on the GuiObject. Arguments 'x', and 'y' specify the top-left absolute position of the GuiObject when the event is fired.
+
+
+ -
+
+ MouseEnter
+ Fired when the mouse enters a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseLeave
+ Fired when the mouse leaves a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseMoved
+ Fired when the mouse is inside a GuiObject and moves, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+
+ -
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+
+
+
+
+ -
+
+ NotificationBox
+ false
+
+
+ -
+
+ NotificationObject
+ false
+
+
+ -
+
+ Frame
+ A container object used to layout other GUI objects
+ 15
+ 48
+ StarterGui
+
+
-
+
-
+
+ Style
+ Determines how a frame will look. Uses Enum.FrameStyle. <a href="http://wiki.roblox.com/index.php/Framestyle" target="_blank">More info</a>
+
+
+
+
+ -
+
+ ScrollingFrame
+ A container object used to layout other GUI objects, and allows for scrolling.
+ 15
+ 48
+ StarterGui
+
+
-
+
-
+
+ ScrollingEnabled
+ Determines whether or not scrolling is allowed on this frame. If turned off, no scroll bars will be rendered.
+
+
+ -
+
+ CanvasSize
+ Determines the size of the area that is scrollable. The UDim2 is calculated using the parent gui's size, similar to the regular Size property on gui objects.
+
+
+ -
+
+ CanvasPosition
+ The absolute position the scroll frame is in respect to the canvas size. The minimum this can be set to is (0,0), while the max is the absolute canvas size - AbsoluteWindowSize.
+
+
+ -
+
+ AbsoluteWindowSize
+ The size in pixels of the frame, without the scrollbars.
+
+
+ -
+
+ ScrollBarThickness
+ How thick the scroll bar appears. This applies to both the horizontal and vertical scroll bars. Can be set to 0 for no bars render.
+
+
+ -
+
+ TopImage
+ The "Up" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "left" image on the horizontal scroll bar.
+
+
+ -
+
+ MidImage
+ The "Middle" image on the vertical scrollbar. Size of this can vary in the y direction, but is always set at ScrollBarThickness in x direction. This is also used as the "mid" image on the horizontal scroll bar.
+
+
+ -
+
+ BottomImage
+ The "Down" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "right" image on the horizontal scroll bar.
+
+
+
+
+ -
+
+ ImageLabel
+ A GUI object containing an Image
+ 18
+ 49
+ StarterGui
+
+
-
+
-
+
+ Image
+ Specifies the id of the texture to display. <a href="http://wiki.roblox.com/index.php/Image" target="_blank">More info</a>
+
+
+
+
+ -
+
+ TextLabel
+ A GUI object containing text
+ 19
+ 50
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextButton
+ A GUI button containing text
+ 17
+ 51
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextBox
+ A text entry box
+ 17
+ 51
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ GuiButton
+ A GUI button containing an Image
+ false
+ 16
+ 52
+
+
-
+
-
+
+ AutoButtonColor
+ Determines whether a button changes color automatically when reacting to mouse events.
+
+
+ -
+
+ Modal
+ Allows the mouse to be free in first person mode. If a button with this property set to true is visible, the mouse is 'free' in first person mode.
+
+
+ -
+
+ Style
+ Determines how a button will look, including mouse event states. Uses Enum.ButtonStyle. <a href="http://wiki.roblox.com/index.php/ButtonStyle_(Enum)" target="_blank">More info</a>
+
+
+
+ -
+
-
+
+ MouseButton1Click
+ Fired when the mouse is over the button, and the mouse down and up events fire without the mouse leaving the button.
+
+
+ -
+
+ MouseButton1Down
+ Fired when the mouse button is pushed down on a button.
+
+
+ -
+
+ MouseButton1Up
+ Fired when the mouse button is released on a button.
+
+
+ -
+
+ MouseButton2Click
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Down
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Up
+ This function currently does not work :(
+
+
+
+
+
+ -
+
+ ImageButton
+ A GUI button containing an Image
+ 16
+ 52
+ StarterGui
+
+
-
+
-
+
+ Image
+ Specifies the asset id of the texture to display. <a href="http://wiki.roblox.com/index.php/Image" target="_blank">More info</a>
+
+
+
+
+ -
+
+ Handles
+ A 3D GUI object to represent draggable handles
+
+ 19
+ 53
+
+
+ -
+
+ ArcHandles
+ A 3D GUI object to represent draggable arc handles
+
+ 20
+ 56
+
+
+ -
+
+ SelectionBox
+ A 3D GUI object to represent the visible selection around an object
+ 21
+ 54
+
+
+ -
+
+ SurfaceSelection
+ A 3D GUI object to represent the visible selection around a face of an object
+ 21
+ 55
+
+
+ -
+
+ Configuration
+ An object that can be placed under parts to hold Value objects that represent that part's configuration
+ 22
+ 58
+
+
+ -
+
+ SelectionPartLasso
+ A visual line drawn representation between two part objects
+ 22
+ 57
+
+
+ -
+
+ SelectionPointLasso
+ A visual line drawn representation between two positions
+ 22
+ 57
+
+
+ -
+
+ PartPairLasso
+ A visual line drawn representation between two parts.
+ 22
+ 57
+
+
+ -
+
+ Pose
+ The pose of a joint relative to it's parent part in a keyframe
+ 22
+ 60
+
+
+ -
+
+ Keyframe
+ One keyframe of an animation
+ 22
+ 60
+
+
+ -
+
+ Animation
+ Represents a linked animation object, containing keyframes and poses.
+ 22
+ 60
+
+
+ -
+
+ AnimationTrack
+ Returned by a call to LoadAnimation. Controls the playback of an animation on a Humanoid.
+ 22
+ 60
+
+
-
+
-
+
+ Stopped
+ true
+ This event is never raised
+
+
+
+
+ -
+
+ AnimationController
+ Allows animations to be played on joints of the parent object.
+ 22
+ 60
+
+
+ -
+
+ CharacterMesh
+ Modifies the appearance of a body part.
+ 22
+ 60
+
+
+ -
+
+ Dialog
+ An object used to make dialog trees to converse with players
+ 22
+ 62
+
+
+ -
+
+ DialogChoice
+ An object used to make dialog trees to converse with players
+ 22
+ 63
+
+
+ -
+
+ Terrain
+ Object representing a high performance bounded grid of static 4x4 parts
+ true
+ 0
+ 65
+
+
-
+
-
+
+ GetCell
+ Returns CellMaterial, CellBlock, CellOrientation
+
+
+ -
+
+ GetWaterCell
+
+ Returns hasAnyWater, WaterForce, WaterDirection
+
+
+ -
+
+ SetWaterCell
+
+
+
+
+
+ -
+
+ PointLight
+ Makes the parent part emit light in a spherical shape
+ 3
+ 13
+
+
+ -
+
+ SpotLight
+ Makes the parent part emit light in a conical shape
+ 3
+ 13
+
+
+ -
+
+ RemoteFunction
+ Allow functions defined in one script to be called by another script across client/server boundary
+ 4
+ 66
+
+
+ -
+
+ RemoteEvent
+ Allow events defined in one script to be subscribed to by another script across client/server boundary
+ 5
+ 67
+
+
+ -
+
+ TerrainRegion
+ Object representing a snapshot of the region of terrain
+ true
+ 0
+ 65
+
+
+ -
+
+ ModuleScript
+ A script fragment. Only runs when another script uses require() on it.
+ 5
+ 66
+
+
+
+
diff --git a/Client2014/RobloxProxy.dll b/Client2014/RobloxProxy.dll
new file mode 100644
index 0000000..c382d6d
Binary files /dev/null and b/Client2014/RobloxProxy.dll differ
diff --git a/Client2014/SyntaxPlayerBeta.exe b/Client2014/SyntaxPlayerBeta.exe
new file mode 100644
index 0000000..754f400
Binary files /dev/null and b/Client2014/SyntaxPlayerBeta.exe differ
diff --git a/Client2014/VMProtectSDK32.dll b/Client2014/VMProtectSDK32.dll
new file mode 100644
index 0000000..ac30c03
Binary files /dev/null and b/Client2014/VMProtectSDK32.dll differ
diff --git a/Client2014/boost.dll b/Client2014/boost.dll
new file mode 100644
index 0000000..6f48268
Binary files /dev/null and b/Client2014/boost.dll differ
diff --git a/Client2014/content/fonts/Arial.font b/Client2014/content/fonts/Arial.font
new file mode 100644
index 0000000..f0209da
Binary files /dev/null and b/Client2014/content/fonts/Arial.font differ
diff --git a/Client2014/content/fonts/ArialBold.font b/Client2014/content/fonts/ArialBold.font
new file mode 100644
index 0000000..dab0c94
Binary files /dev/null and b/Client2014/content/fonts/ArialBold.font differ
diff --git a/Client2014/content/fonts/CompositExtraSlot0.mesh b/Client2014/content/fonts/CompositExtraSlot0.mesh
new file mode 100644
index 0000000..87b9d85
Binary files /dev/null and b/Client2014/content/fonts/CompositExtraSlot0.mesh differ
diff --git a/Client2014/content/fonts/CompositExtraSlot1.mesh b/Client2014/content/fonts/CompositExtraSlot1.mesh
new file mode 100644
index 0000000..6874c5e
Binary files /dev/null and b/Client2014/content/fonts/CompositExtraSlot1.mesh differ
diff --git a/Client2014/content/fonts/CompositExtraSlot2.mesh b/Client2014/content/fonts/CompositExtraSlot2.mesh
new file mode 100644
index 0000000..423f198
Binary files /dev/null and b/Client2014/content/fonts/CompositExtraSlot2.mesh differ
diff --git a/Client2014/content/fonts/CompositExtraSlot3.mesh b/Client2014/content/fonts/CompositExtraSlot3.mesh
new file mode 100644
index 0000000..de05ced
Binary files /dev/null and b/Client2014/content/fonts/CompositExtraSlot3.mesh differ
diff --git a/Client2014/content/fonts/CompositExtraSlot4.mesh b/Client2014/content/fonts/CompositExtraSlot4.mesh
new file mode 100644
index 0000000..ff9cb62
Binary files /dev/null and b/Client2014/content/fonts/CompositExtraSlot4.mesh differ
diff --git a/Client2014/content/fonts/CompositFullAtlasBaseTexture.mesh b/Client2014/content/fonts/CompositFullAtlasBaseTexture.mesh
new file mode 100644
index 0000000..b7e6595
Binary files /dev/null and b/Client2014/content/fonts/CompositFullAtlasBaseTexture.mesh differ
diff --git a/Client2014/content/fonts/CompositFullAtlasOverlayTexture.mesh b/Client2014/content/fonts/CompositFullAtlasOverlayTexture.mesh
new file mode 100644
index 0000000..eda1938
Binary files /dev/null and b/Client2014/content/fonts/CompositFullAtlasOverlayTexture.mesh differ
diff --git a/Client2014/content/fonts/CompositLeftArmBase.mesh b/Client2014/content/fonts/CompositLeftArmBase.mesh
new file mode 100644
index 0000000..5bcc4ae
Binary files /dev/null and b/Client2014/content/fonts/CompositLeftArmBase.mesh differ
diff --git a/Client2014/content/fonts/CompositLeftLegBase.mesh b/Client2014/content/fonts/CompositLeftLegBase.mesh
new file mode 100644
index 0000000..f4712ce
Binary files /dev/null and b/Client2014/content/fonts/CompositLeftLegBase.mesh differ
diff --git a/Client2014/content/fonts/CompositPantsTemplate.mesh b/Client2014/content/fonts/CompositPantsTemplate.mesh
new file mode 100644
index 0000000..756ee03
Binary files /dev/null and b/Client2014/content/fonts/CompositPantsTemplate.mesh differ
diff --git a/Client2014/content/fonts/CompositRightArmBase.mesh b/Client2014/content/fonts/CompositRightArmBase.mesh
new file mode 100644
index 0000000..02f2721
Binary files /dev/null and b/Client2014/content/fonts/CompositRightArmBase.mesh differ
diff --git a/Client2014/content/fonts/CompositRightLegBase.mesh b/Client2014/content/fonts/CompositRightLegBase.mesh
new file mode 100644
index 0000000..b287939
Binary files /dev/null and b/Client2014/content/fonts/CompositRightLegBase.mesh differ
diff --git a/Client2014/content/fonts/CompositShirtTemplate.mesh b/Client2014/content/fonts/CompositShirtTemplate.mesh
new file mode 100644
index 0000000..75487e1
Binary files /dev/null and b/Client2014/content/fonts/CompositShirtTemplate.mesh differ
diff --git a/Client2014/content/fonts/CompositTShirt.mesh b/Client2014/content/fonts/CompositTShirt.mesh
new file mode 100644
index 0000000..b39b8ac
Binary files /dev/null and b/Client2014/content/fonts/CompositTShirt.mesh differ
diff --git a/Client2014/content/fonts/CompositTorsoBase.mesh b/Client2014/content/fonts/CompositTorsoBase.mesh
new file mode 100644
index 0000000..0388bde
Binary files /dev/null and b/Client2014/content/fonts/CompositTorsoBase.mesh differ
diff --git a/Client2014/content/fonts/LoadingScript.lua b/Client2014/content/fonts/LoadingScript.lua
new file mode 100644
index 0000000..22969c6
--- /dev/null
+++ b/Client2014/content/fonts/LoadingScript.lua
@@ -0,0 +1,177 @@
+--rbxsig%YL1mzy/MHYBZIy/YPyTW5a+2IGIvi1rHoU0jlxv53VXzZYPw+HeXMzjSBg7YzXUS9p1Ft5aLlmul1YmvXypBGIcMKU/prdq4y9s9W3RG0/77IvYwMjZgKkTMhLyU8qvz70OKNqvdcCklqNC/fPHV35VvgqQk3we3CLShSXmIyMk=%
+--rbxassetid%158948138%
+-- Creates the generic "ROBLOX" loading screen on startup
+-- Written by Ben Tkacheff, 2014
+
+local frame
+local forceRemovalTime = 5
+local destroyed = false
+
+Game:GetService("ContentProvider"):Preload("rbxasset://textures/roblox-logo.png")
+
+-- get control functions set up immediately
+function removeLoadingScreen()
+ if frame then frame:Destroy() end
+ if script then script:Destroy() end
+ destroyed = true
+end
+
+function startForceLoadingDoneTimer()
+ wait(forceRemovalTime)
+ removeLoadingScreen()
+end
+
+function gameIsLoaded()
+ if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
+ removeLoadingScreen()
+ else
+ startForceLoadingDoneTimer()
+ end
+end
+
+function makeDefaultLoadingScreen()
+ if not settings():GetFFlag("NewLoadingScreen") then return end
+ if destroyed then return end
+
+ frame = Instance.new("Frame")
+ frame.ZIndex = 10
+ frame.Active = true
+ frame.Size = UDim2.new(1,0,1,0)
+ frame.BackgroundColor3 = Color3.new(48/255,90/255,206/255)
+
+ local robloxLogo = Instance.new("ImageLabel")
+ robloxLogo.BackgroundTransparency = 1
+ robloxLogo.ZIndex = 10
+ robloxLogo.Image = "rbxasset://textures/roblox-logo.png"
+ robloxLogo.Size = UDim2.new(0,1031,0,265)
+ robloxLogo.Position = UDim2.new(0.5,-515,0.5,-132)
+ robloxLogo.Name = "RobloxLogo"
+ robloxLogo.Parent = frame
+
+ local poweredByText = Instance.new("TextLabel")
+ poweredByText.Font = Enum.Font.SourceSansBold
+ poweredByText.FontSize = Enum.FontSize.Size24
+ poweredByText.TextWrap = true
+ poweredByText.TextColor3 = Color3.new(1,1,1)
+ poweredByText.BackgroundTransparency = 1
+ poweredByText.ZIndex = 10
+ poweredByText.Text = "This Game Powered By"
+ poweredByText.TextXAlignment = Enum.TextXAlignment.Left
+ poweredByText.Size = UDim2.new(1,0,0,40)
+ poweredByText.Position = UDim2.new(0,0,0,-50)
+ poweredByText.Name = "PoweredByText"
+ poweredByText.Parent = robloxLogo
+
+ local exitButton = Instance.new("ImageButton")
+ exitButton.ZIndex = 10
+ exitButton.BackgroundTransparency = 1
+ exitButton.Image = "rbxasset://textures/ui/CloseButton.png"
+ exitButton.Size = UDim2.new(0,22,0,22)
+ exitButton.Position = UDim2.new(1,-23,0,1)
+ exitButton.Name = "ExitButton"
+ exitButton:SetVerb("Exit")
+
+ UserSettings().GameSettings.FullscreenChanged:connect(function ( isFullScreen )
+ if isFullScreen then
+ exitButton.Parent = frame
+ else
+ exitButton.Parent = nil
+ end
+ end)
+ if UserSettings().GameSettings:InFullScreen()then
+ exitButton.Parent = frame
+ end
+
+ -- put something visible up asap
+ frame.Parent = Game.CoreGui.RobloxGui
+
+ local instanceText = Instance.new("TextLabel")
+ instanceText.Font = Enum.Font.SourceSansBold
+ instanceText.FontSize = Enum.FontSize.Size18
+ instanceText.TextWrap = true
+ instanceText.TextColor3 = Color3.new(1,1,1)
+ instanceText.BackgroundTransparency = 1
+ instanceText.ZIndex = 10
+ instanceText.Text = ""
+ instanceText.Size = UDim2.new(1,0,0,40)
+ instanceText.Position = UDim2.new(0,0,1,-60)
+ instanceText.Name = "InstanceText"
+ instanceText.Parent = frame
+
+ local loadingText = Instance.new("TextLabel")
+ loadingText.Font = Enum.Font.SourceSansBold
+ loadingText.FontSize = Enum.FontSize.Size36
+ loadingText.TextWrap = true
+ loadingText.TextColor3 = Color3.new(1,1,1)
+ loadingText.BackgroundTransparency = 1
+ loadingText.ZIndex = 10
+ loadingText.Text = "Loading"
+ loadingText.Size = UDim2.new(1,0,0,40)
+ loadingText.Position = UDim2.new(0,0,1,20)
+ loadingText.Name = "LoadingText"
+ loadingText.Parent = robloxLogo
+
+ local howManyDots = 0
+ local lastUpdateTime = tick()
+ local minUpdateTime = 0.3
+ local aspectRatio = 1031/265
+
+ function ResolutionChanged( prop )
+ if prop == "AbsoluteSize" then
+ local size = Game.CoreGui.RobloxGui.AbsoluteSize
+ if size.X >= 1031 then
+ robloxLogo.Size = UDim2.new(0,1031,0,265)
+ robloxLogo.Position = UDim2.new(0.5,-515,0.5,-132)
+ else
+ local sizeReducer = -0.05
+ while size.X < robloxLogo.AbsoluteSize.X do
+
+ robloxLogo.Size = UDim2.new(sizeReducer,1031,0,265)
+ local newY = robloxLogo.AbsoluteSize.X * 265/1031
+ robloxLogo.Size = UDim2.new(sizeReducer,1031,0,newY)
+ robloxLogo.Position = UDim2.new(0.5 - (sizeReducer/2),-515,0.5,-132)
+
+ sizeReducer = sizeReducer - 0.1
+ end
+ end
+ end
+ end
+
+ ResolutionChanged("AbsoluteSize")
+ Game.CoreGui.RobloxGui.Changed:connect(ResolutionChanged)
+
+ Game:GetService("RunService").RenderStepped:connect(function()
+ instanceText.Text = Game:GetMessage()
+
+ if tick() - lastUpdateTime >= minUpdateTime then
+ howManyDots = howManyDots + 1
+ if howManyDots > 5 then
+ howManyDots = 0
+ end
+
+ loadingText.Text = "Loading"
+ for i = 1, howManyDots do
+ loadingText.Text = loadingText.Text .. "."
+ end
+ lastUpdateTime = tick()
+ end
+ end)
+end
+
+makeDefaultLoadingScreen()
+
+Game.ReplicatedFirst.RemoveDefaultLoadingGuiSignal:connect(function()
+ removeLoadingScreen()
+end)
+if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
+ removeLoadingScreen()
+ return
+end
+
+Game.Loaded:connect(function()
+ gameIsLoaded()
+end)
+
+if Game:IsLoaded() then
+ gameIsLoaded()
+end
\ No newline at end of file
diff --git a/Client2014/content/fonts/Rocket.rbxm b/Client2014/content/fonts/Rocket.rbxm
new file mode 100644
index 0000000..72beea5
--- /dev/null
+++ b/Client2014/content/fonts/Rocket.rbxm
@@ -0,0 +1,102 @@
+
+ null
+ nil
+ -
+
+ false
+ -0.5
+ 0.5
+ 3
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+ 23
+
+ -0.5
+ 0.5
+ 0
+ -1.1920929e-007
+ 1.00000012
+ 0
+ 1.00000012
+ -1.1920929e-007
+ 0
+ 0
+ 0
+ -1.00000024
+
+ true
+ true
+ 0
+ true
+ true
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 3
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+ false
+ Rocket
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ 1
+
+ 1
+ 1
+ 4
+
+
+
-
+
+ true
+ Swoosh
+ 0
+ false
+ rbxasset://sounds\Rocket whoosh 01.wav
+ 0.699999988
+
+
+ -
+
+ false
+ Explosion
+ 0
+ true
+ rbxasset://sounds\collide.wav
+ 1
+
+
+ -
+
+ Script
+ r = game:service("RunService")
shaft = script.Parent
position = Vector3.new(0,0,0)
function fly()
direction = shaft.CFrame.lookVector
position = position + direction
error = position - shaft.Position
shaft.Velocity = 7*error
end
function blow()
swoosh:Stop()
explosion = Instance.new("Explosion")
explosion.Position = shaft.Position
explosion.Parent = game.Workspace
connection:disconnect()
shaft:remove()
end
t, s = r.Stepped:wait()
swoosh = script.Parent.Swoosh
swoosh:Play()
position = shaft.Position
d = t + 10.0 - s
connection = shaft.Touched:connect(blow)
while t < d do
fly()
t = r.Stepped:wait()
end
script.Parent.Explosion.PlayOnRemove = false
swoosh:Stop()
shaft:remove()
+
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/SlingshotPellet.rbxm b/Client2014/content/fonts/SlingshotPellet.rbxm
new file mode 100644
index 0000000..d753b0a
--- /dev/null
+++ b/Client2014/content/fonts/SlingshotPellet.rbxm
@@ -0,0 +1,82 @@
+
+ null
+ nil
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 194
+
+ 0
+ 6.4000001
+ -8
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ true
+ true
+ 0
+ true
+ true
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ false
+ Pellet
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ 0
+
+ 2
+ 2
+ 2
+
+
+
-
+
+ Script
+
pellet = script.Parent
damage = 8
function onTouched(hit)
humanoid = hit.Parent:findFirstChild("Humanoid")
if humanoid~=nil then
humanoid.Health = humanoid.Health - damage
connection:disconnect()
else
damage = damage / 2
if damage < 0.1 then
connection:disconnect()
end
end
end
connection = pellet.Touched:connect(onTouched)
r = game:service("RunService")
t, s = r.Stepped:wait()
d = t + 1.0 - s
while t < d do
t = r.Stepped:wait()
end
pellet.Parent = nil
+
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/SourceSans.font b/Client2014/content/fonts/SourceSans.font
new file mode 100644
index 0000000..ea67ffc
Binary files /dev/null and b/Client2014/content/fonts/SourceSans.font differ
diff --git a/Client2014/content/fonts/SourceSansBold.font b/Client2014/content/fonts/SourceSansBold.font
new file mode 100644
index 0000000..1749dab
Binary files /dev/null and b/Client2014/content/fonts/SourceSansBold.font differ
diff --git a/Client2014/content/fonts/character.rbxm b/Client2014/content/fonts/character.rbxm
new file mode 100644
index 0000000..7bf4b8a
--- /dev/null
+++ b/Client2014/content/fonts/character.rbxm
@@ -0,0 +1,527 @@
+
+ null
+ nil
+ -
+
+ 7
+ true
+
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ erik.cassel
+
[RBX1]
+ true
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 0
+ 4.5
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Head
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 1
+ 1
+
+
+
-
+
+
+ 0
+ Mesh
+
+ 1.25
+ 1.25
+ 1.25
+
+
+
+ 1
+ 1
+ 1
+
+ true
+
+
+ -
+
+ 5
+ face
+ 20
+ 0
+ rbxasset://textures/face.png
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ true
+ Torso
+ 0
+ 0
+ 0
+ 2
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
-
+
+ 5
+ roblox
+ 20
+ 0
+
+
+
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ -1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ 0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ -0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ 100
+ false
+ 100
+ Humanoid
+ false
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 0
+
[null]
+
+ 0
+ 0
+ 0
+
+ true
+
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/character3.rbxm b/Client2014/content/fonts/character3.rbxm
new file mode 100644
index 0000000..e39f9d6
--- /dev/null
+++ b/Client2014/content/fonts/character3.rbxm
@@ -0,0 +1,599 @@
+
+ null
+ nil
+ -
+
+ 7
+ true
+
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ erik.cassel
+
[RBX1]
+ true
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 0
+ 4.5
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Head
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 1
+ 1
+
+
+
-
+
+
+ 0
+ Mesh
+
+ 1.25
+ 1.25
+ 1.25
+
+
+
+ 1
+ 1
+ 1
+
+ true
+
+
+ -
+
+ 5
+ face
+ 20
+ 0
+ rbxasset://textures/face.png
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ true
+ Torso
+ 0
+ 0
+ 0
+ 2
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
-
+
+ 5
+ roblox
+ 20
+ 0
+
+
+
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ -1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ 0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ -0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ 100
+ false
+ 100
+ Humanoid
+ false
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 0
+
[null]
+
+ 0
+ 0
+ 0
+
+ true
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ true
+ HumanoidRootPart
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 1
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/comics.fnt b/Client2014/content/fonts/comics.fnt
new file mode 100644
index 0000000..6b71c7e
Binary files /dev/null and b/Client2014/content/fonts/comics.fnt differ
diff --git a/Client2014/content/fonts/diogenes.fnt b/Client2014/content/fonts/diogenes.fnt
new file mode 100644
index 0000000..c43fded
--- /dev/null
+++ b/Client2014/content/fonts/diogenes.fnt
@@ -0,0 +1,356 @@
+a 6>
+4=:90
+4;499,
+4; &
+4&=:90
+4&=:90&
+4&&=:90
+4&&=:90&
+4&&><&&0'
+704&!<49
+7 !!3 6>0'
+7 !!=4<'
+7 !!&0-
+7 !!&06&
+7 !!&0>&
+6=<;>
+6<'690?0'>
+69
+6:6>{
+6:6>&
+6:6>& 6>
+6:6>& 6>01
+6:6>& 6>0'
+6:6>& 6><;2
+6:6>& 6>&
+6:>
+6:;1:8
+6:;1:8&
+6::!0'
+6 8
+6 880'
+6 88<;2
+6 8&
+6 8&=:!
+6 8&=:!
+6 ;<9<;2 &
+6 ;<99<;2 &
+6 ;;<9<;2 &
+6 ;!
+6 ;!9<6>
+6 ;!9<6>0'
+6 ;!9<6><;2
+6 ;!&
+6,70'3 6
+6,70'3 6>
+6,70'3 6>01
+6,70'3 6>0'
+6,70'3 6>0'&
+6,70'3 6><;2
+1<6>
+1<6>&
+1<>0
+1<91:
+1<91:
+1<91:&
+1<91:&
+1<%&=0
+0?46 94!0
+0?46 94!01
+0?46 94!0&
+0?46 94!<;2
+0?46 94!<;2&
+0?46 94!<:;
+30'
+3<;2
+342
+3420!
+3422
+34220!
+3422<;2
+3422
+36><;2
+3094!<:
+3094!<:
+30994!<:
+3<;20'74;2
+3<;20'3 6>
+3<;20'3 6>01
+3<;20'3 6>0'
+3<;20'3 6>0'&
+3<;20'3 6><;2
+3<;20'3 6>&
+3<&!3 6>
+3<&!3 6>01
+3<&!3 6>0'
+3<&!3 6>0'&
+3<&!3 6><;2
+3<&!3 6><;2&
+3<&!3 6>&
+3:6><;2
+3 6>
+3 6>t
+3 6>0
+3 6>01
+3 6>0;
+3 6>0'
+3 6>0'&
+3 6><;
+3 6><;2
+3 6><;2&
+3 6>>>>>>>>>>>>>>>>>
+3 6>80
+3 6>&
+3 6>!4'1
+3 6>,:
+3 >
+3 >0'
+3 ><;
+3 ><;2
+3 >>
+3 >&
+3 '7 '20'
+24;274;2
+24;274;201
+24;274;2&
+24,
+24,&0-
+24/:;24&
+24/:;20'&
+2:;41&
+2::>
+=4'16:'0&0-
+=4'1:;
+=:8:
+=::>0'
+=:';<0&!
+=:';,
+=:!&0-
+= 8%
+?46>4&&
+?46><;2:33
+?46>:33
+?46>x:33
+?4%
+?0'>x:33
+?0"
+?<&8
+?
+?8
+?/
+><>0
+>>>
+>:6>
+>:;1 8
+>:;1 8&
+> 8
+> 880'
+> 88<;2
+> 8&
+> ;<9<;2 &
+90&7<4;
+90&7:
+9 &!<;2
+80'10
+8:90&!
+8:!=43 6>
+8:!=43 6>
+8:!=43 6>4
+8:!=43 6>4
+8:!=43 6>4&
+8:!=43 6>4&
+8:!=43 6>4/
+8:!=43 6>4/
+8:!=43 6>01
+8:!=43 6>01
+8:!=43 6>0'
+8:!=43 6>0'
+8:!=43 6>0'&
+8:!=43 6>0'&
+8:!=43 6><;
+8:!=43 6><;
+8:!=43 6><;2
+8:!=43 6><;2
+8:!=43 6><;2&
+8:!=43 6><;2&
+8:!=43 6>&
+8:!=43 6>&
+8:!=0'3 6>
+8:!=0'3 6>
+8:!=0'3 6>01
+8:!=0'3 6>0'
+8:!=0'3 6>0'
+8:!=0'3 6>0'&
+8:!=0'3 6>0'&
+8:!=0'3 6><;
+8:!=0'3 6><;
+8:!=0'3 6><;2
+8:!=0'3 6><;2
+8:!=0'3 6><;2&
+8:!=0'3 6><;2&
+8:!=0'3 6>&
+8:!=0'3 6>&
+;4/<
+;<20'
+;<224
+;<224&
+;<220'
+;<220'
+;<220'&
+;<220'&
+:'24&<8
+:'24&<8&
+:'24&8
+:'24&8&
+%06>0'
+%0;<&
+%=:;0&0-
+%= >01
+%= ><;2
+%= >>01
+%= >><;2
+%= >
+%= >&
+%= $
+%<8%
+%<&&:33
+%:';
+%:';:
+%:';:2'4%=,
+%:';:&
+%'<6>
+%'<6>&
+%':&!
+& 6>
+!'48%
+!"4!
+#42<;4
+#<7'4!:'
+"4;2
+"4;>
+"4;>0'
+"0!746>
+"=:'0
+":%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client2014/content/fonts/fonts.dds b/Client2014/content/fonts/fonts.dds
new file mode 100644
index 0000000..add0f07
Binary files /dev/null and b/Client2014/content/fonts/fonts.dds differ
diff --git a/Client2014/content/fonts/head.mesh b/Client2014/content/fonts/head.mesh
new file mode 100644
index 0000000..26db950
Binary files /dev/null and b/Client2014/content/fonts/head.mesh differ
diff --git a/Client2014/content/fonts/headA.mesh b/Client2014/content/fonts/headA.mesh
new file mode 100644
index 0000000..76b2e72
Binary files /dev/null and b/Client2014/content/fonts/headA.mesh differ
diff --git a/Client2014/content/fonts/headB.mesh b/Client2014/content/fonts/headB.mesh
new file mode 100644
index 0000000..7705a05
Binary files /dev/null and b/Client2014/content/fonts/headB.mesh differ
diff --git a/Client2014/content/fonts/headC.mesh b/Client2014/content/fonts/headC.mesh
new file mode 100644
index 0000000..4672c59
Binary files /dev/null and b/Client2014/content/fonts/headC.mesh differ
diff --git a/Client2014/content/fonts/headD.mesh b/Client2014/content/fonts/headD.mesh
new file mode 100644
index 0000000..ff6cd6c
Binary files /dev/null and b/Client2014/content/fonts/headD.mesh differ
diff --git a/Client2014/content/fonts/headE.mesh b/Client2014/content/fonts/headE.mesh
new file mode 100644
index 0000000..d722d29
Binary files /dev/null and b/Client2014/content/fonts/headE.mesh differ
diff --git a/Client2014/content/fonts/headF.mesh b/Client2014/content/fonts/headF.mesh
new file mode 100644
index 0000000..7c0b311
Binary files /dev/null and b/Client2014/content/fonts/headF.mesh differ
diff --git a/Client2014/content/fonts/headG.mesh b/Client2014/content/fonts/headG.mesh
new file mode 100644
index 0000000..38db235
Binary files /dev/null and b/Client2014/content/fonts/headG.mesh differ
diff --git a/Client2014/content/fonts/headH.mesh b/Client2014/content/fonts/headH.mesh
new file mode 100644
index 0000000..fe7365b
Binary files /dev/null and b/Client2014/content/fonts/headH.mesh differ
diff --git a/Client2014/content/fonts/headI.mesh b/Client2014/content/fonts/headI.mesh
new file mode 100644
index 0000000..8ff7ba1
Binary files /dev/null and b/Client2014/content/fonts/headI.mesh differ
diff --git a/Client2014/content/fonts/headJ.mesh b/Client2014/content/fonts/headJ.mesh
new file mode 100644
index 0000000..ff76d44
Binary files /dev/null and b/Client2014/content/fonts/headJ.mesh differ
diff --git a/Client2014/content/fonts/headK.mesh b/Client2014/content/fonts/headK.mesh
new file mode 100644
index 0000000..b08bffc
Binary files /dev/null and b/Client2014/content/fonts/headK.mesh differ
diff --git a/Client2014/content/fonts/headL.mesh b/Client2014/content/fonts/headL.mesh
new file mode 100644
index 0000000..645531b
Binary files /dev/null and b/Client2014/content/fonts/headL.mesh differ
diff --git a/Client2014/content/fonts/headM.mesh b/Client2014/content/fonts/headM.mesh
new file mode 100644
index 0000000..ba144e8
Binary files /dev/null and b/Client2014/content/fonts/headM.mesh differ
diff --git a/Client2014/content/fonts/headN.mesh b/Client2014/content/fonts/headN.mesh
new file mode 100644
index 0000000..6fc4620
Binary files /dev/null and b/Client2014/content/fonts/headN.mesh differ
diff --git a/Client2014/content/fonts/headO.mesh b/Client2014/content/fonts/headO.mesh
new file mode 100644
index 0000000..a41f85f
Binary files /dev/null and b/Client2014/content/fonts/headO.mesh differ
diff --git a/Client2014/content/fonts/headP.mesh b/Client2014/content/fonts/headP.mesh
new file mode 100644
index 0000000..cdb1647
Binary files /dev/null and b/Client2014/content/fonts/headP.mesh differ
diff --git a/Client2014/content/fonts/humanoidAnimate.rbxm b/Client2014/content/fonts/humanoidAnimate.rbxm
new file mode 100644
index 0000000..7a59cb9
--- /dev/null
+++ b/Client2014/content/fonts/humanoidAnimate.rbxm
@@ -0,0 +1,296 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+ -- Now with exciting TeamColors HACK!
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+-- TEAM COLORS
+
+
+function onTeamChanged(player)
+
+ wait(1)
+
+ local char = player.Character
+ if char == nil then return end
+
+ if player.Neutral then
+ -- Replacing the current BodyColor object will force a reset
+ local old = char:findFirstChild("Body Colors")
+ if not old then return end
+ old:clone().Parent = char
+ old.Parent = nil
+ else
+ local head = char:findFirstChild("Head")
+ local torso = char:findFirstChild("Torso")
+ local left_arm = char:findFirstChild("Left Arm")
+ local right_arm = char:findFirstChild("Right Arm")
+ local left_leg = char:findFirstChild("Left Leg")
+ local right_leg = char:findFirstChild("Right Leg")
+
+ if head then head.BrickColor = BrickColor.new(24) end
+ if torso then torso.BrickColor = player.TeamColor end
+ if left_arm then left_arm.BrickColor = BrickColor.new(26) end
+ if right_arm then right_arm.BrickColor = BrickColor.new(26) end
+ if left_leg then left_leg.BrickColor = BrickColor.new(26) end
+ if right_leg then right_leg.BrickColor = BrickColor.new(26) end
+ end
+end
+
+function onPlayerPropChanged(property, player)
+ if property == "Character" then
+ onTeamChanged(player)
+ end
+ if property== "TeamColor" or property == "Neutral" then
+ onTeamChanged(player)
+ end
+end
+
+
+local cPlayer = game.Players:GetPlayerFromCharacter(script.Parent)
+cPlayer.Changed:connect(function(property) onPlayerPropChanged(property, cPlayer) end )
+onTeamChanged(cPlayer)
+
+
+-- ANIMATION
+
+-- declarations
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local toolAnim = "None"
+local toolAnimTime = 0
+
+-- functions
+
+function onRunning(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ pose = "Jumping"
+end
+
+function onClimbing()
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function moveJump()
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+
+-- same as jump for now
+
+function moveFreeFall()
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ RightShoulder:SetDesiredAngle(1.57)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ RightShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(0)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightHip.MaxVelocity = 0.5
+ LeftHip.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(1.57)
+ LeftShoulder:SetDesiredAngle(1.0)
+ RightHip:SetDesiredAngle(1.57)
+ LeftHip:SetDesiredAngle(1.0)
+ return
+ end
+end
+
+function move(time)
+ local amplitude
+ local frequency
+
+ if (pose == "Jumping") then
+ moveJump()
+ return
+ end
+
+ if (pose == "FreeFall") then
+ moveFreeFall()
+ return
+ end
+
+ if (pose == "Seated") then
+ moveSit()
+ return
+ end
+
+ local climbFudge = 0
+
+ if (pose == "Running") then
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ amplitude = 1
+ frequency = 9
+ elseif (pose == "Climbing") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ amplitude = 1
+ frequency = 9
+ climbFudge = 3.14
+ else
+ amplitude = 0.1
+ frequency = 1
+ end
+
+ desiredAngle = amplitude * math.sin(time*frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+
+
+ local tool = getTool()
+
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+
+
+ else
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+
+-- connect events
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+
+-- main program
+
+local runService = game:service("RunService");
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidAnimateLocal.rbxm b/Client2014/content/fonts/humanoidAnimateLocal.rbxm
new file mode 100644
index 0000000..5c18211
--- /dev/null
+++ b/Client2014/content/fonts/humanoidAnimateLocal.rbxm
@@ -0,0 +1,336 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+
+
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+-- ANIMATION
+
+-- declarations
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local toolAnim = "None"
+local toolAnimTime = 0
+
+local jumpMaxLimbVelocity = 0.75
+
+-- functions
+
+function onRunning(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ pose = "Jumping"
+end
+
+function onClimbing()
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function onSwimming(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function moveJump()
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+
+-- same as jump for now
+
+function moveFreeFall()
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ RightShoulder:SetDesiredAngle(1.57)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ RightShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(0)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightHip.MaxVelocity = 0.5
+ LeftHip.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(1.57)
+ LeftShoulder:SetDesiredAngle(1.0)
+ RightHip:SetDesiredAngle(1.57)
+ LeftHip:SetDesiredAngle(1.0)
+ return
+ end
+end
+
+function move(time)
+ local amplitude
+ local frequency
+
+ if (pose == "Jumping") then
+ moveJump()
+ return
+ end
+
+ if (pose == "FreeFall") then
+ moveFreeFall()
+ return
+ end
+
+ if (pose == "Seated") then
+ moveSit()
+ return
+ end
+
+ local climbFudge = 0
+
+ if (pose == "Running") then
+ if (RightShoulder.CurrentAngle > 1.5 or RightShoulder.CurrentAngle < -1.5) then
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ else
+ RightShoulder.MaxVelocity = 0.15
+ end
+ if (LeftShoulder.CurrentAngle > 1.5 or LeftShoulder.CurrentAngle < -1.5) then
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ else
+ LeftShoulder.MaxVelocity = 0.15
+ end
+ amplitude = 1
+ frequency = 9
+ elseif (pose == "Climbing") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ amplitude = 1
+ frequency = 9
+ climbFudge = 3.14
+ else
+ amplitude = 0.1
+ frequency = 1
+ end
+
+ desiredAngle = amplitude * math.sin(time*frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+
+
+ local tool = getTool()
+
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+
+
+ else
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+
+-- connect events
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+Humanoid.Swimming:connect(onSwimming)
+-- main program
+
+local runService = game:service("RunService");
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+ true
+
+
+ -
+
+ false
+
+
+
+ RobloxTeam
+
+ -- Now with exciting TeamColors HACK!
+
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+ end
+
+ -- TEAM COLORS
+
+
+ function onTeamChanged(player)
+
+ wait(1)
+
+ local char = player.Character
+ if char == nil then return end
+
+ if player.Neutral then
+ -- Replacing the current BodyColor object will force a reset
+ local old = char:findFirstChild("Body Colors")
+ if not old then return end
+ old:clone().Parent = char
+ old.Parent = nil
+ else
+ local head = char:findFirstChild("Head")
+ local torso = char:findFirstChild("Torso")
+ local left_arm = char:findFirstChild("Left Arm")
+ local right_arm = char:findFirstChild("Right Arm")
+ local left_leg = char:findFirstChild("Left Leg")
+ local right_leg = char:findFirstChild("Right Leg")
+
+ if head then head.BrickColor = BrickColor.new(24) end
+ if torso then torso.BrickColor = player.TeamColor end
+ if left_arm then left_arm.BrickColor = BrickColor.new(26) end
+ if right_arm then right_arm.BrickColor = BrickColor.new(26) end
+ if left_leg then left_leg.BrickColor = BrickColor.new(26) end
+ if right_leg then right_leg.BrickColor = BrickColor.new(26) end
+ end
+ end
+
+ function onPlayerPropChanged(property, player)
+ if property == "Character" then
+ onTeamChanged(player)
+ end
+ if property== "TeamColor" or property == "Neutral" then
+ onTeamChanged(player)
+ end
+ end
+
+
+ local cPlayer = game.Players:GetPlayerFromCharacter(script.Parent)
+ cPlayer.Changed:connect(function(property) onPlayerPropChanged(property, cPlayer) end )
+ onTeamChanged(cPlayer)
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidAnimateLocalKeyframe.rbxm b/Client2014/content/fonts/humanoidAnimateLocalKeyframe.rbxm
new file mode 100644
index 0000000..981e3cb
--- /dev/null
+++ b/Client2014/content/fonts/humanoidAnimateLocalKeyframe.rbxm
@@ -0,0 +1,606 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local currentAnim = ""
+local currentAnimTrack = nil
+local currentAnimKeyframeHandler = nil
+local currentAnimSpeed = 1.0
+local oldAnimTrack = nil
+local animTable = {}
+local animNames = {
+ idle = {
+ { id = "http://www.roblox.com/asset/?id=125750544", weight = 9 },
+ { id = "http://www.roblox.com/asset/?id=125750618", weight = 1 }
+ },
+ walk = {
+ { id = "http://www.roblox.com/asset/?id=125749145", weight = 10 }
+ },
+ run = {
+ { id = "run.xml", weight = 10 }
+ },
+ jump = {
+ { id = "http://www.roblox.com/asset/?id=125750702", weight = 10 }
+ },
+ fall = {
+ { id = "http://www.roblox.com/asset/?id=125750759", weight = 10 }
+ },
+ climb = {
+ { id = "http://www.roblox.com/asset/?id=125750800", weight = 10 }
+ },
+ toolnone = {
+ { id = "http://www.roblox.com/asset/?id=125750867", weight = 10 }
+ },
+ toolslash = {
+ { id = "http://www.roblox.com/asset/?id=129967390", weight = 10 }
+-- { id = "slash.xml", weight = 10 }
+ },
+ toollunge = {
+ { id = "http://www.roblox.com/asset/?id=129967478", weight = 10 }
+ },
+ wave = {
+ { id = "http://www.roblox.com/asset/?id=128777973", weight = 10 }
+ },
+ point = {
+ { id = "http://www.roblox.com/asset/?id=128853357", weight = 10 }
+ },
+ dance = {
+ { id = "http://www.roblox.com/asset/?id=130018893", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=132546839", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=132546884", weight = 10 }
+ },
+ laugh = {
+ { id = "http://www.roblox.com/asset/?id=129423131", weight = 10 }
+ },
+ cheer = {
+ { id = "http://www.roblox.com/asset/?id=129423030", weight = 10 }
+ },
+}
+
+-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
+local emoteNames = { wave = false, point = false, dance = true, laugh = false, cheer = false}
+
+math.randomseed(tick())
+
+-- Setup animation objects
+for name, fileList in pairs(animNames) do
+ animTable[name] = {}
+ animTable[name].count = 0
+ animTable[name].totalWeight = 0
+
+ -- check for config values
+ local config = script:FindFirstChild(name)
+ if (config ~= nil) then
+-- print("Loading anims " .. name)
+ local idx = 1
+ for _, childPart in pairs(config:GetChildren()) do
+ animTable[name][idx] = {}
+ animTable[name][idx].anim = childPart
+ local weightObject = childPart:FindFirstChild("Weight")
+ if (weightObject == nil) then
+ animTable[name][idx].weight = 1
+ else
+ animTable[name][idx].weight = weightObject.Value
+ end
+ animTable[name].count = animTable[name].count + 1
+ animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
+-- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")")
+ idx = idx + 1
+ end
+ end
+
+ -- fallback to defaults
+ if (animTable[name].count <= 0) then
+ for idx, anim in pairs(fileList) do
+ animTable[name][idx] = {}
+ animTable[name][idx].anim = Instance.new("Animation")
+ animTable[name][idx].anim.Name = name
+ animTable[name][idx].anim.AnimationId = anim.id
+ animTable[name][idx].weight = anim.weight
+ animTable[name].count = animTable[name].count + 1
+ animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
+-- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
+ end
+ end
+end
+
+-- ANIMATION
+
+-- declarations
+local toolAnim = "None"
+local toolAnimTime = 0
+
+local jumpAnimTime = 0
+local jumpAnimDuration = 0.175
+
+local toolTransitionTime = 0.1
+local fallTransitionTime = 0.2
+local jumpMaxLimbVelocity = 0.75
+
+-- functions
+
+function stopAllAnimations()
+ local oldAnim = currentAnim
+
+ -- return to idle if finishing an emote
+ if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then
+ oldAnim = "idle"
+ end
+
+ currentAnim = ""
+ if (currentAnimKeyframeHandler ~= nil) then
+ currentAnimKeyframeHandler:disconnect()
+ end
+
+ if (oldAnimTrack ~= nil) then
+ oldAnimTrack:Stop()
+ oldAnimTrack:Destroy()
+ oldAnimTrack = nil
+ end
+ if (currentAnimTrack ~= nil) then
+ currentAnimTrack:Stop()
+ currentAnimTrack:Destroy()
+ currentAnimTrack = nil
+ end
+ return oldAnim
+end
+
+function setAnimationSpeed(speed)
+ if speed ~= currentAnimSpeed then
+ currentAnimSpeed = speed
+ currentAnimTrack:AdjustSpeed(currentAnimSpeed)
+ end
+end
+
+function keyFrameReachedFunc(frameName)
+ if (frameName == "End") then
+-- print("Keyframe : ".. frameName)
+ local repeatAnim = stopAllAnimations()
+ local animSpeed = currentAnimSpeed
+ playAnimation(repeatAnim, 0.0, Humanoid)
+ setAnimationSpeed(animSpeed)
+ end
+end
+
+-- Preload animations
+function playAnimation(animName, transitionTime, humanoid)
+ if (animName ~= currentAnim) then
+
+ if (oldAnimTrack ~= nil) then
+ oldAnimTrack:Stop()
+ oldAnimTrack:Destroy()
+ end
+
+ currentAnimSpeed = 1.0
+ local roll = math.random(1, animTable[animName].totalWeight)
+ local origRoll = roll
+ local idx = 1
+ while (roll > animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ -- load it to the humanoid; get AnimationTrack
+ oldAnimTrack = currentAnimTrack
+ currentAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ currentAnimTrack:Play(transitionTime)
+ currentAnim = animName
+
+ -- set up keyframe name triggers
+ if (currentAnimKeyframeHandler ~= nil) then
+ currentAnimKeyframeHandler:disconnect()
+ end
+ currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
+ end
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+local toolAnimName = ""
+local toolOldAnimTrack = nil
+local toolAnimTrack = nil
+local currentToolAnimKeyframeHandler = nil
+
+function toolKeyFrameReachedFunc(frameName)
+ if (frameName == "End") then
+-- print("Keyframe : ".. frameName)
+ local repeatAnim = stopToolAnimations()
+ playToolAnimation(repeatAnim, 0.0, Humanoid)
+ end
+end
+
+
+function playToolAnimation(animName, transitionTime, humanoid)
+ if (animName ~= toolAnimName) then
+
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ transitionTime = 0
+ end
+
+ local roll = math.random(1, animTable[animName].totalWeight)
+ local origRoll = roll
+ local idx = 1
+ while (roll > animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ -- load it to the humanoid; get AnimationTrack
+ toolOldAnimTrack = toolAnimTrack
+ toolAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ toolAnimTrack:Play(transitionTime)
+ toolAnimName = animName
+
+ currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
+ end
+end
+
+function stopToolAnimations()
+ local oldAnim = toolAnimName
+
+ if (currentToolAnimKeyframeHandler ~= nil) then
+ currentToolAnimKeyframeHandler:disconnect()
+ end
+
+ toolAnimName = ""
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ toolAnimTrack = nil
+ end
+
+
+ return oldAnim
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+
+function onRunning(speed)
+ if speed>0 then
+ playAnimation("walk", 0.1, Humanoid)
+ pose = "Running"
+ else
+ playAnimation("idle", 0.1, Humanoid)
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ playAnimation("jump", 0.1, Humanoid)
+ jumpAnimTime = jumpAnimDuration
+ pose = "Jumping"
+end
+
+function onClimbing(speed)
+ playAnimation("climb", 0.1, Humanoid)
+ setAnimationSpeed(speed / 12.0)
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ if (jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ end
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function onSwimming(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ playToolAnimation("toolnone", toolTransitionTime, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ playToolAnimation("toolslash", 0, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ playToolAnimation("toollunge", 0, Humanoid)
+ return
+ end
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+local lastTick = 0
+
+function move(time)
+ local amplitude = 1
+ local frequency = 1
+ local deltaTime = time - lastTick
+ lastTick = time
+
+ local climbFudge = 0
+ local setAngles = false
+
+ if (jumpAnimTime > 0) then
+ jumpAnimTime = jumpAnimTime - deltaTime
+ end
+
+ if (pose == "FreeFall" and jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ elseif (pose == "Seated") then
+ stopAllAnimations()
+ moveSit()
+ return
+ elseif (pose == "Running") then
+ playAnimation("walk", 0.1, Humanoid)
+ elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
+-- print("Wha " .. pose)
+ amplitude = 0.1
+ frequency = 1
+ setAngles = true
+ end
+
+ if (setAngles) then
+ desiredAngle = amplitude * math.sin(time * frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+ end
+
+ -- Tool Animation handling
+ local tool = getTool()
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+ else
+ stopToolAnimations()
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+-- connect events
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+Humanoid.Swimming:connect(onSwimming)
+
+-- setup emote chat hook
+Game.Players.LocalPlayer.Chatted:connect(function(msg)
+ local emote = ""
+ if (string.sub(msg, 1, 3) == "/e ") then
+ emote = string.sub(msg, 4)
+ elseif (string.sub(msg, 1, 7) == "/emote ") then
+ emote = string.sub(msg, 8)
+ end
+
+ if (pose == "Standing" and emoteNames[emote] ~= nil) then
+ playAnimation(emote, 0.1, Humanoid)
+ end
+-- print("===> " .. string.sub(msg, 1, 3) .. "(" .. emote .. ")")
+end)
+
+
+-- main program
+
+local runService = game:service("RunService");
+
+-- initialize to idle
+playAnimation("idle", 0.1, Humanoid)
+pose = "Standing"
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+
+
+
+
-
+
+ idle
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750544
+ Animation1
+
+
-
+
+ Weight
+ 9
+
+
+
+ -
+
+ http://www.roblox.com/asset/?id=125750618
+ Animation2
+
+
-
+
+ Weight
+ 1
+
+
+
+
+ -
+
+ walk
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125749145
+ WalkAnim
+
+
+
+ -
+
+ run
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125749145
+ RunAnim
+
+
+
+ -
+
+ jump
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750702
+ JumpAnim
+
+
+
+ -
+
+ climb
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750800
+ ClimbAnim
+
+
+
+ -
+
+ toolnone
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750867
+ ToolNoneAnim
+
+
+
+ -
+
+ fall
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750759
+ FallAnim
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidExtra.rbxm b/Client2014/content/fonts/humanoidExtra.rbxm
new file mode 100644
index 0000000..ea08e27
--- /dev/null
+++ b/Client2014/content/fonts/humanoidExtra.rbxm
@@ -0,0 +1,11 @@
+
+ null
+ nil
+ -
+
+ false
+ Script
+
while script.Parent.Head==nil do
wait(0.05)
end
function newSound(id)
local sound = Instance.new("Sound")
sound.SoundId = id
sound.Parent = script.Parent.Head
return sound
end
sDied = newSound("rbxasset://sounds/uuhhh.wav")
sFallingDown = newSound("rbxasset://sounds/splat.wav")
sFreeFalling = newSound("rbxasset://sounds/swoosh.wav")
sGettingUp = newSound("rbxasset://sounds/hit.wav")
sJumping = newSound("rbxasset://sounds/button.wav")
sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3")
sRunning.Looped = true
function onDied()
sDied:play()
end
function onState(state, sound)
if state then
sound:play()
else
sound:pause()
end
end
function onRunning(speed)
if speed>0 then
sRunning:play()
else
sRunning:pause()
end
end
while script.Parent.Humanoid==nil do
wait(0.05)
end
h = script.Parent.Humanoid
h.Died:connect(onDied)
h.Running:connect(onRunning)
h.Jumping:connect(function(state) onState(state, sJumping) end)
h.GettingUp:connect(function(state) onState(state, sGettingUp) end)
h.FreeFalling:connect(function(state) onState(state, sFreeFalling) end)
h.FallingDown:connect(function(state) onState(state, sFallingDown) end)
-- regeneration
while true do
local s = wait(1)
local health=h.Health
if health>0 and health<h.MaxHealth then
health = health + 0.01*s*h.MaxHealth
if health*1.05 < h.MaxHealth then
h.Health = health
else
h.Health = h.MaxHealth
end
end
end
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidHealth.rbxm b/Client2014/content/fonts/humanoidHealth.rbxm
new file mode 100644
index 0000000..12cdbbb
--- /dev/null
+++ b/Client2014/content/fonts/humanoidHealth.rbxm
@@ -0,0 +1,191 @@
+
+ null
+ nil
+ -
+
+ false
+
+ HealthScript v2.0
+ local humanoid = script.Parent.Humanoid
+
+if (humanoid == nil) then
+ print("ERROR: no humanoid found in 'HealthScript v2.0'")
+end
+
+
+function CreateGUI()
+ local p = game.Players:GetPlayerFromCharacter(humanoid.Parent)
+ print("Health for Player: " .. p.Name)
+ script.HealthGUI.Parent = p.PlayerGui
+end
+
+function UpdateGUI(health)
+ local pgui = game.Players:GetPlayerFromCharacter(humanoid.Parent).PlayerGui
+ local tray = pgui.HealthGUI.Tray
+
+ tray.HealthBar.Size = UDim2.new(0.2, 0, 0.8 * (health / humanoid.MaxHealth), 0)
+ tray.HealthBar.Position = UDim2.new(0.4, 0, 0.8 * (1- (health / humanoid.MaxHealth)) , 0)
+
+end
+
+
+function HealthChanged(health)
+ UpdateGUI(health)
+end
+
+
+CreateGUI()
+humanoid.HealthChanged:connect(HealthChanged)
+humanoid.Died:connect(function() HealthChanged(0) end)
+ true
+
+
-
+
+ HealthGUI
+ true
+
+
-
+
+ false
+ 4285215356
+ 1
+ 4279970357
+ 1
+ Tray
+
+ 0.949999988
+ 0
+ 0.380000025
+ 0
+
+
+ 0.0450000018
+ 0
+ 0.340000004
+ 0
+
+ 0
+ true
+ 1
+ true
+
+
-
+
+ false
+ 4294967295
+ 1
+ 4279970357
+ 1
+ http://www.roblox.com/asset/?id=18441769
+ ImageLabel
+
+ 0
+ 0
+ 0.800000012
+ 3
+
+
+ 1
+ 0
+ 0.25
+ 0
+
+ 1
+ true
+ 1
+ true
+
+
+ -
+
+ false
+ 4286892054
+ 0
+ 4278190080
+ 0
+ HealthBar
+
+ 0.420000017
+ 0
+ 0
+ 0
+
+
+ 0.159999996
+ 0
+ 0.800000012
+ 0
+
+ 0
+ true
+ 2
+ true
+
+
+ -
+
+ false
+ 4289733411
+ 0
+ 4278190080
+ 0
+ HealthBarBacking
+
+ 0.419999987
+ 0
+ 0
+ 0
+
+
+ 0.159999996
+ 0
+ 0.800000012
+ 0
+
+ 0
+ true
+ 1
+ true
+
+
+
+
+
+ -
+
+ false
+
+ Health
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+ end
+
+ -- declarations
+
+ local Figure = script.Parent
+ local Head = waitForChild(Figure, "Head")
+ local Humanoid = waitForChild(Figure, "Humanoid")
+
+ -- regeneration
+ while true do
+ local s = wait(1)
+ local health = Humanoid.Health
+ if health > 0 and health < Humanoid.MaxHealth then
+ health = health + 0.01 * s * Humanoid.MaxHealth
+ if health * 1.05 < Humanoid.MaxHealth then
+ Humanoid.Health = health
+ else
+ Humanoid.Health = Humanoid.MaxHealth
+ end
+ end
+ end
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidSound.rbxm b/Client2014/content/fonts/humanoidSound.rbxm
new file mode 100644
index 0000000..0523e7b
--- /dev/null
+++ b/Client2014/content/fonts/humanoidSound.rbxm
@@ -0,0 +1,76 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ -- util
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+function newSound(id)
+ local sound = Instance.new("Sound")
+ sound.SoundId = id
+ sound.archivable = false
+ sound.Parent = script.Parent.Head
+ return sound
+end
+
+-- declarations
+
+local sDied = newSound("rbxasset://sounds/uuhhh.wav")
+local sFallingDown = newSound("rbxasset://sounds/splat.wav")
+local sFreeFalling = newSound("rbxasset://sounds/swoosh.wav")
+local sGettingUp = newSound("rbxasset://sounds/hit.wav")
+local sJumping = newSound("rbxasset://sounds/button.wav")
+local sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3")
+sRunning.Looped = true
+
+local Figure = script.Parent
+local Head = waitForChild(Figure, "Head")
+local Humanoid = waitForChild(Figure, "Humanoid")
+
+-- functions
+
+function onDied()
+ sDied:Play()
+end
+
+function onState(state, sound)
+ if state then
+ sound:Play()
+ else
+ sound:Pause()
+ end
+end
+
+function onRunning(speed)
+ if speed>0 then
+ sRunning:Play()
+ else
+ sRunning:Pause()
+ end
+end
+
+-- connect up
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(function(state) onState(state, sJumping) end)
+Humanoid.GettingUp:connect(function(state) onState(state, sGettingUp) end)
+Humanoid.FreeFalling:connect(function(state) onState(state, sFreeFalling) end)
+Humanoid.FallingDown:connect(function(state) onState(state, sFallingDown) end)
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidSound2.rbxm b/Client2014/content/fonts/humanoidSound2.rbxm
new file mode 100644
index 0000000..01591b3
--- /dev/null
+++ b/Client2014/content/fonts/humanoidSound2.rbxm
@@ -0,0 +1,43 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ -- util
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+function newSound(id, name)
+ local sound = Instance.new("Sound")
+ sound.SoundId = id
+ sound.archivable = false
+ sound.Parent = script.Parent.Head
+ sound.Name = name
+ return sound
+end
+
+-- declarations
+local Figure = script.Parent
+local Head = waitForChild(Figure, "Head")
+local Humanoid = waitForChild(Figure, "Humanoid")
+
+local sDied = newSound("rbxasset://sounds/uuhhh.wav", "DiedSound")
+local sFallingDown = newSound("rbxasset://sounds/splat.wav", "FallingDownSound")
+local sFreeFalling = newSound("rbxasset://sounds/swoosh.wav", "FreeFallingSound")
+local sGettingUp = newSound("rbxasset://sounds/hit.wav", "GettingUpSound")
+local sJumping = newSound("rbxasset://sounds/button.wav", "JumpingSound")
+local sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3", "RunningSound")
+sRunning.Looped = true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/humanoidStatic.rbxm b/Client2014/content/fonts/humanoidStatic.rbxm
new file mode 100644
index 0000000..1c9fcb7
--- /dev/null
+++ b/Client2014/content/fonts/humanoidStatic.rbxm
@@ -0,0 +1,12 @@
+
+ null
+ nil
+ -
+
+ false
+ Static
+ local Figure = script.Parent
local Torso = Figure:findFirstChild("Torso")
Torso:makeJoints()
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2014/content/fonts/leftarm.mesh b/Client2014/content/fonts/leftarm.mesh
new file mode 100644
index 0000000..6e8bb63
Binary files /dev/null and b/Client2014/content/fonts/leftarm.mesh differ
diff --git a/Client2014/content/fonts/leftleg.mesh b/Client2014/content/fonts/leftleg.mesh
new file mode 100644
index 0000000..aba3a29
Binary files /dev/null and b/Client2014/content/fonts/leftleg.mesh differ
diff --git a/Client2014/content/fonts/rightarm.mesh b/Client2014/content/fonts/rightarm.mesh
new file mode 100644
index 0000000..14a52a4
Binary files /dev/null and b/Client2014/content/fonts/rightarm.mesh differ
diff --git a/Client2014/content/fonts/rightleg.mesh b/Client2014/content/fonts/rightleg.mesh
new file mode 100644
index 0000000..dab065d
Binary files /dev/null and b/Client2014/content/fonts/rightleg.mesh differ
diff --git a/Client2014/content/fonts/safechat.xml b/Client2014/content/fonts/safechat.xml
new file mode 100644
index 0000000..199e3b2
--- /dev/null
+++ b/Client2014/content/fonts/safechat.xml
@@ -0,0 +1,737 @@
+
+ null
+ nil
+ Use the Chat menu to talk to me.
+ I can only see menu chats.
+
+ Hello
+
+ Hi
+ Hi there!
+ Hi everyone
+
+
+ Howdy
+ Howdy partner!
+
+
+ Greetings
+ Greetings everyone
+ Greetings Robloxians!
+ Seasons greetings!
+
+
+ Welcome
+ Welcome to my place
+ Welcome to our base
+ Welcome to my barbeque
+
+ Hey there!
+
+ What's up?
+ How are you doing?
+ How's it going?
+ What's new?
+
+
+ Good day
+ Good morning
+ Good afternoon
+ Good evening
+ Good night
+
+
+ Silly
+ Waaaaaaaz up?!
+ Hullo!
+ Behold greatness, mortals!
+ Pardon me, is this Sparta?
+ THIS IS SPARTAAAA!
+
+
+ Happy Holidays!
+ Happy New Year!
+ Happy Valentine's Day!
+ Beware the Ides of March!
+ Happy St. Patrick's Day!
+ Happy Easter!
+ Happy Earth Day!
+ Happy 4th of July!
+ Happy Thanksgiving!
+ Happy Halloween!
+ Happy Hanukkah!
+ Merry Christmas!
+ Happy Halloween!
+ Happy Earth Day!
+ Happy May Day!
+ Happy Towel Day!
+ Happy ROBLOX Day!
+ Happy LOL Day!
+
+
+
+ Goodbye
+
+ Good Night
+ Sweet dreams
+ Go to sleep!
+ Lights out!
+ Bedtime
+ Going to bed now
+
+
+ Later
+ See ya later
+ Later gator!
+ See you tomorrow
+
+
+ Bye
+ Hasta la bye bye!
+
+ I'll be right back
+ I have to go
+
+ Farewell
+ Take care
+ Have a nice day
+ Goodluck!
+ Ta-ta for now!
+
+
+ Peace
+ Peace out!
+ Peace dudes!
+ Rest in pieces!
+
+
+ Silly
+ To the batcave!
+ Over and out!
+ Happy trails!
+ I've got to book it!
+ Tootles!
+ Smell you later!
+ GG!
+ My house is on fire! gtg.
+
+
+
+ Friend
+ Wanna be friends?
+
+ Follow me
+ Come to my place!
+ Come to my base!
+ Follow me, team!
+ Follow me
+
+
+ Your place is cool
+ Your place is fun
+ Your place is awesome
+ Your place looks good
+ This place is awesome!
+
+
+ Thank you
+ Thanks for playing
+ Thanks for visiting
+ Thanks for everything
+ No, thank you
+ Thanx
+
+
+ No problem
+ Don't worry
+ That's ok
+ np
+
+
+ You are ...
+ You are great!
+ You are good!
+ You are cool!
+ You are funny!
+ You are silly!
+ You are awesome!
+ You are doing something I don't like, please stop
+
+
+ I like ...
+ I like your name
+ I like your shirt
+ I like your place
+ I like your style
+ I like you
+ I like items
+ I like money
+
+
+ Sorry
+ My bad!
+ I'm sorry
+ Whoops!
+ Please forgive me.
+ I forgive you.
+ I didn't mean to do that.
+ Sorry, I'll stop now.
+
+
+
+ Questions
+
+ Who?
+ Who wants to be my friend?
+ Who wants to be on my team?
+ Who made this brilliant game?
+ LOLWHO?
+
+
+ What?
+ What is your favorite animal?
+ What is your favorite game?
+ What is your favorite movie?
+ What is your favorite TV show?
+ What is your favorite music?
+ What are your hobbies?
+ LOLWUT?
+
+
+ When?
+ When are you online?
+ When is the new version coming out?
+ When can we play again?
+ When will your place be done?
+
+
+ Where?
+ Where do you want to go?
+ Where are you going?
+ Where am I?!
+ Where did you go?
+
+
+ How?
+ How are you today?
+ How did you make this cool place?
+ LOLHOW?
+
+
+ Can I...
+ Can I have a tour?
+ Can I be on your team?
+ Can I be your friend?
+ Can I try something?
+ Can I have that please?
+ Can I have that back please?
+ Can I have borrow your hat?
+ Can I have borrow your gear?
+
+
+
+ Answers
+
+ You need help?
+ Check out the news section
+ Check out the help section
+ Read the wiki!
+ All the answers are in the wiki!
+ I will help you with this.
+
+
+ Some people ...
+ Me
+ Not me
+ You
+ All of us
+ Everyone but you
+ Builderman!
+ Telamon!
+ My team
+ My group
+ Mom
+ Dad
+ Sister
+ Brother
+ Cousin
+ Grandparent
+ Friend
+
+
+ Time ...
+ In the morning
+ In the afternoon
+ At night
+ Tomorrow
+ This week
+ This month
+ Sometime
+ Sometimes
+ Whenever you want
+ Never
+ After this
+ In 10 minutes
+ In a couple hours
+ In a couple days
+
+
+ Animals
+
+ Cats
+ Lion
+ Tiger
+ Leopard
+ Cheetah
+
+
+ Dogs
+ Wolves
+ Beagle
+ Collie
+ Dalmatian
+ Poodle
+ Spaniel
+ Shepherd
+ Terrier
+ Retriever
+
+
+ Horses
+ Ponies
+ Stallions
+ Pwnyz
+
+
+ Reptiles
+ Dinosaurs
+ Lizards
+ Snakes
+ Turtles!
+
+ Hamster
+ Monkey
+ Bears
+
+ Fish
+ Goldfish
+ Sharks
+ Sea Bass
+ Halibut
+ Tropical Fish
+
+
+ Birds
+ Eagles
+ Penguins
+ Parakeets
+ Owls
+ Hawks
+ Pidgeons
+
+ Elephants
+
+ Mythical Beasts
+ Dragons
+ Unicorns
+ Sea Serpents
+ Sphinx
+ Cyclops
+ Minotaurs
+ Goblins
+ Honest Politicians
+ Ghosts
+ Scylla and Charybdis
+
+
+
+ Games
+
+ Roblox
+ BrickBattle
+ Community Building
+ Roblox Minigames
+ Contest Place
+
+ Action
+ Puzzle
+ Strategy
+ Racing
+ RPG
+ Obstacle Course
+ Tycoon
+
+ Board games
+ Chess
+ Checkers
+ Settlers of Catan
+ Tigris and Euphrates
+ El Grande
+ Stratego
+ Carcassonne
+
+
+
+ Sports
+ Hockey
+ Soccer
+ Football
+ Baseball
+ Basketball
+ Volleyball
+ Tennis
+ Sports team practice
+
+ Watersports
+ Surfing
+ Swimming
+ Water Polo
+
+
+ Winter sports
+ Skiing
+ Snowboarding
+ Sledding
+ Skating
+
+
+ Adventure
+ Rock climbing
+ Hiking
+ Fishing
+ Horseback riding
+
+
+ Wacky
+ Foosball
+ Calvinball
+ Croquet
+ Cricket
+ Dodgeball
+ Squash
+ Trampoline
+
+
+
+ Movies/TV
+ Science Fiction
+
+ Animated
+ Anime
+
+ Comedy
+ Romantic
+ Action
+ Fantasy
+
+
+ Music
+ Country
+ Jazz
+ Rap
+ Hip-hop
+ Techno
+ Classical
+ Pop
+ Rock
+
+
+ Hobbies
+
+ Computers
+ Building computers
+ Videogames
+ Coding
+ Hacking
+
+
+ The Internet
+ lol. teh internets!
+ Watching vids
+
+ Dance
+ Gymnastics
+
+ Martial Arts
+ Karate
+ Judo
+ Taikwon Do
+ Wushu
+ Street fighting
+
+ Listening to music
+
+ Music lessons
+ Playing in my band
+ Playing piano
+ Playing guitar
+ Playing violin
+ Playing drums
+ Playing a weird instrument
+
+ Arts and crafts
+
+
+ Location
+
+ USA
+
+ West
+ Alaska
+ Arizona
+ California
+ Colorado
+ Hawaii
+ Idaho
+ Montana
+ Nevada
+ New Mexico
+ Oregon
+ Utah
+ Washington
+ Wyoming
+
+
+ Midwest
+ Illinois
+ Indiana
+ Iowa
+ Kansas
+ Michigan
+ Minnesota
+ Missouri
+ Nebraska
+ North Dakota
+ Ohio
+ South Dakota
+ Wisconsin
+
+
+ Northeast
+ Connecticut
+ Delaware
+ Maine
+ Maryland
+ Massachusetts
+ New Hampshire
+ New Jersey
+ New York
+ Pennsylvania
+ Rhode Island
+ Vermont
+
+
+ South
+ Alabama
+ Arkansas
+ Florida
+ Georgia
+ Kentucky
+ Louisiana
+ Mississippi
+ North Carolina
+ Oklahoma
+ South Carolina
+ Tennessee
+ Texas
+ Virginia
+ West Virginia
+
+
+
+ Canada
+ Alberta
+ British Columbia
+ Manitoba
+ New Brunswick
+ Newfoundland
+ Northwest Territories
+ Nova Scotia
+ Nunavut
+ Ontario
+ Prince Edward Island
+ Quebec
+ Saskatchewan
+ Yukon
+
+ Mexico
+ Central America
+
+ Europe
+
+ Great Britain
+ England
+ Scotland
+ Wales
+ Northern Ireland
+
+ France
+ Germany
+ Spain
+ Italy
+ Poland
+ Switzerland
+ Greece
+ Romania
+ Netherlands
+
+
+ Asia
+ China
+ India
+ Japan
+ Korea
+ Russia
+ Vietnam
+
+
+ South America
+ Argentina
+ Brazil
+
+
+ Africa
+ Eygpt
+ Swaziland
+
+ Australia
+ Middle East
+ Antarctica
+ New Zealand
+
+
+ Age
+ Rugrat
+ Kid
+ Tween
+ Teen
+ Twenties
+ Old
+ Ancient
+ Mesozoic
+ I don't want to say my age. Don't ask.
+
+
+ Mood
+ Good
+ Great!
+ Not bad
+ Sad
+ Hyper
+ Chill
+ Happy
+ Kind of mad
+
+ Boy
+ Girl
+ I don't want to say boy or girl. Don't ask.
+
+
+ Game
+ Let's build
+ Let's battle
+ Nice one!
+ So far so good!
+ Lucky shot!
+ Oh man!
+ I challenge you to a fight!
+ Help me with this
+ Let's go to your game
+ Can you show me how do to that?
+ Backflip!
+ Frontflip!
+ Dance!
+ I'm on your side!
+
+ Game Commands
+ regen
+ reset
+ go
+ fix
+ respawn
+
+
+
+ Silly
+ Muahahahaha!
+ all your base are belong to me!
+ GET OFF MAH LAWN
+ TEH EPIK DUCK IS COMING!!!
+ ROFL
+
+ 1337
+ i r teh pwnz0r!
+ w00t!
+ z0mg h4x!
+ ub3rR0xXorzage!
+
+
+
+ Yes
+ Absolutely!
+ Rock on!
+ Totally!
+ Juice!
+ Yay!
+ Yesh
+
+
+ No
+ Ummm. No.
+ ...
+ Stop!
+ Go away!
+ Don't do that
+ Stop breaking the rules
+ I don't want to
+
+
+ Ok
+ Well... ok
+ Sure
+
+
+ Uncertain
+ Maybe
+ I don't know
+ idk
+ I can't decide
+ Hmm...
+
+
+
+ :-)
+ :-(
+ :D
+ :-O
+ lol
+ =D
+ D=
+ XD
+ ;D
+ ;)
+ O_O
+ =)
+ @_@
+ >_<
+ T_T
+ ^_^
+ <(0_0<) <(0_0)> (>0_0)> KIRBY DANCE
+ )';
+ :3
+
+
+ Ratings
+ Rate it!
+ I give it a 1 out of 10
+ I give it a 2 out of 10
+ I give it a 3 out of 10
+ I give it a 4 out of 10
+ I give it a 5 out of 10
+ I give it a 6 out of 10
+ I give it a 7 out of 10
+ I give it a 8 out of 10
+ I give it a 9 out of 10
+ I give it a 10 out of 10!
+
+
diff --git a/Client2014/content/fonts/torso.mesh b/Client2014/content/fonts/torso.mesh
new file mode 100644
index 0000000..43d58d1
Binary files /dev/null and b/Client2014/content/fonts/torso.mesh differ
diff --git a/Client2014/content/music/bass.wav b/Client2014/content/music/bass.wav
new file mode 100644
index 0000000..5f4b791
Binary files /dev/null and b/Client2014/content/music/bass.wav differ
diff --git a/Client2014/content/music/ufofly.wav b/Client2014/content/music/ufofly.wav
new file mode 100644
index 0000000..359710b
Binary files /dev/null and b/Client2014/content/music/ufofly.wav differ
diff --git a/Client2014/content/particles/explosion.particle b/Client2014/content/particles/explosion.particle
new file mode 100644
index 0000000..a7c5e1f
--- /dev/null
+++ b/Client2014/content/particles/explosion.particle
@@ -0,0 +1,192 @@
+/////////////////////////////////////////////////////////
+// The fast rising center plume of the explosion.
+// Grows and rotates.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionPlume
+{
+ quota 40
+ material explosion/explosionMatl
+ particle_width 6
+ particle_height 6
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Ellipsoid
+ {
+ angle 16
+ colour 1.0 0.4 0.2 1.0
+ colour_range_start 1.0 0.4 0.2 1.0
+ colour_range_end 0.7 0.2 0.1 0.6
+ direction 0 1 0
+ emission_rate 100
+ position 0 6 0
+ velocity 25
+ velocity_min 25
+ velocity_max 38
+ time_to_live 1.5
+ time_to_live_min 1.5
+ time_to_live_max 1.5
+ duration 0.2
+ duration_min 0.2
+ duration_max 0.2
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ width 3
+ height 3
+ depth 3
+ }
+
+ affector ColourFader
+ {
+ red -0.9
+ green -0.5
+ blue -0.3
+ alpha -1.0
+ }
+ affector Scaler
+ {
+ rate 13
+ }
+ affector Rotator
+ {
+ rotation_speed_range_start 100
+ rotation_speed_range_end 200
+ rotation_range_start 100
+ rotation_range_end 300
+ }
+}
+
+
+/////////////////////////////////////////////////////////
+//The slow moving base of the explosion.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionBase
+{
+ quota 40
+ material explosion/explosionMatl
+ particle_width 20
+ particle_height 20
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Ellipsoid
+ {
+ angle 100
+ colour 1.0 0.4 0.2 1.0
+ colour_range_start 1.0 0.4 0.2 1.0
+ colour_range_end 0.7 0.2 0.1 0.6
+ direction 0 1 0
+ emission_rate 80
+ position 0 0 0
+ velocity 11
+ velocity_min 11
+ velocity_max 16
+ time_to_live 1.5
+ time_to_live_min 1.5
+ time_to_live_max 1.5
+ duration 0.2
+ duration_min 0.2
+ duration_max 0.2
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ width 15
+ height 15
+ depth 15
+ }
+
+ affector ColourFader
+ {
+ red -0.9
+ green -0.5
+ blue -0.3
+ alpha -1.0
+ }
+ affector Scaler
+ {
+ rate 5
+ }
+}
+
+
+/////////////////////////////////////////////////////////
+// The fast flying sparks of the explosion.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionSparks
+{
+ quota 120
+ material explosion/explosparkMatl
+ particle_width 3
+ particle_height 3
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Point
+ {
+ angle 120
+ colour 1.0 0.6 0.4 1.0
+ colour_range_start 1.0 0.6 0.4 1.0
+ colour_range_end 1.0 0.6 0.4 1.0
+ direction 0 1 0
+ emission_rate 900
+ position 0 0 0
+ velocity 30
+ velocity_min 30
+ velocity_max 60
+ time_to_live 1.2
+ time_to_live_min 1.2
+ time_to_live_max 1.2
+ duration 0.2
+ duration_min 0.1
+ duration_max 0.1
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ }
+
+ affector ColourFader
+ {
+ red -0.7
+ green -0.6
+ blue -0.4
+ alpha -0.7
+ }
+ affector Scaler
+ {
+ rate -3
+ }
+}
diff --git a/Client2014/content/particles/fire.particle b/Client2014/content/particles/fire.particle
new file mode 100644
index 0000000..442fe8e
--- /dev/null
+++ b/Client2014/content/particles/fire.particle
@@ -0,0 +1,59 @@
+/////////////////////////////////////////////////////////
+// Fire
+/////////////////////////////////////////////////////////
+
+// height and width modified by RbxParticleFactory for user input size
+particle_system FireTemplate
+{
+ material fireMat1
+ particle_width 5
+ particle_height 5
+ cull_each false
+ quota 40
+ renderer billboard
+ billboard_type point
+ point_rendering false
+ accurate_facing false
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+
+ // emission rate is modified by RbxParticleManager for throttling
+ // of particle systems
+ emitter Point
+ {
+ colour_range_start 240 240 240
+ colour_range_end 240 240 240
+ angle 18
+ emission_rate 35
+ time_to_live_min 1
+ time_to_live_max 1
+ direction 0 1 0
+ velocity_min 2.33
+ velocity_max 7.0
+ }
+ affector Rotator
+ {
+ rotation_range_start 0
+ rotation_range_end 365
+ rotation_speed_range_start 0
+ rotation_speed_range_end 100
+ }
+ // modified in RbxParticleFactory for user input size
+ affector Scaler
+ {
+ rate -5.0
+ }
+ // modified in RbxParticleFactory for user input colors
+ affector ColourInterpolator
+ {
+ time0 0
+ colour0 240 240 240 1
+
+ time1 1
+ colour1 240 240 240 1
+
+ }
+
+}
diff --git a/Client2014/content/particles/forceFieldBeam.particle b/Client2014/content/particles/forceFieldBeam.particle
new file mode 100644
index 0000000..22914a9
--- /dev/null
+++ b/Client2014/content/particles/forceFieldBeam.particle
@@ -0,0 +1,55 @@
+/////////////////////////////////////////////////////////
+// Beam
+/////////////////////////////////////////////////////////
+particle_system forceField/beam
+{
+ quota 40
+ material PE/lensflare
+ particle_width 0.5
+ particle_height 2
+ cull_each false
+ billboard_type oriented_common
+ common_direction 0 1 0
+
+ emitter Ring
+ {
+ colour 1 1 1 0
+ angle 0
+ direction 0 1 0
+ emission_rate 20
+ position 0 -2 0
+ velocity_min 2
+ velocity_max 5
+ time_to_live 2
+ duration 0
+ duration_min 0
+ duration_max 0
+ repeat_delay 0
+ repeat_delay_min 0
+ repeat_delay_max 0
+ width 5
+ height 5
+ depth 1
+ inner_width 0.8
+ inner_height 0.8
+ }
+
+ //affector LinearForce
+// {
+ // force_vector 0 -1 0
+ // force_application add
+ //}
+
+ affector ColourFader2
+ {
+ red1 0
+ green1 0
+ blue1 0
+ alpha1 1
+ red2 0
+ green2 0
+ blue2 0
+ alpha2 -1
+ state_change 1
+ }
+}
diff --git a/Client2014/content/particles/forceFieldRadial.particle b/Client2014/content/particles/forceFieldRadial.particle
new file mode 100644
index 0000000..807f93d
--- /dev/null
+++ b/Client2014/content/particles/forceFieldRadial.particle
@@ -0,0 +1,51 @@
+/////////////////////////////////////////////////////////
+// Radial
+/////////////////////////////////////////////////////////
+particle_system forceField/radial
+{
+ material PE/lensflare
+ particle_width 5
+ particle_height 5
+ cull_each false
+ quota 6
+ renderer billboard
+ billboard_type point
+ point_rendering false
+ accurate_facing false
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+
+ // emission rate is modified by RbxParticleManager for throttling
+ // of particle systems
+ emitter Point
+ {
+ angle 18
+ emission_rate 2
+ time_to_live_min 2
+ time_to_live_max 2
+ direction 0 1 0
+ velocity_min 0
+ velocity_max 0.1
+ }
+ affector Rotator
+ {
+ rotation_range_start 0
+ rotation_range_end 365
+ rotation_speed_range_start 4
+ rotation_speed_range_end 100
+ }
+ // modified in RbxParticleFactory for user input size
+ affector Scaler
+ {
+ rate 6.0
+ }
+ affector ColourFader
+ {
+ red 0
+ green 0
+ blue 0
+ alpha -0.5
+ }
+}
diff --git a/Client2014/content/particles/smoke.particle b/Client2014/content/particles/smoke.particle
new file mode 100644
index 0000000..79c6c16
--- /dev/null
+++ b/Client2014/content/particles/smoke.particle
@@ -0,0 +1,57 @@
+particle_system SmokeTemplate
+{
+ quota 70
+ material PE/smoke
+ particle_width 1
+ particle_height 1
+ cull_each false
+ renderer billboard
+ billboard_type point
+
+ emitter Box
+ {
+ angle 180
+ colour 0.8 0.8 0.8 0.3
+ colour_range_start 0.8 0.8 0.8 0.3
+ colour_range_end 0.8 0.8 0.8 0.3
+ direction 0 1 0
+ emission_rate 6
+ position 0 0 0
+ velocity 0.1
+ velocity_min 0
+ velocity_max 0.1
+ time_to_live 4
+ time_to_live_min 4
+ time_to_live_max 6
+ duration 0
+ duration_min 0
+ duration_max 0
+ repeat_delay 0
+ repeat_delay_min 0
+ repeat_delay_max 0
+ width 1
+ height 1
+ depth 1
+ }
+
+ affector ColourFader
+ {
+ red -0.11
+ green -0.11
+ blue -0.11
+ alpha -0.1
+ }
+
+ affector Scaler
+ {
+ rate 1.5
+ }
+
+ affector Rotator
+ {
+ rotation_speed_range_start 0
+ rotation_speed_range_end 0
+ rotation_range_start 0
+ rotation_range_end 0
+ }
+}
diff --git a/Client2014/content/particles/sparkles.particle b/Client2014/content/particles/sparkles.particle
new file mode 100644
index 0000000..60102d0
--- /dev/null
+++ b/Client2014/content/particles/sparkles.particle
@@ -0,0 +1,49 @@
+/////////////////////////////////////////////////////////
+// Sparkles
+/////////////////////////////////////////////////////////
+particle_system SparklesTemplate
+{
+ quota 40
+ material sparkle/sparkleMatl
+ particle_width 0.8
+ particle_height 1
+ cull_each false
+ renderer billboard
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Point
+ {
+ angle 180
+ direction 0 -1 0
+ emission_rate 35
+ position 0 0 0
+ velocity_min 4
+ velocity_max 8
+ duration 0.0
+ time_to_live 1.1
+ //repeat_delay 2.0
+ }
+ affector Rotator
+ {
+ rotation_speed_range_end 360
+ rotation_range_start 0
+ rotation_range_end 360
+ }
+ affector ColourFader
+ {
+ red 0
+ green 0
+ blue 0
+ alpha -1
+ }
+}
+
diff --git a/Client2014/content/sky/lensflare.jpg b/Client2014/content/sky/lensflare.jpg
new file mode 100644
index 0000000..c53f2ec
Binary files /dev/null and b/Client2014/content/sky/lensflare.jpg differ
diff --git a/Client2014/content/sky/moon-alpha.jpg b/Client2014/content/sky/moon-alpha.jpg
new file mode 100644
index 0000000..5e193d5
Binary files /dev/null and b/Client2014/content/sky/moon-alpha.jpg differ
diff --git a/Client2014/content/sky/moon.jpg b/Client2014/content/sky/moon.jpg
new file mode 100644
index 0000000..247b6cd
Binary files /dev/null and b/Client2014/content/sky/moon.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_bk.jpg b/Client2014/content/sky/null_plainsky512_bk.jpg
new file mode 100644
index 0000000..a01c9ef
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_bk.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_dn.jpg b/Client2014/content/sky/null_plainsky512_dn.jpg
new file mode 100644
index 0000000..75f16c1
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_dn.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_ft.jpg b/Client2014/content/sky/null_plainsky512_ft.jpg
new file mode 100644
index 0000000..253cb31
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_ft.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_lf.jpg b/Client2014/content/sky/null_plainsky512_lf.jpg
new file mode 100644
index 0000000..aa3626b
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_lf.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_rt.jpg b/Client2014/content/sky/null_plainsky512_rt.jpg
new file mode 100644
index 0000000..45b5071
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_rt.jpg differ
diff --git a/Client2014/content/sky/null_plainsky512_up.jpg b/Client2014/content/sky/null_plainsky512_up.jpg
new file mode 100644
index 0000000..49940da
Binary files /dev/null and b/Client2014/content/sky/null_plainsky512_up.jpg differ
diff --git a/Client2014/content/sky/skyspheremap.jpg b/Client2014/content/sky/skyspheremap.jpg
new file mode 100644
index 0000000..947a7ee
Binary files /dev/null and b/Client2014/content/sky/skyspheremap.jpg differ
diff --git a/Client2014/content/sky/sun-rays.jpg b/Client2014/content/sky/sun-rays.jpg
new file mode 100644
index 0000000..a76a4d5
Binary files /dev/null and b/Client2014/content/sky/sun-rays.jpg differ
diff --git a/Client2014/content/sky/sun.jpg b/Client2014/content/sky/sun.jpg
new file mode 100644
index 0000000..12b3829
Binary files /dev/null and b/Client2014/content/sky/sun.jpg differ
diff --git a/Client2014/content/sounds/Kerplunk.mp3 b/Client2014/content/sounds/Kerplunk.mp3
new file mode 100644
index 0000000..1211b02
Binary files /dev/null and b/Client2014/content/sounds/Kerplunk.mp3 differ
diff --git a/Client2014/content/sounds/Kid saying Ouch.mp3 b/Client2014/content/sounds/Kid saying Ouch.mp3
new file mode 100644
index 0000000..b3f87e0
Binary files /dev/null and b/Client2014/content/sounds/Kid saying Ouch.mp3 differ
diff --git a/Client2014/content/sounds/Rubber band sling shot.mp3 b/Client2014/content/sounds/Rubber band sling shot.mp3
new file mode 100644
index 0000000..430f96c
Binary files /dev/null and b/Client2014/content/sounds/Rubber band sling shot.mp3 differ
diff --git a/Client2014/content/sounds/Rubber band.mp3 b/Client2014/content/sounds/Rubber band.mp3
new file mode 100644
index 0000000..f815a17
Binary files /dev/null and b/Client2014/content/sounds/Rubber band.mp3 differ
diff --git a/Client2014/content/sounds/SWITCH3.mp3 b/Client2014/content/sounds/SWITCH3.mp3
new file mode 100644
index 0000000..0132c84
Binary files /dev/null and b/Client2014/content/sounds/SWITCH3.mp3 differ
diff --git a/Client2014/content/sounds/bass.mp3 b/Client2014/content/sounds/bass.mp3
new file mode 100644
index 0000000..ffd6286
Binary files /dev/null and b/Client2014/content/sounds/bass.mp3 differ
diff --git a/Client2014/content/sounds/bfsl-minifigfoots1.mp3 b/Client2014/content/sounds/bfsl-minifigfoots1.mp3
new file mode 100644
index 0000000..ca2e697
Binary files /dev/null and b/Client2014/content/sounds/bfsl-minifigfoots1.mp3 differ
diff --git a/Client2014/content/sounds/bfsl-minifigfoots2.mp3 b/Client2014/content/sounds/bfsl-minifigfoots2.mp3
new file mode 100644
index 0000000..113ad8f
Binary files /dev/null and b/Client2014/content/sounds/bfsl-minifigfoots2.mp3 differ
diff --git a/Client2014/content/sounds/button.mp3 b/Client2014/content/sounds/button.mp3
new file mode 100644
index 0000000..1136b2b
Binary files /dev/null and b/Client2014/content/sounds/button.mp3 differ
diff --git a/Client2014/content/sounds/clickfast.mp3 b/Client2014/content/sounds/clickfast.mp3
new file mode 100644
index 0000000..12bfbff
Binary files /dev/null and b/Client2014/content/sounds/clickfast.mp3 differ
diff --git a/Client2014/content/sounds/collide.mp3 b/Client2014/content/sounds/collide.mp3
new file mode 100644
index 0000000..8f69cf0
Binary files /dev/null and b/Client2014/content/sounds/collide.mp3 differ
diff --git a/Client2014/content/sounds/electronicpingshort.mp3 b/Client2014/content/sounds/electronicpingshort.mp3
new file mode 100644
index 0000000..bfb3eb0
Binary files /dev/null and b/Client2014/content/sounds/electronicpingshort.mp3 differ
diff --git a/Client2014/content/sounds/flashbulb.mp3 b/Client2014/content/sounds/flashbulb.mp3
new file mode 100644
index 0000000..fdcf7f6
Binary files /dev/null and b/Client2014/content/sounds/flashbulb.mp3 differ
diff --git a/Client2014/content/sounds/grass.mp3 b/Client2014/content/sounds/grass.mp3
new file mode 100644
index 0000000..e79fb5b
Binary files /dev/null and b/Client2014/content/sounds/grass.mp3 differ
diff --git a/Client2014/content/sounds/grass2.mp3 b/Client2014/content/sounds/grass2.mp3
new file mode 100644
index 0000000..1a1ad7a
Binary files /dev/null and b/Client2014/content/sounds/grass2.mp3 differ
diff --git a/Client2014/content/sounds/grass3.mp3 b/Client2014/content/sounds/grass3.mp3
new file mode 100644
index 0000000..131602a
Binary files /dev/null and b/Client2014/content/sounds/grass3.mp3 differ
diff --git a/Client2014/content/sounds/grassstone.mp3 b/Client2014/content/sounds/grassstone.mp3
new file mode 100644
index 0000000..4e9397c
Binary files /dev/null and b/Client2014/content/sounds/grassstone.mp3 differ
diff --git a/Client2014/content/sounds/grassstone2.mp3 b/Client2014/content/sounds/grassstone2.mp3
new file mode 100644
index 0000000..0a5f1c1
Binary files /dev/null and b/Client2014/content/sounds/grassstone2.mp3 differ
diff --git a/Client2014/content/sounds/grassstone3.mp3 b/Client2014/content/sounds/grassstone3.mp3
new file mode 100644
index 0000000..51df635
Binary files /dev/null and b/Client2014/content/sounds/grassstone3.mp3 differ
diff --git a/Client2014/content/sounds/hit.mp3 b/Client2014/content/sounds/hit.mp3
new file mode 100644
index 0000000..a299c1a
Binary files /dev/null and b/Client2014/content/sounds/hit.mp3 differ
diff --git a/Client2014/content/sounds/ice.mp3 b/Client2014/content/sounds/ice.mp3
new file mode 100644
index 0000000..db528cc
Binary files /dev/null and b/Client2014/content/sounds/ice.mp3 differ
diff --git a/Client2014/content/sounds/ice2.mp3 b/Client2014/content/sounds/ice2.mp3
new file mode 100644
index 0000000..dc4cb7b
Binary files /dev/null and b/Client2014/content/sounds/ice2.mp3 differ
diff --git a/Client2014/content/sounds/ice3.mp3 b/Client2014/content/sounds/ice3.mp3
new file mode 100644
index 0000000..7f3e5b1
Binary files /dev/null and b/Client2014/content/sounds/ice3.mp3 differ
diff --git a/Client2014/content/sounds/icegrass.mp3 b/Client2014/content/sounds/icegrass.mp3
new file mode 100644
index 0000000..2561aff
Binary files /dev/null and b/Client2014/content/sounds/icegrass.mp3 differ
diff --git a/Client2014/content/sounds/icegrass2.mp3 b/Client2014/content/sounds/icegrass2.mp3
new file mode 100644
index 0000000..db6f6d2
Binary files /dev/null and b/Client2014/content/sounds/icegrass2.mp3 differ
diff --git a/Client2014/content/sounds/icegrass3.mp3 b/Client2014/content/sounds/icegrass3.mp3
new file mode 100644
index 0000000..b72c2db
Binary files /dev/null and b/Client2014/content/sounds/icegrass3.mp3 differ
diff --git a/Client2014/content/sounds/icemetal.mp3 b/Client2014/content/sounds/icemetal.mp3
new file mode 100644
index 0000000..5c9d2d4
Binary files /dev/null and b/Client2014/content/sounds/icemetal.mp3 differ
diff --git a/Client2014/content/sounds/icemetal2.mp3 b/Client2014/content/sounds/icemetal2.mp3
new file mode 100644
index 0000000..60f9e4d
Binary files /dev/null and b/Client2014/content/sounds/icemetal2.mp3 differ
diff --git a/Client2014/content/sounds/icemetal3.mp3 b/Client2014/content/sounds/icemetal3.mp3
new file mode 100644
index 0000000..2ee4312
Binary files /dev/null and b/Client2014/content/sounds/icemetal3.mp3 differ
diff --git a/Client2014/content/sounds/icestone.mp3 b/Client2014/content/sounds/icestone.mp3
new file mode 100644
index 0000000..37b99bb
Binary files /dev/null and b/Client2014/content/sounds/icestone.mp3 differ
diff --git a/Client2014/content/sounds/icestone2.mp3 b/Client2014/content/sounds/icestone2.mp3
new file mode 100644
index 0000000..1f5e264
Binary files /dev/null and b/Client2014/content/sounds/icestone2.mp3 differ
diff --git a/Client2014/content/sounds/icestone3.mp3 b/Client2014/content/sounds/icestone3.mp3
new file mode 100644
index 0000000..e51ce3d
Binary files /dev/null and b/Client2014/content/sounds/icestone3.mp3 differ
diff --git a/Client2014/content/sounds/metal.mp3 b/Client2014/content/sounds/metal.mp3
new file mode 100644
index 0000000..32473b1
Binary files /dev/null and b/Client2014/content/sounds/metal.mp3 differ
diff --git a/Client2014/content/sounds/metal2.mp3 b/Client2014/content/sounds/metal2.mp3
new file mode 100644
index 0000000..023273f
Binary files /dev/null and b/Client2014/content/sounds/metal2.mp3 differ
diff --git a/Client2014/content/sounds/metal3.mp3 b/Client2014/content/sounds/metal3.mp3
new file mode 100644
index 0000000..e407be0
Binary files /dev/null and b/Client2014/content/sounds/metal3.mp3 differ
diff --git a/Client2014/content/sounds/metalgrass.mp3 b/Client2014/content/sounds/metalgrass.mp3
new file mode 100644
index 0000000..46fdef4
Binary files /dev/null and b/Client2014/content/sounds/metalgrass.mp3 differ
diff --git a/Client2014/content/sounds/metalgrass2.mp3 b/Client2014/content/sounds/metalgrass2.mp3
new file mode 100644
index 0000000..3a7dad2
Binary files /dev/null and b/Client2014/content/sounds/metalgrass2.mp3 differ
diff --git a/Client2014/content/sounds/metalgrass3.mp3 b/Client2014/content/sounds/metalgrass3.mp3
new file mode 100644
index 0000000..e8172ad
Binary files /dev/null and b/Client2014/content/sounds/metalgrass3.mp3 differ
diff --git a/Client2014/content/sounds/metalstone.mp3 b/Client2014/content/sounds/metalstone.mp3
new file mode 100644
index 0000000..6910e46
Binary files /dev/null and b/Client2014/content/sounds/metalstone.mp3 differ
diff --git a/Client2014/content/sounds/metalstone2.mp3 b/Client2014/content/sounds/metalstone2.mp3
new file mode 100644
index 0000000..0dd924e
Binary files /dev/null and b/Client2014/content/sounds/metalstone2.mp3 differ
diff --git a/Client2014/content/sounds/metalstone3.mp3 b/Client2014/content/sounds/metalstone3.mp3
new file mode 100644
index 0000000..37e1198
Binary files /dev/null and b/Client2014/content/sounds/metalstone3.mp3 differ
diff --git a/Client2014/content/sounds/plasticgrass.mp3 b/Client2014/content/sounds/plasticgrass.mp3
new file mode 100644
index 0000000..579d4ab
Binary files /dev/null and b/Client2014/content/sounds/plasticgrass.mp3 differ
diff --git a/Client2014/content/sounds/plasticgrass2.mp3 b/Client2014/content/sounds/plasticgrass2.mp3
new file mode 100644
index 0000000..f77843a
Binary files /dev/null and b/Client2014/content/sounds/plasticgrass2.mp3 differ
diff --git a/Client2014/content/sounds/plasticgrass3.mp3 b/Client2014/content/sounds/plasticgrass3.mp3
new file mode 100644
index 0000000..9274ff0
Binary files /dev/null and b/Client2014/content/sounds/plasticgrass3.mp3 differ
diff --git a/Client2014/content/sounds/plasticice.mp3 b/Client2014/content/sounds/plasticice.mp3
new file mode 100644
index 0000000..668ba91
Binary files /dev/null and b/Client2014/content/sounds/plasticice.mp3 differ
diff --git a/Client2014/content/sounds/plasticice2.mp3 b/Client2014/content/sounds/plasticice2.mp3
new file mode 100644
index 0000000..041e4ca
Binary files /dev/null and b/Client2014/content/sounds/plasticice2.mp3 differ
diff --git a/Client2014/content/sounds/plasticice3.mp3 b/Client2014/content/sounds/plasticice3.mp3
new file mode 100644
index 0000000..180b476
Binary files /dev/null and b/Client2014/content/sounds/plasticice3.mp3 differ
diff --git a/Client2014/content/sounds/plasticmetal.mp3 b/Client2014/content/sounds/plasticmetal.mp3
new file mode 100644
index 0000000..1eadf0c
Binary files /dev/null and b/Client2014/content/sounds/plasticmetal.mp3 differ
diff --git a/Client2014/content/sounds/plasticmetal2.mp3 b/Client2014/content/sounds/plasticmetal2.mp3
new file mode 100644
index 0000000..6d4119a
Binary files /dev/null and b/Client2014/content/sounds/plasticmetal2.mp3 differ
diff --git a/Client2014/content/sounds/plasticmetal3.mp3 b/Client2014/content/sounds/plasticmetal3.mp3
new file mode 100644
index 0000000..c777ee4
Binary files /dev/null and b/Client2014/content/sounds/plasticmetal3.mp3 differ
diff --git a/Client2014/content/sounds/plasticplastic.mp3 b/Client2014/content/sounds/plasticplastic.mp3
new file mode 100644
index 0000000..7283013
Binary files /dev/null and b/Client2014/content/sounds/plasticplastic.mp3 differ
diff --git a/Client2014/content/sounds/plasticplastic2.mp3 b/Client2014/content/sounds/plasticplastic2.mp3
new file mode 100644
index 0000000..f9710c7
Binary files /dev/null and b/Client2014/content/sounds/plasticplastic2.mp3 differ
diff --git a/Client2014/content/sounds/plasticplastic3.mp3 b/Client2014/content/sounds/plasticplastic3.mp3
new file mode 100644
index 0000000..c7cd1ca
Binary files /dev/null and b/Client2014/content/sounds/plasticplastic3.mp3 differ
diff --git a/Client2014/content/sounds/plasticstone.mp3 b/Client2014/content/sounds/plasticstone.mp3
new file mode 100644
index 0000000..d33e553
Binary files /dev/null and b/Client2014/content/sounds/plasticstone.mp3 differ
diff --git a/Client2014/content/sounds/plasticstone2.mp3 b/Client2014/content/sounds/plasticstone2.mp3
new file mode 100644
index 0000000..cd33d00
Binary files /dev/null and b/Client2014/content/sounds/plasticstone2.mp3 differ
diff --git a/Client2014/content/sounds/plasticstone3.mp3 b/Client2014/content/sounds/plasticstone3.mp3
new file mode 100644
index 0000000..5732f38
Binary files /dev/null and b/Client2014/content/sounds/plasticstone3.mp3 differ
diff --git a/Client2014/content/sounds/snap.mp3 b/Client2014/content/sounds/snap.mp3
new file mode 100644
index 0000000..8dd8d5a
Binary files /dev/null and b/Client2014/content/sounds/snap.mp3 differ
diff --git a/Client2014/content/sounds/splat.mp3 b/Client2014/content/sounds/splat.mp3
new file mode 100644
index 0000000..934a634
Binary files /dev/null and b/Client2014/content/sounds/splat.mp3 differ
diff --git a/Client2014/content/sounds/stone.mp3 b/Client2014/content/sounds/stone.mp3
new file mode 100644
index 0000000..e9dd548
Binary files /dev/null and b/Client2014/content/sounds/stone.mp3 differ
diff --git a/Client2014/content/sounds/stone2.mp3 b/Client2014/content/sounds/stone2.mp3
new file mode 100644
index 0000000..f582a22
Binary files /dev/null and b/Client2014/content/sounds/stone2.mp3 differ
diff --git a/Client2014/content/sounds/stone3.mp3 b/Client2014/content/sounds/stone3.mp3
new file mode 100644
index 0000000..b8bfa31
Binary files /dev/null and b/Client2014/content/sounds/stone3.mp3 differ
diff --git a/Client2014/content/sounds/switch.mp3 b/Client2014/content/sounds/switch.mp3
new file mode 100644
index 0000000..69e9442
Binary files /dev/null and b/Client2014/content/sounds/switch.mp3 differ
diff --git a/Client2014/content/sounds/swoosh.mp3 b/Client2014/content/sounds/swoosh.mp3
new file mode 100644
index 0000000..99014d0
Binary files /dev/null and b/Client2014/content/sounds/swoosh.mp3 differ
diff --git a/Client2014/content/sounds/swordlunge.mp3 b/Client2014/content/sounds/swordlunge.mp3
new file mode 100644
index 0000000..c5b017a
Binary files /dev/null and b/Client2014/content/sounds/swordlunge.mp3 differ
diff --git a/Client2014/content/sounds/swordslash.mp3 b/Client2014/content/sounds/swordslash.mp3
new file mode 100644
index 0000000..cf5b902
Binary files /dev/null and b/Client2014/content/sounds/swordslash.mp3 differ
diff --git a/Client2014/content/sounds/unsheath.mp3 b/Client2014/content/sounds/unsheath.mp3
new file mode 100644
index 0000000..6913873
Binary files /dev/null and b/Client2014/content/sounds/unsheath.mp3 differ
diff --git a/Client2014/content/sounds/uuhhh.mp3 b/Client2014/content/sounds/uuhhh.mp3
new file mode 100644
index 0000000..81b3565
Binary files /dev/null and b/Client2014/content/sounds/uuhhh.mp3 differ
diff --git a/Client2014/content/sounds/victory.mp3 b/Client2014/content/sounds/victory.mp3
new file mode 100644
index 0000000..793b1ba
Binary files /dev/null and b/Client2014/content/sounds/victory.mp3 differ
diff --git a/Client2014/content/sounds/woodgrass.mp3 b/Client2014/content/sounds/woodgrass.mp3
new file mode 100644
index 0000000..f70237c
Binary files /dev/null and b/Client2014/content/sounds/woodgrass.mp3 differ
diff --git a/Client2014/content/sounds/woodgrass2.mp3 b/Client2014/content/sounds/woodgrass2.mp3
new file mode 100644
index 0000000..0d12b62
Binary files /dev/null and b/Client2014/content/sounds/woodgrass2.mp3 differ
diff --git a/Client2014/content/sounds/woodgrass3.mp3 b/Client2014/content/sounds/woodgrass3.mp3
new file mode 100644
index 0000000..f234835
Binary files /dev/null and b/Client2014/content/sounds/woodgrass3.mp3 differ
diff --git a/Client2014/content/sounds/woodice.mp3 b/Client2014/content/sounds/woodice.mp3
new file mode 100644
index 0000000..5604dcf
Binary files /dev/null and b/Client2014/content/sounds/woodice.mp3 differ
diff --git a/Client2014/content/sounds/woodice2.mp3 b/Client2014/content/sounds/woodice2.mp3
new file mode 100644
index 0000000..dc3a586
Binary files /dev/null and b/Client2014/content/sounds/woodice2.mp3 differ
diff --git a/Client2014/content/sounds/woodice3.mp3 b/Client2014/content/sounds/woodice3.mp3
new file mode 100644
index 0000000..300dea9
Binary files /dev/null and b/Client2014/content/sounds/woodice3.mp3 differ
diff --git a/Client2014/content/sounds/woodmetal.mp3 b/Client2014/content/sounds/woodmetal.mp3
new file mode 100644
index 0000000..666db63
Binary files /dev/null and b/Client2014/content/sounds/woodmetal.mp3 differ
diff --git a/Client2014/content/sounds/woodmetal2.mp3 b/Client2014/content/sounds/woodmetal2.mp3
new file mode 100644
index 0000000..60e87dc
Binary files /dev/null and b/Client2014/content/sounds/woodmetal2.mp3 differ
diff --git a/Client2014/content/sounds/woodmetal3.mp3 b/Client2014/content/sounds/woodmetal3.mp3
new file mode 100644
index 0000000..29ec64a
Binary files /dev/null and b/Client2014/content/sounds/woodmetal3.mp3 differ
diff --git a/Client2014/content/sounds/woodplastic.mp3 b/Client2014/content/sounds/woodplastic.mp3
new file mode 100644
index 0000000..d909b8a
Binary files /dev/null and b/Client2014/content/sounds/woodplastic.mp3 differ
diff --git a/Client2014/content/sounds/woodplastic2.mp3 b/Client2014/content/sounds/woodplastic2.mp3
new file mode 100644
index 0000000..c4e9b19
Binary files /dev/null and b/Client2014/content/sounds/woodplastic2.mp3 differ
diff --git a/Client2014/content/sounds/woodplastic3.mp3 b/Client2014/content/sounds/woodplastic3.mp3
new file mode 100644
index 0000000..4398179
Binary files /dev/null and b/Client2014/content/sounds/woodplastic3.mp3 differ
diff --git a/Client2014/content/sounds/woodstone.mp3 b/Client2014/content/sounds/woodstone.mp3
new file mode 100644
index 0000000..3f7c071
Binary files /dev/null and b/Client2014/content/sounds/woodstone.mp3 differ
diff --git a/Client2014/content/sounds/woodstone2.mp3 b/Client2014/content/sounds/woodstone2.mp3
new file mode 100644
index 0000000..1b4505a
Binary files /dev/null and b/Client2014/content/sounds/woodstone2.mp3 differ
diff --git a/Client2014/content/sounds/woodstone3.mp3 b/Client2014/content/sounds/woodstone3.mp3
new file mode 100644
index 0000000..6e04dec
Binary files /dev/null and b/Client2014/content/sounds/woodstone3.mp3 differ
diff --git a/Client2014/content/sounds/woodwood.mp3 b/Client2014/content/sounds/woodwood.mp3
new file mode 100644
index 0000000..8279e0c
Binary files /dev/null and b/Client2014/content/sounds/woodwood.mp3 differ
diff --git a/Client2014/content/sounds/woodwood2.mp3 b/Client2014/content/sounds/woodwood2.mp3
new file mode 100644
index 0000000..ad29d7f
Binary files /dev/null and b/Client2014/content/sounds/woodwood2.mp3 differ
diff --git a/Client2014/content/sounds/woodwood3.mp3 b/Client2014/content/sounds/woodwood3.mp3
new file mode 100644
index 0000000..e8bf04f
Binary files /dev/null and b/Client2014/content/sounds/woodwood3.mp3 differ
diff --git a/Client2014/content/textures/AnchorCursor.png b/Client2014/content/textures/AnchorCursor.png
new file mode 100644
index 0000000..5c4cac7
Binary files /dev/null and b/Client2014/content/textures/AnchorCursor.png differ
diff --git a/Client2014/content/textures/ArrowCursor.png b/Client2014/content/textures/ArrowCursor.png
new file mode 100644
index 0000000..0f839d0
Binary files /dev/null and b/Client2014/content/textures/ArrowCursor.png differ
diff --git a/Client2014/content/textures/ArrowCursorDecalDrag.png b/Client2014/content/textures/ArrowCursorDecalDrag.png
new file mode 100644
index 0000000..0f839d0
Binary files /dev/null and b/Client2014/content/textures/ArrowCursorDecalDrag.png differ
diff --git a/Client2014/content/textures/ArrowFarCursor.png b/Client2014/content/textures/ArrowFarCursor.png
new file mode 100644
index 0000000..c3ce391
Binary files /dev/null and b/Client2014/content/textures/ArrowFarCursor.png differ
diff --git a/Client2014/content/textures/BWGradient.png b/Client2014/content/textures/BWGradient.png
new file mode 100644
index 0000000..0a5edb5
Binary files /dev/null and b/Client2014/content/textures/BWGradient.png differ
diff --git a/Client2014/content/textures/BackgroundImage.png b/Client2014/content/textures/BackgroundImage.png
new file mode 100644
index 0000000..9f76324
Binary files /dev/null and b/Client2014/content/textures/BackgroundImage.png differ
diff --git a/Client2014/content/textures/Blank.png b/Client2014/content/textures/Blank.png
new file mode 100644
index 0000000..d8860f6
Binary files /dev/null and b/Client2014/content/textures/Blank.png differ
diff --git a/Client2014/content/textures/CameraTiltDown.png b/Client2014/content/textures/CameraTiltDown.png
new file mode 100644
index 0000000..398f1f6
Binary files /dev/null and b/Client2014/content/textures/CameraTiltDown.png differ
diff --git a/Client2014/content/textures/CameraTiltDown_dn.png b/Client2014/content/textures/CameraTiltDown_dn.png
new file mode 100644
index 0000000..3f078ce
Binary files /dev/null and b/Client2014/content/textures/CameraTiltDown_dn.png differ
diff --git a/Client2014/content/textures/CameraTiltDown_ds.png b/Client2014/content/textures/CameraTiltDown_ds.png
new file mode 100644
index 0000000..bb4f78c
Binary files /dev/null and b/Client2014/content/textures/CameraTiltDown_ds.png differ
diff --git a/Client2014/content/textures/CameraTiltDown_ovr.png b/Client2014/content/textures/CameraTiltDown_ovr.png
new file mode 100644
index 0000000..3f078ce
Binary files /dev/null and b/Client2014/content/textures/CameraTiltDown_ovr.png differ
diff --git a/Client2014/content/textures/CameraTiltUp.png b/Client2014/content/textures/CameraTiltUp.png
new file mode 100644
index 0000000..a6c1645
Binary files /dev/null and b/Client2014/content/textures/CameraTiltUp.png differ
diff --git a/Client2014/content/textures/CameraTiltUp_dn.png b/Client2014/content/textures/CameraTiltUp_dn.png
new file mode 100644
index 0000000..9e6a9d6
Binary files /dev/null and b/Client2014/content/textures/CameraTiltUp_dn.png differ
diff --git a/Client2014/content/textures/CameraTiltUp_ds.png b/Client2014/content/textures/CameraTiltUp_ds.png
new file mode 100644
index 0000000..dd22842
Binary files /dev/null and b/Client2014/content/textures/CameraTiltUp_ds.png differ
diff --git a/Client2014/content/textures/CameraTiltUp_ovr.png b/Client2014/content/textures/CameraTiltUp_ovr.png
new file mode 100644
index 0000000..9e6a9d6
Binary files /dev/null and b/Client2014/content/textures/CameraTiltUp_ovr.png differ
diff --git a/Client2014/content/textures/CameraZoomIn.png b/Client2014/content/textures/CameraZoomIn.png
new file mode 100644
index 0000000..5825340
Binary files /dev/null and b/Client2014/content/textures/CameraZoomIn.png differ
diff --git a/Client2014/content/textures/CameraZoomIn_dn.png b/Client2014/content/textures/CameraZoomIn_dn.png
new file mode 100644
index 0000000..dfb4626
Binary files /dev/null and b/Client2014/content/textures/CameraZoomIn_dn.png differ
diff --git a/Client2014/content/textures/CameraZoomIn_ds.png b/Client2014/content/textures/CameraZoomIn_ds.png
new file mode 100644
index 0000000..eac143e
Binary files /dev/null and b/Client2014/content/textures/CameraZoomIn_ds.png differ
diff --git a/Client2014/content/textures/CameraZoomIn_ovr.png b/Client2014/content/textures/CameraZoomIn_ovr.png
new file mode 100644
index 0000000..dfb4626
Binary files /dev/null and b/Client2014/content/textures/CameraZoomIn_ovr.png differ
diff --git a/Client2014/content/textures/CameraZoomOut.png b/Client2014/content/textures/CameraZoomOut.png
new file mode 100644
index 0000000..0c3e470
Binary files /dev/null and b/Client2014/content/textures/CameraZoomOut.png differ
diff --git a/Client2014/content/textures/CameraZoomOut_dn.png b/Client2014/content/textures/CameraZoomOut_dn.png
new file mode 100644
index 0000000..0bb2995
Binary files /dev/null and b/Client2014/content/textures/CameraZoomOut_dn.png differ
diff --git a/Client2014/content/textures/CameraZoomOut_ds.png b/Client2014/content/textures/CameraZoomOut_ds.png
new file mode 100644
index 0000000..ce63a1c
Binary files /dev/null and b/Client2014/content/textures/CameraZoomOut_ds.png differ
diff --git a/Client2014/content/textures/CameraZoomOut_ovr.png b/Client2014/content/textures/CameraZoomOut_ovr.png
new file mode 100644
index 0000000..0bb2995
Binary files /dev/null and b/Client2014/content/textures/CameraZoomOut_ovr.png differ
diff --git a/Client2014/content/textures/Chat.png b/Client2014/content/textures/Chat.png
new file mode 100644
index 0000000..4fd0c0d
Binary files /dev/null and b/Client2014/content/textures/Chat.png differ
diff --git a/Client2014/content/textures/Chat_dn.png b/Client2014/content/textures/Chat_dn.png
new file mode 100644
index 0000000..4e8604e
Binary files /dev/null and b/Client2014/content/textures/Chat_dn.png differ
diff --git a/Client2014/content/textures/Chat_ds.png b/Client2014/content/textures/Chat_ds.png
new file mode 100644
index 0000000..97e075a
Binary files /dev/null and b/Client2014/content/textures/Chat_ds.png differ
diff --git a/Client2014/content/textures/Chat_ovr.png b/Client2014/content/textures/Chat_ovr.png
new file mode 100644
index 0000000..be854e8
Binary files /dev/null and b/Client2014/content/textures/Chat_ovr.png differ
diff --git a/Client2014/content/textures/Clone.png b/Client2014/content/textures/Clone.png
new file mode 100644
index 0000000..31915a9
Binary files /dev/null and b/Client2014/content/textures/Clone.png differ
diff --git a/Client2014/content/textures/CloneCursor.png b/Client2014/content/textures/CloneCursor.png
new file mode 100644
index 0000000..afe32c0
Binary files /dev/null and b/Client2014/content/textures/CloneCursor.png differ
diff --git a/Client2014/content/textures/CloneDownCursor.png b/Client2014/content/textures/CloneDownCursor.png
new file mode 100644
index 0000000..b33240d
Binary files /dev/null and b/Client2014/content/textures/CloneDownCursor.png differ
diff --git a/Client2014/content/textures/CloneOverCursor.png b/Client2014/content/textures/CloneOverCursor.png
new file mode 100644
index 0000000..5c97ee1
Binary files /dev/null and b/Client2014/content/textures/CloneOverCursor.png differ
diff --git a/Client2014/content/textures/DragCursor.png b/Client2014/content/textures/DragCursor.png
new file mode 100644
index 0000000..a8f1894
Binary files /dev/null and b/Client2014/content/textures/DragCursor.png differ
diff --git a/Client2014/content/textures/DropperCursor.png b/Client2014/content/textures/DropperCursor.png
new file mode 100644
index 0000000..d98bcb6
Binary files /dev/null and b/Client2014/content/textures/DropperCursor.png differ
diff --git a/Client2014/content/textures/Exit.png b/Client2014/content/textures/Exit.png
new file mode 100644
index 0000000..523d2c5
Binary files /dev/null and b/Client2014/content/textures/Exit.png differ
diff --git a/Client2014/content/textures/Exit_dn.png b/Client2014/content/textures/Exit_dn.png
new file mode 100644
index 0000000..b2359c5
Binary files /dev/null and b/Client2014/content/textures/Exit_dn.png differ
diff --git a/Client2014/content/textures/Exit_ovr.png b/Client2014/content/textures/Exit_ovr.png
new file mode 100644
index 0000000..b2359c5
Binary files /dev/null and b/Client2014/content/textures/Exit_ovr.png differ
diff --git a/Client2014/content/textures/FillCursor.png b/Client2014/content/textures/FillCursor.png
new file mode 100644
index 0000000..752cebc
Binary files /dev/null and b/Client2014/content/textures/FillCursor.png differ
diff --git a/Client2014/content/textures/FlagCursor.png b/Client2014/content/textures/FlagCursor.png
new file mode 100644
index 0000000..59c3798
Binary files /dev/null and b/Client2014/content/textures/FlagCursor.png differ
diff --git a/Client2014/content/textures/FlatCursor.png b/Client2014/content/textures/FlatCursor.png
new file mode 100644
index 0000000..feba33a
Binary files /dev/null and b/Client2014/content/textures/FlatCursor.png differ
diff --git a/Client2014/content/textures/GameTool.png b/Client2014/content/textures/GameTool.png
new file mode 100644
index 0000000..86bee9f
Binary files /dev/null and b/Client2014/content/textures/GameTool.png differ
diff --git a/Client2014/content/textures/GrabCursor.png b/Client2014/content/textures/GrabCursor.png
new file mode 100644
index 0000000..d411bae
Binary files /dev/null and b/Client2014/content/textures/GrabCursor.png differ
diff --git a/Client2014/content/textures/GrabRotateCursor.png b/Client2014/content/textures/GrabRotateCursor.png
new file mode 100644
index 0000000..0cd0c13
Binary files /dev/null and b/Client2014/content/textures/GrabRotateCursor.png differ
diff --git a/Client2014/content/textures/Grass_Texture.jpg b/Client2014/content/textures/Grass_Texture.jpg
new file mode 100644
index 0000000..cd273dc
Binary files /dev/null and b/Client2014/content/textures/Grass_Texture.jpg differ
diff --git a/Client2014/content/textures/GunCursor.png b/Client2014/content/textures/GunCursor.png
new file mode 100644
index 0000000..d1b6afc
Binary files /dev/null and b/Client2014/content/textures/GunCursor.png differ
diff --git a/Client2014/content/textures/GunWaitCursor.png b/Client2014/content/textures/GunWaitCursor.png
new file mode 100644
index 0000000..0c812be
Binary files /dev/null and b/Client2014/content/textures/GunWaitCursor.png differ
diff --git a/Client2014/content/textures/HammerCursor.png b/Client2014/content/textures/HammerCursor.png
new file mode 100644
index 0000000..ad2b622
Binary files /dev/null and b/Client2014/content/textures/HammerCursor.png differ
diff --git a/Client2014/content/textures/HammerDownCursor.png b/Client2014/content/textures/HammerDownCursor.png
new file mode 100644
index 0000000..cdbcfe2
Binary files /dev/null and b/Client2014/content/textures/HammerDownCursor.png differ
diff --git a/Client2014/content/textures/HammerOverCursor.png b/Client2014/content/textures/HammerOverCursor.png
new file mode 100644
index 0000000..4182d69
Binary files /dev/null and b/Client2014/content/textures/HammerOverCursor.png differ
diff --git a/Client2014/content/textures/HingeCursor.png b/Client2014/content/textures/HingeCursor.png
new file mode 100644
index 0000000..e507cd3
Binary files /dev/null and b/Client2014/content/textures/HingeCursor.png differ
diff --git a/Client2014/content/textures/LockCursor.png b/Client2014/content/textures/LockCursor.png
new file mode 100644
index 0000000..4c4c6b2
Binary files /dev/null and b/Client2014/content/textures/LockCursor.png differ
diff --git a/Client2014/content/textures/MaterialCursor.png b/Client2014/content/textures/MaterialCursor.png
new file mode 100644
index 0000000..f43fa99
Binary files /dev/null and b/Client2014/content/textures/MaterialCursor.png differ
diff --git a/Client2014/content/textures/MissingCursor.png b/Client2014/content/textures/MissingCursor.png
new file mode 100644
index 0000000..4145456
Binary files /dev/null and b/Client2014/content/textures/MissingCursor.png differ
diff --git a/Client2014/content/textures/MotorCursor.png b/Client2014/content/textures/MotorCursor.png
new file mode 100644
index 0000000..c363ab6
Binary files /dev/null and b/Client2014/content/textures/MotorCursor.png differ
diff --git a/Client2014/content/textures/MouseLockedCursor.png b/Client2014/content/textures/MouseLockedCursor.png
new file mode 100644
index 0000000..c3b44db
Binary files /dev/null and b/Client2014/content/textures/MouseLockedCursor.png differ
diff --git a/Client2014/content/textures/ResizeCursor.png b/Client2014/content/textures/ResizeCursor.png
new file mode 100644
index 0000000..e9e06f5
Binary files /dev/null and b/Client2014/content/textures/ResizeCursor.png differ
diff --git a/Client2014/content/textures/RustGradient.png b/Client2014/content/textures/RustGradient.png
new file mode 100644
index 0000000..0180253
Binary files /dev/null and b/Client2014/content/textures/RustGradient.png differ
diff --git a/Client2014/content/textures/Smoke.png b/Client2014/content/textures/Smoke.png
new file mode 100644
index 0000000..b86df5d
Binary files /dev/null and b/Client2014/content/textures/Smoke.png differ
diff --git a/Client2014/content/textures/SpawnCursor.png b/Client2014/content/textures/SpawnCursor.png
new file mode 100644
index 0000000..37fb08e
Binary files /dev/null and b/Client2014/content/textures/SpawnCursor.png differ
diff --git a/Client2014/content/textures/SpawnLocation.png b/Client2014/content/textures/SpawnLocation.png
new file mode 100644
index 0000000..049c2d3
Binary files /dev/null and b/Client2014/content/textures/SpawnLocation.png differ
diff --git a/Client2014/content/textures/SurfacesDefault.png b/Client2014/content/textures/SurfacesDefault.png
new file mode 100644
index 0000000..53b1505
Binary files /dev/null and b/Client2014/content/textures/SurfacesDefault.png differ
diff --git a/Client2014/content/textures/UnAnchorCursor.png b/Client2014/content/textures/UnAnchorCursor.png
new file mode 100644
index 0000000..fa4e9cb
Binary files /dev/null and b/Client2014/content/textures/UnAnchorCursor.png differ
diff --git a/Client2014/content/textures/UnlockCursor.png b/Client2014/content/textures/UnlockCursor.png
new file mode 100644
index 0000000..052a07a
Binary files /dev/null and b/Client2014/content/textures/UnlockCursor.png differ
diff --git a/Client2014/content/textures/WeldCursor.png b/Client2014/content/textures/WeldCursor.png
new file mode 100644
index 0000000..c2a4292
Binary files /dev/null and b/Client2014/content/textures/WeldCursor.png differ
diff --git a/Client2014/content/textures/advClosed-hand-no-weld.png b/Client2014/content/textures/advClosed-hand-no-weld.png
new file mode 100644
index 0000000..beb2fd4
Binary files /dev/null and b/Client2014/content/textures/advClosed-hand-no-weld.png differ
diff --git a/Client2014/content/textures/advClosed-hand-weld.png b/Client2014/content/textures/advClosed-hand-weld.png
new file mode 100644
index 0000000..b79d71b
Binary files /dev/null and b/Client2014/content/textures/advClosed-hand-weld.png differ
diff --git a/Client2014/content/textures/advClosed-hand.png b/Client2014/content/textures/advClosed-hand.png
new file mode 100644
index 0000000..38fcea4
Binary files /dev/null and b/Client2014/content/textures/advClosed-hand.png differ
diff --git a/Client2014/content/textures/advCursor-default.png b/Client2014/content/textures/advCursor-default.png
new file mode 100644
index 0000000..58c115b
Binary files /dev/null and b/Client2014/content/textures/advCursor-default.png differ
diff --git a/Client2014/content/textures/advCursor-openedHand.png b/Client2014/content/textures/advCursor-openedHand.png
new file mode 100644
index 0000000..c972e29
Binary files /dev/null and b/Client2014/content/textures/advCursor-openedHand.png differ
diff --git a/Client2014/content/textures/advCursor-white.png b/Client2014/content/textures/advCursor-white.png
new file mode 100644
index 0000000..8a68e4f
Binary files /dev/null and b/Client2014/content/textures/advCursor-white.png differ
diff --git a/Client2014/content/textures/advancedMove.png b/Client2014/content/textures/advancedMove.png
new file mode 100644
index 0000000..da15757
Binary files /dev/null and b/Client2014/content/textures/advancedMove.png differ
diff --git a/Client2014/content/textures/advancedMoveResize.png b/Client2014/content/textures/advancedMoveResize.png
new file mode 100644
index 0000000..8b1264a
Binary files /dev/null and b/Client2014/content/textures/advancedMoveResize.png differ
diff --git a/Client2014/content/textures/advancedMove_joint.png b/Client2014/content/textures/advancedMove_joint.png
new file mode 100644
index 0000000..17079e0
Binary files /dev/null and b/Client2014/content/textures/advancedMove_joint.png differ
diff --git a/Client2014/content/textures/advancedMove_keysOnly.png b/Client2014/content/textures/advancedMove_keysOnly.png
new file mode 100644
index 0000000..36eb233
Binary files /dev/null and b/Client2014/content/textures/advancedMove_keysOnly.png differ
diff --git a/Client2014/content/textures/advancedMove_noJoint.png b/Client2014/content/textures/advancedMove_noJoint.png
new file mode 100644
index 0000000..62752c4
Binary files /dev/null and b/Client2014/content/textures/advancedMove_noJoint.png differ
diff --git a/Client2014/content/textures/blackBkg_round.png b/Client2014/content/textures/blackBkg_round.png
new file mode 100644
index 0000000..7070a7c
Binary files /dev/null and b/Client2014/content/textures/blackBkg_round.png differ
diff --git a/Client2014/content/textures/blackBkg_square.png b/Client2014/content/textures/blackBkg_square.png
new file mode 100644
index 0000000..dc97acf
Binary files /dev/null and b/Client2014/content/textures/blackBkg_square.png differ
diff --git a/Client2014/content/textures/chatBubble_botBlue_bkg.png b/Client2014/content/textures/chatBubble_botBlue_bkg.png
new file mode 100644
index 0000000..9f0b008
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botBlue_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botBlue_notify_bkg.png b/Client2014/content/textures/chatBubble_botBlue_notify_bkg.png
new file mode 100644
index 0000000..0b03982
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botBlue_notify_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botBlue_tail.png b/Client2014/content/textures/chatBubble_botBlue_tail.png
new file mode 100644
index 0000000..316bc9d
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botBlue_tail.png differ
diff --git a/Client2014/content/textures/chatBubble_botBlue_tailRight.png b/Client2014/content/textures/chatBubble_botBlue_tailRight.png
new file mode 100644
index 0000000..da047a8
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botBlue_tailRight.png differ
diff --git a/Client2014/content/textures/chatBubble_botGreen_bkg.png b/Client2014/content/textures/chatBubble_botGreen_bkg.png
new file mode 100644
index 0000000..e158c85
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botGreen_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botGreen_notify_bkg.png b/Client2014/content/textures/chatBubble_botGreen_notify_bkg.png
new file mode 100644
index 0000000..d0a0c47
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botGreen_notify_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botGreen_tail.png b/Client2014/content/textures/chatBubble_botGreen_tail.png
new file mode 100644
index 0000000..01e6a00
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botGreen_tail.png differ
diff --git a/Client2014/content/textures/chatBubble_botGreen_tailRight.png b/Client2014/content/textures/chatBubble_botGreen_tailRight.png
new file mode 100644
index 0000000..8cd6293
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botGreen_tailRight.png differ
diff --git a/Client2014/content/textures/chatBubble_botRed_bkg.png b/Client2014/content/textures/chatBubble_botRed_bkg.png
new file mode 100644
index 0000000..66e411f
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botRed_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botRed_notify_bkg.png b/Client2014/content/textures/chatBubble_botRed_notify_bkg.png
new file mode 100644
index 0000000..e7376eb
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botRed_notify_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_botRed_tail.png b/Client2014/content/textures/chatBubble_botRed_tail.png
new file mode 100644
index 0000000..b29c2af
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botRed_tail.png differ
diff --git a/Client2014/content/textures/chatBubble_botRed_tailRight.png b/Client2014/content/textures/chatBubble_botRed_tailRight.png
new file mode 100644
index 0000000..1e39788
Binary files /dev/null and b/Client2014/content/textures/chatBubble_botRed_tailRight.png differ
diff --git a/Client2014/content/textures/chatBubble_bot_notifyGray_dotDotDot.png b/Client2014/content/textures/chatBubble_bot_notifyGray_dotDotDot.png
new file mode 100644
index 0000000..f5b017d
Binary files /dev/null and b/Client2014/content/textures/chatBubble_bot_notifyGray_dotDotDot.png differ
diff --git a/Client2014/content/textures/chatBubble_bot_notify_bang.png b/Client2014/content/textures/chatBubble_bot_notify_bang.png
new file mode 100644
index 0000000..1ccef6c
Binary files /dev/null and b/Client2014/content/textures/chatBubble_bot_notify_bang.png differ
diff --git a/Client2014/content/textures/chatBubble_bot_notify_dotDotDot.png b/Client2014/content/textures/chatBubble_bot_notify_dotDotDot.png
new file mode 100644
index 0000000..4318458
Binary files /dev/null and b/Client2014/content/textures/chatBubble_bot_notify_dotDotDot.png differ
diff --git a/Client2014/content/textures/chatBubble_bot_notify_money.png b/Client2014/content/textures/chatBubble_bot_notify_money.png
new file mode 100644
index 0000000..54f58c5
Binary files /dev/null and b/Client2014/content/textures/chatBubble_bot_notify_money.png differ
diff --git a/Client2014/content/textures/chatBubble_bot_notify_question.png b/Client2014/content/textures/chatBubble_bot_notify_question.png
new file mode 100644
index 0000000..0a91c4f
Binary files /dev/null and b/Client2014/content/textures/chatBubble_bot_notify_question.png differ
diff --git a/Client2014/content/textures/chatBubble_white_bkg.png b/Client2014/content/textures/chatBubble_white_bkg.png
new file mode 100644
index 0000000..7e6648c
Binary files /dev/null and b/Client2014/content/textures/chatBubble_white_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_white_notify_bkg.png b/Client2014/content/textures/chatBubble_white_notify_bkg.png
new file mode 100644
index 0000000..828e362
Binary files /dev/null and b/Client2014/content/textures/chatBubble_white_notify_bkg.png differ
diff --git a/Client2014/content/textures/chatBubble_white_tail.png b/Client2014/content/textures/chatBubble_white_tail.png
new file mode 100644
index 0000000..77d1bd4
Binary files /dev/null and b/Client2014/content/textures/chatBubble_white_tail.png differ
diff --git a/Client2014/content/textures/dirt.jpg b/Client2014/content/textures/dirt.jpg
new file mode 100644
index 0000000..05f5c94
Binary files /dev/null and b/Client2014/content/textures/dirt.jpg differ
diff --git a/Client2014/content/textures/explosion.png b/Client2014/content/textures/explosion.png
new file mode 100644
index 0000000..5124cb2
Binary files /dev/null and b/Client2014/content/textures/explosion.png differ
diff --git a/Client2014/content/textures/face.png b/Client2014/content/textures/face.png
new file mode 100644
index 0000000..5555669
Binary files /dev/null and b/Client2014/content/textures/face.png differ
diff --git a/Client2014/content/textures/fire_0.png b/Client2014/content/textures/fire_0.png
new file mode 100644
index 0000000..bbada0f
Binary files /dev/null and b/Client2014/content/textures/fire_0.png differ
diff --git a/Client2014/content/textures/glow.png b/Client2014/content/textures/glow.png
new file mode 100644
index 0000000..db4a99e
Binary files /dev/null and b/Client2014/content/textures/glow.png differ
diff --git a/Client2014/content/textures/lua.png b/Client2014/content/textures/lua.png
new file mode 100644
index 0000000..2791c43
Binary files /dev/null and b/Client2014/content/textures/lua.png differ
diff --git a/Client2014/content/textures/roblox-logo.png b/Client2014/content/textures/roblox-logo.png
new file mode 100644
index 0000000..cf5d0c2
Binary files /dev/null and b/Client2014/content/textures/roblox-logo.png differ
diff --git a/Client2014/content/textures/script.png b/Client2014/content/textures/script.png
new file mode 100644
index 0000000..0f9ed4d
Binary files /dev/null and b/Client2014/content/textures/script.png differ
diff --git a/Client2014/content/textures/spark.png b/Client2014/content/textures/spark.png
new file mode 100644
index 0000000..486f47c
Binary files /dev/null and b/Client2014/content/textures/spark.png differ
diff --git a/Client2014/content/textures/sparkle.png b/Client2014/content/textures/sparkle.png
new file mode 100644
index 0000000..5fa5e2a
Binary files /dev/null and b/Client2014/content/textures/sparkle.png differ
diff --git a/Client2014/content/textures/ui/CloneButton.png b/Client2014/content/textures/ui/CloneButton.png
new file mode 100644
index 0000000..7e24cc6
Binary files /dev/null and b/Client2014/content/textures/ui/CloneButton.png differ
diff --git a/Client2014/content/textures/ui/CloneButton_dn.png b/Client2014/content/textures/ui/CloneButton_dn.png
new file mode 100644
index 0000000..adbfe60
Binary files /dev/null and b/Client2014/content/textures/ui/CloneButton_dn.png differ
diff --git a/Client2014/content/textures/ui/CloseButton.png b/Client2014/content/textures/ui/CloseButton.png
new file mode 100644
index 0000000..59d62c0
Binary files /dev/null and b/Client2014/content/textures/ui/CloseButton.png differ
diff --git a/Client2014/content/textures/ui/CloseButton_dn.png b/Client2014/content/textures/ui/CloseButton_dn.png
new file mode 100644
index 0000000..2a92663
Binary files /dev/null and b/Client2014/content/textures/ui/CloseButton_dn.png differ
diff --git a/Client2014/content/textures/ui/Concrete.png b/Client2014/content/textures/ui/Concrete.png
new file mode 100644
index 0000000..79ee458
Binary files /dev/null and b/Client2014/content/textures/ui/Concrete.png differ
diff --git a/Client2014/content/textures/ui/CorrodedMetal.png b/Client2014/content/textures/ui/CorrodedMetal.png
new file mode 100644
index 0000000..76483c7
Binary files /dev/null and b/Client2014/content/textures/ui/CorrodedMetal.png differ
diff --git a/Client2014/content/textures/ui/DPadSheet.png b/Client2014/content/textures/ui/DPadSheet.png
new file mode 100644
index 0000000..dbef643
Binary files /dev/null and b/Client2014/content/textures/ui/DPadSheet.png differ
diff --git a/Client2014/content/textures/ui/DeleteButton.png b/Client2014/content/textures/ui/DeleteButton.png
new file mode 100644
index 0000000..7f5757c
Binary files /dev/null and b/Client2014/content/textures/ui/DeleteButton.png differ
diff --git a/Client2014/content/textures/ui/DeleteButton_dn.png b/Client2014/content/textures/ui/DeleteButton_dn.png
new file mode 100644
index 0000000..184a615
Binary files /dev/null and b/Client2014/content/textures/ui/DeleteButton_dn.png differ
diff --git a/Client2014/content/textures/ui/DiamondPlate.png b/Client2014/content/textures/ui/DiamondPlate.png
new file mode 100644
index 0000000..ad9d4d0
Binary files /dev/null and b/Client2014/content/textures/ui/DiamondPlate.png differ
diff --git a/Client2014/content/textures/ui/Foil.png b/Client2014/content/textures/ui/Foil.png
new file mode 100644
index 0000000..7cf51fc
Binary files /dev/null and b/Client2014/content/textures/ui/Foil.png differ
diff --git a/Client2014/content/textures/ui/Gear.png b/Client2014/content/textures/ui/Gear.png
new file mode 100644
index 0000000..de60a6a
Binary files /dev/null and b/Client2014/content/textures/ui/Gear.png differ
diff --git a/Client2014/content/textures/ui/Gear_dn.png b/Client2014/content/textures/ui/Gear_dn.png
new file mode 100644
index 0000000..53c8366
Binary files /dev/null and b/Client2014/content/textures/ui/Gear_dn.png differ
diff --git a/Client2014/content/textures/ui/Glue.png b/Client2014/content/textures/ui/Glue.png
new file mode 100644
index 0000000..3ceed9c
Binary files /dev/null and b/Client2014/content/textures/ui/Glue.png differ
diff --git a/Client2014/content/textures/ui/Grass.png b/Client2014/content/textures/ui/Grass.png
new file mode 100644
index 0000000..fd390c4
Binary files /dev/null and b/Client2014/content/textures/ui/Grass.png differ
diff --git a/Client2014/content/textures/ui/GroupMoveButton.png b/Client2014/content/textures/ui/GroupMoveButton.png
new file mode 100644
index 0000000..61a48b4
Binary files /dev/null and b/Client2014/content/textures/ui/GroupMoveButton.png differ
diff --git a/Client2014/content/textures/ui/GroupMoveButton_dn.png b/Client2014/content/textures/ui/GroupMoveButton_dn.png
new file mode 100644
index 0000000..7500d53
Binary files /dev/null and b/Client2014/content/textures/ui/GroupMoveButton_dn.png differ
diff --git a/Client2014/content/textures/ui/Hinge.png b/Client2014/content/textures/ui/Hinge.png
new file mode 100644
index 0000000..c2ab9c9
Binary files /dev/null and b/Client2014/content/textures/ui/Hinge.png differ
diff --git a/Client2014/content/textures/ui/Ice.png b/Client2014/content/textures/ui/Ice.png
new file mode 100644
index 0000000..e9d0a32
Binary files /dev/null and b/Client2014/content/textures/ui/Ice.png differ
diff --git a/Client2014/content/textures/ui/Inlets.png b/Client2014/content/textures/ui/Inlets.png
new file mode 100644
index 0000000..cac89e3
Binary files /dev/null and b/Client2014/content/textures/ui/Inlets.png differ
diff --git a/Client2014/content/textures/ui/InsertButton.png b/Client2014/content/textures/ui/InsertButton.png
new file mode 100644
index 0000000..4058f36
Binary files /dev/null and b/Client2014/content/textures/ui/InsertButton.png differ
diff --git a/Client2014/content/textures/ui/InsertButton_dn.png b/Client2014/content/textures/ui/InsertButton_dn.png
new file mode 100644
index 0000000..03e72b2
Binary files /dev/null and b/Client2014/content/textures/ui/InsertButton_dn.png differ
diff --git a/Client2014/content/textures/ui/MaterialButton.png b/Client2014/content/textures/ui/MaterialButton.png
new file mode 100644
index 0000000..4191aab
Binary files /dev/null and b/Client2014/content/textures/ui/MaterialButton.png differ
diff --git a/Client2014/content/textures/ui/MaterialButton_dn.png b/Client2014/content/textures/ui/MaterialButton_dn.png
new file mode 100644
index 0000000..d61978c
Binary files /dev/null and b/Client2014/content/textures/ui/MaterialButton_dn.png differ
diff --git a/Client2014/content/textures/ui/MaterialMenu.png b/Client2014/content/textures/ui/MaterialMenu.png
new file mode 100644
index 0000000..c4a1c73
Binary files /dev/null and b/Client2014/content/textures/ui/MaterialMenu.png differ
diff --git a/Client2014/content/textures/ui/Motor.png b/Client2014/content/textures/ui/Motor.png
new file mode 100644
index 0000000..e9b63eb
Binary files /dev/null and b/Client2014/content/textures/ui/Motor.png differ
diff --git a/Client2014/content/textures/ui/PaintButton.png b/Client2014/content/textures/ui/PaintButton.png
new file mode 100644
index 0000000..03b99a7
Binary files /dev/null and b/Client2014/content/textures/ui/PaintButton.png differ
diff --git a/Client2014/content/textures/ui/PaintButton_dn.png b/Client2014/content/textures/ui/PaintButton_dn.png
new file mode 100644
index 0000000..af4c64d
Binary files /dev/null and b/Client2014/content/textures/ui/PaintButton_dn.png differ
diff --git a/Client2014/content/textures/ui/PartMoveButton.png b/Client2014/content/textures/ui/PartMoveButton.png
new file mode 100644
index 0000000..a8f8fce
Binary files /dev/null and b/Client2014/content/textures/ui/PartMoveButton.png differ
diff --git a/Client2014/content/textures/ui/PartMoveButton_dn.png b/Client2014/content/textures/ui/PartMoveButton_dn.png
new file mode 100644
index 0000000..3c866db
Binary files /dev/null and b/Client2014/content/textures/ui/PartMoveButton_dn.png differ
diff --git a/Client2014/content/textures/ui/Plastic.png b/Client2014/content/textures/ui/Plastic.png
new file mode 100644
index 0000000..8f8bbf3
Binary files /dev/null and b/Client2014/content/textures/ui/Plastic.png differ
diff --git a/Client2014/content/textures/ui/PlayerListFriendRequestReceivedIcon.png b/Client2014/content/textures/ui/PlayerListFriendRequestReceivedIcon.png
new file mode 100644
index 0000000..ab292da
Binary files /dev/null and b/Client2014/content/textures/ui/PlayerListFriendRequestReceivedIcon.png differ
diff --git a/Client2014/content/textures/ui/PlayerListFriendRequestSentIcon.png b/Client2014/content/textures/ui/PlayerListFriendRequestSentIcon.png
new file mode 100644
index 0000000..e10634b
Binary files /dev/null and b/Client2014/content/textures/ui/PlayerListFriendRequestSentIcon.png differ
diff --git a/Client2014/content/textures/ui/PlayerlistFriendIcon.png b/Client2014/content/textures/ui/PlayerlistFriendIcon.png
new file mode 100644
index 0000000..21619a5
Binary files /dev/null and b/Client2014/content/textures/ui/PlayerlistFriendIcon.png differ
diff --git a/Client2014/content/textures/ui/PropertyButton.png b/Client2014/content/textures/ui/PropertyButton.png
new file mode 100644
index 0000000..254e00d
Binary files /dev/null and b/Client2014/content/textures/ui/PropertyButton.png differ
diff --git a/Client2014/content/textures/ui/PropertyButton_dn.png b/Client2014/content/textures/ui/PropertyButton_dn.png
new file mode 100644
index 0000000..c95ec8d
Binary files /dev/null and b/Client2014/content/textures/ui/PropertyButton_dn.png differ
diff --git a/Client2014/content/textures/ui/RecordStop.png b/Client2014/content/textures/ui/RecordStop.png
new file mode 100644
index 0000000..6b86baf
Binary files /dev/null and b/Client2014/content/textures/ui/RecordStop.png differ
diff --git a/Client2014/content/textures/ui/ResetIcon.png b/Client2014/content/textures/ui/ResetIcon.png
new file mode 100644
index 0000000..b9558d4
Binary files /dev/null and b/Client2014/content/textures/ui/ResetIcon.png differ
diff --git a/Client2014/content/textures/ui/ScaleButton.png b/Client2014/content/textures/ui/ScaleButton.png
new file mode 100644
index 0000000..05ab151
Binary files /dev/null and b/Client2014/content/textures/ui/ScaleButton.png differ
diff --git a/Client2014/content/textures/ui/ScaleButton_dn.png b/Client2014/content/textures/ui/ScaleButton_dn.png
new file mode 100644
index 0000000..c5010fa
Binary files /dev/null and b/Client2014/content/textures/ui/ScaleButton_dn.png differ
diff --git a/Client2014/content/textures/ui/SearchIcon.png b/Client2014/content/textures/ui/SearchIcon.png
new file mode 100644
index 0000000..d72741c
Binary files /dev/null and b/Client2014/content/textures/ui/SearchIcon.png differ
diff --git a/Client2014/content/textures/ui/SettingsButton.png b/Client2014/content/textures/ui/SettingsButton.png
new file mode 100644
index 0000000..196cf23
Binary files /dev/null and b/Client2014/content/textures/ui/SettingsButton.png differ
diff --git a/Client2014/content/textures/ui/SettingsButton_dn.png b/Client2014/content/textures/ui/SettingsButton_dn.png
new file mode 100644
index 0000000..e6f4799
Binary files /dev/null and b/Client2014/content/textures/ui/SettingsButton_dn.png differ
diff --git a/Client2014/content/textures/ui/SettingsButton_ds.png b/Client2014/content/textures/ui/SettingsButton_ds.png
new file mode 100644
index 0000000..2aca460
Binary files /dev/null and b/Client2014/content/textures/ui/SettingsButton_ds.png differ
diff --git a/Client2014/content/textures/ui/SettingsButton_ovr.png b/Client2014/content/textures/ui/SettingsButton_ovr.png
new file mode 100644
index 0000000..e6f4799
Binary files /dev/null and b/Client2014/content/textures/ui/SettingsButton_ovr.png differ
diff --git a/Client2014/content/textures/ui/Slate.png b/Client2014/content/textures/ui/Slate.png
new file mode 100644
index 0000000..4f90fb8
Binary files /dev/null and b/Client2014/content/textures/ui/Slate.png differ
diff --git a/Client2014/content/textures/ui/Slider.png b/Client2014/content/textures/ui/Slider.png
new file mode 100644
index 0000000..63c4dea
Binary files /dev/null and b/Client2014/content/textures/ui/Slider.png differ
diff --git a/Client2014/content/textures/ui/Slider_dn.png b/Client2014/content/textures/ui/Slider_dn.png
new file mode 100644
index 0000000..d98cb85
Binary files /dev/null and b/Client2014/content/textures/ui/Slider_dn.png differ
diff --git a/Client2014/content/textures/ui/Slider_sel.png b/Client2014/content/textures/ui/Slider_sel.png
new file mode 100644
index 0000000..d98cb85
Binary files /dev/null and b/Client2014/content/textures/ui/Slider_sel.png differ
diff --git a/Client2014/content/textures/ui/Smooth.png b/Client2014/content/textures/ui/Smooth.png
new file mode 100644
index 0000000..e4d6c4d
Binary files /dev/null and b/Client2014/content/textures/ui/Smooth.png differ
diff --git a/Client2014/content/textures/ui/StampToolButton.png b/Client2014/content/textures/ui/StampToolButton.png
new file mode 100644
index 0000000..34e7994
Binary files /dev/null and b/Client2014/content/textures/ui/StampToolButton.png differ
diff --git a/Client2014/content/textures/ui/StampToolButton_dn.png b/Client2014/content/textures/ui/StampToolButton_dn.png
new file mode 100644
index 0000000..affebf4
Binary files /dev/null and b/Client2014/content/textures/ui/StampToolButton_dn.png differ
diff --git a/Client2014/content/textures/ui/Studs.png b/Client2014/content/textures/ui/Studs.png
new file mode 100644
index 0000000..194a02b
Binary files /dev/null and b/Client2014/content/textures/ui/Studs.png differ
diff --git a/Client2014/content/textures/ui/SurfaceButton.png b/Client2014/content/textures/ui/SurfaceButton.png
new file mode 100644
index 0000000..78c90f0
Binary files /dev/null and b/Client2014/content/textures/ui/SurfaceButton.png differ
diff --git a/Client2014/content/textures/ui/SurfaceButton_dn.png b/Client2014/content/textures/ui/SurfaceButton_dn.png
new file mode 100644
index 0000000..850e099
Binary files /dev/null and b/Client2014/content/textures/ui/SurfaceButton_dn.png differ
diff --git a/Client2014/content/textures/ui/SurfaceMenu.png b/Client2014/content/textures/ui/SurfaceMenu.png
new file mode 100644
index 0000000..1582479
Binary files /dev/null and b/Client2014/content/textures/ui/SurfaceMenu.png differ
diff --git a/Client2014/content/textures/ui/TinyBcIcon.png b/Client2014/content/textures/ui/TinyBcIcon.png
new file mode 100644
index 0000000..1e2c7ef
Binary files /dev/null and b/Client2014/content/textures/ui/TinyBcIcon.png differ
diff --git a/Client2014/content/textures/ui/TinyObcIcon.png b/Client2014/content/textures/ui/TinyObcIcon.png
new file mode 100644
index 0000000..f12104d
Binary files /dev/null and b/Client2014/content/textures/ui/TinyObcIcon.png differ
diff --git a/Client2014/content/textures/ui/TinyTbcIcon.png b/Client2014/content/textures/ui/TinyTbcIcon.png
new file mode 100644
index 0000000..d5c37fe
Binary files /dev/null and b/Client2014/content/textures/ui/TinyTbcIcon.png differ
diff --git a/Client2014/content/textures/ui/ToggleFullScreen_ds.png b/Client2014/content/textures/ui/ToggleFullScreen_ds.png
new file mode 100644
index 0000000..07d7de0
Binary files /dev/null and b/Client2014/content/textures/ui/ToggleFullScreen_ds.png differ
diff --git a/Client2014/content/textures/ui/ToolButton.png b/Client2014/content/textures/ui/ToolButton.png
new file mode 100644
index 0000000..ca9a395
Binary files /dev/null and b/Client2014/content/textures/ui/ToolButton.png differ
diff --git a/Client2014/content/textures/ui/ToolButton_dn.png b/Client2014/content/textures/ui/ToolButton_dn.png
new file mode 100644
index 0000000..e53c826
Binary files /dev/null and b/Client2014/content/textures/ui/ToolButton_dn.png differ
diff --git a/Client2014/content/textures/ui/ToolButton_ds.png b/Client2014/content/textures/ui/ToolButton_ds.png
new file mode 100644
index 0000000..016ae9c
Binary files /dev/null and b/Client2014/content/textures/ui/ToolButton_ds.png differ
diff --git a/Client2014/content/textures/ui/TouchControlsSheet.png b/Client2014/content/textures/ui/TouchControlsSheet.png
new file mode 100644
index 0000000..d3b740e
Binary files /dev/null and b/Client2014/content/textures/ui/TouchControlsSheet.png differ
diff --git a/Client2014/content/textures/ui/Universal.png b/Client2014/content/textures/ui/Universal.png
new file mode 100644
index 0000000..508fac8
Binary files /dev/null and b/Client2014/content/textures/ui/Universal.png differ
diff --git a/Client2014/content/textures/ui/Weld.png b/Client2014/content/textures/ui/Weld.png
new file mode 100644
index 0000000..d45375b
Binary files /dev/null and b/Client2014/content/textures/ui/Weld.png differ
diff --git a/Client2014/content/textures/ui/Wood.png b/Client2014/content/textures/ui/Wood.png
new file mode 100644
index 0000000..93898de
Binary files /dev/null and b/Client2014/content/textures/ui/Wood.png differ
diff --git a/Client2014/content/textures/ui/btn_grey.png b/Client2014/content/textures/ui/btn_grey.png
new file mode 100644
index 0000000..5e46696
Binary files /dev/null and b/Client2014/content/textures/ui/btn_grey.png differ
diff --git a/Client2014/content/textures/ui/btn_greyTransp.png b/Client2014/content/textures/ui/btn_greyTransp.png
new file mode 100644
index 0000000..df5989b
Binary files /dev/null and b/Client2014/content/textures/ui/btn_greyTransp.png differ
diff --git a/Client2014/content/textures/ui/btn_red.png b/Client2014/content/textures/ui/btn_red.png
new file mode 100644
index 0000000..17666e6
Binary files /dev/null and b/Client2014/content/textures/ui/btn_red.png differ
diff --git a/Client2014/content/textures/ui/btn_redGlow.png b/Client2014/content/textures/ui/btn_redGlow.png
new file mode 100644
index 0000000..5cf7081
Binary files /dev/null and b/Client2014/content/textures/ui/btn_redGlow.png differ
diff --git a/Client2014/content/textures/ui/btn_white.png b/Client2014/content/textures/ui/btn_white.png
new file mode 100644
index 0000000..d2a1cf2
Binary files /dev/null and b/Client2014/content/textures/ui/btn_white.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_off.png b/Client2014/content/textures/ui/mouseLock_off.png
new file mode 100644
index 0000000..e170d2c
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_off.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_off_ds.png b/Client2014/content/textures/ui/mouseLock_off_ds.png
new file mode 100644
index 0000000..85b9a10
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_off_ds.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_off_ovr.png b/Client2014/content/textures/ui/mouseLock_off_ovr.png
new file mode 100644
index 0000000..6c06e1e
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_off_ovr.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_on.png b/Client2014/content/textures/ui/mouseLock_on.png
new file mode 100644
index 0000000..caa9d52
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_on.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_on_ds.png b/Client2014/content/textures/ui/mouseLock_on_ds.png
new file mode 100644
index 0000000..0fa160e
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_on_ds.png differ
diff --git a/Client2014/content/textures/ui/mouseLock_on_ovr.png b/Client2014/content/textures/ui/mouseLock_on_ovr.png
new file mode 100644
index 0000000..653535f
Binary files /dev/null and b/Client2014/content/textures/ui/mouseLock_on_ovr.png differ
diff --git a/Client2014/content/textures/ui/scrollbar.png b/Client2014/content/textures/ui/scrollbar.png
new file mode 100644
index 0000000..9d7a4ff
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbar.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonDown.png b/Client2014/content/textures/ui/scrollbuttonDown.png
new file mode 100644
index 0000000..a3e6539
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonDown.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonDown_dn.png b/Client2014/content/textures/ui/scrollbuttonDown_dn.png
new file mode 100644
index 0000000..f7002ce
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonDown_dn.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonDown_ds.png b/Client2014/content/textures/ui/scrollbuttonDown_ds.png
new file mode 100644
index 0000000..eac4eb9
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonDown_ds.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonDown_ovr.png b/Client2014/content/textures/ui/scrollbuttonDown_ovr.png
new file mode 100644
index 0000000..f7002ce
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonDown_ovr.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonUp.png b/Client2014/content/textures/ui/scrollbuttonUp.png
new file mode 100644
index 0000000..5754f55
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonUp.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonUp_dn.png b/Client2014/content/textures/ui/scrollbuttonUp_dn.png
new file mode 100644
index 0000000..f12d690
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonUp_dn.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonUp_ds.png b/Client2014/content/textures/ui/scrollbuttonUp_ds.png
new file mode 100644
index 0000000..1e1b9db
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonUp_ds.png differ
diff --git a/Client2014/content/textures/ui/scrollbuttonUp_ovr.png b/Client2014/content/textures/ui/scrollbuttonUp_ovr.png
new file mode 100644
index 0000000..f12d690
Binary files /dev/null and b/Client2014/content/textures/ui/scrollbuttonUp_ovr.png differ
diff --git a/Client2014/content/textures/water_Subsurface.dds b/Client2014/content/textures/water_Subsurface.dds
new file mode 100644
index 0000000..0435f14
Binary files /dev/null and b/Client2014/content/textures/water_Subsurface.dds differ
diff --git a/Client2014/content/textures/water_Wave.dds b/Client2014/content/textures/water_Wave.dds
new file mode 100644
index 0000000..fc2f7a0
Binary files /dev/null and b/Client2014/content/textures/water_Wave.dds differ
diff --git a/Client2014/content/textures/wrench.png b/Client2014/content/textures/wrench.png
new file mode 100644
index 0000000..5c8213f
Binary files /dev/null and b/Client2014/content/textures/wrench.png differ
diff --git a/Client2014/fmodex.dll b/Client2014/fmodex.dll
new file mode 100644
index 0000000..d91f410
Binary files /dev/null and b/Client2014/fmodex.dll differ
diff --git a/Client2014/msvcp110.dll b/Client2014/msvcp110.dll
new file mode 100644
index 0000000..93fab56
Binary files /dev/null and b/Client2014/msvcp110.dll differ
diff --git a/Client2014/msvcr110.dll b/Client2014/msvcr110.dll
new file mode 100644
index 0000000..1ce960d
Binary files /dev/null and b/Client2014/msvcr110.dll differ
diff --git a/Client2014/shaders/shaders.json b/Client2014/shaders/shaders.json
new file mode 100644
index 0000000..83eda67
--- /dev/null
+++ b/Client2014/shaders/shaders.json
@@ -0,0 +1,105 @@
+[
+ { "name": "AdornVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornVS" },
+ { "name": "AdornSelfLitVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornSelfLitVS" },
+ { "name": "AdornSelfLitHighlightVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornSelfLitHighlightVS" },
+ { "name": "AdornLightingVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornVS", "defines": "PIN_LIGHTING" },
+ { "name": "AdornFS", "source": "adorn.hlsl", "target": "ps_2_0", "entrypoint": "AdornPS" },
+ { "name": "DefaultStaticVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS" },
+ { "name": "DefaultStaticHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_HQ" },
+ { "name": "DefaultSkinnedVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED" },
+ { "name": "DefaultSkinnedHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_HQ" },
+ { "name": "DefaultStaticDebugVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_DEBUG" },
+ { "name": "DefaultSkinnedDebugVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_DEBUG" },
+ { "name": "DefaultFS", "source": "default.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultHQFS", "source": "default.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultHQGBufferFS", "source": "default.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultStaticReflectionVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultSkinnedReflectionVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_REFLECTION" },
+ { "name": "DefaultStaticSurfaceHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SURFACE PIN_HQ" },
+ { "name": "DefaultSkinnedSurfaceHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_SURFACE PIN_HQ" },
+ { "name": "DefaultPlasticFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultPlasticHQFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultPlasticHQGBufferFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultPlasticReflectionFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultPlasticReflectionHQFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ" },
+ { "name": "DefaultPlasticReflectionHQGBufferFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSmoothPlasticFS", "source": "smoothplastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultSmoothPlasticHQFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSmoothPlasticHQGBufferFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSmoothPlasticReflectionFS", "source": "smoothplastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultSmoothPlasticReflectionHQFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ" },
+ { "name": "DefaultSmoothPlasticReflectionHQGBufferFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultWoodHQFS", "source": "wood.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultWoodHQGBufferFS", "source": "wood.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultMarbleHQFS", "source": "marble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultMarbleHQGBufferFS", "source": "marble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSlateHQFS", "source": "slate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSlateHQGBufferFS", "source": "slate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultGraniteHQFS", "source": "granite.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultGraniteHQGBufferFS", "source": "granite.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultConcreteHQFS", "source": "concrete.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultConcreteHQGBufferFS", "source": "concrete.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultPebbleHQFS", "source": "pebble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultPebbleHQGBufferFS", "source": "pebble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultBrickHQFS", "source": "brick.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultBrickHQGBufferFS", "source": "brick.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultRustHQFS", "source": "rust.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultRustHQGBufferFS", "source": "rust.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultDiamondplateHQFS", "source": "diamondplate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultDiamondplateHQGBufferFS", "source": "diamondplate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultAluminumHQFS", "source": "aluminum.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultAluminumHQGBufferFS", "source": "aluminum.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultGrassHQFS", "source": "grass.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultGrassHQGBufferFS", "source": "grass.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSandHQFS", "source": "sand.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSandHQGBufferFS", "source": "sand.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultFabricHQFS", "source": "fabric.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultFabricHQGBufferFS", "source": "fabric.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultIceHQFS", "source": "ice.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultIceHQGBufferFS", "source": "ice.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "MegaClusterVS", "source": "megacluster.hlsl", "target": "vs_2_0", "entrypoint": "MegaClusterVS" },
+ { "name": "MegaClusterHQVS", "source": "megacluster.hlsl", "target": "vs_2_0", "entrypoint": "MegaClusterVS", "defines": "PIN_HQ" },
+ { "name": "MegaClusterFS", "source": "megacluster.hlsl", "target": "ps_2_0", "entrypoint": "MegaClusterPS" },
+ { "name": "MegaClusterHQFS", "source": "megacluster.hlsl", "target": "ps_2_a", "entrypoint": "MegaClusterPS", "defines": "PIN_HQ" },
+ { "name": "MegaClusterHQGBufferFS", "source": "megacluster.hlsl", "target": "ps_2_a", "entrypoint": "MegaClusterPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "ParticleVS", "source": "particle.hlsl", "target": "vs_1_1", "entrypoint": "vs" },
+ { "name": "ParticleAddFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psAdd" },
+ { "name": "ParticleMulFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psMul" },
+ { "name": "ShadowExtrudeVS", "source": "shadowextrude.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS" },
+ { "name": "ShadowExtrudeFS", "source": "shadowextrude.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "ShadowQuadVS", "source": "shadowquad.hlsl", "target": "vs_1_1", "entrypoint": "QuadVS" },
+ { "name": "ShadowQuadFS", "source": "shadowquad.hlsl", "target": "ps_2_0", "entrypoint": "QuadPS" },
+ { "name": "SkyVS", "source": "sky.hlsl", "target": "vs_1_1", "entrypoint": "SkyVS" },
+ { "name": "SkyFS", "source": "sky.hlsl", "target": "ps_2_0", "entrypoint": "SkyPS" },
+ { "name": "TexCompVS", "source": "texcomp.hlsl", "target": "vs_1_1", "entrypoint": "TexCompVS" },
+ { "name": "TexCompFS", "source": "texcomp.hlsl", "target": "ps_2_0", "entrypoint": "TexCompPS" },
+ { "name": "TexCompPMAFS", "source": "texcomp.hlsl", "target": "ps_2_0", "entrypoint": "TexCompPMAPS" },
+ { "name": "UIVS", "source": "ui.hlsl", "target": "vs_1_1", "entrypoint": "UIVS" },
+ { "name": "UIFogVS", "source": "ui.hlsl", "target": "vs_1_1", "entrypoint": "UIVS", "defines": "PIN_FOG" },
+ { "name": "UIFS", "source": "ui.hlsl", "target": "ps_2_0", "entrypoint": "UIPS" },
+ { "name": "UIFogFS", "source": "ui.hlsl", "target": "ps_2_0", "entrypoint": "UIPS", "defines": "PIN_FOG" },
+ { "name": "WaterVS", "source": "water.hlsl", "target": "vs_2_0", "entrypoint": "water_vs" },
+ { "name": "WaterHQVS", "source": "water.hlsl", "target": "vs_2_0", "entrypoint": "water_vs", "defines": "PIN_HQ" },
+ { "name": "WaterFS", "source": "water.hlsl", "target": "ps_2_0", "entrypoint": "water_ps" },
+ { "name": "WaterHQFS", "source": "water.hlsl", "target": "ps_2_a", "entrypoint": "water_ps", "defines": "PIN_HQ" },
+
+ { "name": "OLD_WaterVS", "source": "water_r3.hlsl", "target": "vs_2_0", "entrypoint": "water_vs" },
+ { "name": "OLD_WaterHQVS", "source": "water_r3.hlsl", "target": "vs_2_0", "entrypoint": "water_vs", "defines": "PIN_HQ" },
+ { "name": "OLD_WaterFS", "source": "water_r3.hlsl", "target": "ps_2_0", "entrypoint": "water_ps" },
+ { "name": "OLD_WaterHQFS", "source": "water_r3.hlsl", "target": "ps_2_a", "entrypoint": "water_ps", "defines": "PIN_HQ" },
+
+
+ { "name": "SSAOVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssao_vs", "exclude": "glsles" },
+ { "name": "SSAOFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssao_ps", "exclude": "glsles" },
+ { "name": "SSAODepthDownVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoDepthDown_vs", "exclude": "glsles" },
+ { "name": "SSAODepthDownFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoDepthDown_ps", "exclude": "glsles" },
+ { "name": "SSAOBlurXVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoBlurX_vs", "exclude": "glsles" },
+ { "name": "SSAOBlurXFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoBlurX_ps", "exclude": "glsles" },
+ { "name": "SSAOBlurYVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoBlurY_vs", "exclude": "glsles" },
+ { "name": "SSAOBlurYFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoBlurY_ps", "exclude": "glsles" },
+ { "name": "SSAOCompositVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoComposit_vs", "exclude": "glsles" },
+ { "name": "SSAOCompositBlankFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoCompositBlank_ps", "exclude": "glsles" },
+ { "name": "SSAOCompositFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoComposit_ps", "exclude": "glsles" },
+ { "name": "MSAACompositVS", "source": "msaa.hlsl", "target": "vs_1_1", "entrypoint": "msaaComposit_vs" },
+ { "name": "MSAACompositFS", "source": "msaa.hlsl", "target": "ps_2_0", "entrypoint": "msaaComposit_ps" }
+]
diff --git a/Client2014/shaders/shaders_d3d9.pack b/Client2014/shaders/shaders_d3d9.pack
new file mode 100644
index 0000000..d1136e2
Binary files /dev/null and b/Client2014/shaders/shaders_d3d9.pack differ
diff --git a/Client2014/shaders/shaders_glsl.pack b/Client2014/shaders/shaders_glsl.pack
new file mode 100644
index 0000000..7592a73
Binary files /dev/null and b/Client2014/shaders/shaders_glsl.pack differ
diff --git a/Client2014/shaders/shaders_glsles.pack b/Client2014/shaders/shaders_glsles.pack
new file mode 100644
index 0000000..f98429f
Binary files /dev/null and b/Client2014/shaders/shaders_glsles.pack differ
diff --git a/Client2014/shaders/source/adorn.hlsl b/Client2014/shaders/source/adorn.hlsl
new file mode 100644
index 0000000..a574f3c
--- /dev/null
+++ b/Client2014/shaders/source/adorn.hlsl
@@ -0,0 +1,88 @@
+#include "globals.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float3 Normal : NORMAL0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+
+ float FogFactor : TEXCOORD1;
+};
+
+uniform float4x4 WorldMatrix;
+
+uniform float4 Color;
+
+VertexOutput AdornSelfLitVSGeneric(Appdata IN, float ambient)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+ float3 normal = normalize(mul((float3x3)WorldMatrix, IN.Normal));
+
+ float3 light = normalize(G.CameraPosition - position.xyz);
+ float ndotl = saturate(dot(normal, light));
+
+ float lighting = ambient + (1 - ambient) * ndotl;
+ float specular = pow(ndotl, 64.0);
+
+ OUT.HPosition = mul(G.ViewProjection, mul(WorldMatrix, IN.Position));
+ OUT.Uv = IN.Uv;
+ OUT.Color = float4(Color.rgb * lighting + specular, Color.a);
+
+ OUT.FogFactor = (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w;
+
+ return OUT;
+}
+
+VertexOutput AdornSelfLitVS(Appdata IN)
+{
+ return AdornSelfLitVSGeneric(IN, 0.5f);
+}
+
+VertexOutput AdornSelfLitHighlightVS(Appdata IN)
+{
+ return AdornSelfLitVSGeneric(IN, 0.75f);
+}
+
+VertexOutput AdornVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+
+#ifdef PIN_LIGHTING
+ float3 normal = normalize(mul((float3x3)WorldMatrix, IN.Normal));
+ float ndotl = dot(normal, -G.Lamp0Dir);
+ float3 lighting = G.AmbientColor + saturate(ndotl) * G.Lamp0Color + saturate(-ndotl) * G.Lamp1Color;
+#else
+ float3 lighting = 1;
+#endif
+
+ OUT.HPosition = mul(G.ViewProjection, position);
+ OUT.Uv = IN.Uv;
+ OUT.Color = float4(Color.rgb * lighting, Color.a);
+
+ OUT.FogFactor = (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w;
+
+ return OUT;
+}
+
+sampler2D DiffuseMap: register(s0);
+
+float4 AdornPS(VertexOutput IN): COLOR0
+{
+ float4 result = tex2D(DiffuseMap, IN.Uv) * IN.Color;
+
+ result.rgb = lerp(G.FogColor, result.rgb, saturate(IN.FogFactor));
+
+ return result;
+}
diff --git a/Client2014/shaders/source/aluminum.hlsl b/Client2014/shaders/source/aluminum.hlsl
new file mode 100644
index 0000000..f327503
--- /dev/null
+++ b/Client2014/shaders/source/aluminum.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0.6
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.94
+#define CFG_GLOSS_LOD 240
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0.75
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_DIFFUSE_CONST
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/brick.hlsl b/Client2014/shaders/source/brick.hlsl
new file mode 100644
index 0000000..eb7c8db
--- /dev/null
+++ b/Client2014/shaders/source/brick.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.3
+#define CFG_GLOSS_SCALE 64
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.26
+#define CFG_GLOSS_LOD 26
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/common.h b/Client2014/shaders/source/common.h
new file mode 100644
index 0000000..c598916
--- /dev/null
+++ b/Client2014/shaders/source/common.h
@@ -0,0 +1,140 @@
+#include "globals.h"
+
+// GLSLES has limited number of vertex shader registers so we have to use less bones
+#ifdef GLSLES
+#define MAX_BONE_COUNT 32
+#else
+#define MAX_BONE_COUNT 72
+#endif
+
+// PowerVR saturate() is compiled to min/max pair
+// These are cross-platform specialized saturates that are free on PC and only cost 1 cycle on PowerVR
+#ifdef GLSLES
+float saturate0(float v) { return max(v, 0); }
+float saturate1(float v) { return min(v, 1); }
+#else
+float saturate0(float v) { return saturate(v); }
+float saturate1(float v) { return saturate(v); }
+#endif
+
+#define GBUFFER_MAX_DEPTH 500.0f
+
+float4 gbufferPack(float depth, float3 diffuse, float3 specular, float fog)
+{
+ depth = saturate(depth / GBUFFER_MAX_DEPTH);
+
+ const float3 bitSh = float3(255*255, 255, 1);
+ const float3 lumVec = float3(0.299, 0.587, 0.114);
+
+ float2 comp;
+ comp = depth*float2(255,255*256);
+ comp = frac(comp);
+ comp = float2(depth,comp.x*256/255) - float2(comp.x, comp.y)/255;
+
+ float4 result;
+
+ result.r = lerp(1, dot(specular, lumVec), saturate(3 * fog));
+ result.g = lerp(0, dot(diffuse, lumVec), saturate(3 * fog));
+ result.ba = comp.yx;
+
+ return result;
+}
+
+float3 getPosInLightSpace(float3 posIn)
+{
+ float3 lightToWorld = posIn - G.BlobShadowData0.xyz;
+ return float3(dot(G.Lamp0Right, lightToWorld), dot(G.Lamp0Up, lightToWorld), dot(G.Lamp0Dir, lightToWorld));
+}
+
+float getSingleBlobShadowOrigin(float3 lightSpacePos, float4 blobData)
+{
+ float distSq = dot(lightSpacePos.xy, lightSpacePos.xy);
+
+ // OH MY GOD! a BRANCH? Why? Because this produces a better assembly over other solution
+ float projDistScaled = lightSpacePos.z * 0.04;
+ if (lightSpacePos.z < 0)
+ projDistScaled = lightSpacePos.z * -0.3;
+
+ return min(1, distSq * G.OutlineBrightness_ShadowInfo.z + projDistScaled + blobData.a);
+}
+
+float getSingleBlobShadow(float3 lightSpacePos, float4 blobData)
+{
+ return getSingleBlobShadowOrigin(lightSpacePos - blobData.xyz, blobData);
+}
+
+float getBlobShadow(float3 lightSpacePos)
+{
+ #ifdef PIN_HQ
+ float shadow = min(getSingleBlobShadowOrigin(lightSpacePos, G.BlobShadowData0), getSingleBlobShadow(lightSpacePos, G.BlobShadowData1));
+ shadow = min(getSingleBlobShadow(lightSpacePos, G.BlobShadowData2), shadow);
+ shadow = min(getSingleBlobShadow(lightSpacePos, G.BlobShadowData3), shadow);
+ return shadow;
+ #else
+ return getSingleBlobShadowOrigin(lightSpacePos, G.BlobShadowData0);
+ #endif
+}
+
+float3 lgridOffset(float3 v, float3 n)
+{
+ // cells are 4 studs in size
+ // offset in normal direction to prevent self-occlusion
+ // the offset has to be 1.5 cells in order to fully eliminate the influence of the source cell with trilinear filtering
+ // (i.e. 1 cell is enough for point filtering, but is not enough for trilinear filtering)
+ return v + n * (1.5f * 4.f);
+}
+
+float3 lgridPrepareSample(float3 c)
+{
+ // yxz swizzle is necessary for GLSLES sampling to work efficiently
+ // (having .y as the first component allows to do the LUT lookup as a non-dependent texture fetch)
+ return c.yxz * G.LightConfig0.xyz + G.LightConfig1.xyz;
+}
+
+#ifdef GLSLES
+#define LGRID_SAMPLER sampler2D
+
+float4 lgridSample(LGRID_SAMPLER t, sampler2D lut, float3 data)
+{
+ float4 offsets = tex2D(lut, data.xy);
+
+ // texture is 64 pixels high
+ // let's compute slice lerp coeff
+ float slicef = frac(data.x * 64);
+
+ // texture has 64 slices with 8x8 atlas setup
+ float2 base = saturate(data.yz) * 0.125;
+
+ float4 s0 = tex2D(t, base + offsets.xy);
+ float4 s1 = tex2D(t, base + offsets.zw);
+
+ return lerp(s0, s1, slicef);
+}
+#else
+#define LGRID_SAMPLER sampler3D
+
+float4 lgridSample(LGRID_SAMPLER t, sampler2D lut, float3 data)
+{
+ float3 edge = step(G.LightConfig3.xyz, abs(data - G.LightConfig2.xyz));
+ float edgef = saturate1(dot(edge, 1));
+
+ // replace data with 0 on edges to minimize texture cache misses
+ float4 light = tex3D(t, data.yzx - data.yzx * edgef);
+
+ return lerp(light, G.LightBorder, edgef);
+}
+#endif
+
+#ifdef GLSLES
+float3 nmapUnpack(float4 value)
+{
+ return value.rgb * 2 - 1;
+}
+#else
+float3 nmapUnpack(float4 value)
+{
+ float2 xy = value.ag * 2 - 1;
+
+ return float3(xy, sqrt(saturate(1 + dot(-xy, xy))));
+}
+#endif
diff --git a/Client2014/shaders/source/concrete.hlsl b/Client2014/shaders/source/concrete.hlsl
new file mode 100644
index 0000000..e068502
--- /dev/null
+++ b/Client2014/shaders/source/concrete.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.3
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.07
+#define CFG_GLOSS_LOD 22
+
+#define CFG_NORMAL_DETAIL_TILING 10
+#define CFG_NORMAL_DETAIL_SCALE 1
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/default.hlsl b/Client2014/shaders/source/default.hlsl
new file mode 100644
index 0000000..11f4cec
--- /dev/null
+++ b/Client2014/shaders/source/default.hlsl
@@ -0,0 +1,267 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float2 Uv : TEXCOORD0;
+ float2 UvStuds : TEXCOORD1;
+
+ float4 Color : COLOR0;
+
+ // int4 produces better D3D asm, float4 produces better GLSL code
+#ifdef GLSL
+ float4 Extra : COLOR1;
+#else
+ int4 Extra : COLOR1;
+#endif
+
+#ifdef PIN_SURFACE
+ float3 Tangent : TEXCOORD2;
+#endif
+ float4 EdgeDistances : TEXCOORD3;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float4 Uv_EdgeDistance1 : TEXCOORD0;
+ float4 UvStuds_EdgeDistance2 : TEXCOORD1;
+
+ float4 Color : COLOR0;
+ float4 LightPosition_Fog : TEXCOORD2;
+
+ #if defined(PIN_HQ) || defined(PIN_REFLECTION)
+ float4 View_DepthMulFadeout : TEXCOORD3;
+ float4 Normal_SpecPower : TEXCOORD4;
+ #endif
+
+ #ifdef PIN_SURFACE
+ float3 Tangent : TEXCOORD5;
+ #else
+ float4 Diffuse_Specular : COLOR1;
+ #endif
+
+ float4 PosLightSpace_Reflectance: TEXCOORD6;
+};
+
+#ifdef PIN_SKINNED
+uniform float4 WorldMatrixArray[MAX_BONE_COUNT * 3];
+#endif
+
+#ifdef PIN_DEBUG
+uniform float4 DebugColor;
+#endif
+
+VertexOutput DefaultVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ // Transform position and normal to world space
+#ifdef PIN_SKINNED
+ int boneIndex = IN.Extra.r;
+
+ float4 worldRow0 = WorldMatrixArray[boneIndex * 3 + 0];
+ float4 worldRow1 = WorldMatrixArray[boneIndex * 3 + 1];
+ float4 worldRow2 = WorldMatrixArray[boneIndex * 3 + 2];
+
+ float3 posWorld = float3(dot(worldRow0, IN.Position), dot(worldRow1, IN.Position), dot(worldRow2, IN.Position));
+ float3 normalWorld = float3(dot(worldRow0.xyz, IN.Normal), dot(worldRow1.xyz, IN.Normal), dot(worldRow2.xyz, IN.Normal));
+#else
+ float3 posWorld = IN.Position.xyz;
+ float3 normalWorld = IN.Normal;
+#endif
+
+ // Decode diffuse/specular parameters; encoding depends on the skinned flag due to vertex declaration differences
+#if defined(PIN_DEBUG)
+ float4 color = DebugColor;
+#else
+ float4 color = IN.Color;
+#endif
+
+ float specularIntensity = IN.Extra.g / 255.f;
+ float specularPower = IN.Extra.b;
+
+ float ndotl = dot(normalWorld, -G.Lamp0Dir);
+
+#ifdef PIN_HQ
+ // We'll calculate specular in pixel shader
+ float2 lt = float2(saturate(ndotl), (ndotl > 0));
+#else
+ // Using lit here improves performance on software vertex shader implementations
+ float2 lt = lit(ndotl, dot(normalize(-G.Lamp0Dir + normalize(G.CameraPosition - posWorld.xyz)), normalWorld), specularPower).yz;
+#endif
+
+ OUT.HPosition = mul(G.ViewProjection, float4(posWorld, 1));
+
+ OUT.Uv_EdgeDistance1.xy = IN.Uv;
+ OUT.UvStuds_EdgeDistance2.xy = IN.UvStuds;
+
+ OUT.Color = color;
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w);
+
+ #if defined(PIN_HQ) || defined(PIN_REFLECTION)
+ OUT.View_DepthMulFadeout = float4(G.CameraPosition - posWorld, OUT.HPosition.w * G.FadeDistance.y);
+ float4 edgeDistances = IN.EdgeDistances*G.FadeDistance.z + 0.5 * OUT.View_DepthMulFadeout.w;
+ OUT.Uv_EdgeDistance1.zw = edgeDistances.xy;
+ OUT.UvStuds_EdgeDistance2.zw = edgeDistances.zw;
+ OUT.Normal_SpecPower = float4(normalWorld, specularPower);
+ OUT.PosLightSpace_Reflectance.w = IN.Extra.a / 255.f;
+ #endif
+
+ #ifdef PIN_SURFACE
+ #ifdef PIN_SKINNED
+ float3 tangent = float3(dot(worldRow0.xyz, IN.Tangent), dot(worldRow1.xyz, IN.Tangent), dot(worldRow2.xyz, IN.Tangent));
+ #else
+ float3 tangent = IN.Tangent;
+ #endif
+
+ OUT.Tangent = tangent;
+ #else
+ float3 diffuse = lt.x * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
+
+ OUT.Diffuse_Specular = float4(diffuse, lt.y * specularIntensity);
+ #endif
+
+ OUT.PosLightSpace_Reflectance.xyz = getPosInLightSpace(posWorld);
+
+ return OUT;
+}
+
+#ifdef PIN_SURFACE
+struct SurfaceInput
+{
+ float4 Color;
+ float2 Uv;
+ float2 UvStuds;
+
+#ifdef PIN_REFLECTION
+ float Reflectance;
+#endif
+};
+
+struct Surface
+{
+ float3 albedo;
+ float3 normal;
+ float specular;
+ float gloss;
+ float reflectance;
+};
+
+Surface surfaceShader(SurfaceInput IN, float fade);
+
+Surface surfaceShaderExec(VertexOutput IN)
+{
+ SurfaceInput SIN;
+ SIN.Color = IN.Color;
+ SIN.Uv = IN.Uv_EdgeDistance1.xy;
+ SIN.UvStuds = IN.UvStuds_EdgeDistance2.xy;
+
+ #ifdef PIN_REFLECTION
+ SIN.Reflectance = IN.PosLightSpace_Reflectance.w;
+ #endif
+
+ float fade = saturate0(1 - IN.View_DepthMulFadeout.w);
+
+ return surfaceShader(SIN, fade);
+}
+#endif
+
+sampler2D StudsMap: register(s0);
+LGRID_SAMPLER LightMap: register(s1);
+sampler2D LightMapLookup: register(s2);
+
+sampler2D DiffuseMap: register(s3);
+sampler2D NormalMap: register(s4);
+samplerCUBE EnvironmentMap: register(s5);
+
+sampler2D SpecularMap: register(s6);
+sampler2D NormalDetailMap: register(s7);
+
+void DefaultPS(VertexOutput IN,
+#ifdef PIN_GBUFFER
+ out float4 oColor1: COLOR1,
+#endif
+ out float4 oColor0: COLOR0)
+{
+ // Compute albedo term
+#ifdef PIN_SURFACE
+ Surface surface = surfaceShaderExec(IN);
+
+ float4 albedo = float4(surface.albedo, IN.Color.a);
+
+ float3 bitangent = cross(IN.Normal_SpecPower.xyz, IN.Tangent.xyz);
+ float3 normal = normalize(surface.normal.x * IN.Tangent.xyz + surface.normal.y * bitangent + surface.normal.z * IN.Normal_SpecPower.xyz);
+
+ float ndotl = dot(normal, -G.Lamp0Dir);
+
+ float3 diffuseIntensity = saturate0(ndotl) * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
+ float specularIntensity = step(0, ndotl) * surface.specular;
+ float specularPower = surface.gloss;
+
+ float reflectance = surface.reflectance;
+#else
+ #ifdef PIN_PLASTIC
+ float4 studs = tex2D(StudsMap, IN.UvStuds_EdgeDistance2.xy);
+ float4 albedo = float4(IN.Color.rgb * 2 * studs.rgb, IN.Color.a);
+ #else
+ float4 albedo = tex2D(DiffuseMap, IN.Uv_EdgeDistance1.xy) * IN.Color;
+ #endif
+
+ #ifdef PIN_HQ
+ float3 normal = normalize(IN.Normal_SpecPower.xyz);
+ float specularPower = IN.Normal_SpecPower.w;
+ #elif defined(PIN_REFLECTION)
+ float3 normal = IN.Normal_SpecPower.xyz;
+ #endif
+
+ float3 diffuseIntensity = IN.Diffuse_Specular.xyz;
+ float specularIntensity = IN.Diffuse_Specular.w;
+
+ #ifdef PIN_REFLECTION
+ float reflectance = IN.PosLightSpace_Reflectance.w;
+ #endif
+
+#endif
+
+ float4 light = lgridSample(LightMap, LightMapLookup, IN.LightPosition_Fog.xyz);
+
+ // Compute reflection term
+#if defined(PIN_SURFACE) || defined(PIN_REFLECTION)
+ float3 reflection = texCUBE(EnvironmentMap, reflect(-IN.View_DepthMulFadeout.xyz, normal)).rgb;
+
+ albedo.rgb = lerp(albedo.rgb, reflection.rgb, reflectance);
+#endif
+
+ float shadow = getBlobShadow(IN.PosLightSpace_Reflectance.xyz) * light.a;
+
+ // Compute diffuse term
+ float3 diffuse = (G.AmbientColor + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
+
+ // Compute specular term
+#ifdef PIN_HQ
+ float3 specular = G.Lamp0Color * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G.Lamp0Dir + normalize(IN.View_DepthMulFadeout.xyz)))), specularPower));
+#else
+ float3 specular = G.Lamp0Color * (specularIntensity * shadow);
+#endif
+
+ // Combine
+ oColor0.rgb = diffuse.rgb + specular.rgb;
+ oColor0.a = albedo.a;
+
+#ifdef PIN_HQ
+ float outlineFade = saturate1(IN.View_DepthMulFadeout.w * G.OutlineBrightness_ShadowInfo.x + G.OutlineBrightness_ShadowInfo.y);
+ float2 minIntermediate = min(IN.Uv_EdgeDistance1.wz, IN.UvStuds_EdgeDistance2.wz);
+ float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / IN.View_DepthMulFadeout.w;
+ oColor0.rgb *= saturate1(outlineFade *(1.5 - minEdgesPlus) + minEdgesPlus);
+#endif
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+ oColor0.rgb = lerp(G.FogColor, oColor0.rgb, fogAlpha);
+
+#ifdef PIN_GBUFFER
+ oColor1 = gbufferPack(IN.View_DepthMulFadeout.w*G.FadeDistance.x, diffuse.rgb, specular.rgb, fogAlpha);
+#endif
+}
diff --git a/Client2014/shaders/source/diamondplate.hlsl b/Client2014/shaders/source/diamondplate.hlsl
new file mode 100644
index 0000000..6b0c8f8
--- /dev/null
+++ b/Client2014/shaders/source/diamondplate.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2.7
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.9
+#define CFG_GLOSS_LOD 160
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/fabric.hlsl b/Client2014/shaders/source/fabric.hlsl
new file mode 100644
index 0000000..3dafd80
--- /dev/null
+++ b/Client2014/shaders/source/fabric.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.2
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.2
+
+#define CFG_SPECULAR_LOD 0.03
+#define CFG_GLOSS_LOD 16
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/globals.h b/Client2014/shaders/source/globals.h
new file mode 100644
index 0000000..2387b0b
--- /dev/null
+++ b/Client2014/shaders/source/globals.h
@@ -0,0 +1,34 @@
+struct Globals
+{
+ float4x4 ViewProjection;
+
+ float4 ViewRight;
+ float4 ViewUp;
+ float3 CameraPosition;
+
+ float3 AmbientColor;
+ float3 Lamp0Color;
+ float3 Lamp0Dir;
+ float3 Lamp0Right;
+ float3 Lamp0Up;
+ float3 Lamp1Color;
+
+ float3 FogColor;
+ float4 FogParams;
+
+ float4 LightBorder;
+ float4 LightConfig0;
+ float4 LightConfig1;
+ float4 LightConfig2;
+ float4 LightConfig3;
+
+ float3 FadeDistance;
+ float4 OutlineBrightness_ShadowInfo;
+
+ float4 BlobShadowData0;
+ float4 BlobShadowData1;
+ float4 BlobShadowData2;
+ float4 BlobShadowData3;
+};
+
+uniform Globals G: register(c0);
diff --git a/Client2014/shaders/source/granite.hlsl b/Client2014/shaders/source/granite.hlsl
new file mode 100644
index 0000000..77c4aed
--- /dev/null
+++ b/Client2014/shaders/source/granite.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.5
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0.2
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.19
+#define CFG_GLOSS_LOD 24
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/grass.hlsl b/Client2014/shaders/source/grass.hlsl
new file mode 100644
index 0000000..177cdb4
--- /dev/null
+++ b/Client2014/shaders/source/grass.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.17
+#define CFG_GLOSS_LOD 18
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/ice.hlsl b/Client2014/shaders/source/ice.hlsl
new file mode 100644
index 0000000..493698a
--- /dev/null
+++ b/Client2014/shaders/source/ice.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1.0
+#define CFG_SPECULAR_SCALE 1.2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0.3
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 1
+#define CFG_GLOSS_LOD 190
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0.75
+
+#define CFG_OPT_DIFFUSE_CONST
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/marble.hlsl b/Client2014/shaders/source/marble.hlsl
new file mode 100644
index 0000000..4447ca8
--- /dev/null
+++ b/Client2014/shaders/source/marble.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.0
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0.2
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.7
+#define CFG_GLOSS_LOD 54
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/material.hlsl b/Client2014/shaders/source/material.hlsl
new file mode 100644
index 0000000..cce8c53
--- /dev/null
+++ b/Client2014/shaders/source/material.hlsl
@@ -0,0 +1,74 @@
+#define PIN_SURFACE
+#include "default.hlsl"
+
+float4 sampleFar(sampler2D s, float2 uv, float fade, float cutoff)
+{
+#ifdef GLSLES
+ return tex2D(s, uv);
+#else
+ if (cutoff == 0)
+ return tex2D(s, uv);
+ else
+ {
+ float cscale = 1 / (1 - cutoff);
+
+ return lerp(tex2D(s, uv * (CFG_FAR_TILING)), tex2D(s, uv), saturate0(fade * cscale - cutoff * cscale));
+ }
+#endif
+}
+
+Surface surfaceShader(SurfaceInput IN, float fade)
+{
+ float2 uv = IN.Uv * (CFG_TEXTURE_TILING);
+
+#ifdef CFG_OPT_DIFFUSE_CONST
+ float4 diffuse = 1;
+#else
+ float4 diffuse = sampleFar(DiffuseMap, uv, fade, CFG_FAR_DIFFUSE_CUTOFF);
+
+ diffuse.rgb = lerp(float3(1, 1, 1), diffuse.rgb * (CFG_DIFFUSE_SCALE), fade);
+#endif
+
+#ifdef CFG_OPT_NORMAL_CONST
+ float3 normal = float3(0, 0, 1);
+#else
+ float3 normal = nmapUnpack(sampleFar(NormalMap, uv, fade, CFG_FAR_NORMAL_CUTOFF));
+#endif
+
+#ifndef GLSLES
+ float3 normalDetail = nmapUnpack(tex2D(NormalDetailMap, uv * (CFG_NORMAL_DETAIL_TILING)));
+
+ normal.xy += normalDetail.xy * (CFG_NORMAL_DETAIL_SCALE);
+#endif
+
+ normal.xy *= fade;
+
+ float shadowFactor = 1 + normal.x * (CFG_NORMAL_SHADOW_SCALE);
+
+#ifdef CFG_OPT_BLEND_COLOR
+ float3 albedo = lerp(float3(1, 1, 1), IN.Color.rgb, lerp(1, diffuse.a, fade)) * diffuse.rgb * shadowFactor;
+#else
+ float3 albedo = IN.Color.rgb * diffuse.rgb * shadowFactor;
+#endif
+
+#ifndef GLSLES
+ float4 studs = tex2D(StudsMap, IN.UvStuds);
+
+ albedo *= studs.rgb * 2;
+#endif
+
+ float2 specular = sampleFar(SpecularMap, uv, fade, CFG_FAR_SPECULAR_CUTOFF).rg;
+
+ // make sure glossiness is never 0 to avoid fp specials
+ float2 specbase = specular * float2(CFG_SPECULAR_SCALE, CFG_GLOSS_SCALE) + float2(0, 0.01);
+ float2 specfade = lerp(float2(CFG_SPECULAR_LOD, CFG_GLOSS_LOD), specbase, fade);
+
+ Surface surface = (Surface)0;
+ surface.albedo = albedo;
+ surface.normal = normal;
+ surface.specular = specfade.r;
+ surface.gloss = specfade.g;
+ surface.reflectance = specular.g * fade * (CFG_REFLECTION_SCALE);
+
+ return surface;
+}
diff --git a/Client2014/shaders/source/megacluster.hlsl b/Client2014/shaders/source/megacluster.hlsl
new file mode 100644
index 0000000..e6bfb8a
--- /dev/null
+++ b/Client2014/shaders/source/megacluster.hlsl
@@ -0,0 +1,150 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float4 Uv : TEXCOORD0;
+#ifdef PIN_HQ
+ float4 EdgeDistances: TEXCOORD1;
+ float3 Tangent : TEXCOORD2;
+#endif
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float4 UvHigh_EdgeDistance1 : TEXCOORD0;
+ float4 UvLow_EdgeDistance2 : TEXCOORD1;
+
+ float4 LightPosition_Fog : TEXCOORD2;
+
+#ifdef PIN_HQ
+ float4 View_Depth : TEXCOORD3;
+ float4 Normal_Blend : TEXCOORD4;
+ float3 Tangent : TEXCOORD5;
+#else
+ float4 Diffuse_Blend : COLOR0;
+#endif
+
+ float3 PosLightSpace : TEXCOORD7;
+};
+
+uniform float4x4 WorldMatrix;
+
+VertexOutput MegaClusterVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ // Decode vertex data
+ IN.Normal = (IN.Normal - 127) / 127;
+ IN.Uv /= 2048;
+
+ // Transform position and normal to world space
+ // Note: world matrix does not contain rotation/scale for static geometry so we can avoid transforming normal
+ float3 posWorld = mul(WorldMatrix, IN.Position).xyz;
+ float3 normalWorld = IN.Normal;
+
+ OUT.HPosition = mul(G.ViewProjection, float4(posWorld, 1));
+
+ float blend = OUT.HPosition.w / 200;
+
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w);
+
+ OUT.UvHigh_EdgeDistance1.xy = IN.Uv.xy;
+ OUT.UvLow_EdgeDistance2.xy = IN.Uv.zw;
+
+#ifdef PIN_HQ
+ OUT.View_Depth = float4(posWorld, OUT.HPosition.w * G.FadeDistance.y);
+ float4 edgeDistances = IN.EdgeDistances*G.FadeDistance.z + 0.5 * OUT.View_Depth.w;
+
+ OUT.UvHigh_EdgeDistance1.zw = edgeDistances.xy;
+ OUT.UvLow_EdgeDistance2.zw = edgeDistances.zw;
+
+ OUT.View_Depth.xyz = G.CameraPosition - posWorld;
+ OUT.Normal_Blend = float4(IN.Normal, blend);
+ // decode tangent
+ OUT.Tangent = (IN.Tangent - 127) / 127;
+#else
+ // IF LQ shading is performed in VS
+ float ndotl = dot(normalWorld, -G.Lamp0Dir);
+ float3 diffuse = saturate(ndotl) * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
+
+ OUT.Diffuse_Blend = float4(diffuse, blend);
+#endif
+
+ OUT.PosLightSpace = getPosInLightSpace(posWorld);
+
+ return OUT;
+}
+
+sampler2D DiffuseHighMap: register(s0);
+sampler2D DiffuseLowMap: register(s1);
+sampler2D NormalMap: register(s2);
+sampler2D SpecularMap: register(s3);
+LGRID_SAMPLER LightMap: register(s4);
+sampler2D LightMapLookup: register(s5);
+
+void MegaClusterPS(VertexOutput IN,
+#ifdef PIN_GBUFFER
+ out float4 oColor1: COLOR1,
+#endif
+ out float4 oColor0: COLOR0)
+{
+ float4 high = tex2D(DiffuseHighMap, IN.UvHigh_EdgeDistance1.xy);
+ float4 low = tex2D(DiffuseLowMap, IN.UvLow_EdgeDistance2.xy);
+
+ float4 light = lgridSample(LightMap, LightMapLookup, IN.LightPosition_Fog.xyz);
+ float shadow = getBlobShadow(IN.PosLightSpace) * light.a;
+
+#ifdef PIN_HQ
+ float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Normal_Blend.a));
+
+ // sample normal map and specular map
+ float4 normalMapSample = tex2D(NormalMap, IN.UvHigh_EdgeDistance1.xy);
+ float4 specularMapSample = tex2D(SpecularMap, IN.UvHigh_EdgeDistance1.xy);
+
+ // compute bitangent and world space normal
+ float3 bitangent = cross(IN.Normal_Blend.xyz, IN.Tangent.xyz);
+ float3 nmap = nmapUnpack(normalMapSample);
+ float3 normal = normalize(nmap.x * IN.Tangent.xyz + nmap.y * bitangent + nmap.z * IN.Normal_Blend.xyz);
+
+ float ndotl = dot(normal, -G.Lamp0Dir);
+ float3 diffuseIntensity = saturate0(ndotl) * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
+ float specularIntensity = step(0, ndotl) * specularMapSample.r;
+ float specularPower = specularMapSample.g * 255 + 0.01;
+
+ // Compute diffuse and specular and combine them
+ float3 diffuse = (G.AmbientColor + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
+ float3 specular = G.Lamp0Color * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G.Lamp0Dir + normalize(IN.View_Depth.xyz)))), specularPower));
+ oColor0.rgb = diffuse + specular;
+
+ // apply outlines
+ float outlineFade = saturate1(IN.View_Depth.w * G.OutlineBrightness_ShadowInfo.x + G.OutlineBrightness_ShadowInfo.y);
+ float2 minIntermediate = min(IN.UvHigh_EdgeDistance1.wz, IN.UvLow_EdgeDistance2.wz);
+ float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / IN.View_Depth.w;
+ oColor0.rgb *= saturate1(outlineFade * (1.5 - minEdgesPlus) + minEdgesPlus);
+
+ oColor0.a = 1;
+
+#else
+ float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Diffuse_Blend.a));
+
+ // Compute diffuse term
+ float3 diffuse = (G.AmbientColor + IN.Diffuse_Blend.rgb * shadow + light.rgb) * albedo.rgb;
+
+ // Combine
+ oColor0.rgb = diffuse;
+ oColor0.a = 1;
+
+#endif
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+ oColor0.rgb = lerp(G.FogColor, oColor0.rgb, fogAlpha);
+
+#ifdef PIN_GBUFFER
+ oColor1 = gbufferPack(IN.View_Depth.w*G.FadeDistance.x, diffuse.rgb, 0, fogAlpha);
+#endif
+}
diff --git a/Client2014/shaders/source/msaa.hlsl b/Client2014/shaders/source/msaa.hlsl
new file mode 100644
index 0000000..3cdf77d
--- /dev/null
+++ b/Client2014/shaders/source/msaa.hlsl
@@ -0,0 +1,40 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+struct VertexOutput
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+
+float4 convertPosition(float4 p, float scale)
+{
+ return p;
+}
+
+float2 convertUv(float4 p)
+{
+ return p.xy * 0.5 + 0.5;
+}
+
+VertexOutput msaaComposit_vs(Appdata IN)
+{
+ float2 uv = convertUv(IN.p);
+
+ VertexOutput OUT;
+ OUT.p = convertPosition(IN.p, 1);
+ OUT.uv = uv;
+
+ return OUT;
+}
+
+float4 msaaComposit_ps(float2 uv : TEXCOORD0, uniform sampler2D colorMap: register(s0)): COLOR0
+{
+ return tex2D(colorMap, uv);
+}
diff --git a/Client2014/shaders/source/particle.hlsl b/Client2014/shaders/source/particle.hlsl
new file mode 100644
index 0000000..b38cadd
--- /dev/null
+++ b/Client2014/shaders/source/particle.hlsl
@@ -0,0 +1,84 @@
+#include "globals.h"
+
+sampler2D tex : register(s0);
+
+//#define
+
+uniform float4 colorBias;
+uniform float4 throttleFactor; // .x = alpha cutoff, .y = alpha boost (clamp)
+
+struct VS_INPUT
+{
+ float4 pos : POSITION;
+ float4 scaleRotLife : TEXCOORD0; // transform matrix
+ float2 disp : TEXCOORD1; // .xy = corner, either (0,0), (1,0), (0,1), or (1,1)
+ float4 color0: COLOR0;
+ float4 color1: COLOR1;
+};
+
+struct VS_OUTPUT
+{
+ float4 pos : POSITION;
+ float3 uvFog : TEXCOORD0;
+ float4 color : COLOR0;
+};
+
+float4 rotScale( float4 scaleRotLife )
+{
+ float cr = cos( scaleRotLife.z );
+ float sr = sin( scaleRotLife.z );
+
+ float4 r;
+ r.x = cr * scaleRotLife.x;
+ r.y = -sr * scaleRotLife.x;
+ r.z = sr * scaleRotLife.y;
+ r.w = cr * scaleRotLife.y;
+
+ return r;
+}
+
+
+VS_OUTPUT vs( VS_INPUT input )
+{
+ VS_OUTPUT o;
+
+ float4 pos = float4( input.pos.xyz, 1 );
+ float2 disp = input.disp.xy * 2 - 1; // -1..1
+
+ input.scaleRotLife *= float4( 1/256.0f, 1/256.0f, 2 * 3.1415926f / 32767, 1 / 32767.0f );
+
+ float4 rs = rotScale( input.scaleRotLife );
+
+ pos += G.ViewRight * dot( disp, rs.xy );
+ pos += G.ViewUp * dot( disp, rs.zw );
+ o.pos = mul( G.ViewProjection, pos );
+
+ o.uvFog.xy = input.disp.xy;
+ o.uvFog.y = 1 - o.uvFog.y;
+ o.uvFog.z = (G.FogParams.z - o.pos.w) * G.FogParams.w;
+ float t = max( 0, min(1, input.scaleRotLife.w ) );
+ o.color = lerp( input.color1, input.color0, t );
+
+ // alpha channel magic for particle throttling
+ float2 cmp = o.color.aa < throttleFactor.xy;
+ o.pos.xyz += cmp.xxx * (1e10f).xxx; // move the particle off-screen
+ o.color.a = lerp( o.color.a, throttleFactor.y, cmp.y ); // if below threshold, alpha = threshold
+
+ return o;
+}
+
+float4 psAdd( VS_OUTPUT input ) : COLOR0 // #0
+{
+ float4 color = tex2D( tex, input.uvFog.xy );
+ float4 result = float4( input.color.rgb + color.rgb + colorBias.rgb, color.a * input.color.a );
+ result.rgb = lerp( G.FogColor.rgb, result.rgb, saturate( input.uvFog.zzz ) );
+ return result;
+}
+
+float4 psMul( VS_OUTPUT input ) : COLOR0 // #1
+{
+ float4 color = tex2D( tex, input.uvFog.xy );
+ float4 result = input.color * color;
+ result.rgb = lerp( G.FogColor.rgb, result.rgb, saturate( input.uvFog.zzz ) );
+ return result;
+}
diff --git a/Client2014/shaders/source/pebble.hlsl b/Client2014/shaders/source/pebble.hlsl
new file mode 100644
index 0000000..9e35fe9
--- /dev/null
+++ b/Client2014/shaders/source/pebble.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2.5
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.15
+#define CFG_GLOSS_LOD 22
+
+#define CFG_NORMAL_DETAIL_TILING 6
+#define CFG_NORMAL_DETAIL_SCALE 1.5
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/plastic.hlsl b/Client2014/shaders/source/plastic.hlsl
new file mode 100644
index 0000000..8320b1d
--- /dev/null
+++ b/Client2014/shaders/source/plastic.hlsl
@@ -0,0 +1,46 @@
+#if defined(PIN_HQ)
+#define PIN_SURFACE
+#include "default.hlsl"
+
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_BUMP_INTENSITY 0.5
+
+#define CFG_SPECULAR 0.4
+#define CFG_GLOSS 9
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+Surface surfaceShader(SurfaceInput IN, float fade)
+{
+ float4 studs = tex2D(DiffuseMap, IN.UvStuds);
+ float3 normal = nmapUnpack(tex2D(NormalMap, IN.UvStuds));
+
+ float3 noise = nmapUnpack(tex2D(NormalDetailMap, IN.Uv * (CFG_TEXTURE_TILING)));
+
+ float noiseScale = saturate0(IN.Color.a * 2 * (CFG_BUMP_INTENSITY) - 1 * (CFG_BUMP_INTENSITY));
+
+#ifdef PIN_REFLECTION
+ noiseScale *= saturate(1 - 2 * IN.Reflectance);
+#endif
+
+ normal.xy += noise.xy * noiseScale;
+
+ normal.xy *= fade;
+
+ Surface surface = (Surface)0;
+ surface.albedo = IN.Color.rgb * studs.rgb * 2;
+ surface.normal = normal;
+ surface.specular = (CFG_SPECULAR);
+ surface.gloss = (CFG_GLOSS);
+
+#ifdef PIN_REFLECTION
+ surface.reflectance = IN.Reflectance;
+#endif
+
+ return surface;
+}
+#else
+#define PIN_PLASTIC
+#include "default.hlsl"
+#endif
diff --git a/Client2014/shaders/source/rust.hlsl b/Client2014/shaders/source/rust.hlsl
new file mode 100644
index 0000000..4a9a736
--- /dev/null
+++ b/Client2014/shaders/source/rust.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.35
+#define CFG_GLOSS_LOD 103
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.5
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/sand.hlsl b/Client2014/shaders/source/sand.hlsl
new file mode 100644
index 0000000..f64f6c1
--- /dev/null
+++ b/Client2014/shaders/source/sand.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.4
+#define CFG_GLOSS_SCALE 32
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.07
+#define CFG_GLOSS_LOD 6
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/shadowextrude.hlsl b/Client2014/shaders/source/shadowextrude.hlsl
new file mode 100644
index 0000000..ea26762
--- /dev/null
+++ b/Client2014/shaders/source/shadowextrude.hlsl
@@ -0,0 +1,41 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+
+ int4 BoneIndices : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+};
+
+uniform float ShadowExtrusionDistance;
+
+uniform float4 WorldMatrixArray[MAX_BONE_COUNT * 3];
+
+VertexOutput DefaultVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ int boneIndex = IN.BoneIndices.r;
+
+ float4 worldRow0 = WorldMatrixArray[boneIndex * 3 + 0];
+ float4 worldRow1 = WorldMatrixArray[boneIndex * 3 + 1];
+ float4 worldRow2 = WorldMatrixArray[boneIndex * 3 + 2];
+
+ float3 posWorld = float3(dot(worldRow0, IN.Position), dot(worldRow1, IN.Position), dot(worldRow2, IN.Position));
+
+ float3 extrusion = G.Lamp0Dir * (ShadowExtrusionDistance * IN.BoneIndices.g);
+
+ OUT.HPosition = mul(G.ViewProjection, float4(posWorld + extrusion, 1));
+
+ return OUT;
+}
+
+float4 DefaultPS(): COLOR0
+{
+ return float4(0, 0, 0, 1);
+}
diff --git a/Client2014/shaders/source/shadowquad.hlsl b/Client2014/shaders/source/shadowquad.hlsl
new file mode 100644
index 0000000..30709ca
--- /dev/null
+++ b/Client2014/shaders/source/shadowquad.hlsl
@@ -0,0 +1,28 @@
+#include "globals.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+};
+
+uniform float4 Color;
+
+VertexOutput QuadVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = IN.Position;
+ OUT.HPosition.z = 0.5; // force set depth to avoid depth clipping
+
+ return OUT;
+}
+
+float4 QuadPS(): COLOR0
+{
+ return Color;
+}
diff --git a/Client2014/shaders/source/sky.hlsl b/Client2014/shaders/source/sky.hlsl
new file mode 100644
index 0000000..088427f
--- /dev/null
+++ b/Client2014/shaders/source/sky.hlsl
@@ -0,0 +1,50 @@
+#include "globals.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float PSize : PSIZE;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+uniform float4x4 WorldMatrix;
+
+uniform float4 Color;
+uniform float4 Color2;
+
+VertexOutput SkyVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 wpos = mul(WorldMatrix, IN.Position);
+
+ OUT.HPosition = mul(G.ViewProjection, wpos);
+
+ // snap to far plane to prevent scene-sky intersections
+ // small offset is needed to prevent 0/0 division in case w=0, which causes rasterization issues
+ OUT.HPosition.z = OUT.HPosition.w - 1.f / 16;
+
+ OUT.PSize = 2.0; // star size
+
+ OUT.Uv = IN.Uv;
+ OUT.Color = IN.Color * lerp(Color2,Color,wpos.y/1700);
+ //OUT.Color = IN.Color * Color;
+
+ return OUT;
+}
+
+sampler2D DiffuseMap: register(s0);
+
+float4 SkyPS(VertexOutput IN): COLOR0
+{
+ return tex2D(DiffuseMap, IN.Uv) * IN.Color;
+}
diff --git a/Client2014/shaders/source/slate.hlsl b/Client2014/shaders/source/slate.hlsl
new file mode 100644
index 0000000..cd135ba
--- /dev/null
+++ b/Client2014/shaders/source/slate.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.9
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.14
+#define CFG_GLOSS_LOD 20
+
+#define CFG_NORMAL_DETAIL_TILING 5
+#define CFG_NORMAL_DETAIL_SCALE 1
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/shaders/source/smoothplastic.hlsl b/Client2014/shaders/source/smoothplastic.hlsl
new file mode 100644
index 0000000..fb0aa90
--- /dev/null
+++ b/Client2014/shaders/source/smoothplastic.hlsl
@@ -0,0 +1,2 @@
+#define PIN_PLASTIC
+#include "default.hlsl"
diff --git a/Client2014/shaders/source/ssao.hlsl b/Client2014/shaders/source/ssao.hlsl
new file mode 100644
index 0000000..e782e1a
--- /dev/null
+++ b/Client2014/shaders/source/ssao.hlsl
@@ -0,0 +1,447 @@
+#include "common.h"
+
+// tweakables
+#define SSAO_NUM_PAIRS 8
+#define SSAO_SPHERE_RAD 2.0f // world-space
+#define SSAO_MIN_PIXEL_RANGE 10.0f
+#define SSAO_MAX_PIXEL_RANGE 100.0f
+#define BLUR_DEPTH_DELTA 0.4f
+
+#define COMPOSITE_DEPTH_DELTA 0.02f
+#define COMPOSITE_DEPTH_DELTA2 0.4f
+
+struct Appdata
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+struct VertexOutput
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+
+// .xy = gbuffer width/height, .zw = inverse gbuffer width/height
+uniform float4 TextureSize;
+
+#ifdef GLSL
+float4 convertPosition(float4 p, float scale)
+{
+ return p;
+}
+
+float2 convertUv(float4 p)
+{
+ return p.xy * 0.5 + 0.5;
+}
+#else
+float4 convertPosition(float4 p, float scale)
+{
+ // half-pixel offset
+ return p + float4(-TextureSize.z, TextureSize.w, 0, 0) * scale;
+}
+
+float2 convertUv(float4 p)
+{
+ return p.xy * float2(0.5, -0.5) + 0.5;
+}
+#endif
+
+VertexOutput ssao_vs(Appdata IN)
+{
+ float2 uv = convertUv(IN.p);
+
+ VertexOutput OUT;
+ OUT.p = convertPosition(IN.p, 1);
+ OUT.uv = uv;
+
+ return OUT;
+}
+
+// used for depth downsampling pass
+struct VertexOutput_4uv
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+ float4 uv12 : TEXCOORD1;
+ float4 uv34 : TEXCOORD2;
+};
+
+VertexOutput_4uv ssaoDepthDown_vs(Appdata IN)
+{
+ float2 uv = convertUv(IN.p);
+
+ VertexOutput_4uv OUT;
+ OUT.p = convertPosition(IN.p, 2);
+ OUT.uv = uv;
+
+ float2 uvOffset = TextureSize.zw * 0.5f;
+
+ OUT.uv12.xy = uv + uvOffset * float2(-1, -1);
+ OUT.uv12.zw = uv + uvOffset * float2(+1, -1);
+ OUT.uv34.xy = uv + uvOffset * float2(-1, +1);
+ OUT.uv34.zw = uv + uvOffset * float2(+1, +1);
+
+ return OUT;
+}
+
+struct VertexOutput_8uv
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+ float4 uv12 : TEXCOORD1;
+ float4 uv34 : TEXCOORD2;
+ float4 uv56 : TEXCOORD3;
+ float4 uv78 : TEXCOORD4;
+};
+
+// used for ssao blurring passes
+VertexOutput_8uv ssaoBlur_vs(Appdata IN, float2 uvOffset)
+{
+ float2 uv = convertUv(IN.p);
+
+ VertexOutput_8uv OUT;
+ OUT.p = convertPosition(IN.p, 2);
+ OUT.uv = uv;
+
+ OUT.uv12.xy = uv + 1 * uvOffset;
+ OUT.uv12.zw = uv + 2 * uvOffset;
+ OUT.uv34.xy = uv + 3 * uvOffset;
+ OUT.uv34.zw = uv + 4 * uvOffset;
+
+ OUT.uv56.xy = uv - 1 * uvOffset;
+ OUT.uv56.zw = uv - 2 * uvOffset;
+ OUT.uv78.xy = uv - 3 * uvOffset;
+ OUT.uv78.zw = uv - 4 * uvOffset;
+
+ return OUT;
+}
+
+VertexOutput_8uv ssaoBlurX_vs(Appdata IN)
+{
+ return ssaoBlur_vs(IN, float2(TextureSize.z * 2, 0));
+}
+
+VertexOutput_8uv ssaoBlurY_vs(Appdata IN)
+{
+ return ssaoBlur_vs(IN, float2(0, TextureSize.w * 2));
+}
+
+float unpackDepth( sampler2D s, float2 uv )
+{
+ float4 geomTex = tex2D(s, uv);
+ float d = geomTex.z * (1.0f/256.0f) + geomTex.w;
+ return d;
+}
+
+float getDepth( sampler2D s, float2 uv )
+{
+ return (float)tex2D(s,uv).r;
+}
+
+#define NUM_PAIRS SSAO_NUM_PAIRS
+#define RANGE 60.0/1024.0
+
+#define pi 3.14159265359
+#define RAD(X) ( (X) * (pi/180) )
+
+float2 GetRotatedSample(float i)
+{
+ return (i+1) / (NUM_PAIRS+2) * float2(cos( RAD(45) + i / NUM_PAIRS * 2 * pi ), sin( RAD(45) + i / NUM_PAIRS * 2 * pi ) );
+}
+
+#define NUM_SAMPLES NUM_PAIRS*2+1
+
+float4 ssao_ps(
+ float2 uv: TEXCOORD0,
+ uniform sampler2D depthBuffer: register(s0),
+ uniform sampler2D randMap: register(s1)): COLOR0
+{
+ float2 mapSize = TextureSize.xy / 2;
+
+ float baseDepth = getDepth( depthBuffer, uv );
+
+ float4 noiseTex = tex2D(randMap, uv*mapSize/4) * 2 - 1;
+
+ float2x2 rotation =
+ {
+ { noiseTex.y, noiseTex.x },
+ { -noiseTex.x, noiseTex.y }
+ };
+
+ float2 OFFSETS1[NUM_PAIRS] =
+ {
+ GetRotatedSample(0),
+ GetRotatedSample(1),
+ GetRotatedSample(2),
+ GetRotatedSample(3),
+ GetRotatedSample(4),
+ GetRotatedSample(5),
+#if NUM_PAIRS > 6
+ GetRotatedSample(6),
+ GetRotatedSample(7),
+#if NUM_PAIRS > 8
+ GetRotatedSample(8),
+ GetRotatedSample(9),
+ GetRotatedSample(10),
+ GetRotatedSample(11),
+#endif
+#endif
+ };
+
+ float occ = 1;
+
+ float sphereRadiusZB = (float) ( 2.0f / GBUFFER_MAX_DEPTH );
+
+#define MINPIXEL SSAO_MIN_PIXEL_RANGE
+#define MAXPIXEL SSAO_MAX_PIXEL_RANGE
+
+ float radiusTex = (float)clamp( 0.5*sphereRadiusZB / baseDepth, MINPIXEL / mapSize.x, MAXPIXEL / mapSize.y);
+
+ float numSamples = 2;
+
+ for(int i = 0; i < NUM_PAIRS; i++)
+ {
+ float2 offset1 = mul(rotation, OFFSETS1[i]);
+
+ float2 offseted1 = uv + offset1 * radiusTex;
+ float2 offseted2 = uv - offset1 * radiusTex;
+
+ float2 offsetDepth;
+ offsetDepth.x = getDepth( depthBuffer, offseted1 );
+ offsetDepth.y = getDepth( depthBuffer, offseted2 );
+
+ float2 diff = offsetDepth - baseDepth.xx;
+
+ float normalizedOffsetLen = (float)(i+1)/(NUM_PAIRS+2);
+
+ float segmentDiff = (float) ( 1.5f*sphereRadiusZB*sqrt(1-normalizedOffsetLen*normalizedOffsetLen) );
+
+ float2 normalizedDiff = (diff / segmentDiff) + 0.5;
+
+ float minDiff = min(normalizedDiff.x, normalizedDiff.y);
+
+ // At 0, full sample
+ // At -1, zero sample, zero weight
+
+ float sampleadd = (float) saturate(1+minDiff);
+
+ float a = (float)(saturate(normalizedDiff.x) + saturate(normalizedDiff.y))*sampleadd;
+ occ += a;
+ numSamples += 2 * sampleadd;
+ }
+
+ occ = occ / numSamples;
+
+ float finalocc = (float)saturate(occ*2);
+
+ if(baseDepth - (1.0f-1/256.0f) > 0)
+ finalocc += 1;
+
+ return float4(finalocc, finalocc, finalocc, 1);
+}
+
+// this function estimates depth discrepancy tolerance for the blur filter
+float depthTolerance( float baseDepth, float sphereRadiusZB )
+{
+ float ramp = 80; // tweak
+ return ( clamp( sphereRadiusZB * (baseDepth * ramp) , 0.1f * sphereRadiusZB, 40*sphereRadiusZB ) );
+}
+
+float ssaoBlur(
+ float2 uv,
+
+ float4 uv12,
+ float4 uv34,
+ float4 uv56,
+ float4 uv78,
+
+ sampler2D map,
+ sampler2D depthBuffer
+ )
+{
+ float sphereRadiusZB = BLUR_DEPTH_DELTA / GBUFFER_MAX_DEPTH;
+ float4 i = { 1, 2, 3, 4 };
+ float4 iw = 4-i;
+ float4 denom = 1;
+
+
+ float4 sum = tex2D(map, uv).rrrr * denom;
+
+ float baseDepth = getDepth( depthBuffer, uv );
+
+ float4 newDepth, delta, ssample, coef;
+
+ newDepth.x = getDepth( depthBuffer, uv12.xy );
+ newDepth.y = getDepth( depthBuffer, uv12.zw );
+ newDepth.z = getDepth( depthBuffer, uv34.xy );
+ newDepth.w = getDepth( depthBuffer, uv34.zw );
+
+ delta = (newDepth - baseDepth.xxxx);
+ coef = iw * ( abs(delta) < depthTolerance( baseDepth, sphereRadiusZB ).xxxx );
+
+
+ ssample.x = tex2D( map, uv12.xy ).r;
+ ssample.y = tex2D( map, uv12.zw ).r;
+ ssample.z = tex2D( map, uv34.xy ).r;
+ ssample.w = tex2D( map, uv34.zw ).r;
+
+ sum += ssample * coef;
+ denom += coef;
+
+ ////////////////////////////////////////
+
+ newDepth.x = getDepth( depthBuffer, uv56.xy );
+ newDepth.y = getDepth( depthBuffer, uv56.zw );
+ newDepth.z = getDepth( depthBuffer, uv78.xy );
+ newDepth.w = getDepth( depthBuffer, uv78.zw );
+
+ delta = newDepth - baseDepth.xxxx;
+ coef = iw * ( abs(delta) < depthTolerance( baseDepth, sphereRadiusZB ).xxxx );
+
+ ssample.x = tex2D( map, uv56.xy ).r;
+ ssample.y = tex2D( map, uv56.zw ).r;
+ ssample.z = tex2D( map, uv78.xy ).r;
+ ssample.w = tex2D( map, uv78.zw ).r;
+
+ sum += ssample * coef;
+ denom += coef;
+
+ return dot( sum, float4(1,1,1,1) ) / dot( denom, float4(1,1,1,1) );
+}
+
+
+float4 ssaoBlurX_ps(
+ float2 uv : TEXCOORD0,
+ float4 uv12 : TEXCOORD1,
+ float4 uv34 : TEXCOORD2,
+ float4 uv56 : TEXCOORD3,
+ float4 uv78 : TEXCOORD4,
+
+ uniform sampler2D map : register(s0), uniform sampler2D depthBuffer : register(s1) ): COLOR0
+{
+ //return tex2D( map, uv );
+ float ssaoTerm = ssaoBlur( uv, uv12, uv34, uv56, uv78, map, depthBuffer);
+
+ return float4(ssaoTerm.xxx, 1);
+}
+
+#define SPECULAR_WEIGHT 3
+
+
+float4 ssaoBlurY_ps(
+ float2 uv : TEXCOORD0,
+ float4 uv12 : TEXCOORD1,
+ float4 uv34 : TEXCOORD2,
+ float4 uv56 : TEXCOORD3,
+ float4 uv78 : TEXCOORD4,
+
+ uniform sampler2D map : register(s0), uniform sampler2D depthBuffer : register(s1), uniform sampler2D geomMap : register(s2) ): COLOR0
+{
+ float ssaoTerm = ssaoBlur(uv, uv12, uv34, uv56, uv78, map, depthBuffer);
+
+ float4 geom = tex2D(geomMap, uv);
+
+ float specular = geom.x;
+ float diffuse = geom.y;
+
+ // Making specular kill SSAO faster, so it doesn't get capped by 1
+ return (SPECULAR_WEIGHT*specular + diffuse * ssaoTerm) / (SPECULAR_WEIGHT*specular + diffuse + 0.001);
+}
+
+
+
+float4 ssaoDepthDown_ps(
+ float2 uv : TEXCOORD0,
+ float4 uv12 : TEXCOORD1,
+ float4 uv34 : TEXCOORD2,
+
+ uniform sampler2D depthBuffer : register(s0)
+) : COLOR0
+{
+
+ float4 d;
+ d.x = unpackDepth( depthBuffer, uv12.xy );
+ d.y = unpackDepth( depthBuffer, uv12.zw );
+ d.z = unpackDepth( depthBuffer, uv34.xy );
+ d.w = unpackDepth( depthBuffer, uv34.zw );
+
+ float2 tmp = min( d.xy, d.zw );
+ return min( tmp.x, tmp.y ).x;
+}
+
+VertexOutput_4uv ssaoComposit_vs(Appdata IN)
+{
+ float2 uv = convertUv(IN.p);
+
+ VertexOutput_4uv OUT;
+ OUT.p = convertPosition(IN.p, 1);
+ OUT.uv = uv;
+
+ float2 uvOffset = TextureSize.zw * 2;
+
+ OUT.uv12.xy = uv + float2(uvOffset.x, 0);
+ OUT.uv12.zw = uv - float2(uvOffset.x, 0);
+ OUT.uv34.xy = uv + float2(0, uvOffset.y);
+ OUT.uv34.zw = uv - float2(0, uvOffset.y);
+
+ return OUT;
+}
+
+float4 ssaoCompositBlank_ps(float2 uv : TEXCOORD0, uniform sampler2D colorMap: register(s0)): COLOR0
+{
+ return tex2D(colorMap, uv);
+}
+
+#define CMP_LESS(X,Y) ( (X) < (Y) )
+
+float4 ssaoComposit_ps(
+ float2 uv : TEXCOORD0,
+ float4 uv12 : TEXCOORD1,
+ float4 uv34 : TEXCOORD2,
+
+ uniform sampler2D colorMap : register(s0),
+ uniform sampler2D map : register(s1),
+ uniform sampler2D gbuffer : register(s2),
+ uniform sampler2D depthBuffer: register(s3)
+ ): COLOR0
+{
+ //return float4(1,0,0,1);
+ float depth_range = COMPOSITE_DEPTH_DELTA / GBUFFER_MAX_DEPTH;
+ float depth_range2 = COMPOSITE_DEPTH_DELTA2 / GBUFFER_MAX_DEPTH;
+
+ // we're here
+ float baseDepth = unpackDepth( gbuffer, uv );
+ float ssaoTerm = 1.0f;
+
+ float depth = getDepth( depthBuffer, uv );
+ float diff = abs( depth - baseDepth );
+ ssaoTerm = tex2D( map, uv ).x;
+
+ float chk1 = CMP_LESS( depth_range, diff ); // can we trust the base depth? 0 - yes, 1 - no
+ float4 ssaoTermNew = 0, chk2, depth2, diff2;
+
+ depth2.x = getDepth( depthBuffer, uv12.xy );
+ depth2.y = getDepth( depthBuffer, uv12.zw );
+ depth2.z = getDepth( depthBuffer, uv34.xy );
+ depth2.w = getDepth( depthBuffer, uv34.zw );
+
+ ssaoTermNew.x = tex2D( map, uv12.xy ).x;
+ ssaoTermNew.y = tex2D( map, uv12.zw ).x;
+ ssaoTermNew.z = tex2D( map, uv34.xy ).x;
+ ssaoTermNew.w = tex2D( map, uv34.zw ).x;
+
+ diff2 = abs( depth2 - baseDepth.xxxx );
+ chk2 = CMP_LESS( diff2, depth_range2.xxxx );
+
+ ssaoTermNew *= chk2;
+ float den = dot( chk2, 1 ); // + 1e-5f; - TODO: add this if we encounter glitches; //
+ ssaoTermNew.x = dot( ssaoTermNew, 1 ) / den;
+
+ // the final decision: pick the base sample or its estimate, if base depth in unauthorative
+ ssaoTerm = saturate(den*chk1) ? ssaoTermNew.x : ssaoTerm;
+
+ return tex2D(colorMap, uv) * ssaoTerm;
+}
diff --git a/Client2014/shaders/source/texcomp.hlsl b/Client2014/shaders/source/texcomp.hlsl
new file mode 100644
index 0000000..a333e2c
--- /dev/null
+++ b/Client2014/shaders/source/texcomp.hlsl
@@ -0,0 +1,39 @@
+#include "globals.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float2 Uv : TEXCOORD0;
+};
+
+VertexOutput TexCompVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = mul(G.ViewProjection, IN.Position);
+ OUT.Uv = IN.Uv;
+
+ return OUT;
+}
+
+sampler2D DiffuseMap: register(s0);
+
+uniform float4 Color;
+
+float4 TexCompPS(VertexOutput IN): COLOR0
+{
+ return tex2Dbias(DiffuseMap, float4(IN.Uv, 0, -10)) * Color;
+}
+
+float4 TexCompPMAPS(VertexOutput IN): COLOR0
+{
+ float4 tex = tex2Dbias(DiffuseMap, float4(IN.Uv, 0, -10));
+
+ return float4(tex.rgb * tex.a * Color.rgb, tex.a * Color.a);
+}
diff --git a/Client2014/shaders/source/ui.hlsl b/Client2014/shaders/source/ui.hlsl
new file mode 100644
index 0000000..ea3281f
--- /dev/null
+++ b/Client2014/shaders/source/ui.hlsl
@@ -0,0 +1,50 @@
+#include "globals.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+
+#if defined(PIN_FOG)
+ float FogFactor : TEXCOORD1;
+#endif
+};
+
+VertexOutput UIVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = mul(G.ViewProjection, IN.Position);
+
+ OUT.Uv = IN.Uv;
+ OUT.Color = IN.Color;
+
+#if defined(PIN_FOG)
+ OUT.FogFactor = (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w;
+#endif
+
+ return OUT;
+}
+
+sampler2D DiffuseMap: register(s0);
+
+float4 UIPS(VertexOutput IN): COLOR0
+{
+ float4 base = tex2D(DiffuseMap, IN.Uv);
+ float4 result = IN.Color * base;
+
+#if defined(PIN_FOG)
+ result.rgb = lerp(G.FogColor, result.rgb, saturate(IN.FogFactor));
+#endif
+
+ return result;
+}
diff --git a/Client2014/shaders/source/water.hlsl b/Client2014/shaders/source/water.hlsl
new file mode 100644
index 0000000..c596b04
--- /dev/null
+++ b/Client2014/shaders/source/water.hlsl
@@ -0,0 +1,220 @@
+
+//
+// Water shader.
+// Big, fat and ugly.
+//
+// All (most) things considered, I have converged to this particular way of rendering water:
+//
+// Vertex waves
+// No transparency. Solid color for deep water.
+// Fresnel law, reflects environment.
+// Phong speculars.
+// Ripples via animated normal map. Adjustable intensity, speed and scale. Affect reflection and speculars.
+
+#include "common.h"
+
+uniform float4x4 WorldMatrix;
+
+uniform float4 nmAnimLerp; // ratio between normal map frames
+uniform float4 waveParams; // .x = frequency .y = phase .z = height
+uniform float4 WaterColor; // deep water color
+
+#ifdef PIN_HQ
+# define WATER_LOD 1
+#else
+# define WATER_LOD 2
+#endif
+
+#define LODBIAS (-1)
+
+float fadeFactor( float3 wspos )
+{
+ return saturate( -0.4f + 1.4f*length( G.CameraPosition.xyz - wspos.xyz ) * G.FadeDistance.y );
+}
+
+float wave( float4 wspos )
+{
+ float x = sin( ( wspos.z - wspos.x - waveParams.y ) * waveParams.x );
+ float z = sin( ( wspos.z + wspos.x + waveParams.y ) * waveParams.x );
+ float p = (x + z) * waveParams.z;
+ return p - p * fadeFactor( wspos.xyz );
+}
+
+
+
+// perturbs the water mesh and vertex normals
+void makeWaves( inout float4 wspos, inout float3 wsnrm )
+{
+#if WATER_LOD == 0
+ float gridSize = 4.0f;
+
+ float4 wspos1 = wspos;
+ float4 wspos2 = wspos;
+
+ wspos1.x += gridSize;
+ wspos2.z += gridSize;
+
+ wspos.y += wave(wspos) ;
+ wspos1.y += wave(wspos1);
+ wspos2.y += wave(wspos2);
+
+ wsnrm = normalize( cross( wspos2.xyz - wspos.xyz, wspos1.xyz - wspos.xyz ) );
+#elif WATER_LOD == 1
+ wspos.y += wave( wspos );
+#else /* do n0thing */
+#endif
+}
+
+struct V2P
+{
+ float4 pos : POSITION;
+ float4 tc0Fog : TEXCOORD0;
+ float4 wspos : TEXCOORD1;
+ float3 wsnrm : TEXCOORD2;
+ float3 light : TEXCOORD3;
+ float3 fade : TEXCOORD4;
+};
+
+V2P water_vs(
+ float4 pos : POSITION,
+ float3 nrm : NORMAL
+)
+{
+ V2P o;
+
+ // Decode vertex data
+ nrm = (nrm - 127) / 127;
+
+ nrm = normalize(nrm);
+
+ float4 wspos = mul( WorldMatrix, pos );
+ float3 wsnrm = nrm;
+
+ wspos.y -= 2*waveParams.z;
+
+ makeWaves( /*INOUT*/ wspos, /*INOUT*/ wsnrm );
+
+ o.wspos = wspos;
+ o.wsnrm = wsnrm;
+
+ if( nrm.y < 0.01f ) o.wsnrm = nrm;
+
+ // box mapping
+ //float3x2 m = { wspos.xz, wspos.xy, wspos.yz };
+ //float2 tcselect = mul( abs( nrm.yzx ), m );
+
+ float2 tcselect;
+ float3 wspostc = float3( wspos.x, -wspos.y, wspos.z );
+
+ tcselect.x = dot( abs( nrm.yxz ), wspostc.xzx );
+ tcselect.y = dot( abs( nrm.yxz ), wspostc.zyy );
+
+ o.pos = mul( G.ViewProjection, wspos );
+ o.tc0Fog.xy = tcselect * .05f;
+ o.tc0Fog.z = saturate( (G.FogParams.z - o.pos.w) * G.FogParams.w );
+ o.tc0Fog.w = LODBIAS;
+
+ o.light = lgridPrepareSample(lgridOffset(wspos.xyz, wsnrm.xyz));
+
+ o.fade.x = fadeFactor( wspos.xyz );
+ o.fade.y = (1-o.fade.x) * saturate( dot( wsnrm, -G.Lamp0Dir ) ) * 100;
+ o.fade.z = 1 - 0.9*saturate1( exp( -0.005 * length( G.CameraPosition.xyz - wspos.xyz ) ) );
+
+ return o;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+sampler2D NormalMap1 : register(s0);
+sampler2D NormalMap2 : register(s1);
+samplerCUBE EnvMap : register(s2);
+LGRID_SAMPLER LightMap : register(s3);
+sampler2D LightMapLookup: register(s4);
+
+
+
+float3 pixelNormal( float4 tc0 )
+{
+ float4 nm1 = tex2Dbias( NormalMap1, tc0 );
+#if WATER_LOD <= 1
+ float4 nm2 = tex2Dbias( NormalMap2, tc0 );
+ float3 normal = lerp( nm1, nm2, nmAnimLerp.xxxx ).agb;
+#else
+ float3 normal = nm1.agb;
+#endif
+ //normal = nm2;
+ normal.xy = 2*normal.xy - 1;
+ normal.z = sqrt( 1.001 - saturate1( dot( normal.xy, normal.xy ) ) );
+ return normal;
+}
+
+// Fresnel approximation. N1 and N2 are refractive indices.
+// for above water, use n1 = 1, n2 = 1.3, for underwater use n1 = 1.3, n2 = 1
+float fresnel( float3 N, float3 V, float n1, float n2, float p, float fade )
+{
+#if WATER_LOD == 0
+ float r0 = (n1-n2)/(n1+n2);
+ r0 *= r0;
+ return r0 + (1-r0) * pow( 1 - abs( dot( normalize(N), V ) ), p );
+#else
+ return 0.1 + saturate( - 1.9 * abs( dot( N, V ) ) + 0.8); // HAXX!
+ //return 1 - 2 * abs( dot( N, V ) );
+#endif
+}
+
+float4 envColor( float3 N, float3 V, float fade )
+{
+ float3 dir = reflect( V, N );
+ return texCUBE(EnvMap, dir) * 0.91f;
+}
+
+float4 deepWaterColor(float4 light)
+{
+ //float4 tint = 5*float4( 0.1f, 0.1f, 0.13f, 1);
+ float4 tint = 0.8f*float4( 118, 143, 153, 255 ) / 255;
+ return (light + texCUBEbias( EnvMap, float4( 0,1,0, 10.0f) )) * tint;
+}
+
+
+//////////////////////////////////////////
+//////////////////////////////////////////
+
+
+
+float4 water_ps( V2P v ) : COLOR0
+{
+
+ float4 WaterColorTest = 0.5 * float4( 26, 169, 185, 0 ) / 255;
+ float4 FogColorTest = 0.8 * float4( 35, 107, 130, 0 ) / 255;
+
+ float3 N2 = v.wsnrm;
+ float3 N1 = pixelNormal( v.tc0Fog ).xzy;
+ float3 N3 = 0.5*(N2 + N1);
+
+ N3 = lerp( N3, N2, v.fade.z );
+
+ float3 L = /*normalize*/(-G.Lamp0Dir.xyz);
+ float3 E = normalize( G.CameraPosition.xyz - v.wspos.xyz );
+
+ float4 light = lgridSample(LightMap, LightMapLookup, v.light.xyz);
+
+ float fre = fresnel( N3, E, 1.0f, 1.3f, 5, v.fade.x );
+ float3 diffuse = deepWaterColor(light).rgb;
+ float3 env = envColor( N3, -E, v.fade.x ).rgb;
+
+ float3 R = reflect( -L, N1 );
+
+#if WATER_LOD <= 1
+ float specular = pow( saturate0( dot( R, E ) ), 1600 ) * L.y * 100; // baseline
+# ifndef GLSLES
+ specular = 0.65 * saturate1( specular * saturate0( light.a - 0.4f ) );
+# endif
+#else
+ float specular = 0;
+#endif
+
+ float3 result = lerp( diffuse, env, fre ) + specular.xxx;
+ result = lerp( G.FogColor.rgb, result, v.tc0Fog.z );
+
+ return float4( result, 1 );
+}
diff --git a/Client2014/shaders/source/water_r3.hlsl b/Client2014/shaders/source/water_r3.hlsl
new file mode 100644
index 0000000..a3bea01
--- /dev/null
+++ b/Client2014/shaders/source/water_r3.hlsl
@@ -0,0 +1,208 @@
+
+//
+// Old new water saved here for possible damage control.
+// To be removed in a couple of weeks.
+//
+// - Max
+//
+
+#include "common.h"
+
+uniform float4x4 WorldMatrix;
+
+uniform float4 nmAnimLerp; // ratio between normal map frames
+uniform float4 waveParams; // .x = frequency .y = phase .z = height
+uniform float4 WaterColor; // deep water color
+
+#ifdef PIN_HQ
+# define WATER_LOD 1
+#else
+# define WATER_LOD 2
+#endif
+
+//#undef WATER_LOD
+//#define WATER_LOD 0
+
+float fadeFactor( float3 wspos )
+{
+ return saturate( -0.4f + 1.4f*length( G.CameraPosition.xyz - wspos.xyz ) * G.FadeDistance.y );
+}
+
+float wave( float4 wspos )
+{
+ float x = sin( ( wspos.z - wspos.x - waveParams.y ) * waveParams.x );
+ float z = sin( ( wspos.z + wspos.x + waveParams.y ) * waveParams.x );
+ float p = (x + z) * waveParams.z;
+ return p - p * fadeFactor( wspos.xyz );
+}
+
+// Fresnel approximation. N1 and N2 are refractive indices.
+// for above water, use n1 = 1, n2 = 1.3, for underwater use n1 = 1.3, n2 = 1
+// TODO: use mul/bias hack on ipad
+float fresnel( float3 N, float3 V, float n1, float n2, float p, float fade )
+{
+#if WATER_LOD == 0
+ float r0 = (n1-n2)/(n1+n2);
+ r0 *= r0;
+ return r0 + (1-r0) * pow( 1 - abs( dot( N, V ) ), p );
+#else
+ return saturate( - 2.5 * abs( dot( N, V ) ) + 0.78 ); // HAXX!
+ //return 1 - 2 * abs( dot( N, V ) );
+#endif
+}
+
+// perturbs the water mesh and vertex normals
+// TODO: remove costly normal computations on ipad
+void makeWaves( inout float4 wspos, inout float3 wsnrm )
+{
+#if WATER_LOD == 0
+ float gridSize = 4.0f;
+
+ float4 wspos1 = wspos;
+ float4 wspos2 = wspos;
+
+ wspos1.x += gridSize;
+ wspos2.z += gridSize;
+
+ wspos.y += wave(wspos) ;
+ wspos1.y += wave(wspos1);
+ wspos2.y += wave(wspos2);
+
+ wsnrm = normalize( cross( wspos2.xyz - wspos.xyz, wspos1.xyz - wspos.xyz ) );
+#elif WATER_LOD == 1
+ wspos.y += wave( wspos );
+#else /* do n0thing */
+#endif
+}
+
+struct V2P
+{
+ float4 pos : POSITION;
+ float3 tc0Fog : TEXCOORD0;
+ float4 wspos : TEXCOORD1;
+ float3 wsnrm : TEXCOORD2;
+ float3 light : TEXCOORD3;
+ float2 fade : TEXCOORD4;
+};
+
+V2P water_vs(
+ float4 pos : POSITION,
+ float3 nrm : NORMAL
+)
+{
+ V2P o;
+
+ // Decode vertex data
+ nrm = (nrm - 127) / 127;
+
+ nrm = normalize(nrm);
+
+ float4 wspos = mul( WorldMatrix, pos );
+ float3 wsnrm = nrm;
+
+ wspos.y -= 2*waveParams.z;
+
+ makeWaves( /*INOUT*/ wspos, /*INOUT*/ wsnrm );
+
+ o.wspos = wspos;
+ o.wsnrm = wsnrm;
+
+ if( nrm.y < 0.01f ) o.wsnrm = nrm;
+
+ // box mapping
+ //float3x2 m = { wspos.xz, wspos.xy, wspos.yz };
+ //float2 tcselect = mul( abs( nrm.yzx ), m );
+
+ float2 tcselect;
+ float3 wspostc = float3( wspos.x, -wspos.y, wspos.z );
+
+ tcselect.x = dot( abs( nrm.yxz ), wspostc.xzx );
+ tcselect.y = dot( abs( nrm.yxz ), wspostc.zyy );
+
+ o.pos = mul( G.ViewProjection, wspos );
+ o.tc0Fog.xy = tcselect * .05f;
+ o.tc0Fog.z = saturate( (G.FogParams.z - o.pos.w) * G.FogParams.w );
+
+ o.light = lgridPrepareSample(lgridOffset(wspos.xyz, wsnrm.xyz));
+
+ o.fade.x = fadeFactor( wspos.xyz );
+ o.fade.y = (1-o.fade.x) * saturate( dot( wsnrm, -G.Lamp0Dir ) ) * 100;
+
+ return o;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+sampler2D NormalMap1 : register(s0);
+sampler2D NormalMap2 : register(s1);
+samplerCUBE EnvMap : register(s2);
+LGRID_SAMPLER LightMap : register(s3);
+sampler2D LightMapLookup: register(s4);
+
+float3 pixelNormal( float2 tc0 )
+{
+ float4 nm1 = tex2D( NormalMap1, tc0 );
+#if WATER_LOD <= 1
+ float4 nm2 = tex2D( NormalMap2, tc0 );
+ float3 normal = lerp( nm1, nm2, nmAnimLerp.xxxx ).agb;
+#else
+ float3 normal = nm1.agb;
+#endif
+ //normal = nm2;
+ normal.xy = 2*normal.xy - 1;
+ normal.z = sqrt( 1.001 - saturate1( dot( normal.xy, normal.xy ) ) );
+ return normal;
+}
+
+
+float4 envColor( float3 N, float3 V, float fade )
+{
+ float4 solidColor = float4( 0.65f, 0.85f, 0.93f, 1 )*.95f;
+#if WATER_LOD > 1
+ return solidColor;
+#endif
+
+ float3 dir = reflect( V, N );
+ return lerp( texCUBE( EnvMap, V ), solidColor, fade );
+
+ //return float3( 0.8f, 0.8f, 0.93f )*.91f;
+}
+
+//////////////////////////////////////////
+//////////////////////////////////////////
+
+
+
+float4 water_ps( V2P v ) : COLOR0
+{
+ float4 WaterColorTest = 0.5 * float4( 26, 169, 185, 0 ) / 255;
+ float4 FogColorTest = 0.8 * float4( 35, 107, 130, 0 ) / 255;
+
+ float3 N2 = v.wsnrm;
+ float3 N1 = pixelNormal( v.tc0Fog.xy ).xzy;
+ float3 N3 = 0.5f * (N2 + N1);
+
+ float3 L = /*normalize*/(-G.Lamp0Dir.xyz);
+ float3 E = normalize( G.CameraPosition.xyz - v.wspos.xyz );
+
+ float4 light = lgridSample(LightMap, LightMapLookup, v.light.xyz);
+
+ float3 ambient = ( light.rgb + G.AmbientColor.rgb );
+ float fre = fresnel( N3, E, 1.0f, 1.3f, 8, v.fade.x );
+ float3 diffuse = WaterColor.rgb + N1.y*0.02f;
+
+ float3 env = envColor( N3, E, v.fade.x ).rgb;
+
+ float3 R = reflect( -L, N1 );
+
+#if WATER_LOD <= 1
+ float3 specular = pow( saturate( dot( R, E ) ), 900 ) * saturate( light.a - 0.4f ) * v.fade.y; // * (L.y * 100);
+#else
+ float3 specular = 0;
+#endif
+
+ float3 result = lerp( diffuse, env, fre ) * ( G.Lamp0Color.rgb * light.a + ambient ) + specular;
+ result = lerp( G.FogColor.rgb, result, v.tc0Fog.z );
+
+ return float4( result, 1 );
+}
diff --git a/Client2014/shaders/source/wood.hlsl b/Client2014/shaders/source/wood.hlsl
new file mode 100644
index 0000000..2e7f1e2
--- /dev/null
+++ b/Client2014/shaders/source/wood.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.3
+
+#define CFG_SPECULAR_LOD 0.25
+#define CFG_GLOSS_LOD 32
+
+#define CFG_NORMAL_DETAIL_TILING 7
+#define CFG_NORMAL_DETAIL_SCALE 0.6
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2014/tbb.dll b/Client2014/tbb.dll
new file mode 100644
index 0000000..919da8b
Binary files /dev/null and b/Client2014/tbb.dll differ
diff --git a/Client2014/tbb_debug.dll b/Client2014/tbb_debug.dll
new file mode 100644
index 0000000..c368a7e
Binary files /dev/null and b/Client2014/tbb_debug.dll differ
diff --git a/Client2016/AppSettings.xml b/Client2016/AppSettings.xml
new file mode 100644
index 0000000..52b2249
--- /dev/null
+++ b/Client2016/AppSettings.xml
@@ -0,0 +1,7 @@
+
+
+ https://www.syntax.eco
+ content
+ 0
+ 0
+
diff --git a/Client2016/COPYRIGHT.txt b/Client2016/COPYRIGHT.txt
new file mode 100644
index 0000000..82ff85c
--- /dev/null
+++ b/Client2016/COPYRIGHT.txt
@@ -0,0 +1,31 @@
+COPYRIGHT.txt
+
+This product uses third party open source libraries. Their copyright notices are reproduced below.
+
+/=================================================================================
+Copyright (c) 2007-2016. The YARA Authors. All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Client2016/PlatformContent/pc/terrain/diffuse.dds b/Client2016/PlatformContent/pc/terrain/diffuse.dds
new file mode 100644
index 0000000..a279877
Binary files /dev/null and b/Client2016/PlatformContent/pc/terrain/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/terrain/materials.json b/Client2016/PlatformContent/pc/terrain/materials.json
new file mode 100644
index 0000000..6ce791d
--- /dev/null
+++ b/Client2016/PlatformContent/pc/terrain/materials.json
@@ -0,0 +1,118 @@
+{
+ "platform": "pc",
+ "atlas":
+ {
+ "pc": {
+ "width": 4096,
+ "height": 4096,
+ "tileSize": 512,
+ "tileCount": 6,
+
+ "borderSize": 85
+ },
+ "ios": {
+ "width": 2048,
+ "height": 2048,
+ "tileSize": 304,
+ "tileCount": 5,
+
+ "borderSize": 85
+ },
+ "android": {
+ "width": 2048,
+ "height": 2048,
+ "tileSize": 304,
+ "tileCount": 5,
+
+ "borderSize": 85
+ }
+ },
+ "materials":
+ [
+ {
+ "name": "Air"
+ },
+ {
+ "name": "Water",
+ "water": 0.5
+ },
+ {
+ "name": "Grass",
+ "texture_top": { "tiling": 0.25, "detiling": 0.25 },
+ "texture_side": { "tiling": 0.2, "detiling": 0.2 },
+ "texture_bottom": { "tiling": 0.45, "detiling": 0.45 }
+ },
+ {
+ "name": "Slate",
+ "shift": 0.1,
+ "texture": { "tiling": 0.55, "detiling": 0.55 }
+ },
+ {
+ "name": "Concrete",
+ "quantize": 0.5,
+ "type": "hard",
+ "texture_top": { "tiling": 0.5, "detiling": 0.8 },
+ "texture_side": { "tiling": 0.4, "detiling": 0.4 }
+ },
+ {
+ "name": "Brick",
+ "cubify": 1,
+ "type": "hard",
+ "mapping": "cube",
+ "texture": { "tiling": 0.80, "detiling": 0.20 }
+ },
+ {
+ "name": "Sand",
+ "texture_top": { "tiling": 0.25, "detiling": 0.25 },
+ "texture_side": { "tiling": 0.25, "detiling": 0.25 }
+ },
+ {
+ "name": "WoodPlanks",
+ "cubify": 1.0,
+ "type": "hard",
+ "mapping": "cube",
+ "texture": { "tiling": 0.8, "detiling": 0.5 }
+ },
+ {
+ "name": "Rock",
+ "shift": 0.3,
+ "type": "hardsoft",
+ "texture": { "tiling": 0.55, "detiling": 0.55 }
+ },
+ {
+ "name": "Glacier",
+ "texture_top": { "tiling": 0.23, "detiling": 0.23 },
+ "texture_side": { "tiling": 0.2, "detiling": 0.9},
+ "texture_bottom": { "tiling": 0.23, "detiling": 0.6 }
+ },
+ {
+ "name": "Snow",
+ "texture": { "tiling": 0.3, "detiling": 0.3 }
+ },
+ {
+ "name": "Sandstone",
+ "texture_top": { "tiling": 0.5, "detiling": 0.7 },
+ "texture_side": { "tiling": 0.3, "detiling": 0.5003},
+ "texture_bottom": { "tiling": 0.45, "detiling": 0.45 }
+ },
+ {
+ "name": "Mud",
+ "texture": { "tiling": 0.3, "detiling": 0.1 }
+ },
+ {
+ "name": "Basalt",
+ "shift": 0.2,
+ "type": "hardsoft",
+ "texture": { "tiling": 0.55, "detiling": 0.55 }
+ },
+ {
+ "name": "Ground",
+ "texture": { "tiling": 0.3, "detiling": 0.3 }
+ },
+ {
+ "name": "CrackedLava",
+ "shift": 0.1,
+ "texture": { "tiling": 0.28, "detiling": 0.3 }
+ }
+ ]
+}
diff --git a/Client2016/PlatformContent/pc/terrain/normal.dds b/Client2016/PlatformContent/pc/terrain/normal.dds
new file mode 100644
index 0000000..8bd4aa3
Binary files /dev/null and b/Client2016/PlatformContent/pc/terrain/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/terrain/specular.dds b/Client2016/PlatformContent/pc/terrain/specular.dds
new file mode 100644
index 0000000..8b2c531
Binary files /dev/null and b/Client2016/PlatformContent/pc/terrain/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/aluminum/diffuse.dds b/Client2016/PlatformContent/pc/textures/aluminum/diffuse.dds
new file mode 100644
index 0000000..fee64f0
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/aluminum/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/aluminum/normal.dds b/Client2016/PlatformContent/pc/textures/aluminum/normal.dds
new file mode 100644
index 0000000..466fcb4
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/aluminum/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/aluminum/normaldetail.dds b/Client2016/PlatformContent/pc/textures/aluminum/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/aluminum/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/aluminum/specular.dds b/Client2016/PlatformContent/pc/textures/aluminum/specular.dds
new file mode 100644
index 0000000..1cd4a27
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/aluminum/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/brick/diffuse.dds b/Client2016/PlatformContent/pc/textures/brick/diffuse.dds
new file mode 100644
index 0000000..a9f10fa
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/brick/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/brick/normal.dds b/Client2016/PlatformContent/pc/textures/brick/normal.dds
new file mode 100644
index 0000000..1131f06
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/brick/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/brick/normaldetail.dds b/Client2016/PlatformContent/pc/textures/brick/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/brick/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/brick/specular.dds b/Client2016/PlatformContent/pc/textures/brick/specular.dds
new file mode 100644
index 0000000..58faad2
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/brick/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/cobblestone/diffuse.dds b/Client2016/PlatformContent/pc/textures/cobblestone/diffuse.dds
new file mode 100644
index 0000000..1ff6add
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/cobblestone/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/cobblestone/normal.dds b/Client2016/PlatformContent/pc/textures/cobblestone/normal.dds
new file mode 100644
index 0000000..87e3a3f
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/cobblestone/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/cobblestone/normaldetail.dds b/Client2016/PlatformContent/pc/textures/cobblestone/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/cobblestone/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/cobblestone/specular.dds b/Client2016/PlatformContent/pc/textures/cobblestone/specular.dds
new file mode 100644
index 0000000..423e0b4
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/cobblestone/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/concrete/diffuse.dds b/Client2016/PlatformContent/pc/textures/concrete/diffuse.dds
new file mode 100644
index 0000000..2174765
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/concrete/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/concrete/normal.dds b/Client2016/PlatformContent/pc/textures/concrete/normal.dds
new file mode 100644
index 0000000..dfd9bb8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/concrete/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/concrete/normaldetail.dds b/Client2016/PlatformContent/pc/textures/concrete/normaldetail.dds
new file mode 100644
index 0000000..5c11a43
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/concrete/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/concrete/specular.dds b/Client2016/PlatformContent/pc/textures/concrete/specular.dds
new file mode 100644
index 0000000..bfeb384
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/concrete/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/diamondplate/diffuse.dds b/Client2016/PlatformContent/pc/textures/diamondplate/diffuse.dds
new file mode 100644
index 0000000..e4f5f3a
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/diamondplate/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/diamondplate/normal.dds b/Client2016/PlatformContent/pc/textures/diamondplate/normal.dds
new file mode 100644
index 0000000..88ece5f
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/diamondplate/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/diamondplate/normaldetail.dds b/Client2016/PlatformContent/pc/textures/diamondplate/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/diamondplate/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/diamondplate/specular.dds b/Client2016/PlatformContent/pc/textures/diamondplate/specular.dds
new file mode 100644
index 0000000..9154362
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/diamondplate/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/fabric/diffuse.dds b/Client2016/PlatformContent/pc/textures/fabric/diffuse.dds
new file mode 100644
index 0000000..a0efd50
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/fabric/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/fabric/normal.dds b/Client2016/PlatformContent/pc/textures/fabric/normal.dds
new file mode 100644
index 0000000..4025a92
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/fabric/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/fabric/normaldetail.dds b/Client2016/PlatformContent/pc/textures/fabric/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/fabric/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/fabric/specular.dds b/Client2016/PlatformContent/pc/textures/fabric/specular.dds
new file mode 100644
index 0000000..e3c973d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/fabric/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/granite/diffuse.dds b/Client2016/PlatformContent/pc/textures/granite/diffuse.dds
new file mode 100644
index 0000000..bd67946
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/granite/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/granite/normal.dds b/Client2016/PlatformContent/pc/textures/granite/normal.dds
new file mode 100644
index 0000000..1a168d9
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/granite/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/granite/normaldetail.dds b/Client2016/PlatformContent/pc/textures/granite/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/granite/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/granite/specular.dds b/Client2016/PlatformContent/pc/textures/granite/specular.dds
new file mode 100644
index 0000000..aba04d5
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/granite/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/grass/diffuse.dds b/Client2016/PlatformContent/pc/textures/grass/diffuse.dds
new file mode 100644
index 0000000..c648fe4
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/grass/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/grass/normal.dds b/Client2016/PlatformContent/pc/textures/grass/normal.dds
new file mode 100644
index 0000000..829c341
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/grass/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/grass/normaldetail.dds b/Client2016/PlatformContent/pc/textures/grass/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/grass/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/grass/specular.dds b/Client2016/PlatformContent/pc/textures/grass/specular.dds
new file mode 100644
index 0000000..e47ed61
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/grass/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/ice/diffuse.dds b/Client2016/PlatformContent/pc/textures/ice/diffuse.dds
new file mode 100644
index 0000000..fee64f0
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/ice/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/ice/normal.dds b/Client2016/PlatformContent/pc/textures/ice/normal.dds
new file mode 100644
index 0000000..8752407
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/ice/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/ice/normaldetail.dds b/Client2016/PlatformContent/pc/textures/ice/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/ice/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/ice/specular.dds b/Client2016/PlatformContent/pc/textures/ice/specular.dds
new file mode 100644
index 0000000..4689e14
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/ice/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/marble/diffuse.dds b/Client2016/PlatformContent/pc/textures/marble/diffuse.dds
new file mode 100644
index 0000000..028e920
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/marble/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/marble/normal.dds b/Client2016/PlatformContent/pc/textures/marble/normal.dds
new file mode 100644
index 0000000..ba3641b
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/marble/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/marble/normaldetail.dds b/Client2016/PlatformContent/pc/textures/marble/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/marble/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/marble/specular.dds b/Client2016/PlatformContent/pc/textures/marble/specular.dds
new file mode 100644
index 0000000..d2a1c7e
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/marble/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/metal/diffuse.dds b/Client2016/PlatformContent/pc/textures/metal/diffuse.dds
new file mode 100644
index 0000000..a1f7fd2
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/metal/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/metal/normal.dds b/Client2016/PlatformContent/pc/textures/metal/normal.dds
new file mode 100644
index 0000000..b7d6a83
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/metal/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/metal/normaldetail.dds b/Client2016/PlatformContent/pc/textures/metal/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/metal/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/metal/specular.dds b/Client2016/PlatformContent/pc/textures/metal/specular.dds
new file mode 100644
index 0000000..98a9f60
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/metal/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/pebble/diffuse.dds b/Client2016/PlatformContent/pc/textures/pebble/diffuse.dds
new file mode 100644
index 0000000..48b56cc
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/pebble/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/pebble/normal.dds b/Client2016/PlatformContent/pc/textures/pebble/normal.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/pebble/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/pebble/normaldetail.dds b/Client2016/PlatformContent/pc/textures/pebble/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/pebble/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/pebble/specular.dds b/Client2016/PlatformContent/pc/textures/pebble/specular.dds
new file mode 100644
index 0000000..bfeb384
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/pebble/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/plastic/diffuse.dds b/Client2016/PlatformContent/pc/textures/plastic/diffuse.dds
new file mode 100644
index 0000000..c33c9e5
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/plastic/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/plastic/normal.dds b/Client2016/PlatformContent/pc/textures/plastic/normal.dds
new file mode 100644
index 0000000..7804947
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/plastic/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/plastic/normaldetail.dds b/Client2016/PlatformContent/pc/textures/plastic/normaldetail.dds
new file mode 100644
index 0000000..b29ac42
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/plastic/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/rust/diffuse.dds b/Client2016/PlatformContent/pc/textures/rust/diffuse.dds
new file mode 100644
index 0000000..abd195a
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/rust/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/rust/normal.dds b/Client2016/PlatformContent/pc/textures/rust/normal.dds
new file mode 100644
index 0000000..7d15959
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/rust/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/rust/normaldetail.dds b/Client2016/PlatformContent/pc/textures/rust/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/rust/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/rust/specular.dds b/Client2016/PlatformContent/pc/textures/rust/specular.dds
new file mode 100644
index 0000000..9c3133e
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/rust/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/sand/diffuse.dds b/Client2016/PlatformContent/pc/textures/sand/diffuse.dds
new file mode 100644
index 0000000..5b91413
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sand/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/sand/normal.dds b/Client2016/PlatformContent/pc/textures/sand/normal.dds
new file mode 100644
index 0000000..c8a2c84
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sand/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/sand/normaldetail.dds b/Client2016/PlatformContent/pc/textures/sand/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sand/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/sand/specular.dds b/Client2016/PlatformContent/pc/textures/sand/specular.dds
new file mode 100644
index 0000000..6efec1b
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sand/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_bk.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_bk.tex
new file mode 100644
index 0000000..fcdd232
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_bk.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_dn.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_dn.tex
new file mode 100644
index 0000000..d63e52d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_dn.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_ft.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_ft.tex
new file mode 100644
index 0000000..215b51b
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_ft.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_lf.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_lf.tex
new file mode 100644
index 0000000..a096acf
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_lf.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_rt.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_rt.tex
new file mode 100644
index 0000000..6c0aaf1
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_rt.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/sky/sky512_up.tex b/Client2016/PlatformContent/pc/textures/sky/sky512_up.tex
new file mode 100644
index 0000000..a973654
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/sky/sky512_up.tex differ
diff --git a/Client2016/PlatformContent/pc/textures/slate/diffuse.dds b/Client2016/PlatformContent/pc/textures/slate/diffuse.dds
new file mode 100644
index 0000000..ff7ca6d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/slate/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/slate/normal.dds b/Client2016/PlatformContent/pc/textures/slate/normal.dds
new file mode 100644
index 0000000..6f38346
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/slate/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/slate/normaldetail.dds b/Client2016/PlatformContent/pc/textures/slate/normaldetail.dds
new file mode 100644
index 0000000..7e6b0ca
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/slate/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/slate/specular.dds b/Client2016/PlatformContent/pc/textures/slate/specular.dds
new file mode 100644
index 0000000..271b6c1
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/slate/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/studs.dds b/Client2016/PlatformContent/pc/textures/studs.dds
new file mode 100644
index 0000000..8f11167
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/studs.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/terrain/diffuse.dds b/Client2016/PlatformContent/pc/textures/terrain/diffuse.dds
new file mode 100644
index 0000000..26b370d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/terrain/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/terrain/diffusefar.dds b/Client2016/PlatformContent/pc/textures/terrain/diffusefar.dds
new file mode 100644
index 0000000..657e10b
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/terrain/diffusefar.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/terrain/normal.dds b/Client2016/PlatformContent/pc/textures/terrain/normal.dds
new file mode 100644
index 0000000..a64ba4a
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/terrain/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/terrain/specular.dds b/Client2016/PlatformContent/pc/textures/terrain/specular.dds
new file mode 100644
index 0000000..82bc31f
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/terrain/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/wangIndex.dds b/Client2016/PlatformContent/pc/textures/wangIndex.dds
new file mode 100644
index 0000000..e613ff1
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/wangIndex.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_01.dds b/Client2016/PlatformContent/pc/textures/water/normal_01.dds
new file mode 100644
index 0000000..d3ba9cc
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_01.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_02.dds b/Client2016/PlatformContent/pc/textures/water/normal_02.dds
new file mode 100644
index 0000000..012bf30
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_02.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_03.dds b/Client2016/PlatformContent/pc/textures/water/normal_03.dds
new file mode 100644
index 0000000..343de72
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_03.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_04.dds b/Client2016/PlatformContent/pc/textures/water/normal_04.dds
new file mode 100644
index 0000000..19a6276
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_04.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_05.dds b/Client2016/PlatformContent/pc/textures/water/normal_05.dds
new file mode 100644
index 0000000..721320d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_05.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_06.dds b/Client2016/PlatformContent/pc/textures/water/normal_06.dds
new file mode 100644
index 0000000..1e13691
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_06.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_07.dds b/Client2016/PlatformContent/pc/textures/water/normal_07.dds
new file mode 100644
index 0000000..5edd661
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_07.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_08.dds b/Client2016/PlatformContent/pc/textures/water/normal_08.dds
new file mode 100644
index 0000000..14693e8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_08.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_09.dds b/Client2016/PlatformContent/pc/textures/water/normal_09.dds
new file mode 100644
index 0000000..5b161c7
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_09.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_10.dds b/Client2016/PlatformContent/pc/textures/water/normal_10.dds
new file mode 100644
index 0000000..353590e
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_10.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_11.dds b/Client2016/PlatformContent/pc/textures/water/normal_11.dds
new file mode 100644
index 0000000..8e2c7a0
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_11.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_12.dds b/Client2016/PlatformContent/pc/textures/water/normal_12.dds
new file mode 100644
index 0000000..5babefd
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_12.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_13.dds b/Client2016/PlatformContent/pc/textures/water/normal_13.dds
new file mode 100644
index 0000000..fdc82da
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_13.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_14.dds b/Client2016/PlatformContent/pc/textures/water/normal_14.dds
new file mode 100644
index 0000000..7ca5c06
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_14.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_15.dds b/Client2016/PlatformContent/pc/textures/water/normal_15.dds
new file mode 100644
index 0000000..601ebdc
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_15.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_16.dds b/Client2016/PlatformContent/pc/textures/water/normal_16.dds
new file mode 100644
index 0000000..ae10be5
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_16.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_17.dds b/Client2016/PlatformContent/pc/textures/water/normal_17.dds
new file mode 100644
index 0000000..86667b2
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_17.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_18.dds b/Client2016/PlatformContent/pc/textures/water/normal_18.dds
new file mode 100644
index 0000000..3cd7cfb
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_18.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_19.dds b/Client2016/PlatformContent/pc/textures/water/normal_19.dds
new file mode 100644
index 0000000..01db6d4
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_19.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_20.dds b/Client2016/PlatformContent/pc/textures/water/normal_20.dds
new file mode 100644
index 0000000..0fcdfa8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_20.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_21.dds b/Client2016/PlatformContent/pc/textures/water/normal_21.dds
new file mode 100644
index 0000000..2aa6e82
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_21.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_22.dds b/Client2016/PlatformContent/pc/textures/water/normal_22.dds
new file mode 100644
index 0000000..3e91016
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_22.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_23.dds b/Client2016/PlatformContent/pc/textures/water/normal_23.dds
new file mode 100644
index 0000000..91e13c6
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_23.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_24.dds b/Client2016/PlatformContent/pc/textures/water/normal_24.dds
new file mode 100644
index 0000000..87bbbdf
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_24.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/water/normal_25.dds b/Client2016/PlatformContent/pc/textures/water/normal_25.dds
new file mode 100644
index 0000000..a0a4b49
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/water/normal_25.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/wood/diffuse.dds b/Client2016/PlatformContent/pc/textures/wood/diffuse.dds
new file mode 100644
index 0000000..941b70f
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/wood/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/wood/normal.dds b/Client2016/PlatformContent/pc/textures/wood/normal.dds
new file mode 100644
index 0000000..aa3190c
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/wood/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/wood/normaldetail.dds b/Client2016/PlatformContent/pc/textures/wood/normaldetail.dds
new file mode 100644
index 0000000..5630e27
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/wood/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/wood/specular.dds b/Client2016/PlatformContent/pc/textures/wood/specular.dds
new file mode 100644
index 0000000..f5a8470
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/wood/specular.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/woodplanks/diffuse.dds b/Client2016/PlatformContent/pc/textures/woodplanks/diffuse.dds
new file mode 100644
index 0000000..df819fd
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/woodplanks/diffuse.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/woodplanks/normal.dds b/Client2016/PlatformContent/pc/textures/woodplanks/normal.dds
new file mode 100644
index 0000000..5f4dcf9
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/woodplanks/normal.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/woodplanks/normaldetail.dds b/Client2016/PlatformContent/pc/textures/woodplanks/normaldetail.dds
new file mode 100644
index 0000000..818b2a8
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/woodplanks/normaldetail.dds differ
diff --git a/Client2016/PlatformContent/pc/textures/woodplanks/specular.dds b/Client2016/PlatformContent/pc/textures/woodplanks/specular.dds
new file mode 100644
index 0000000..6a1371d
Binary files /dev/null and b/Client2016/PlatformContent/pc/textures/woodplanks/specular.dds differ
diff --git a/Client2016/ReflectionMetadata.xml b/Client2016/ReflectionMetadata.xml
new file mode 100644
index 0000000..feea260
--- /dev/null
+++ b/Client2016/ReflectionMetadata.xml
@@ -0,0 +1,4241 @@
+
+ -
+
+
-
+
+ BindableFunction
+ Allow functions defined in one script to be called by another script
+ 4
+ 66
+
+
+
-
+
-
+
+ Invoke
+ Causes the function assigned to OnInvoke to be called. Arguments passed to this function get passed to OnInvoke function.
+
+
+
+ -
+
-
+
+ OnInvoke
+ Should be defined as a function. This function is called when Invoke() is called. Number of arguments is variable.
+
+
+
+
+ -
+
+ BindableEvent
+ Allow events defined in one script to be subscribed to by another script
+
+ 5
+ 67
+
+
-
+
-
+
+ Fire
+ Used to make the custom event fire (see Event for more info). Arguments can be variable length.
+
+
+
+ -
+
-
+
+ Event
+ This event fires when the Fire() method is used. Receives the variable length arguments from Fire().
+
+
+
+
+ -
+
+ TouchTransmitter
+ Used by networking and replication code to transmit touch events - no other purpose
+
+ false
+ 3
+ 37
+
+
+ -
+
+ ForceField
+ Prevents joint breakage from explosions, and stops Humanoids from taking damage
+ 3
+ 37
+
+
+ -
+
+ PluginManager
+
+
+
+ -
+
+ TeleportService
+ Allows players to seamlessly leave a game and join another
+
+
-
+
+ CustomizedTeleportUI
+ true
+ Deprecated
+
+
+
+ -
+
+ StudioTool
+
+
+
+ -
+
+ Plugin
+
+
+
+ -
+
+ PluginMouse
+
+
+
+ -
+
+ Glue
+
+
+ -
+
+ CollectionService
+
+
+ -
+
+ JointsService
+
+
+ -
+
+ BadgeService
+
+
+ -
+
+ LogService
+
+
+ -
+
+ AssetService
+ A service used to set and get information about assets stored on the Roblox website.
+
+
-
+
-
+
+ RevertAsset
+ Reverts a given place id to the version number provided. Returns true if successful on reverting, false otherwise.
+
+
+ -
+
+ SetPlacePermissions
+ Sets the permissions for a placeID to the place accessType. An optional table (inviteList) can be included that will set the accessType for only the player names provided. The table should be set up as an array of usernames (strings).
+
+
+ -
+
+ GetPlacePermissions
+ Given a placeID, this function will return a table with the permissions of the place. Useful for determining what kind of permissions a particular user may have for a place.
+
+
+ -
+
+ GetAssetVersions
+ Given a placeID, this function will return a table with the version info of the place. An optional arg of page number can be used to page through all revisions (a single page may hold about 50 revisions).
+
+
+ -
+
+ GetCreatorAssetID
+ Given a creationID, this function will return the asset that created the creationID. If no other asset created the given creationID, 0 is returned.
+
+
+
+
+ -
+
+ HttpService
+ 101
+
+
+
-
+
-
+
+ HttpEnabled
+ true
+ Enabling http requests from scripts
+
+
+
+
+ -
+
+ InsertService
+ A service used to insert objects stored on the website into the game.
+
+
-
+
-
+
+ GetCollection
+ Returns a table for the assets stored in the category. A category is an setId from www.roblox.com that links to a set. <a href="http://wiki.roblox.com/index.php?title=API:Class/InsertService/GetCollection" target="_blank">More info on table format</a>. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ Insert
+ Inserts the Instance into the workspace. It is recommended to use Instance.Parent = game.Workspace instead, as this can cause issues currently.
+
+
+ -
+
+ ApproveAssetId
+ true
+ Deprecated
+
+
+ -
+
+ ApproveAssetVersionId
+ true
+ Deprecated
+
+
+
+
+ -
+
-
+
+ GetBaseSets
+ Returns a table containing a list of the various setIds that are ROBLOX approved. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetUserSets
+ Returns a table containing a list of the various setIds that correspond to argument 'userId'. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetBaseCategories
+ true
+ Deprecated. Use GetBaseSets() instead.
+
+
+ -
+
+ GetUserCategories
+ true
+ Deprecated. Use GetUserSets() instead.
+
+
+ -
+
+ LoadAsset
+ Returns a Model containing the Instance that resides at AssetId on the web. This call will also yield the script until the model is returned. Script execution can still continue, however, if you use a <a href="http://wiki.roblox.com/index.php?title=Coroutine" target="_blank">coroutine</a>.
+
+
+ -
+
+ LoadAssetVersion
+ Similar to LoadAsset, but instead an AssetVersionId is passed in, which refers to a particular version of the asset which is not neccessarily the latest version.
+
+
+
+
+ -
+
+ Hat
+ 3
+ 45
+ true
+
+
+ -
+
+ Accessory
+ 3
+ 32
+
+
+ -
+
+ LocalBackpack
+
+
+ -
+
+ LocalBackpackItem
+
+
+ -
+
+ MotorFeature
+ true
+
+
+ -
+
+ Mouse
+ Used to receive input from the user. Actually tracks mouse events and keyboard events.
+
+
-
+
-
+
+ Hit
+ The CoordinateFrame of where the Mouse ray is currently hitting a 3D object in the Workspace. If the mouse is not over any 3D objects in the Workspace, this property is nil.
+
+
+ -
+
+ Icon
+ The current Texture of the Mouse Icon. Stored as a string, for more information on how to format the string <a href="http://wiki.roblox.com/index.php/Content" target="_blank">go here</a>
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking.
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking. This CoordinateFrame will be very close to the Camera.CoordinateFrame.
+
+
+ -
+
+ Target
+ The Part the mouse is currently over. If the mouse is not currently over any object (on the skybox, for example) this property is nil.
+
+
+ -
+
+ TargetFilter
+ A Part or Model that the Mouse will ignore when trying to find the Target, TargetSurface and Hit.
+
+
+ -
+
+ TargetSurface
+ The NormalId (Top, Left, Down, etc.) of the face of the part the Mouse is currently over.
+
+
+ -
+
+ UnitRay
+ The Unit Ray from where the mouse is (Origin) to the current Mouse.Target.
+
+
+ -
+
+ ViewSizeX
+ The viewport's (game window) width in pixels.
+
+
+ -
+
+ ViewSizeY
+ The viewport's (game window) height in pixels.
+
+
+ -
+
+ X
+ The absolute pixel position of the Mouse along the x-axis of the viewport (game window). Values start at 0 on the left hand side of the screen and increase to the right.
+
+
+ -
+
+ Y
+ The absolute pixel position of the Mouse along the y-axis of the viewport (game window). Values start at 0 on the stop of the screen and increase to the bottom.
+
+
+
+ -
+
-
+
+ Button1Down
+ Fired when the first button (usually the left, but could be another) on the mouse is depressed.
+
+
+ -
+
+ Button1Up
+ Fired when the first button (usually the left, but could be another) on the mouse is release.
+
+
+ -
+
+ Button2Down
+ This event is currently non-operational.
+
+
+ -
+
+ Button2Up
+ This event is currently non-operational.
+
+
+ -
+
+ Idle
+ Fired constantly when the mouse is not firing any other event (i.e. the mouse isn't moving, nor any buttons being pressed or depressed).
+
+
+ -
+
+ KeyDown
+ Fired when a user presses a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ KeyUp
+ Fired when a user releases a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ Move
+ Fired when the mouse X or Y member changes.
+
+
+ -
+
+ WheelBackward
+ This event is currently non-operational.
+
+
+ -
+
+ WheelForward
+ This event is currently non-operational.
+
+
+
+
+ -
+
+ ProfilingItem
+
+
+ -
+
+ ChangeHistoryService
+
+
+ -
+
+ RotateP
+
+
+ -
+
+ RotateV
+
+
+ -
+
+ ScriptContext
+
+
+ -
+
+ Selection
+
+
+ -
+
+ VelocityMotor
+
+
+ -
+
+ Weld
+ 20
+ 34
+
+
+ -
+
+ TaskScheduler
+
+
-
+
-
+
+ SetThreadShare
+ true
+ Deprecated
+
+
+
+
+ -
+
+ StatsItem
+
+
+ -
+
+ Snap
+
+
+ -
+
+ FileMesh
+
+
+
+ -
+
+ ClickDetector
+ Raises mouse events for parent object
+ 3
+ 41
+
+
-
+
-
+
+ MaxActivationDistance
+ The maximum distance a Player's character can be from the ClickDetector's parent Part that will allow the Player's mouse to fire events on this object.
+
+
+
+ -
+
-
+
+ MouseClick
+ Fired when a player clicks on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverEnter
+ Fired when a player's mouse enters on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverLeave
+ Fired when a player's mouse leaves the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+
+
+
+ -
+
+ Clothing
+ 0
+
+
+
+ -
+
+ Smoke
+ Makes the parent part or model object emit smoke
+ 3
+ 59
+
+
+
+ -
+
+ ParticleEmitter
+ A generic particle system.
+ 3
+ 80
+
+
-
+
-
+
+ LightEmission
+ 0
+ 1
+
+
+
+
+
+ -
+
+ Sparkles
+ Makes the parent part or model object fantastic
+ 3
+ 42
+
+
+ -
+
+ Explosion
+ 3
+ 36
+ Creates an Explosion! This can be used as a purely graphical effect, or can be made to damage objects.
+
+
-
+
-
+
+ BlastPressure
+ How much force this Explosion exerts on objects within it's BlastRadius. Setting this to 0 creates a purely graphical effect. A larger number will cause Parts to fly away at higher velocities.
+
+
+ -
+
+ BlastRadius
+ How big the Explosion is. This is a circle starting from the center of the Explosion's Position, the larger this property the larger the circle of destruction.
+
+
+ -
+
+ Position
+ Where the Explosion occurs in absolute world coordinates.
+
+
+ -
+
+ ExplosionType
+ Defines the behavior of the Explosion. <a href="http://wiki.roblox.com/index.php/ExplosionType" target="_blank">More info</a>
+
+
+
+
+ -
+
+ Fire
+ Makes the parent part or model object emit fire
+ 3
+ 61
+
+
-
+
-
+
+ Color
+ The color of the base of the fire. See SecondaryColor for more.
+
+
+ -
+
+ Heat
+ How hot the fire appears to be. The flame moves quicker the higher this value is set.
+
+
+ -
+
+ SecondaryColor
+ The color the fire interpolates to from Color. The longer a particle exists in the fire, the close to this color it becomes.
+
+
+ -
+
+ Size
+ How large the fire appears to be.
+
+
+
+
+ -
+
+ Seat
+ 3
+ 35
+
+
+ -
+
+ Platform
+
+ Equivalent to a seat, except that the character stands up rather than sits down.
+ 3
+ 35
+
+
+ -
+
+ SkateboardPlatform
+ true
+ 3
+ 35
+
+
+ -
+
+ VehicleSeat
+ Automatically finds and powers hinge joints in an assembly. Ignores motors.
+ 3
+ 35
+
+
+ -
+
+ Tool
+ 3
+ 17
+
+
+ -
+
+ Flag
+ true
+ 3
+ 38
+
+
-
+
-
+
+ CanBeDropped
+ If someone is carrying this flag, this bool determines whether or not they can drop it and run.
+
+
+ -
+
+ TeamColor
+ The Team this flag is for. Corresponds with the TeamColors in the Teams service.
+
+
+
+
+ -
+
+ FlagStand
+ true
+ 3
+ 39
+
+
+ -
+
+ BackpackItem
+ 0
+
+
+ -
+
+ Decal
+ 4
+ 7
+ Descibes a texture that is placed on one of the sides of the Part it is parented to.
+
+
-
+
-
+
+ Face
+ Describes the face of the Part the decal will be applied to. <a href="http://wiki.roblox.com/index.php/NormalId" target="_blank">More info</a>
+
+
+ -
+
+ Shiny
+ How much light will appear to reflect off of the decal.
+
+
+ -
+
+ Specular
+ How light will react to the surface of the decal.
+
+
+ -
+
+ Transparency
+ How visible the decal is. 1 is completely invisible, while 0 is completely opaque
+ 0
+ 1
+
+
+
+
+ -
+
+ JointInstance
+ 20
+ 34
+
+
+ -
+
+ Message
+ 11
+ 33
+ true
+ StarterGui
+
+
+ -
+
+ Hint
+ true
+ 11
+ 33
+
+
+ -
+
+ IntValue
+ 3
+ 4
+ Stores a int value in it's Value member. Useful to share int information across multiple scripts.
+
+
+ -
+
+ RayValue
+ 3
+ 4
+ Stores a Ray value in it's Value member. Useful to share Ray information across multiple scripts.
+
+
+ -
+
+ IntConstrainedValue
+ 3
+ 4
+ Stores an int value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share int information across multiple scripts.
+
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+ -
+
+ DoubleConstrainedValue
+ 3
+ 4
+ Stores a double value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share double information across multiple scripts.
+
+
-
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+
+ -
+
+ BoolValue
+ 3
+ 4
+ Stores a boolean value in it's Value member. Useful to share boolean information across multiple scripts.
+
+
+ -
+
+ CustomEvent
+ 3
+ true
+ 4
+
+
+ -
+
+ CustomEventReceiver
+ 3
+ true
+ 4
+
+
+ -
+
+ TextureTrail
+ true
+ 3
+ 4
+
+
+ -
+
+ FloorWire
+ true
+ 3
+ 4
+ Renders a thin cylinder than can be adorned with textures that 'flow' from one object to the next. Has basic pathing abilities and attempts to to not intersect anything. <a href="http://wiki.roblox.com/index.php/FloorWire_Guide" target="_blank">More info</a>
+
+
-
+
-
+
+ CycleOffset
+ Controls how the decals are positioned along the wire. <a href="http://wiki.roblox.com/index.php/CycleOffset" target="_blank">More info</a>
+
+
+ -
+
+ From
+ The object the FloorWire 'emits' from
+
+
+ -
+
+ StudsBetweenTextures
+ The space between two textures on the wire. Note: studs are relative depending on how far the camera is from the FloorWire.
+
+
+ -
+
+ Texture
+ The image we use to render the textures that flow from beginning to end of the FloorWire.
+
+
+ -
+
+ TextureSize
+ The size in studs of the Texture we use to flow from one object to the next.
+
+
+ -
+
+ To
+ The object the FloorWire 'emits' to
+
+
+ -
+
+ Velocity
+ The rate of travel that the textures flow along the wire.
+
+
+ -
+
+ WireRadius
+ How thick the wire is.
+
+
+
+
+ -
+
+ NumberValue
+ 3
+ 4
+
+
+ -
+
+ StringValue
+ 3
+ 4
+
+
+ -
+
+ Vector3Value
+ 3
+ 4
+
+
+ -
+
+ CFrameValue
+ 3
+ 4
+ Stores a CFrame value in it's Value member. Useful to share CFrame information across multiple scripts.
+
+
+ -
+
+ Color3Value
+ 3
+ 4
+ Stores a Color3 value in it's Value member. Useful to share Color3 information across multiple scripts.
+
+
+ -
+
+ BrickColorValue
+ 3
+ 4
+ Stores a BrickColor value in it's Value member. Useful to share BrickColor information across multiple scripts.
+
+
+ -
+
+ ObjectValue
+ 3
+ 4
+
+
+ -
+
+ SpecialMesh
+ 3
+ 8
+
+
+ -
+
+ BlockMesh
+ 3
+ 8
+
+
+
+ -
+
+ CylinderMesh
+ 3
+ 8
+
+
+
+ -
+
+ BevelMesh
+ false
+ true
+
+
+ -
+
+ DataModelMesh
+ false
+
+
+
+ -
+
+ Texture
+ 4
+ 10
+
+
+ -
+
+ Sound
+ 1
+ 11
+
+
-
+
-
+
+ play
+ true
+ Deprecated. Use Play() instead
+
+
+
+ -
+
-
+
+ PlayOnRemove
+ The sound will play when it is removed from the Workspace. Looped sounds don't play
+
+
+
+
+ -
+
+ StockSound
+ false
+ -1
+
+
+ -
+
+ SoundService
+ 50
+ 31
+
+
-
+
+
-
+
+ AmbientReverb
+
+ The ambient sound environment. May not work when using hardware sound
+
+
+ -
+
+ DopplerScale
+
+ The doppler scale is a general scaling factor for how much the pitch varies due to doppler shifting in 3D sound. Doppler is the pitch bending effect when a sound comes towards the listener or moves away from it, much like the effect you hear when a train goes past you with its horn sounding. With dopplerscale you can exaggerate or diminish the effect.
+
+
+ -
+
+ DistanceFactor
+
+ the relative distance factor, compared to 1.0 meters.
+
+
+ -
+
+ RolloffScale
+
+ Setting this value makes the sound drop off faster or slower. The higher the value, the faster volume will attenuate, and conversely the lower the value, the slower it will attenuate. For example a rolloff factor of 1 will simulate the real world, where as a value of 2 will make sounds attenuate 2 times quicker.
+
+
+
+
+ -
+
+ Backpack
+ 3
+ 20
+
+
+ -
+
+ StarterPack
+ 3
+ 20
+
+
+ -
+
+ StarterPlayer
+ 3
+ 79
+
+
+ -
+
+ StarterGear
+ 3
+ 20
+
+
+
+ -
+
+ StarterGui
+ 3
+ 46
+
+
+
-
+
-
+
+ SetCoreGuiEnabled
+ Will stop/begin certain core gui elements being rendered. See CoreGuiType for core guis that can be modified.
+
+
+ -
+
+ GetCoreGuiEnabled
+ Returns a boolean describing whether a CoreGuiType is currently being rendered.
+
+
+
+
+
+ -
+
+ CoreGui
+ false
+ 46
+
+
+
+ -
+
+ ContextActionService
+ A service used to bind input to various lua functions.
+
+
+
-
+
-
+
+ BindAction
+ Binds 'functionToBind' to fire when any 'inputTypes' happen. InputTypes can be variable in number and type. Types can be Enum.KeyCode, single character strings corresponding to keys, or Enum.UserInputType. 'actionName' is a key used by many other ContextActionService functions to query state. 'createTouchButton' if true will create a button on screen on touch devices. This button will fire 'functionToBind' with three arguments: first argument is the actionName, second argument is the UserInputState of the input, and the third is the InputObject that fired this function.
+
+
+ -
+
+ SetTitle
+ If 'actionName' key contains a bound action, then 'title' is set as the title of the touch button. Does nothing if a touch button was not created. No guarantees are made whether title will be set when button is manipulated.
+
+
+ -
+
+ SetDescription
+ If 'actionName' key contains a bound action, then 'description' is set as the description of the bound action. This description will appear for users in a listing of current actions availables.
+
+
+ -
+
+ SetImage
+ If 'actionName' key contains a bound action, then 'image' is set as the image of the touch button. Does nothing if a touch button was not created. No guarantees are made whether image will be set when button is manipulated.
+
+
+ -
+
+ SetPosition
+ If 'actionName' key contains a bound action, then 'position' is set as the position of the touch button. Does nothing if a touch button was not created. No guarantees are made whether position will be set when button is manipulated.
+
+
+ -
+
+ UnbindAction
+ If 'actionName' key contains a bound action, removes function from being called by all input that it was bound by (if function was also bound by a different action name as well, those bound input are still active). Will also remove any touch button created (if button was manipulated manually there is no guarantee it will be cleaned up).
+
+
+ -
+
+ UnbindAllActions
+ Removes all functions bound. No actionNames will remain. All touch buttons will be removed. If button was manipulated manually there is no guarantee it will be cleaned up.
+
+
+ -
+
+ GetBoundActionInfo
+ Returns a table with info regarding the function bound with 'actionName'. Table has the keys 'title' (current title that was set with SetTitle) 'image' (image set with SetImage) 'description' (description set with SetDescription) 'inputTypes' (tuple containing all input bound for this 'actionName') 'createTouchButton' (whether or not we created a touch button for this 'actionName').
+
+
+ -
+
+ GetAllBoundActionInfo
+ Returns a table with all bound action info. Each entry is a key with 'actionName' and value being the same table you would get from ContextActionService:GetBoundActionInfo('actionName').
+
+
+
+
+ -
+
-
+
+ GetButton
+ If 'actionName' key contains a bound action, then this will return the touch button (if was created). Returns nil if a touch button was not created. No guarantees are made whether button will be retrievable when button is manipulated.
+
+
+
+
+
+ -
+
+ PointsService
+ A service used to query and award points for Roblox users using the universal point system.
+
+
+
-
+
-
+
+ PointsAwarded
+ Fired when points are successfully awarded 'userId'. Also returns the updated balance of points for usedId in universe via 'userBalanceInUniverse', total points via 'userTotalBalance', and the amount points that were awarded via 'pointsAwarded'. This event fires on the server and also all clients in the game that awarded the points.
+
+
+
+
+ -
+
-
+
+ AwardPoints
+ Will attempt to award the 'amount' points to 'userId', returns 'userId' awarded to, the number of points awarded, the new point total the user has in the game, and the total number of points the user now has. Will also fire PointsService.PointsAwarded. Works with server scripts ONLY.
+
+
+ -
+
+ GetPointBalance
+ Returns the overall balance of points that player with userId has (the sum of all points across all games). Works with server scripts ONLY.
+
+
+ -
+
+ GetGamePointBalance
+ Returns the balance of points that player with userId has in the current game (all placeID points combined within the game). Works with server scripts ONLY.
+
+
+ -
+
+ GetAwardablePoints
+ Returns the number of points the current universe can award to players. Works with server scripts ONLY.
+
+
+
+
+
+ -
+
+ Chat
+
+
-
+
-
+
+ FilterStringForPlayerAsync
+ Will return an appropriately filtered string for the player passed in.
+
+
+
+
+
+ -
+
+ MarketplaceService
+ 46
+
+
+
-
+
-
+
+ PromptPurchase
+ Will prompt 'player' to purchase the item associated with 'assetId'. 'equipIfPurchased' is an optional argument that will give the item to the player immediately if they buy it (only applies to gear). 'currencyType' is also optional and will attempt to prompt the user with a specified currency if the product can be purchased with this currency, otherwise we use the default currency of the product.
+
+
+
+
+ -
+
-
+
+ GetProductInfo
+ Takes one argument "assetId" which should be a number of an asset on www.roblox.com. Returns a table containing the product information (if this process fails, returns an empty table).
+
+
+ -
+
+ PlayerOwnsAsset
+ Checks to see if 'Player' owns the product associated with 'assetId'. Returns true if the player owns it, false otherwise. This call will produce a warning if called on a guest player.
+
+
+
+ -
+
-
+
+ ProcessReceipt
+ Callback that is executed for pending Developer Product receipts.
+
+ If this function does not return Enum.ProductPurchaseDecision.PurchaseGranted, then you will not be granted the money for the purchase!
+
+ The callback will be invoked with a table, containing the following informational fields:
+ PlayerId - the id of the player making the purchase.
+ PlaceIdWherePurchased - the specific place where the purchase was made.
+ PurchaseId - a unique identifier for the purchase, should be used to prevent granting an item multiple times for one purchase.
+ ProductId - the id of the purchased product.
+ CurrencyType - the type of currency used (Tix, Robux).
+ CurrencySpent - the amount of currency spent on the product for this purchase.
+
+
+
+
+ -
+
-
+
+ PromptPurchaseFinished
+ Fired when a 'player' dismisses a purchase dialog for 'assetId'. If the player purchased the item 'isPurchased' will be true, otherwise it will be false. This call will produce a warning if called on a guest player.
+
+
+
+
+
+ -
+
+ UserInputService
+
+
-
+
-
+
+ TouchEnabled
+ Returns true if the local device accepts touch input, false otherwise.
+
+
+ -
+
+ KeyboardEnabled
+ Returns true if the local device accepts keyboard input, false otherwise.
+
+
+ -
+
+ MouseEnabled
+ Returns true if the local device accepts mouse input, false otherwise.
+
+
+ -
+
+ AccelerometerEnabled
+ Returns true if the local device has an accelerometer, false otherwise.
+
+
+ -
+
+ GyroscopeEnabled
+ Returns true if the local device has an gyroscope, false otherwise.
+
+
+
+
+ -
+
-
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ TouchStarted
+ Fired when a user places their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchMoved
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchEnded
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ TextBoxFocused
+ Fired when a user clicks/taps on a textbox to begin text entry. Argument is the textbox that was put in focus. This also fires if a textbox forces focus on the user. This event only fires locally.
+
+
+ -
+
+ TextBoxFocusReleased
+ Fired when a user stops text entry into a textbox (usually by pressing return or clicking/tapping somewhere else on the screen). Argument is the textbox that was taken out of focus. This event only fires locally.
+
+
+ -
+
+ DeviceAccelerationChanged
+ Fired when a user moves a device that has an accelerometer. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. This event only fires locally.
+
+
+ -
+
+ DeviceGravityChanged
+ Fired when the force of gravity changes on a device that has an accelerometer. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. This event only fires locally.
+
+
+ -
+
+ DeviceRotationChanged
+ Fired when a user rotates a device that has an gyroscope. This is fired with an InputObject, which has type Enum.InputType.Gyroscope, and position that shows total rotation in each local device axis. The delta property describes the amount of rotation that last happened. A second argument of Vector4 is the device's current quaternion rotation in reference to it's default reference frame. This event only fires locally.
+
+
+
+
+ -
+
-
+
+ GetDeviceAcceleration
+ Returns an InputObject that describes the device's current acceleration. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. The delta property describes the amount of rotation that last happened. This event only fires locally.
+
+
+ -
+
+ GetDeviceGravity
+ Returns an InputObject that describes the device's current gravity vector. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. The delta property describes the amount of rotation that last happened. This event only fires locally.
+
+
+ -
+
+ GetDeviceRotation
+ Returns an InputObject and a Vector4 that describes the device's current rotation vector. This is fired with an InputObject, which has type Enum.InputType.Gyroscope, and position that shows total rotation in each local device axis. The delta property describes the amount of rotation that last happened. The Vector4 is the device's current quaternion rotation in reference to it's default reference frame. This event only fires locally.
+
+
+
+
+
+ -
+
+ Sky
+ 0
+ 28
+
+
+ -
+
+ Motor
+
+ 0
+
+
+ -
+
+ Humanoid
+ 3
+ 9
+
+
-
+
+
-
+
+ MoveTo
+ Attempts to move the Humanoid and it's associated character to 'part'. 'location' is used as an offset from part's origin.
+
+
+ -
+
+ Jump
+
+
+ -
+
+ Sit
+
+
+ -
+
+ TakeDamage
+ Decreases health by the amount. Use this instead of changing health directly to make sure weapons are filtered for things such as ForceField(s).
+
+
+ -
+
+ UnequipTools
+
+ Takes any active gear/tools that the Humanoid is using and puts them into the backpack. This function only works on Humanoids with a corresponding Player.
+
+
+ -
+
+ EquipTool
+
+ Takes a specified tool and equips it to the Humanoid's Character. Tool argument should be of type 'Tool'.
+
+
+
+ -
+
-
+
+ NameOcclusion
+
+ Sets how to display other humanoid names to this humanoid's player. <a href="http://wiki.roblox.com/index.php/NameOcclusion" target="_blank">More info</a>
+
+
+ Health
+ How many hit points the Humanoid has. When this number reaches 0 or goes below 0, the Humanoid's character falls apart and will respawn.
+
+
+ MaxHealth
+ The maximum number of hit points a Humanoid's health can reach. If the Humanoid's health is set over this amount, the health gets set to this value.
+
+
+ TargetPoint
+ The location that the Humanoid is trying to walk to.
+
+
+
+
+ -
+
+ BodyColors
+
+ 0
+
+
+ -
+
+ Shirt
+ 0
+ 43
+
+
+ -
+
+ Pants
+ 0
+ 44
+
+
+ -
+
+ ShirtGraphic
+ 0
+ 40
+
+
+ -
+
+ Skin
+ true
+ 0
+
+
+ -
+
+ DebugSettings
+ false
+ 0
+
+
+ -
+
+ FaceInstance
+ false
+
+
+ -
+
+ GameSettings
+ false
+ 0
+
+
+ -
+
+ GlobalSettings
+ false
+ 0
+
+
+ -
+
+ Item
+ false
+ 0
+
+
+ -
+
+ NetworkPeer
+ false
+
+
+ -
+
+ NetworkSettings
+ false
+ 0
+
+
+ -
+
+ PVInstance
+ false
+
+
-
+
-
+
+ CoordinateFrame
+ true
+ Deprecated. Use CFrame instead
+
+
+
+
+ -
+
+ RenderSettings
+ false
+ 0
+
+
+ -
+
+ RootInstance
+ false
+
+
+ -
+
+ ServiceProvider
+ false
+
+
-
+
-
+
+ service
+ true
+ Use GetService() instead
+
+
+
+
+ -
+
+ ProfilingItem
+ false
+
+
+ -
+
+ NetworkMarker
+ false
+
+
+
+ -
+
+ Hopper
+ true
+ Use StarterPack instead
+ 0
+
+
+
+ -
+
+ Instance
+ false
+
+
+
-
+
-
+
+ Archivable
+ Determines whether or not an Instance can be saved when the game closes/attempts to save the game. Note: this only applies to games that use Data Persistence, or Personal Build Servers.
+
+
+ -
+
+ ClassName
+ The string name of this Instance's most derived class.
+
+
+ -
+
+ Parent
+ The Instance that is directly above this Instance in the tree.
+
+
+
+
+ -
+
+
-
+
+ GetDebugId
+ false
+ This function is for internal testing. Don't use in production code
+
+
+ -
+
+ Clone
+ Returns a copy of this Object and all its children. The copy's Parent is nil
+
+
+ -
+
+ clone
+ true
+ Use Clone() instead
+
+
+ -
+
+ isA
+ true
+ Use IsA() instead
+
+
+ -
+
+ IsA
+ Returns a boolean if this Instance is of type 'className' or a is a subclass of type 'className'. If 'className' is not a valid class type in ROBLOX, this function will always return false. <a href="http://wiki.roblox.com/index.php/IsA" target="_blank">More info</a>
+
+
+ -
+
+ FindFirstChild
+ Returns the first child of this Instance that matches the first argument 'name'. The second argument 'recursive' is an optional boolean (defaults to false) that will force the call to traverse down thru all of this Instance's descendants until it finds an object with a name that matches the 'name' argument. The function will return nil if no Instance is found.
+
+
+ -
+
+ GetFullName
+ Returns a string that shows the path from the root node (DataModel) to this Instance. This string does not include the root node (DataModel).
+
+
+ -
+
+ children
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ getChildren
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ GetChildren
+ Returns a read-only table of this Object's children
+
+
+ -
+
+ GetDescendants
+ Returns a ready-only table of this Object's descendants
+
+
+ -
+
+ Remove
+ Deprecated. Use ClearAllChildren() to get rid of all child objects, or Destroy() to invalidate this object and its descendants
+ true
+
+
+ -
+
+ remove
+ true
+ Use Remove() instead
+
+
+ -
+
+ ClearAllChildren
+ Removes all children (but not this object) from the workspace.
+
+
+ -
+
+ Destroy
+ Removes object and all of its children from the workspace. Disconnects object and all children from open connections. Object and children may not be usable after calling Destroy.
+
+
+ -
+
+ findFirstChild
+ true
+ Use FindFirstChild() instead
+
+
+
+ -
+
+
-
+
+ AncestryChanged
+ Fired when any of this object's ancestors change. First argument 'child' is the object whose parent changed. Second argument 'parent' is the first argument's new parent.
+
+
+ -
+
+ DescendantAdded
+ Fired after an Instance is parented to this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ DescendantRemoving
+ Fired after an Instance is unparented from this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ Changed
+ Fired after a property changes value. The property argument is the name of the property
+
+
+
+
+
+ -
+
+ BodyGyro
+ Attempts to maintain a fixed orientation of its parent Part
+ 14
+ 14
+
+
-
+
+
-
+
+ MaxTorque
+ The maximum torque that will be exerted on the Part
+
+
+ -
+
+ maxTorque
+ true
+ Use MaxTorque instead
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power continually applied to this force
+
+
+ -
+
+ CFrame
+ The cframe that this force is trying to orient its parent Part to. Note: this force only uses the rotation of the cframe, not the position.
+
+
+ -
+
+ cframe
+ true
+ Use CFrame instead
+
+
+
+
+ -
+
+ BodyPosition
+ 14
+ 14
+
+
-
+
+
-
+
+ MaxForce
+ The maximum force that will be exerted on the Part
+
+
+ -
+
+ maxForce
+ true
+ Use MaxForce instead
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power factor continually applied to this force
+
+
+ -
+
+ Position
+ The Vector3 that this force is trying to position its parent Part to.
+
+
+ -
+
+ position
+ true
+ Use position instead
+
+
+
+
+ -
+
+ RocketPropulsion
+
+ 14
+ 14
+ A propulsion system that mimics a rocket
+
+
+ -
+
+ BodyVelocity
+ 14
+ 14
+
+
-
+
-
+
+ MaxForce
+ The maximum force that will be exerted on the Part in each axis
+
+
+ -
+
+ maxForce
+ true
+ Use MaxForce instead
+
+
+ -
+
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+
+ -
+
+ Velocity
+ The velocity this system tries to achieve. How quickly the system reaches this velocity (if ever) is defined by P.
+
+
+ -
+
+ velocity
+ true
+ Use Velocity instead
+
+
+
+
+ -
+
+ BodyAngularVelocity
+ 14
+ 14
+
+
-
+
-
+ MaxTorque
+ The maximum torque that will be exerted on the Part in each axis
+
+ -
+ maxTorque
+ true
+ Use MaxTorque instead
+
+ -
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+ -
+ AngularVelocity
+ The rotational velocity this system tries to achieve. How quickly the system reaches this velocity is defined by P.
+
+ -
+ angularVelocity
+ true
+ Use AngularVelocity instead
+
+
+
+ -
+
+ BodyForce
+ 14
+ 14
+ When parented to a physical part, BodyForce will continually exert a force upon its parent object.
+
+
-
+
-
+ Force
+ The continual force exerted on an object, defined in each axis.
+
+ -
+ force
+ true
+ Use Force instead
+
+
+
+ -
+
+ BodyThrust
+ 14
+ 14
+
+
-
+
+
-
+
+ Force
+ The power continually applied to this force
+
+
+ -
+
+ force
+ true
+ Use Force instead
+
+
+ -
+
+ Location
+ The Vector3 location of where to apply the force to.
+
+
+ -
+
+ location
+ true
+ Use Location instead
+
+
+
+
+ -
+
+ Hole
+ true
+ 0
+
+
+ -
+
+ Feature
+ 0
+
+
+
+ -
+
+ Teams
+ This Service-level object is the container for all Team objects in a level. A map that supports team games must have a Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 14
+ 23
+
+
+
+ -
+
+ Team
+ The Team class is used to represent a faction in a team game. The only valid location for a Team object is under the Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 1
+ 24
+
+
+ -
+
+ SpawnLocation
+ 3
+ 25
+
+
+ -
+
+ NetworkClient
+ 3
+ 16
+
+
+ -
+
+ NetworkServer
+ 3
+ 15
+
+
+
+ -
+
+ Script
+ 3
+ 6
+
+
-
+
+
-
+
+ LinkedScript
+
+ This property is under development. Do not use
+
+
+
+
+
+ -
+
+ LocalScript
+ 4
+ 18
+ A script that runs on clients, NOT servers. LocalScripts can only run when parented under the PlayerGui currently.
+
+
+
+ -
+
+ NetworkReplicator
+ 3
+ 29
+
+
+
+ -
+
+ Model
+ 10
+ 2
+ A construct used to group Parts and other objects together, also allows manipulation of multiple objects.
+
+
-
+
-
+
+ BreakJoints
+ Breaks all surface joints contained within
+
+
+ -
+
+ GetModelCFrame
+ Returns a CFrame that has position of the centroid of all Parts in the Model. The rotation matrix is either the rotation matrix of the user-defined PrimaryPart, or if not specified then a part in the Model chosen by the engine.
+
+
+ -
+
+ GetModelSize
+ Returns a Vector3 that is union of the extents of all Parts in the model.
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints between all touching Parts contrained within the model. Technically, this function calls MakeJoints() on all Parts inside the model.
+
+
+ -
+
+ MoveTo
+ Moves the centroid of the Model to the specified location, respecting all relative distances between parts in the model.
+
+
+ -
+
+ ResetOrientationToIdentity
+ Rotates all parts in the model to the orientation that was set using SetIdentityOrientation(). If this function has never been called, rotation is reset to GetModelCFrame()'s rotation.
+
+
+ -
+
+ SetIdentityOrientation
+ Takes the current rotation matrix of the model and stores it as the model's identity matrix. The rotation is applied when ResetOrientationToIdentity() is called.
+
+
+ -
+
+ TranslateBy
+ Similar to MoveTo(), except instead of moving to an explicit location, we use the model's current CFrame location and offset it.
+
+
+ -
+
+ GetPrimaryPartCFrame
+ Returns the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error.
+
+
+ -
+
+ SetPrimaryPartCFrame
+ Sets the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error. This also sets the cframe of all descendant Parts relative to the cframe change to PrimaryPart.
+
+
+ -
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+ -
+
-
+
+ PrimaryPart
+ A Part that serves as a reference for the Model's CFrame. Used in conjunction with GetModelPrimaryPartCFrame and SetModelPrimaryPartCFrame. Use this to rotate/translate all Parts relative to the PrimaryPart.
+
+
+
+
+
+ -
+
+ Status
+ true
+ 10
+ 2
+
+
-
+
-
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+
+
+ -
+
+ DataModel
+
+
+
-
+
+
+
-
+
+ Workspace
+
+
+ -
+
+ workspace
+ true
+ Deprecated. Use Workspace
+
+
+ -
+
+ ShowMouse
+ true
+ Deprecated. Use Workspace.IsMouseCursorVisible
+
+
+ -
+
+ IsLoaded
+ Returns true if the game has finished loading, false otherwise. Check this before listening to the Loaded signal to ensure a script knows when a game finishes loading.
+
+
+
+
+ -
+
-
+
+ Loaded
+ Fires when the game finishes loading. Use this to know when to remove your custom loading gui. It is best to check IsLoaded() before connecting to this event, as the game may load before the event is connected to.
+
+
+
+
+ -
+
-
+
+ get
+ true
+ Use GetObjects() instead
+
+
+ -
+
+ SetPlaceID
+ true
+ Use SetPlaceId() instead
+
+
+ -
+
+ SetCreatorID
+ true
+ Use SetCreatorId() instead
+
+
+
+
+
+ -
+
+ HopperBin
+ true
+ 24
+ 22
+
+
+
+ -
+
+ Camera
+ 5
+ 5
+
+
-
+
-
+
+ CameraSubject
+ Where the Camera's focus is. Any rotation of the camera will be about this subject.
+
+
+ -
+
+ CameraType
+ Defines how the camera will behave. <a href="http://wiki.roblox.com/index.php/CameraType" target="_blank">More info</a>
+
+
+ -
+
+ CoordinateFrame
+ true
+ The current position and rotation of the Camera. For most CameraTypes, the rotation is set such that the CoordinateFrame lookVector is pointing at the Focus.
+
+
+ -
+
+ CFrame
+ The current position and rotation of the Camera. For most CameraTypes, the rotation is set such that the CoordinateFrame lookVector is pointing at the Focus.
+
+
+ -
+
+ FieldOfView
+ The current angle, or width, of what the camera can see. Current acceptable values are from 20 degrees to 80.
+
+
+ -
+
+ Focus
+ The current CoordinateFrame that the camera is looking at. Note: it is not always guaranteed that the camera is always looking here.
+
+
+ -
+
+ ViewportSize
+ Holds the x,y screen resolution of the viewport the camera is presenting (note: this can differ from the AbsoluteSize property of a full screen gui).
+
+
+
+ -
+
-
+
+ GetRoll
+ Returns the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+ -
+
+ WorldToScreenPoint
+ Takes a 3D position in the world and projects it onto x,y coordinates of screen space. Returns two values, first is a Vector3 that has x,y position and z position which is distance from camera (negative if behind camera, positive if in front). Second return value is a boolean indicating if the first argument is an on-screen coordinate.
+
+
+ -
+
+ ScreenPointToRay
+ Takes a 2D screen position and produces a Ray object to be used for 3D raycasting. Input is x,y screen coordinates, and a (optional, defaults to 0) z position which sets how far in the camera look vector to start the ray origin.
+
+
+ -
+
+ ViewportPointToRay
+ Same as ScreenPointToRay, except no GUI offsets are taken into account. Useful for things like casting a ray from the middle of the Camera.ViewportSize
+
+
+ -
+
+ WorldToViewportPoint
+ Same as WorldToScreenPoint, except no GUI offsets are taken into account.
+
+
+ -
+
+ SetRoll
+ Sets the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+
+
+
+ -
+
+ Players
+ 2
+ 21
+
+
-
+
-
+
+ CharacterAutoLoads
+ true
+ Set to true, when a player joins a game, they get a character automatically, as well as when they die. When set to false, characters do not auto load and will only load in using Player:LoadCharacter().
+
+
+
+ -
+
-
+
+ players
+ true
+ Use GetPlayers() instead
+
+
+
+
+
+ -
+
+ ReplicatedStorage
+ 3
+ 70
+ A container whose contents are replicated to all clients and the server.
+
+
+
+ -
+
+ RobloxReplicatedStorage
+ false
+
+
+
+ -
+
+ ReplicatedFirst
+ 3
+ 70
+ A container whose contents are replicated to all clients (but not back to the server) first before anything else. Useful for creating loading guis, tutorials, etc.
+
+
-
+
-
+
+ RemoveRobloxLoadingScreen
+ Removes the default Roblox loading screen from view. Call this when you are ready to either show your own loading gui, or when the game is ready to play.
+
+
+
+
+
+ -
+
+ ServerStorage
+ 3
+ 69
+ A container whose contents are only on the server.
+
+
+
+ -
+
+ ServerScriptService
+ 3
+ 71
+ A container whose contents should be scripts. Scripts that are added to the container are run on the server.
+
+
+
+ -
+
+ Lighting
+ 3
+ 13
+ Responsible for all lighting aspects of the world (affects how things are rendered).
+
+
-
+
-
+
+ GetMinutesAfterMidnight
+ The number of minutes that the current time is past midnight. If currently at midnight, returns 0. Will return decimal values if not at an exact minute.
+
+
+ -
+
+ GetMoonDirection
+ Returns the lookVector (Vector3) of the moon. If this lookVector was used in a CFrame, the Part would face the moon.
+
+
+ -
+
+ GetMoonPhase
+ Currently always returns 0.75. MoonPhase cannot be edited.
+
+
+ -
+
+ GetSunDirection
+ Returns the lookVector (Vector3) of the sun. If this lookVector was used in a CFrame, the Part would face the moon.
+
+
+ -
+
+ SetMinutesAfterMidnight
+ Sets the time to be a certain number of minutes after midnight. This works with integer and decimal values.
+
+
+
+ -
+
-
+
+ Ambient
+ The hue of the global lighting. Changing this changes the color tint of all objects in the Workspace.
+
+
+ -
+
+ Brightness
+ How much global light each Part in the Workspace receives. Standard range is 0 to 1 (0 being little light), but can be increased all the way to 5 (colors start to be appear very different at this value).
+
+
+ -
+
+ ColorShift_Bottom
+ The hue of global lighting on the bottom surfaces of an object.
+
+
+ -
+
+ ColorShift_Top
+ The hue of global lighting on the top surfaces of an object.
+
+
+ -
+
+ FogColor
+ A Color3 value that changes the hue of distance fog.
+
+
+ -
+
+ FogEnd
+ The distance at which fog completely blocks your vision. This distance is relative to the camera position. Units are in studs
+
+
+ -
+
+ FogStart
+ The distance at which the fog gradient begins. This distance is relative to the camera position. Units are in studs.
+
+
+ -
+
+ GeographicLatitude
+ The latitude position the level is placed at. This affects sun position. <a href="http://wiki.roblox.com/index.php/GeographicLatitude" target="_blank">More info</a>
+
+
+ -
+
+ GlobalShadows
+ Flag enabling shadows from sun and moon in the place
+
+
+ -
+
+ OutdoorAmbient
+ Effective ambient value for outdoors, effectively shadow color outdoors (requires GlobalShadows enabled)
+
+
+ -
+
+ Outlines
+ Flag enabling or disabling outlines on parts and terrain
+
+
+ -
+
+ ShadowColor
+ Color the shadows appear as. Shadows are drawn mostly for characters, but depending on the lighting will also show for Parts in the Workspace. Rendering settings can also affect if shadows are drawn.
+
+
+ -
+
+ TimeOfDay
+ A string that represent the current time of day. Time is in 24-hour clock format "XX::YY:ZZ", where X is hour, Y is minute, and Z is seconds.
+
+
+
+ -
+
-
+
+ LightingChanged
+ Fired whenever a property of Lighting is changed, or a skybox is added or removed. Skyboxes are of type 'Sky' and should be parented directly to lighting.
+
+
+
+
+
+ -
+
+ TestService
+ 100
+ 68
+
+
+
+ -
+
+ DebuggerManager
+
+
+
+
+
+ -
+
+ ScriptDebugger
+
+
+
+
+
+ -
+
+ DebuggerBreakpoint
+
+
+
+
+
+ -
+
+ DebuggerWatch
+
+
+
+
+
+ -
+
+ Debris
+ -1
+ 30
+ A service that provides utility in cleaning up objects
+
+
-
+
-
+
+ addItem
+ true
+ Use AddItem() instead
+
+
+ -
+
+ AddItem
+ Adds an Instance into the debris service that will later be destroyed. Second argument 'lifetime' is optional and specifies how long (in seconds) to wait before destroying the item. If no time is specified then the item added will automatically be destroyed in 10 seconds.
+
+
+
+ -
+
-
+
+ MaxItems
+ true
+ Deprecated. No replacement
+
+
+
+
+
+ -
+
+ Accoutrement
+ 0
+ 32
+
+
+
+ -
+
+ Player
+ 1
+ 12
+
+
-
+
+
-
+
+ CharacterAppearance
+ false
+
+
+ -
+
+ CameraMode
+ An enum that describes how a Player's camera is allowed to behave. <a href="http://wiki.roblox.com/index.php/CameraMode" target="_blank">More info</a>.
+
+
+ -
+
+ DataReady
+ Read-only. If true, this Player's persistent data can be loaded, false otherwise. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+
+ -
+
+
-
+
+ LoadCharacter
+ true
+ Loads in a new character for this player. This will replace the player's current character, if they have one. This should be used in conjunction with Players.CharacterAutoLoads to control spawning of characters. This function only works from a server-side script (NOT a LocalScript).
+
+
+ -
+
+ playerFromCharacter
+ true
+ Use GetPlayerFromCharacter() instead
+
+
+ -
+
+ SetUnder13
+ true
+
+
+
+
+ -
+
-
+
+ WaitForDataReady
+ true
+ Yields until the persistent data for this Player is ready to be loaded. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+ -
+
+ GetWebPersonalServerRank
+ true
+
+
+
+
+ -
+
+
-
+
+ Idled
+ Fired periodically after the user has been AFK for a while. Currently this event is only fired for the *local* Player. "time" is the time in seconds that the user has been idle.
+
+
+
+
+
+ -
+
+ Workspace
+ 1
+ 19
+
+
-
+
-
+
+ FindPartsInRegion3
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartsInRegion3WithIgnoreList
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartOnRay
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+ -
+
+ FindPartOnRayWithIgnoreList
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+
+ -
+
-
+
+ PGSPhysicsSolverEnabled
+ Boolean used to enable the experimental physics solver
+
+
+ -
+
+ FallenPartsDestroyHeight
+ Sets the height at which falling characters and parts are destroyed. This property is not scriptable and can only be set in Studio
+
+
+
+
+
+ -
+
+ BasePart
+ A structural class, not creatable
+ -1
+ false
+
+
+
-
+
-
+
+ Color
+ true
+ Deprecated. Use BrickColor instead
+
+
+ -
+
+ CFrame
+ Contains information regarding the Part's position and a matrix that defines the Part's rotation. Can read/write. <a href="http://wiki.roblox.com/index.php/Cframe" target="_blank">More info</a>
+
+
+ -
+
+ CanCollide
+ Determines whether physical interactions with other Parts are respected. If true, will collide and react with physics to other Parts. If false, other parts will pass thru instead of colliding
+
+
+ -
+
+ Anchored
+ Determines whether or not physics acts upon the Part. If true, part stays 'Anchored' in space, not moving regardless of any collision/forces acting upon it. If false, physics works normally on the part.
+
+
+ -
+
+ Elasticity
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will rebound against another. a value of 1 is like a superball, and 0 is like a lead block.
+ 0
+ 1
+
+
+ -
+
+ Friction
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will be able to slide. a value of 1 is no sliding, and 0 is no friction, so infinite sliding.
+ 0
+ 2
+
+
+ -
+
+ Locked
+ Determines whether building tools (in-game and studio) can manipulate this Part. If true, no editing allowed. If false, editing is allowed.
+
+
+ -
+
+ Material
+ Specifies the look and feel the Part should have. Note: this does not define the color the Part is, see BrickColor for that. <a href="http://wiki.roblox.com/index.php/Material" target="_blank">More info</a>
+
+
+ -
+
+ Reflectance
+ Specifies how shiny the Part is. A value of 1 is completely reflective (chrome), while a value of 0 is no reflectance (concrete wall)
+ 0
+ 1
+
+
+ -
+
+ ResizeIncrement
+ Sets the value for the smallest change in size allowable by the Resize(NormalId, int) function.
+
+
+ -
+
+ ResizeableFaces
+ Sets the value for the faces allowed to be resized by the Resize(NormalId, int) function.
+
+
+ -
+
+ Transparency
+ Sets how visible an object is. A value of 1 makes the object invisible, while a value of 0 makes the object opaque.
+ 0
+ 1
+
+
+ -
+
+ Velocity
+ How fast the Part is traveling in studs/second. This property is NOT recommended to be modified directly, unless there is good reason. Otherwise, try using a BodyForce to move a Part.
+
+
+
+
+ -
+
-
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model). This uses the SurfaceTypes defined on the surfaces of parts to create the appropriate welds. <a href="http://wiki.roblox.com/index.php/MakeJoints" target="_blank">More info</a>
+
+
+ -
+
+ BreakJoints
+ Destroys SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model).
+
+
+ -
+
+ GetMass
+ Returns a number that is the mass of this Instance. Mass of a Part is immutable, and is changed only by the size of the Part.
+
+
+ -
+
+ Resize
+ Resizes a Part in the direction of the face defined by 'NormalId', by the amount specified by 'deltaAmount'. If the operation will expand the part to intersect another Instance, the part will not resize at all. Return true if the call is successful, false otherwise.
+
+
+ -
+
+ getMass
+ Use GetMass() instead
+ true
+
+
+
+ -
+
-
+
+ OutfitChanged
+ true
+
+
+ -
+
+ LocalSimulationTouched
+ true
+ Deprecated. Use Touched instead
+
+
+ -
+
+ StoppedTouching
+
+ Deprecated. Use TouchEnded instead
+
+
+ -
+
+ TouchEnded
+ Fired when the part stops touching another part
+
+
+
+
+ -
+
+ Part
+ A plastic building block - the fundamental component of ROBLOX
+ 11
+ 1
+
+
+ -
+
+ TrussPart
+ An extendable building truss
+ 12
+ 1
+
+
+ -
+
+ WedgePart
+ A Wedge Part
+ 12
+ 1
+
+
+ -
+
+ PrismPart
+ A Prism Part
+ false
+ true
+ 12
+ 1
+
+
+ -
+
+ PyramidPart
+ A Pyramid Part
+ false
+ true
+ 12
+ 1
+
+
+ -
+
+ ParallelRampPart
+ A ParallelRamp Part
+ false
+ true
+ 12
+ 1
+
+
+ -
+
+ RightAngleRampPart
+ A RightAngleRamp Part
+ false
+ true
+ 12
+ 1
+
+
+ -
+
+ CornerWedgePart
+ A CornerWedge Part
+ 12
+ 1
+
+
+ -
+
+ PlayerGui
+ A container instance that syncs data between a single player and the server. ScreenGui objects that are placed in this container will be shown to the Player parent only
+ 13
+ 46
+
+
-
+
-
+
+ SelectionImageObject
+ Overrides the default selection adornment (used for gamepads). For best results, this should point to a GuiObject.
+
+
+
+
+ -
+
+ PlayerScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be exectue only when a Player is the parent.
+ 13
+ 78
+
+
+ -
+
+ StarterPlayerScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be copied to new Players on startup.
+ 13
+ 78
+
+
+ -
+
+ StarterCharacterScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be copied to new characters on startup.
+ 13
+ 78
+
+
+
+ -
+
+ GuiMain
+ Deprecated, please use ScreenGui
+ true
+ 14
+ 47
+
+
+
+ -
+
+ ScreenGui
+ The core GUI object on which tools are built. Add Frames/Labels/Buttons to this object to have them rendered as a 2D overlay
+ 14
+ 47
+ StarterGui
+
+
+ -
+
+ FunctionalTest
+ Deprecated. Use TestService instead
+ true
+ 1
+
+
+ -
+
+ BillboardGui
+ A GUI that adorns an object in the 3D world. Add Frames/Labels/Buttons to this object to have them rendered while attached to a 3D object
+ 14
+ 64
+ StarterGui
+
+
+
-
+
-
+
+ Adornee
+ The Object the billboard gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ AlwaysOnTop
+ If true, billboard gui does not get occluded by 3D objects, but always renders on the screen.
+
+
+ -
+
+ Enabled
+ If true, billboard gui will render, otherwise rendering will be skipped.
+
+
+ -
+
+ ExtentsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the extents of the 3d object it is rendering from.
+
+
+ -
+
+ PlayerToHideFrom
+ Specifies a Player that the BillboardGui will not render to.
+
+
+ -
+
+ StudsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the centroid of the 3d object it is rendering from
+
+
+ -
+
+ SizeOffset
+ A Vector2 (x,y) defined in studs that will offset the gui size from it's current size.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the BillboardGui. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>. Relative values are defined as one-to-one with studs.
+
+
+
+
+
+ -
+
+ SurfaceGui
+ tbd
+ 14
+ 64
+ StarterGui
+
+
+
-
+
-
+
+ Adornee
+ The Object the billboard gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ Enabled
+ If true, billboard gui will render, otherwise rendering will be skipped.
+
+
+
+
+
+
+
+ -
+
+ GuiBase2d
+ false
+
+
+
-
+
-
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+
+
+
+ -
+
+ InputObject
+ An object that describes a particular user input, such as mouse movement, touches, keyboard, and more.
+
+
-
+
-
+
+ UserInputType
+ An enum that describes what kind of input this object is describing (mousebutton, touch, etc.). See Enum.UserInputType for more info.
+
+
+ -
+
+ UserInputState
+ An enum that describes what state of a particular input (touch began, touch moved, touch ended, etc.). See Enum.UserInputState for more info.
+
+
+ -
+
+ Position
+ A Vector3 value that describes a positional value of this input. For mouse and touch input, this is the screen position of the mouse/touch, described in the x and y components. For mouse wheel input, the z component describes whether the wheel was moved forward or backward.
+
+
+ -
+
+ KeyCode
+ An enum that describes what kind of input is being pressed. For types of input like Keyboard, this describes what key was pressed. For input like mousebutton, this provides no additional information.
+
+
+
+
+
+ -
+
+ GuiObject
+ false
+
+
+
-
+
-
+
+ TweenPosition
+ Smoothly moves a GuiObject from its current position to 'endPosition'. The only required argument is 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenPosition" target="_blank">More info</a>
+
+
+ -
+
+ TweenSize
+ Smoothly translates a GuiObject's current size to 'endSize'. The only required argument is 'endSize'. <a href="http://wiki.roblox.com/index.php/TweenSize" target="_blank">More info</a>
+
+
+ -
+
+ TweenSizeAndPosition
+ Smoothly translates a GuiObject's current size to 'endSize', and also smoothly translates the GuiObject's current position to 'endPosition'. The only required arguments are 'endSize' and 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenSizeAndPosition" target="_blank">More info</a>
+
+
+
+
+ -
+
-
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ BackgroundColor3
+ A Color3 value that specifies the background color for the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BackgroundTransparency
+ A number value that specifies how transparent the background of the GuiObject is. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+ 0
+ 1
+
+
+ -
+
+ BorderColor3
+ A Color3 value that specifies the color of the outline of the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BorderSizePixel
+ A number value that specifies the thickness (in pixels) of the outline of the GuiObject. Currently this value can only be set to either 0 or 1, any other number has no effect. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ ClipsDescendants
+ If set to true, any descendants of this GuiObject will only render if contained within it's borders. If set to false, all descendants will render regardless of position.
+
+
+ -
+
+ Draggable
+ If true, allows a GuiObject to be dragged by the user's mouse. The events 'DragBegin' and 'DragStopped' are fired when the appropriate action happens, and only will fire on Draggable=true GuiObjects.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the GuiObject on screen in both absolute and relative coordinates. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ Position
+ A UDim2 value describing the position of the top-left corner of the GuiObject on screen. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ SizeConstraint
+ The direction(s) that an object can be resized in. <a href="http://wiki.roblox.com/index.php/SizeConstraint" target="_blank">More info</a>.
+
+
+ -
+
+ ZIndex
+ Describes the ordering in which overlapping GuiObjects will be drawn. A value of 1 is drawn first, while higher values are drawn in ascending order (each value draws over the last).
+
+
+ -
+
+ BackgroundColor
+ true
+ Deprecated. Use BackgroundColor3 instead
+
+
+ -
+
+ BorderColor
+ true
+ Deprecated. Use BorderColor3 instead
+
+
+ -
+
+ SelectionImageObject
+ Overrides the default selection adornment (used for gamepads). For best results, this should point to a GuiObject.
+
+
+
+
+ -
+
-
+
+ DragBegin
+ Fired when a GuiObject with Draggable set to true starts to be dragged. 'InitialPosition' is a UDim2 value of the position of the GuiObject before any drag operation began.
+
+
+ -
+
+ DragStopped
+ Always fired after a DragBegin event, DragStopped is fired when the user releases the mouse button causing a drag operation on the GuiObject. Arguments 'x', and 'y' specify the top-left absolute position of the GuiObject when the event is fired.
+
+
+ -
+
+ MouseEnter
+ Fired when the mouse enters a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseLeave
+ Fired when the mouse leaves a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseMoved
+ Fired when the mouse is inside a GuiObject and moves, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+
+ -
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+
+
+
+
+ -
+
+ Frame
+ A container object used to layout other GUI objects
+ 15
+ 48
+ StarterGui
+
+
-
+
-
+
+ Style
+ Determines how a frame will look. Uses Enum.FrameStyle. <a href="http://wiki.roblox.com/index.php?title=API:Enum/FrameStyle" target="_blank">More info</a>
+
+
+
+
+ -
+
+ ScrollingFrame
+ A container object used to layout other GUI objects, and allows for scrolling.
+ 15
+ 48
+ StarterGui
+
+
-
+
-
+
+ ScrollingEnabled
+ Determines whether or not scrolling is allowed on this frame. If turned off, no scroll bars will be rendered.
+
+
+ -
+
+ CanvasSize
+ Determines the size of the area that is scrollable. The UDim2 is calculated using the parent gui's size, similar to the regular Size property on gui objects.
+
+
+ -
+
+ CanvasPosition
+ The absolute position the scroll frame is in respect to the canvas size. The minimum this can be set to is (0,0), while the max is the absolute canvas size - AbsoluteWindowSize.
+
+
+ -
+
+ AbsoluteWindowSize
+ The size in pixels of the frame, without the scrollbars.
+
+
+ -
+
+ ScrollBarThickness
+ How thick the scroll bar appears. This applies to both the horizontal and vertical scroll bars. Can be set to 0 for no bars render.
+
+
+ -
+
+ TopImage
+ The "Up" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "left" image on the horizontal scroll bar.
+
+
+ -
+
+ MidImage
+ The "Middle" image on the vertical scrollbar. Size of this can vary in the y direction, but is always set at ScrollBarThickness in x direction. This is also used as the "mid" image on the horizontal scroll bar.
+
+
+ -
+
+ BottomImage
+ The "Down" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "right" image on the horizontal scroll bar.
+
+
+
+
+ -
+
+ ImageLabel
+ A GUI object containing an Image
+ 18
+ 49
+ StarterGui
+
+
-
+
-
+
+ Image
+ Specifies the id of the texture to display. <a href="http://wiki.roblox.com/index.php?title=API:Class/ImageLabel/Image" target="_blank">More info</a>
+
+
+ -
+
+ ScaleType
+ Specifies how an image should be displayed. See ScaleType for more info.
+
+
+ -
+
+ SliceCenter
+ If ScaleType is set to Slice, this Rect is used to specify the central part of the image. Everything outside of this is considered to be the border.
+
+
+
+
+ -
+
+ TextLabel
+ A GUI object containing text
+ 19
+ 50
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextButton
+ A GUI button containing text
+ 17
+ 51
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextBox
+ A text entry box
+ 17
+ 51
+ StarterGui
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ GuiButton
+ A GUI button containing an Image
+ false
+ 16
+ 52
+
+
-
+
-
+
+ AutoButtonColor
+ Determines whether a button changes color automatically when reacting to mouse events.
+
+
+ -
+
+ Modal
+ Allows the mouse to be free in first person mode. If a button with this property set to true is visible, the mouse is 'free' in first person mode.
+
+
+ -
+
+ Style
+ Determines how a button will look, including mouse event states. Uses Enum.ButtonStyle. <a href="http://wiki.roblox.com/index.php?title=API:Class/GuiButton/Style" target="_blank">More info</a>
+
+
+
+ -
+
-
+
+ MouseButton1Click
+ Fired when the mouse is over the button, and the mouse down and up events fire without the mouse leaving the button.
+
+
+ -
+
+ MouseButton1Down
+ Fired when the mouse button is pushed down on a button.
+
+
+ -
+
+ MouseButton1Up
+ Fired when the mouse button is released on a button.
+
+
+ -
+
+ MouseButton2Click
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Down
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Up
+ This function currently does not work :(
+
+
+
+
+
+ -
+
+ ImageButton
+ A GUI button containing an Image
+ 16
+ 52
+ StarterGui
+
+
-
+
-
+
+ Image
+ Specifies the asset id of the texture to display. <a href="http://wiki.roblox.com/index.php?title=API:Class/ImageButton/Image" target="_blank">More info</a>
+
+
+ -
+
+ ScaleType
+ Specifies how an image should be displayed. See ScaleType for more info.
+
+
+ -
+
+ SliceCenter
+ If ScaleType is set to Slice, this Rect is used to specify the central part of the image. Everything outside of this is considered to be the border.
+
+
+
+
+ -
+
+ Handles
+ A 3D GUI object to represent draggable handles
+
+ 19
+ 53
+
+
+ -
+
+ ArcHandles
+ A 3D GUI object to represent draggable arc handles
+
+ 20
+ 56
+
+
+ -
+
+ SelectionBox
+ A 3D GUI object to represent the visible selection around an object
+ 21
+ 54
+
+
+ -
+
+ SelectionSphere
+ A 3D GUI object to represent the visible selection around an object
+ 21
+ 54
+
+
+ -
+
+ SurfaceSelection
+ A 3D GUI object to represent the visible selection around a face of an object
+ 21
+ 55
+
+
+ -
+
+ Configuration
+ An object that can be placed under parts to hold Value objects that represent that part's configuration
+ 22
+ 58
+
+
+ -
+
+ Folder
+ An object that can be created to hold and organize objects
+ 22
+ 77
+
+
+ -
+
+ SelectionPartLasso
+ true
+ A visual line drawn representation between two part objects
+ 22
+ 57
+
+
+ -
+
+ SelectionPointLasso
+ true
+ A visual line drawn representation between two positions
+ 22
+ 57
+
+
+ -
+
+ PartPairLasso
+ A visual line drawn representation between two parts.
+ 22
+ 57
+
+
+ -
+
+ Pose
+ The pose of a joint relative to it's parent part in a keyframe
+ 22
+ 60
+
+
+ -
+
+ Keyframe
+ One keyframe of an animation
+ 22
+ 60
+
+
+ -
+
+ Animation
+ Represents a linked animation object, containing keyframes and poses.
+ 22
+ 60
+
+
+ -
+
+ AnimationTrack
+ Returned by a call to LoadAnimation. Controls the playback of an animation on a Humanoid.
+ 22
+ 60
+
+
-
+
-
+
+ Stopped
+ true
+ This event is never raised
+
+
+
+
+ -
+
+ AnimationController
+ Allows animations to be played on joints of the parent object.
+ 22
+ 60
+
+
+ -
+
+ CharacterMesh
+ Modifies the appearance of a body part.
+ 22
+ 60
+
+
+ -
+
+ Dialog
+ An object used to make dialog trees to converse with players
+ 22
+ 62
+
+
+ -
+
+ DialogChoice
+ An object used to make dialog trees to converse with players
+ 22
+ 63
+
+
+ -
+
+ MeshPart
+ Parts
+ true
+ true
+ 105
+ 73
+ Model
+
+
+ -
+
+ UnionOperation
+ A UnionOperation is a union of multiple parts
+ true
+ false
+ 0
+ 73
+
+
-
+
-
+
+ UsePartColor
+ Override the colors of the mesh with the part color.
+
+
+
+
+ -
+
+ NegateOperation
+ A NegateOperation can be used to create holes in other parts
+ true
+ false
+ 0
+ 72
+
+
-
+
-
+
+ UsePartColor
+ Override the colors of the mesh with the part color.
+
+
+
+
+ -
+
+ Terrain
+ Object representing a high performance bounded grid of static 4x4 parts
+ true
+ 0
+ 65
+
+
-
+
-
+
+ GetCell
+ Returns CellMaterial, CellBlock, CellOrientation
+
+
+ -
+
+ GetWaterCell
+
+ Returns hasAnyWater, WaterForce, WaterDirection
+
+
+ -
+
+ SetWaterCell
+
+
+
+
+
+ -
+
+ PointLight
+ Makes the parent part emit light in a spherical shape
+ 3
+ 13
+
+
+ -
+
+ SpotLight
+ Makes the parent part emit light in a conical shape
+ 3
+ 13
+
+
+ -
+
+ SurfaceLight
+ Makes the parent part emit light in a frustum shape from rectangle defined by part
+ 3
+ 13
+
+
+ -
+
+ RemoteFunction
+ Allow functions defined in one script to be called by another script across client/server boundary
+ 4
+ 74
+
+
+ -
+
+ RemoteEvent
+ Allow events defined in one script to be subscribed to by another script across client/server boundary
+ 5
+ 75
+
+
+ -
+
+ TerrainRegion
+ Object representing a snapshot of the region of terrain
+ true
+ 0
+ 65
+
+
+ -
+
+ ModuleScript
+ A script fragment. Only runs when another script uses require() on it.
+ 5
+ 76
+
+
+
+ -
+
+
-
+
+ Material
+
+
-
+
+ Air
+ false
+
+
+ -
+
+ Water
+ false
+
+
+ -
+
+ Rock
+ false
+
+
+ -
+
+ Glacier
+ false
+
+
+ -
+
+ Snow
+ false
+
+
+ -
+
+ Sandstone
+ false
+
+
+ -
+
+ Mud
+ false
+
+
+ -
+
+ Basalt
+ false
+
+
+ -
+
+ Ground
+ false
+
+
+ -
+
+ CrackedLava
+ false
+
+
+
+ -
+
+ Status
+ true
+
+
-
+
+ Poison
+ true
+
+
+ -
+
+ Confusion
+ true
+
+
+
+
+
diff --git a/Client2016/SDL2.dll b/Client2016/SDL2.dll
new file mode 100644
index 0000000..b118189
Binary files /dev/null and b/Client2016/SDL2.dll differ
diff --git a/Client2016/SyntaxPlayerBeta.exe b/Client2016/SyntaxPlayerBeta.exe
new file mode 100644
index 0000000..a8cd985
Binary files /dev/null and b/Client2016/SyntaxPlayerBeta.exe differ
diff --git a/Client2016/VMProtectSDK64.dll b/Client2016/VMProtectSDK64.dll
new file mode 100644
index 0000000..4f2a936
Binary files /dev/null and b/Client2016/VMProtectSDK64.dll differ
diff --git a/Client2016/content/fonts/Arial.font b/Client2016/content/fonts/Arial.font
new file mode 100644
index 0000000..e223b3d
Binary files /dev/null and b/Client2016/content/fonts/Arial.font differ
diff --git a/Client2016/content/fonts/ArialBold.font b/Client2016/content/fonts/ArialBold.font
new file mode 100644
index 0000000..eda0976
Binary files /dev/null and b/Client2016/content/fonts/ArialBold.font differ
diff --git a/Client2016/content/fonts/CompositExtraSlot0.mesh b/Client2016/content/fonts/CompositExtraSlot0.mesh
new file mode 100644
index 0000000..87b9d85
Binary files /dev/null and b/Client2016/content/fonts/CompositExtraSlot0.mesh differ
diff --git a/Client2016/content/fonts/CompositExtraSlot1.mesh b/Client2016/content/fonts/CompositExtraSlot1.mesh
new file mode 100644
index 0000000..6874c5e
Binary files /dev/null and b/Client2016/content/fonts/CompositExtraSlot1.mesh differ
diff --git a/Client2016/content/fonts/CompositExtraSlot2.mesh b/Client2016/content/fonts/CompositExtraSlot2.mesh
new file mode 100644
index 0000000..423f198
Binary files /dev/null and b/Client2016/content/fonts/CompositExtraSlot2.mesh differ
diff --git a/Client2016/content/fonts/CompositExtraSlot3.mesh b/Client2016/content/fonts/CompositExtraSlot3.mesh
new file mode 100644
index 0000000..de05ced
Binary files /dev/null and b/Client2016/content/fonts/CompositExtraSlot3.mesh differ
diff --git a/Client2016/content/fonts/CompositExtraSlot4.mesh b/Client2016/content/fonts/CompositExtraSlot4.mesh
new file mode 100644
index 0000000..ff9cb62
Binary files /dev/null and b/Client2016/content/fonts/CompositExtraSlot4.mesh differ
diff --git a/Client2016/content/fonts/CompositFullAtlasBaseTexture.mesh b/Client2016/content/fonts/CompositFullAtlasBaseTexture.mesh
new file mode 100644
index 0000000..b7e6595
Binary files /dev/null and b/Client2016/content/fonts/CompositFullAtlasBaseTexture.mesh differ
diff --git a/Client2016/content/fonts/CompositFullAtlasOverlayTexture.mesh b/Client2016/content/fonts/CompositFullAtlasOverlayTexture.mesh
new file mode 100644
index 0000000..eda1938
Binary files /dev/null and b/Client2016/content/fonts/CompositFullAtlasOverlayTexture.mesh differ
diff --git a/Client2016/content/fonts/CompositLeftArmBase.mesh b/Client2016/content/fonts/CompositLeftArmBase.mesh
new file mode 100644
index 0000000..5bcc4ae
Binary files /dev/null and b/Client2016/content/fonts/CompositLeftArmBase.mesh differ
diff --git a/Client2016/content/fonts/CompositLeftLegBase.mesh b/Client2016/content/fonts/CompositLeftLegBase.mesh
new file mode 100644
index 0000000..f4712ce
Binary files /dev/null and b/Client2016/content/fonts/CompositLeftLegBase.mesh differ
diff --git a/Client2016/content/fonts/CompositPantsTemplate.mesh b/Client2016/content/fonts/CompositPantsTemplate.mesh
new file mode 100644
index 0000000..756ee03
Binary files /dev/null and b/Client2016/content/fonts/CompositPantsTemplate.mesh differ
diff --git a/Client2016/content/fonts/CompositRightArmBase.mesh b/Client2016/content/fonts/CompositRightArmBase.mesh
new file mode 100644
index 0000000..02f2721
Binary files /dev/null and b/Client2016/content/fonts/CompositRightArmBase.mesh differ
diff --git a/Client2016/content/fonts/CompositRightLegBase.mesh b/Client2016/content/fonts/CompositRightLegBase.mesh
new file mode 100644
index 0000000..b287939
Binary files /dev/null and b/Client2016/content/fonts/CompositRightLegBase.mesh differ
diff --git a/Client2016/content/fonts/CompositShirtTemplate.mesh b/Client2016/content/fonts/CompositShirtTemplate.mesh
new file mode 100644
index 0000000..75487e1
Binary files /dev/null and b/Client2016/content/fonts/CompositShirtTemplate.mesh differ
diff --git a/Client2016/content/fonts/CompositTShirt.mesh b/Client2016/content/fonts/CompositTShirt.mesh
new file mode 100644
index 0000000..b39b8ac
Binary files /dev/null and b/Client2016/content/fonts/CompositTShirt.mesh differ
diff --git a/Client2016/content/fonts/CompositTorsoBase.mesh b/Client2016/content/fonts/CompositTorsoBase.mesh
new file mode 100644
index 0000000..0388bde
Binary files /dev/null and b/Client2016/content/fonts/CompositTorsoBase.mesh differ
diff --git a/Client2016/content/fonts/LoadingScript.lua b/Client2016/content/fonts/LoadingScript.lua
new file mode 100644
index 0000000..2e03d7f
--- /dev/null
+++ b/Client2016/content/fonts/LoadingScript.lua
@@ -0,0 +1,815 @@
+--rbxsig%hm7SbDaf0GHizpUYxb6qQAHuUU7LfsWX8bgPnc64hv1MnSJFX+Komih+acv/5vqLxpzxHNtvBCnuAwN6l63fYukZ0Yat7mDBHBx0w0CPTaWSCs2P5WDx/W7P+L8AkqpaowXKgCKST9VBErgwqTlUySsi0r9+HfExO+cl3h2lXig=%
+--rbxassetid%158948138%
+-- Creates the generic "ROBLOX" loading screen on startup
+-- Written by ArceusInator & Ben Tkacheff, 2014
+--
+
+-- Constants
+local PLACEID = Game.PlaceId
+
+local MPS = Game:GetService 'MarketplaceService'
+local CP = Game:GetService 'ContentProvider'
+
+local COLORS = {
+ BLACK = Color3.new(0, 0, 0),
+ DARK = Color3.new(35/255, 35/255, 38/255),
+ DARKMED = Color3.new(61/255, 61/255, 67/255),
+ DARKMED2 = Color3.new(75/255, 76/255, 85/255),
+ MED = Color3.new(118/255, 118/255, 129/255),
+ LIGHTMED = Color3.new(190/255, 192/255, 212/255),
+ LIGHT = Color3.new(217/255, 218/255, 231/255),
+ ERROR = Color3.new(253/255,68/255,72/255)
+}
+
+local IMAGES = {
+ BACKGROUND_THUMBNAIL_VIGNETTE = 'rbxasset://textures/loading/loadingvignette.png',
+ ROBLOX_LOGO_256 = 'rbxasset://textures/loading/robloxlogo.png',
+ GAME_THUMBNAIL = 'http://www.roblox.com/Thumbs/Asset.ashx?format=png&width=420&height=230&assetId=',
+ GAME_BACKGROUND = 'rbxasset://textures/loading/loadingTexture.png'
+}
+
+local VALID_TEXT_SIZES = {
+ 12,
+ 14,
+ 18,
+ 24,
+ 36,
+ 48
+}
+
+--
+-- Variables
+local GameAssetInfo -- loaded by InfoProvider:LoadAssets()
+local currScreenGui = nil
+local renderSteppedConnection = nil
+
+--
+-- Utility functions
+local create = function(className, defaultParent)
+ return function(propertyList)
+ local object = Instance.new(className)
+
+ for index, value in next, propertyList do
+ if type(index) == 'string' then
+ object[index] = value
+ else
+ if type(value) == 'function' then
+ value(object)
+ elseif type(value) == 'userdata' then
+ value.Parent = object
+ end
+ end
+ end
+
+ if object.Parent == nil then
+ object.Parent = defaultParent
+ end
+
+ return object
+ end
+end
+
+--
+-- Create objects
+local MainGui = {}
+local InfoProvider = {}
+
+
+function InfoProvider:GetGameName()
+ if GameAssetInfo ~= nil then
+ return GameAssetInfo.Name
+ else
+ return ''
+ end
+end
+
+function InfoProvider:GetCreatorName()
+ if GameAssetInfo ~= nil then
+ return GameAssetInfo.Creator.Name
+ else
+ return ''
+ end
+end
+
+function InfoProvider:LoadAssets()
+ Spawn(function()
+ if PLACEID <= 0 then
+ while Game.PlaceId <= 0 do
+ wait()
+ end
+ PLACEID = Game.PlaceId
+ end
+
+ IMAGES.GAME_THUMBNAIL = IMAGES.GAME_THUMBNAIL .. tostring(PLACEID)
+
+ -- load game asset info
+ coroutine.resume(coroutine.create(function() GameAssetInfo = MPS:GetProductInfo(PLACEID) end))
+
+ while not currScreenGui do
+ wait()
+ end
+ currScreenGui.ThumbnailContainer.Thumbnail.Image = IMAGES.GAME_THUMBNAIL
+
+ -- load images
+ for imageName, imageContent in next, IMAGES do
+ CP:Preload(imageContent)
+ end
+
+ end)
+end
+
+--
+-- Declare member functions
+function MainGui:GenerateMain()
+ local screenGui = create 'ScreenGui' {
+ Name = 'RobloxLoadingGui'
+ }
+
+ --
+ -- create descendant frames
+
+ local mainBackgroundContainer = create 'Frame' {
+ Name = 'MainBackgroundContainer',
+ BackgroundColor3 = COLORS.DARK,
+ Size = UDim2.new(1, 0, 1, 0),
+ Active = true,
+
+ create 'Frame' {
+ Name = 'TopBar',
+ BackgroundColor3 = COLORS.DARKMED,
+ BorderColor3 = COLORS.MED,
+ BorderSizePixel = 3,
+ Position = UDim2.new(0, -220, 0, -205),
+ Rotation = -10,
+ Size = UDim2.new(0, 1000, 0, 220),
+ ZIndex = 5,
+
+ create 'ImageLabel' {
+ Name = 'RobloxLogo',
+ BackgroundTransparency = 1,
+ Image = IMAGES.ROBLOX_LOGO_256,
+ Position = UDim2.new(0, 214, 1, -80),
+ Rotation = 2,
+ Size = UDim2.new(0, 128, 0, 128),
+ ZIndex = 6,
+
+ create 'TextLabel' {
+ Name = 'PoweredBy',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.5, -60, 0, 30),
+ Size = UDim2.new(0, 80, 0, 18),
+ Font = Enum.Font.SourceSans,
+ FontSize = Enum.FontSize.Size18,
+ TextColor3 = Color3.new(1,1,1),
+ Text = "Powered By",
+ ZIndex = 6
+ }
+ }
+ },
+
+ create 'ImageButton' {
+ Name = 'CloseButton',
+ Image = 'rbxasset://textures/ui/CloseButton.png',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(1, -27, 0, 5),
+ Size = UDim2.new(0, 22, 0, 22),
+ Active = true,
+ ZIndex = 10
+ },
+
+ create 'Frame' {
+ Name = 'ErrorFrame',
+ BackgroundColor3 = COLORS.ERROR,
+ BorderSizePixel = 0,
+ Position = UDim2.new(0.25,0,0,0),
+ Size = UDim2.new(0.5, 0, 0, 80),
+ ZIndex = 5,
+ Visible = false,
+
+ create 'TextLabel' {
+ Name = "ErrorText",
+ BackgroundTransparency = 1,
+ ZIndex = 6,
+ Position = UDim2.new(0,5,0,5),
+ Size = UDim2.new(1,-10,1,-10),
+ Font = Enum.Font.SourceSans,
+ FontSize = Enum.FontSize.Size18,
+ Text = "",
+ TextColor3 = Color3.new(1,1,1),
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Center,
+ TextWrap = true
+ }
+ },
+
+ create 'Frame' {
+ Name = 'BottomBar',
+ BorderSizePixel = 0,
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0, 0, 1, -150),
+ Size = UDim2.new(1, 0, 0, 300),
+ ZIndex = 5,
+
+ create 'Frame' {
+ Name = 'BottomBarActual',
+ BackgroundColor3 = COLORS.DARKMED,
+ BorderColor3 = COLORS.MED,
+ BorderSizePixel = 3,
+ Position = UDim2.new(0, 0, 0, 0),
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 5,
+
+ create 'Frame' {
+ Name = 'TextContainer',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0, -5, 0, 5),
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 8,
+
+ create 'TextLabel' {
+ Name = 'CreatorName',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0, 0, 0, 70),
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size48,
+ Text = InfoProvider:GetCreatorName(),
+ TextColor3 = COLORS.LIGHT,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Right,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+
+ create 'TextLabel' {
+ Name = 'GameName',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0, 0, 0, 30),
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size48,
+ Text = InfoProvider:GetGameName(),
+ TextColor3 = COLORS.LIGHT,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Right,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+
+ create 'TextLabel' {
+ Name = 'CreatorNamePrefix',
+ BackgroundTransparency = 1,
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSans,
+ FontSize = Enum.FontSize.Size48,
+ Text = 'By',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Right,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+
+ create 'TextLabel' {
+ Name = 'OnYourWay',
+ BackgroundTransparency = 1,
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSans,
+ FontSize = Enum.FontSize.Size36,
+ Text = 'You\'re on your way to',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Right,
+ TextYAlignment = Enum.TextYAlignment.Top
+ }
+ }
+ }
+ },
+
+ create 'ImageLabel' {
+ Name = 'BackgroundThumbnailVignette',
+ BackgroundTransparency = 1,
+ Image = IMAGES.BACKGROUND_THUMBNAIL_VIGNETTE,
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 3
+ },
+
+ create 'ImageLabel' {
+ Name = 'BackgroundThumbnail',
+ BackgroundTransparency = 1,
+ Image = IMAGES.GAME_BACKGROUND,
+ Size = UDim2.new(1.5, 0, 1.5, 0),
+ Position = UDim2.new(-0.5,0,0,0),
+ ZIndex = 2
+ },
+
+ Parent = screenGui
+ }
+
+ local thumbnailContainer = create 'Frame' {
+ Name = 'ThumbnailContainer',
+ BackgroundColor3 = COLORS.BLACK,
+ BorderColor3 = COLORS.MED,
+ BorderSizePixel = 4,
+ Position = UDim2.new(0.5, -210, 0.5, -115),
+ Size = UDim2.new(0, 420, 0, 230),
+ ZIndex = 8,
+
+ create 'ImageLabel' {
+ Name = 'Thumbnail',
+ BorderColor3 = COLORS.DARKMED2,
+ BorderSizePixel = 3,
+ Image = "",
+ Size = UDim2.new(1, 0, 1, 0),
+ ZIndex = 8
+ },
+
+ create 'Frame' {
+ Name = 'LoadingInfoContainer',
+ BorderColor3 = COLORS.MED,
+ BackgroundColor3 = COLORS.DARKMED,
+ BorderSizePixel = 2,
+ Position = UDim2.new(0,20,1,0),
+ Size = UDim2.new(1,-40,0,40),
+ ZIndex = 7,
+
+ create 'TextLabel' {
+ Name = 'InstancesLabel',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = 'Instances',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+ create 'TextLabel' {
+ Name = 'InstancesValue',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = '0',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Bottom
+ },
+
+
+
+
+ create 'TextLabel' {
+ Name = 'VoxelsLabel',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.75,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = 'Voxels',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+ create 'TextLabel' {
+ Name = 'VoxelsValue',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.75,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = '0',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Bottom
+ },
+
+
+
+ create 'TextLabel' {
+ Name = 'ConnectorsLabel',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.5,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = 'Connectors',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+ create 'TextLabel' {
+ Name = 'ConnectorsValue',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.5,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = '0',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Bottom
+ },
+
+
+
+ create 'TextLabel' {
+ Name = 'BricksLabel',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.25,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = 'Bricks',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Top
+ },
+ create 'TextLabel' {
+ Name = 'BricksValue',
+ BackgroundTransparency = 1,
+ Position = UDim2.new(0.25,0,0,5),
+ Size = UDim2.new(0.25, 0, 1, -10),
+ ZIndex = 9,
+ Font = Enum.Font.SourceSansBold,
+ FontSize = Enum.FontSize.Size14,
+ Text = '0',
+ TextColor3 = COLORS.LIGHTMED,
+ TextStrokeColor3 = COLORS.DARKMED2,
+ TextStrokeTransparency = 0,
+ TextXAlignment = Enum.TextXAlignment.Center,
+ TextYAlignment = Enum.TextYAlignment.Bottom
+ },
+ },
+
+ Parent = screenGui
+ }
+
+ --
+ -- recalculate everything
+ while not Game:GetService("CoreGui") do
+ wait()
+ end
+ screenGui.Parent = Game.CoreGui
+
+ MainGui:RecalculateSizes(screenGui)
+
+ --
+ -- return generated gui
+ return screenGui
+end
+
+function MainGui:RecalculateTextSize(screenGui)
+ local screenSize = screenGui.AbsoluteSize
+
+ local textSizeScale = math.min(screenSize.y/800, 1)
+ local closestValidSizePrevIndex = math.floor(textSizeScale*#VALID_TEXT_SIZES)-1
+ local closestValidSizePrevIndex2 = closestValidSizePrevIndex-1
+ local closestValidTextSize
+ local closestValidTextSizePrev
+ -- next can't take a 0 because it's a total wuss
+ if closestValidSizePrevIndex > 0 then
+ _, closestValidTextSize = next(VALID_TEXT_SIZES, closestValidSizePrevIndex)
+ if closestValidSizePrevIndex2 > 0 then
+ _, closestValidTextSizePrev = next(VALID_TEXT_SIZES, closestValidSizePrevIndex2)
+ else
+ _, closestValidTextSizePrev = next(VALID_TEXT_SIZES) -- not doing t[1] because this looks cleaner
+ end
+ else
+ _, closestValidTextSize = next(VALID_TEXT_SIZES)
+ _, closestValidTextSizePrev = next(VALID_TEXT_SIZES)
+ end
+ local textSizeEnum = Enum.FontSize['Size'..closestValidTextSize]
+ local textSizePrevEnum = Enum.FontSize['Size'..closestValidTextSizePrev]
+
+ if not screenGui:FindFirstChild("MainBackgroundContainer") then return end
+
+ local TextContainer = screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer
+ local currentYBumpDistance = 0
+ TextContainer.OnYourWay.FontSize = textSizePrevEnum
+ currentYBumpDistance = currentYBumpDistance + closestValidTextSizePrev*(40/48)
+ TextContainer.GameName.Position = UDim2.new(0, 0, 0, currentYBumpDistance)
+ TextContainer.GameName.FontSize = textSizeEnum
+ currentYBumpDistance = currentYBumpDistance + closestValidTextSize*(40/48)
+ TextContainer.CreatorName.Position = UDim2.new(0, 0, 0, currentYBumpDistance)
+ TextContainer.CreatorName.FontSize = textSizeEnum
+ local currentXBumpDistance = -(TextContainer.CreatorName.TextBounds.X+5)
+ TextContainer.CreatorNamePrefix.Position = UDim2.new(0, currentXBumpDistance, 0, currentYBumpDistance)
+ TextContainer.CreatorNamePrefix.FontSize = textSizeEnum
+
+ -- recalculate bottom bar size
+ local sizeScale = closestValidTextSize/48
+ screenGui.MainBackgroundContainer.BottomBar.Size = UDim2.new(1, 0, 0, 300 * sizeScale)
+ screenGui.MainBackgroundContainer.BottomBar.Position = UDim2.new(0, 0, 1, -150 * sizeScale)
+ screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.Position = UDim2.new(0, -130 * sizeScale,0,0)
+end
+
+function MainGui:RecalculateSizes(screenGui)
+ local screenSize = screenGui.AbsoluteSize
+
+ -- recalculate thumbnail size
+ local thumbnailSizeScale = math.min(math.max(screenSize.y/630, 50/230), 1)
+ local thumbnailSize = UDim2.new(0, thumbnailSizeScale*420, 0, thumbnailSizeScale*230)
+ local thumbnailPosition = UDim2.new(0.5, -thumbnailSizeScale*420/2, 0.5, -20 - thumbnailSizeScale*230/2 )
+ screenGui.ThumbnailContainer.Size = thumbnailSize
+ screenGui.ThumbnailContainer.Position = thumbnailPosition
+
+ screenGui.ThumbnailContainer.LoadingInfoContainer.Visible = (screenSize.Y > 500)
+
+ -- update names
+
+ -- if we don't have a name yet, keep trying!
+ if InfoProvider:GetCreatorName() == '' or InfoProvider:GetGameName() == '' then
+ Spawn(function()
+
+ while InfoProvider and InfoProvider:GetCreatorName() == '' or InfoProvider:GetGameName() == '' do
+ wait()
+ end
+
+ if screenGui and screenGui:FindFirstChild("MainBackgroundContainer") then
+ screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.CreatorName.Text = InfoProvider:GetCreatorName()
+ screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.GameName.Text = InfoProvider:GetGameName()
+ end
+
+ MainGui:RecalculateTextSize(screenGui)
+ end)
+ else
+ screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.CreatorName.Text = InfoProvider:GetCreatorName()
+ screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.GameName.Text = InfoProvider:GetGameName()
+ end
+
+ MainGui:RecalculateTextSize(screenGui)
+end
+
+function MainGui:Show()
+ currScreenGui = MainGui:GenerateMain()
+ currScreenGui.MainBackgroundContainer.Visible = true
+ currScreenGui.ThumbnailContainer.Visible = true
+
+ currScreenGui.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ MainGui:RecalculateSizes(currScreenGui)
+ end
+ end)
+end
+
+
+
+---------------------------------------------------------
+-- Main Script (show something now + setup connections)
+
+-- start loading assets asap
+InfoProvider:LoadAssets()
+
+MainGui:Show()
+
+local guiService = Game:GetService("GuiService")
+local instanceCount = 0
+local voxelCount = 0
+local brickCount = 0
+local connectorCount = 0
+local setVerb = true
+
+renderSteppedConnection = Game:GetService("RunService").RenderStepped:connect(function()
+
+ instanceCount = guiService:GetInstanceCount()
+ voxelCount = guiService:GetVoxelCount()
+ brickCount = guiService:GetBrickCount()
+ connectorCount = guiService:GetConnectorCount()
+
+ if not currScreenGui then return end
+
+ if setVerb then
+ currScreenGui.MainBackgroundContainer.CloseButton:SetVerb("Exit")
+ setVerb = false
+ end
+
+ currScreenGui.ThumbnailContainer.LoadingInfoContainer.InstancesValue.Text = tostring(instanceCount)
+ currScreenGui.ThumbnailContainer.LoadingInfoContainer.BricksValue.Text = tostring(brickCount)
+ currScreenGui.ThumbnailContainer.LoadingInfoContainer.ConnectorsValue.Text = tostring(connectorCount)
+
+ if voxelCount <= 0 then
+ currScreenGui.ThumbnailContainer.LoadingInfoContainer.VoxelsValue.Text = "0"
+ else
+ currScreenGui.ThumbnailContainer.LoadingInfoContainer.VoxelsValue.Text = tostring(voxelCount) .." million"
+ end
+end)
+
+guiService.ErrorMessageChanged:connect(function()
+ if guiService:GetErrorMessage() ~= '' then
+ currScreenGui.MainBackgroundContainer.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
+ currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = true
+ else
+ currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = false
+ end
+end)
+
+if guiService:GetErrorMessage() ~= '' then
+ currScreenGui.MainBackgroundContainer.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
+ currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = true
+end
+
+
+local forceRemovalTime = 5
+local destroyed = false
+
+function removeLoadingScreen()
+ if renderSteppedConnection then
+ renderSteppedConnection:disconnect()
+ end
+
+ if currScreenGui then
+ currScreenGui:Destroy()
+ currScreenGui = nil
+ end
+
+ if script then script:Destroy() end
+ destroyed = true
+end
+
+
+function startForceLoadingDoneTimer()
+ wait(forceRemovalTime)
+ removeLoadingScreen()
+end
+
+function gameIsLoaded()
+ if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
+ removeLoadingScreen()
+ else
+ startForceLoadingDoneTimer()
+ end
+end
+
+Game.ReplicatedFirst.RemoveDefaultLoadingGuiSignal:connect(function()
+ removeLoadingScreen()
+end)
+
+if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
+ removeLoadingScreen()
+ return
+end
+
+Game.Loaded:connect(function()
+ gameIsLoaded()
+end)
+
+if Game:IsLoaded() then
+ gameIsLoaded()
+end
+
+--------------------------------------------------------------------------
+--
+-- Animation (make the stuff we are showing look cool)
+
+local blockSize = 10
+local blockColor = Color3.new(33/255,66/255,209/255)
+
+local yPosScale = 0
+local yPosOffset = -blockSize * 3.5
+
+local tweenStyle = Enum.EasingStyle.Sine
+local tweenVelocity = 1500
+local tweenTime = (currScreenGui.AbsoluteSize.X/2)/tweenVelocity
+
+function createBlock()
+ local initBlock = Instance.new("Frame")
+ initBlock.ZIndex = 5
+ initBlock.Size = UDim2.new(0,blockSize,0,blockSize)
+ initBlock.BackgroundColor3 = COLORS.DARK
+ initBlock.BorderSizePixel = 0
+ initBlock.Position = UDim2.new(0,-blockSize,yPosScale,yPosOffset)
+ initBlock.Parent = currScreenGui.MainBackgroundContainer.BottomBar
+
+ return initBlock
+end
+
+
+local blocks = {}
+for i = 1,6 do
+ blocks[i] = createBlock()
+end
+
+function getYOffset(newSize)
+ return yPosOffset - (newSize/3)
+end
+
+function rightScreenExit()
+ wait(tweenTime * 3)
+ if not currScreenGui then return end
+
+ local regSize = blocks[6].Size
+ local regPos = blocks[6].Position
+
+ blocks[6].Size = blocks[1].Size
+ blocks[6].Position = blocks[1].Position
+
+ blocks[1].Size = regSize
+ blocks[1].Position = regPos
+
+ wait()
+
+ for i = 1,6 do
+ local delayTime = tweenTime * (i - 1) * 0.5
+ Delay(delayTime, function()
+ if not currScreenGui then return end
+
+ local blockIndex = i
+ local blockSizeMultiplier = 4 - (i * 0.5)
+
+ blocks[blockIndex]:TweenPosition(UDim2.new(1,0,yPosScale,yPosOffset),
+ Enum.EasingDirection.Out,tweenStyle,
+ tweenTime,true)
+ if i == 6 then
+ blocks[6]:TweenSizeAndPosition(UDim2.new(0,blockSize,0,blockSize),
+ UDim2.new(1,0,yPosScale,yPosOffset),
+ Enum.EasingDirection.InOut,tweenStyle,
+ tweenTime,true)
+
+ wait(tweenTime * 1.1)
+ leftScreenEntrance()
+ else
+ local newSize = blockSize * blockSizeMultiplier
+ blocks[6]:TweenSizeAndPosition(UDim2.new(0,newSize,0,newSize),
+ UDim2.new(0.5,-newSize/2,yPosScale,getYOffset(newSize)),
+ Enum.EasingDirection.InOut,tweenStyle,
+ tweenTime * 0.75,true)
+ end
+ end)
+ end
+end
+
+function leftScreenEntrance()
+ if not currScreenGui then return end
+
+ for i = 1,6 do
+ blocks[i].Size = UDim2.new(0,blockSize,0,blockSize)
+ blocks[i].Position = UDim2.new(0,-blockSize,yPosScale,yPosOffset)
+ end
+
+ blocks[1]:TweenPosition(UDim2.new(0.5,-blockSize/2,yPosScale,yPosOffset),Enum.EasingDirection.Out,tweenStyle,tweenTime,true,function()
+ for i = 1, 6 do
+ local delayTime = tweenTime * (i - 1) * 0.5
+
+ Delay(delayTime, function()
+ if not currScreenGui then return end
+
+ local blockIndex = i
+ local blockSizeMultiplier = 1 + (i * 0.5)
+
+ blocks[blockIndex]:TweenPosition(UDim2.new(0.5,-blockSize/2,yPosScale,yPosOffset),
+ Enum.EasingDirection.Out,tweenStyle,
+ tweenTime,true)
+
+ local newSize = blockSize * blockSizeMultiplier
+ blocks[1]:TweenSizeAndPosition(UDim2.new(0,newSize,0,newSize),
+ UDim2.new(0.5,-newSize/2,yPosScale,getYOffset(newSize)),
+ Enum.EasingDirection.InOut,tweenStyle,
+ tweenTime * 0.75,true)
+
+
+ if i == 4 then
+ rightScreenExit()
+ end
+ end)
+ end
+ end)
+end
+
+function startLoadingAnimation()
+ currScreenGui.MainBackgroundContainer.BackgroundThumbnail:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Linear,20,true)
+ leftScreenEntrance()
+end
+
+
+----------------------------------
+-- Animation Begin
+startLoadingAnimation()
\ No newline at end of file
diff --git a/Client2016/content/fonts/Rocket.rbxm b/Client2016/content/fonts/Rocket.rbxm
new file mode 100644
index 0000000..72beea5
--- /dev/null
+++ b/Client2016/content/fonts/Rocket.rbxm
@@ -0,0 +1,102 @@
+
+ null
+ nil
+ -
+
+ false
+ -0.5
+ 0.5
+ 3
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+ 23
+
+ -0.5
+ 0.5
+ 0
+ -1.1920929e-007
+ 1.00000012
+ 0
+ 1.00000012
+ -1.1920929e-007
+ 0
+ 0
+ 0
+ -1.00000024
+
+ true
+ true
+ 0
+ true
+ true
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 3
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+ false
+ Rocket
+ 0
+ -0.5
+ 0.5
+ 3
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ 1
+
+ 1
+ 1
+ 4
+
+
+
-
+
+ true
+ Swoosh
+ 0
+ false
+ rbxasset://sounds\Rocket whoosh 01.wav
+ 0.699999988
+
+
+ -
+
+ false
+ Explosion
+ 0
+ true
+ rbxasset://sounds\collide.wav
+ 1
+
+
+ -
+
+ Script
+ r = game:service("RunService")
shaft = script.Parent
position = Vector3.new(0,0,0)
function fly()
direction = shaft.CFrame.lookVector
position = position + direction
error = position - shaft.Position
shaft.Velocity = 7*error
end
function blow()
swoosh:Stop()
explosion = Instance.new("Explosion")
explosion.Position = shaft.Position
explosion.Parent = game.Workspace
connection:disconnect()
shaft:remove()
end
t, s = r.Stepped:wait()
swoosh = script.Parent.Swoosh
swoosh:Play()
position = shaft.Position
d = t + 10.0 - s
connection = shaft.Touched:connect(blow)
while t < d do
fly()
t = r.Stepped:wait()
end
script.Parent.Explosion.PlayOnRemove = false
swoosh:Stop()
shaft:remove()
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/SlingshotPellet.rbxm b/Client2016/content/fonts/SlingshotPellet.rbxm
new file mode 100644
index 0000000..d753b0a
--- /dev/null
+++ b/Client2016/content/fonts/SlingshotPellet.rbxm
@@ -0,0 +1,82 @@
+
+ null
+ nil
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 194
+
+ 0
+ 6.4000001
+ -8
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ true
+ true
+ 0
+ true
+ true
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ false
+ Pellet
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ 0
+
+ 2
+ 2
+ 2
+
+
+
-
+
+ Script
+
pellet = script.Parent
damage = 8
function onTouched(hit)
humanoid = hit.Parent:findFirstChild("Humanoid")
if humanoid~=nil then
humanoid.Health = humanoid.Health - damage
connection:disconnect()
else
damage = damage / 2
if damage < 0.1 then
connection:disconnect()
end
end
end
connection = pellet.Touched:connect(onTouched)
r = game:service("RunService")
t, s = r.Stepped:wait()
d = t + 1.0 - s
while t < d do
t = r.Stepped:wait()
end
pellet.Parent = nil
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/SourceSans.font b/Client2016/content/fonts/SourceSans.font
new file mode 100644
index 0000000..6b7a4f3
Binary files /dev/null and b/Client2016/content/fonts/SourceSans.font differ
diff --git a/Client2016/content/fonts/SourceSansBold.font b/Client2016/content/fonts/SourceSansBold.font
new file mode 100644
index 0000000..f3520e0
Binary files /dev/null and b/Client2016/content/fonts/SourceSansBold.font differ
diff --git a/Client2016/content/fonts/SourceSansItalic.font b/Client2016/content/fonts/SourceSansItalic.font
new file mode 100644
index 0000000..6c49189
Binary files /dev/null and b/Client2016/content/fonts/SourceSansItalic.font differ
diff --git a/Client2016/content/fonts/SourceSansLight.font b/Client2016/content/fonts/SourceSansLight.font
new file mode 100644
index 0000000..5bb3ac8
Binary files /dev/null and b/Client2016/content/fonts/SourceSansLight.font differ
diff --git a/Client2016/content/fonts/SourceSansPro-Bold.ttf b/Client2016/content/fonts/SourceSansPro-Bold.ttf
new file mode 100644
index 0000000..be46652
Binary files /dev/null and b/Client2016/content/fonts/SourceSansPro-Bold.ttf differ
diff --git a/Client2016/content/fonts/SourceSansPro-It.ttf b/Client2016/content/fonts/SourceSansPro-It.ttf
new file mode 100644
index 0000000..c689cd2
Binary files /dev/null and b/Client2016/content/fonts/SourceSansPro-It.ttf differ
diff --git a/Client2016/content/fonts/SourceSansPro-Light.ttf b/Client2016/content/fonts/SourceSansPro-Light.ttf
new file mode 100644
index 0000000..dcff4e9
Binary files /dev/null and b/Client2016/content/fonts/SourceSansPro-Light.ttf differ
diff --git a/Client2016/content/fonts/SourceSansPro-Regular.ttf b/Client2016/content/fonts/SourceSansPro-Regular.ttf
new file mode 100644
index 0000000..a011dff
Binary files /dev/null and b/Client2016/content/fonts/SourceSansPro-Regular.ttf differ
diff --git a/Client2016/content/fonts/arial.ttf b/Client2016/content/fonts/arial.ttf
new file mode 100644
index 0000000..4ba94d1
Binary files /dev/null and b/Client2016/content/fonts/arial.ttf differ
diff --git a/Client2016/content/fonts/arialbd.ttf b/Client2016/content/fonts/arialbd.ttf
new file mode 100644
index 0000000..2ca4b28
Binary files /dev/null and b/Client2016/content/fonts/arialbd.ttf differ
diff --git a/Client2016/content/fonts/character.rbxm b/Client2016/content/fonts/character.rbxm
new file mode 100644
index 0000000..7bf4b8a
--- /dev/null
+++ b/Client2016/content/fonts/character.rbxm
@@ -0,0 +1,527 @@
+
+ null
+ nil
+ -
+
+ 7
+ true
+
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ erik.cassel
+
[RBX1]
+ true
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 0
+ 4.5
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Head
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 1
+ 1
+
+
+
-
+
+
+ 0
+ Mesh
+
+ 1.25
+ 1.25
+ 1.25
+
+
+
+ 1
+ 1
+ 1
+
+ true
+
+
+ -
+
+ 5
+ face
+ 20
+ 0
+ rbxasset://textures/face.png
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ true
+ Torso
+ 0
+ 0
+ 0
+ 2
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
-
+
+ 5
+ roblox
+ 20
+ 0
+
+
+
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ -1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ 0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ -0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ 100
+ false
+ 100
+ Humanoid
+ false
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 0
+
[null]
+
+ 0
+ 0
+ 0
+
+ true
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/character3.rbxm b/Client2016/content/fonts/character3.rbxm
new file mode 100644
index 0000000..e39f9d6
--- /dev/null
+++ b/Client2016/content/fonts/character3.rbxm
@@ -0,0 +1,599 @@
+
+ null
+ nil
+ -
+
+ 7
+ true
+
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 1
+
+ erik.cassel
+
[RBX1]
+ true
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 0
+ 4.5
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Head
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 1
+ 1
+
+
+
-
+
+
+ 0
+ Mesh
+
+ 1.25
+ 1.25
+ 1.25
+
+
+
+ 1
+ 1
+ 1
+
+ true
+
+
+ -
+
+ 5
+ face
+ 20
+ 0
+ rbxasset://textures/face.png
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ true
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ true
+ Torso
+ 0
+ 0
+ 0
+ 2
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
-
+
+ 5
+ roblox
+ 20
+ 0
+
+
+
+ true
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ 1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 4
+ 0
+ 24
+
+ -1.5
+ 3
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Arm
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ 0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Left Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 119
+
+ -0.5
+ 1
+ 25.5
+ -1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ true
+ Right Leg
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 3
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 1
+ 2
+ 1
+
+
+
+ -
+
+ 100
+ false
+ 100
+ Humanoid
+ false
+
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+
+ 0
+
[null]
+
+ 0
+ 0
+ 0
+
+ true
+
+
+ -
+
+ false
+ -0.5
+ 0.5
+ 0
+ 0
+ -0.5
+ 0.5
+ 0
+ 0
+ 23
+
+ 0
+ 3
+ 25.5
+ -1
+ 0
+ -0
+ -0
+ 1
+ -0
+ -0
+ 0
+ -1
+
+ false
+ 0
+ true
+ false
+ 0.5
+ 0
+ 0.300000012
+ -0.5
+ 0.5
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ true
+ HumanoidRootPart
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ 0
+ 0
+
+ -0.5
+ 0.5
+ 0
+ 0
+ 1
+
+ 0
+ 0
+ 0
+
+ true
+ 1
+
+ 2
+ 2
+ 1
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/characterCameraScript.rbxmx b/Client2016/content/fonts/characterCameraScript.rbxmx
new file mode 100644
index 0000000..ebed40f
--- /dev/null
+++ b/Client2016/content/fonts/characterCameraScript.rbxmx
@@ -0,0 +1,4264 @@
+
+ null
+ nil
+-
+
+ false
+
+ CameraScript
+
+
+
-
+
+
+ ClickToMove
+ y then
+ return x
+ else
+ return y
+ end
+ end
+ end
+ Utility.ViewSizeX = ViewSizeX
+
+ local function ViewSizeY()
+ local camera = workspace.CurrentCamera
+ local x = camera and camera.ViewportSize.X or 0
+ local y = camera and camera.ViewportSize.Y or 0
+ if y == 0 then
+ return 768
+ else
+ if x > y then
+ return y
+ else
+ return x
+ end
+ end
+ end
+ Utility.ViewSizeY = ViewSizeY
+
+ local function AspectRatio()
+ return ViewSizeX() / ViewSizeY()
+ end
+ Utility.AspectRatio = AspectRatio
+
+ local function FindChacterAncestor(part)
+ if part then
+ local humanoid = part:FindFirstChild("Humanoid")
+ if humanoid then
+ return part, humanoid
+ else
+ return FindChacterAncestor(part.Parent)
+ end
+ end
+ end
+ Utility.FindChacterAncestor = FindChacterAncestor
+
+
+ local function GetUnitRay(x, y, viewWidth, viewHeight, camera)
+ return camera:ScreenPointToRay(x, y)
+ end
+ Utility.GetUnitRay = GetUnitRay
+
+ local RayCastIgnoreList = workspace.FindPartOnRayWithIgnoreList
+ local function Raycast(ray, ignoreNonCollidable, ignoreList)
+ local ignoreList = ignoreList or {}
+ local hitPart, hitPos = RayCastIgnoreList(workspace, ray, ignoreList)
+ if hitPart then
+ if ignoreNonCollidable and hitPart.CanCollide == false then
+ table.insert(ignoreList, hitPart)
+ return Raycast(ray, ignoreNonCollidable, ignoreList)
+ end
+ return hitPart, hitPos
+ end
+ return nil, nil
+ end
+ Utility.Raycast = Raycast
+
+
+ Utility.Round = function(num, roundToNearest)
+ roundToNearest = roundToNearest or 1
+ return math.floor((num + roundToNearest/2) / roundToNearest) * roundToNearest
+ end
+
+ local function AveragePoints(positions)
+ local avgPos = Vector2.new(0,0)
+ if #positions > 0 then
+ for i = 1, #positions do
+ avgPos = avgPos + positions[i]
+ end
+ avgPos = avgPos / #positions
+ end
+ return avgPos
+ end
+ Utility.AveragePoints = AveragePoints
+
+ local function FuzzyEquals(numa, numb)
+ return numa + 0.1 > numb and numa - 0.1 < numb
+ end
+ Utility.FuzzyEquals = FuzzyEquals
+
+ local LastInput = 0
+ UIS.InputBegan:connect(function(inputObject, wasSunk)
+ if not wasSunk then
+ if inputObject.UserInputType == Enum.UserInputType.Touch or
+ inputObject.UserInputType == Enum.UserInputType.MouseButton1 or
+ inputObject.UserInputType == Enum.UserInputType.MouseButton2 then
+ LastInput = tick()
+ end
+ end
+ end)
+ Utility.GetLastInput = function()
+ return LastInput
+ end
+end
+
+local humanoidCache = {}
+local function findPlayerHumanoid(player)
+ local character = player and player.Character
+ if character then
+ local resultHumanoid = humanoidCache[player]
+ if resultHumanoid and resultHumanoid.Parent == character then
+ return resultHumanoid
+ else
+ humanoidCache[player] = nil -- Bust Old Cache
+ for _, child in pairs(character:GetChildren()) do
+ if child:IsA('Humanoid') then
+ humanoidCache[player] = child
+ return child
+ end
+ end
+ end
+ end
+end
+
+local function CFrameInterpolator(c0, c1) -- (CFrame from, CFrame to) -> (float theta, (float fraction -> CFrame between))
+ local fromAxisAngle = CFrame.fromAxisAngle
+ local components = CFrame.new().components
+ local inverse = CFrame.new().inverse
+ local v3 = Vector3.new
+ local acos = math.acos
+ local sqrt = math.sqrt
+ local invroot2 = 1 / math.sqrt(2)
+ -- The expanded matrix
+ local _, _, _, xx, yx, zx,
+ xy, yy, zy,
+ xz, yz, zz = components(inverse(c0)*c1)
+ -- The cos-theta of the axisAngles from
+ local cosTheta = (xx + yy + zz - 1)/2
+ -- Rotation axis
+ local rotationAxis = v3(yz-zy, zx-xz, xy-yx)
+ -- The position to tween through
+ local positionDelta = (c1.p - c0.p)
+ -- Theta
+ local theta;
+ -- Catch degenerate cases
+ if cosTheta >= 0.999 then
+ -- Case same rotation, just return an interpolator over the positions
+ return 0, function(t)
+ return c0 + positionDelta*t
+ end
+ elseif cosTheta <= -0.999 then
+ -- Case exactly opposite rotations, disambiguate
+ theta = math.pi
+ xx = (xx + 1) / 2
+ yy = (yy + 1) / 2
+ zz = (zz + 1) / 2
+ if xx > yy and xx > zz then
+ if xx < 0.001 then
+ rotationAxis = v3(0, invroot2, invroot2)
+ else
+ local x = sqrt(xx)
+ xy = (xy + yx) / 4
+ xz = (xz + zx) / 4
+ rotationAxis = v3(x, xy/x, xz/x)
+ end
+ elseif yy > zz then
+ if yy < 0.001 then
+ rotationAxis = v3(invroot2, 0, invroot2)
+ else
+ local y = sqrt(yy)
+ xy = (xy + yx) / 4
+ yz = (yz + zy) / 4
+ rotationAxis = v3(xy/y, y, yz/y)
+ end
+ else
+ if zz < 0.001 then
+ rotationAxis = v3(invroot2, invroot2, 0)
+ else
+ local z = sqrt(zz)
+ xz = (xz + zx) / 4
+ yz = (yz + zy) / 4
+ rotationAxis = v3(xz/z, yz/z, z)
+ end
+ end
+ else
+ -- Normal case, get theta from cosTheta
+ theta = acos(cosTheta)
+ end
+ -- Return the interpolator
+ return theta, function(t)
+ return c0*fromAxisAngle(rotationAxis, theta*t) + positionDelta*t
+ end
+end
+---------------------------------------------------------
+
+local Signal = Utility.Signal
+local Create = Utility.Create
+
+--------------------------CHARACTER CONTROL-------------------------------
+local function CreateController()
+ local this = {}
+
+ this.TorsoLookPoint = nil
+
+ function this:SetTorsoLookPoint(point)
+ local humanoid = findPlayerHumanoid(Player)
+ if humanoid then
+ humanoid.AutoRotate = false
+ end
+ this.TorsoLookPoint = point
+ self:UpdateTorso()
+ delay(2,
+ function()
+ -- this isnt technically correct for detecting if this is the last issue to the setTorso function
+ if this.TorsoLookPoint == point then
+ this.TorsoLookPoint = nil
+ if humanoid then
+ humanoid.AutoRotate = true
+ end
+ end
+ end)
+ end
+
+ function this:UpdateTorso(point)
+ if this.TorsoLookPoint then
+ point = this.TorsoLookPoint
+ else
+ return
+ end
+
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ if torso then
+ local lookVec = (point - torso.CFrame.p).unit
+ local squashedLookVec = Vector3.new(lookVec.X, 0, lookVec.Z).unit
+ torso.CFrame = CFrame.new(torso.CFrame.p, torso.CFrame.p + squashedLookVec)
+ end
+ end
+
+ return this
+end
+
+local CharacterControl = CreateController()
+-----------------------------------------------------------------------
+
+--------------------------PC AUTO JUMPER-------------------------------
+
+local function GetCharacter()
+ return Player and Player.Character
+end
+
+local function GetTorso()
+ local humanoid = findPlayerHumanoid(Player)
+ return humanoid and humanoid.Torso
+end
+
+local function IsPartAHumanoid(part)
+ return part and part.Parent and (part.Parent:FindFirstChild('Humanoid') ~= nil)
+end
+
+local function doAutoJump()
+ local character = GetCharacter()
+ if (character == nil) then
+ return;
+ end
+
+ local humanoid = findPlayerHumanoid(Player)
+ if (humanoid == nil) then
+ return;
+ end
+
+ local rayLength = 1.5;
+ -- This is how high a ROBLOXian jumps from the mid point of his torso
+ local jumpHeight = 7.0;
+
+ local torso = GetTorso()
+ if (torso == nil) then
+ return;
+ end
+
+ local torsoCFrame = torso.CFrame;
+ local torsoLookVector = torsoCFrame.lookVector;
+ local torsoPos = torsoCFrame.p;
+
+ local torsoRay = Ray.new(torsoPos + Vector3.new(0, -torso.Size.Y/2, 0), torsoLookVector * rayLength);
+ local jumpRay = Ray.new(torsoPos + Vector3.new(0, jumpHeight - torso.Size.Y, 0), torsoLookVector * rayLength);
+
+ local hitPart, _ = RayCastIgnoreList(workspace, torsoRay, {character}, false)
+ local jumpHitPart, _ = RayCastIgnoreList(workspace, jumpRay, {character}, false)
+
+ if (hitPart and jumpHitPart == nil and hitPart.CanCollide == true) then
+ -- NOTE: this follow line is not in the C++ impl, but an improvement in Click to Move
+ if not IsPartAHumanoid(hitPart) then
+ humanoid.Jump = true;
+ end
+ end
+end
+
+local NO_JUMP_STATES =
+{
+ [Enum.HumanoidStateType.FallingDown] = false;
+ [Enum.HumanoidStateType.Flying] = false;
+ [Enum.HumanoidStateType.Freefall] = false;
+ [Enum.HumanoidStateType.GettingUp] = false;
+ [Enum.HumanoidStateType.Ragdoll] = false;
+ [Enum.HumanoidStateType.Running] = false;
+ [Enum.HumanoidStateType.Seated] = false;
+ [Enum.HumanoidStateType.Swimming] = false;
+
+ -- Special case to detect if we are on a ladder
+ [Enum.HumanoidStateType.Climbing] = false;
+}
+
+local function enableAutoJump()
+ local humanoid = findPlayerHumanoid(Player)
+ local currentState = humanoid and humanoid:GetState()
+ if currentState then
+ return NO_JUMP_STATES[currentState] == nil
+ end
+ return false
+end
+
+local function getAutoJump()
+ return true
+end
+
+local function vec3IsZero(vec3)
+ return vec3.magnitude < 0.05
+end
+
+-- NOTE: This function is radically different from the engine's implementation
+local function calcDesiredWalkVelocity()
+ -- TEMP
+ return Vector3.new(1,1,1)
+end
+
+local function preStepSimulatorSide(dt)
+ if getAutoJump() and enableAutoJump() then
+ local desiredWalkVelocity = calcDesiredWalkVelocity();
+ if (not vec3IsZero(desiredWalkVelocity)) then
+ doAutoJump();
+ end
+ end
+end
+
+local function AutoJumper()
+ local this = {}
+ local running = false
+ local runRoutine = nil
+
+ function this:Run()
+ running = true
+ local thisRoutine = nil
+ thisRoutine = coroutine.create(function()
+ while running and thisRoutine == runRoutine do
+ this:Step()
+ wait()
+ end
+ end)
+ runRoutine = thisRoutine
+ coroutine.resume(thisRoutine)
+ end
+
+ function this:Stop()
+ running = false
+ end
+
+ function this:Step()
+ preStepSimulatorSide()
+ end
+
+ return this
+end
+
+-----------------------------------------------------------------------------
+
+-----------------------------------PATHER--------------------------------------
+
+local function CreateDestinationIndicator(pos)
+ local destinationGlobe = Create'Part'
+ {
+ Name = 'PathGlobe';
+ TopSurface = 'Smooth';
+ BottomSurface = 'Smooth';
+ Shape = 'Ball';
+ CanCollide = false;
+ Size = Vector3.new(2,2,2);
+ BrickColor = BrickColor.new('Institutional white');
+ Transparency = 0;
+ Anchored = true;
+ CFrame = CFrame.new(pos);
+ }
+ return destinationGlobe
+end
+
+local function Pather(character, point)
+ local this = {}
+
+ this.Cancelled = false
+ this.Started = false
+
+ this.Finished = Signal.Create()
+ this.PathFailed = Signal.Create()
+ this.PathStarted = Signal.Create()
+
+ this.PathComputed = false
+
+ function this:YieldUntilPointReached(character, point, timeout)
+ timeout = timeout or 10000000
+
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ local start = tick()
+ local lastMoveTo = start
+ while torso and tick() - start < timeout and this.Cancelled == false do
+ local diffVector = (point - torso.CFrame.p)
+ local xzMagnitude = (diffVector * Vector3.new(1,0,1)).magnitude
+ if xzMagnitude < 6 then
+ -- Jump if the path is telling is to go upwards
+ if diffVector.Y >= 2.2 then
+ humanoid.Jump = true
+ end
+ end
+ -- The hard-coded number 2 here is from the engine's MoveTo implementation
+ if xzMagnitude < 2 then
+ return true
+ end
+ -- Keep on issuing the move command because it will automatically quit every so often.
+ if tick() - lastMoveTo > 1.5 then
+ humanoid:MoveTo(point)
+ lastMoveTo = tick()
+ end
+ CharacterControl:UpdateTorso(point)
+ wait()
+ end
+ return false
+ end
+
+ function this:Cancel()
+ this.Cancelled = true
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ if humanoid and torso then
+ humanoid:MoveTo(torso.CFrame.p)
+ end
+ end
+
+ function this:CheckOcclusion(point1, point2, character, torsoRadius)
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ if torsoRadius == nil then
+ torsoRadius = torso and Vector3.new(torso.Size.X/2,0,torso.Size.Z/2) or Vector3.new(1,0,1)
+ end
+
+ local diffVector = point2 - point1
+ local directionVector = diffVector.unit
+
+ local rightVector = Vector3.new(0,1,0):Cross(directionVector) * torsoRadius
+
+ local rightPart, _ = Utility.Raycast(Ray.new(point1 + rightVector, diffVector + rightVector), true, {character})
+ local hitPart, _ = Utility.Raycast(Ray.new(point1, diffVector), true, {character})
+ local leftPart, _ = Utility.Raycast(Ray.new(point1 - rightVector, diffVector - rightVector), true, {character})
+
+ if rightPart or hitPart or leftPart then
+ return false
+ end
+
+ -- Make sure we have somewhere to stand on
+ local midPt = (point2 + point1) / 2
+ local studsBetweenSamples = 2
+ for i = 1, math.floor(diffVector.magnitude/studsBetweenSamples) do
+ local downPart, _ = Utility.Raycast(Ray.new(point1 + directionVector * i * studsBetweenSamples, Vector3.new(0,-7,0)), true, {character})
+ if not downPart then
+ return false
+ end
+ end
+
+ return true
+ end
+
+ function this:SmoothPoints(pathToSmooth)
+ local result = {}
+
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ for i = 1, #pathToSmooth do
+ table.insert(result, pathToSmooth[i])
+ end
+
+ -- Backwards for safe-deletion
+ for i = #result - 1, 1, -1 do
+ if i + 1 <= #result then
+
+ local nextPoint = result[i+1]
+ local thisPoint = result[i]
+
+ local lastPoint = result[i-1]
+ if lastPoint == nil then
+ lastPoint = torso and Vector3.new(torso.CFrame.p.X, thisPoint.Y, torso.CFrame.p.Z)
+ end
+
+ if lastPoint and Utility.FuzzyEquals(thisPoint.Y, lastPoint.Y) and Utility.FuzzyEquals(thisPoint.Y, nextPoint.Y) then
+ if this:CheckOcclusion(lastPoint, nextPoint, character) then
+ table.remove(result, i)
+ -- Move i back one to recursively-smooth
+ i = i + 1
+ end
+ end
+ end
+ end
+
+ return result
+ end
+
+ function this:CheckNeighboringCells(character)
+ local pathablePoints = {}
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = character and humanoid and humanoid.Torso
+ if torso then
+ local torsoCFrame = torso.CFrame
+ local torsoPos = torsoCFrame.p
+ -- Minus and plus 2 is so we can get it into the cell-corner space and then translate it back into cell-center space
+ local roundedPos = Vector3.new(Utility.Round(torsoPos.X-2,4)+2, Utility.Round(torsoPos.Y-2,4)+2, Utility.Round(torsoPos.Z-2,4)+2)
+ local neighboringCells = {}
+ for x = -4, 4, 8 do
+ for z = -4, 4, 8 do
+ table.insert(neighboringCells, roundedPos + Vector3.new(x,0,z))
+ end
+ end
+ for _, testPoint in pairs(neighboringCells) do
+ local pathable = this:CheckOcclusion(roundedPos, testPoint, character, Vector3.new(0,0,0))
+ if pathable then
+ table.insert(pathablePoints, testPoint)
+ end
+ end
+ end
+ return pathablePoints
+ end
+
+ function this:ComputeDirectPath()
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ if torso then
+ local startPt = torso.CFrame.p
+ local finishPt = point
+ if (finishPt - startPt).magnitude < 150 then
+ -- move back the destination by 2 studs or otherwise the pather will collide with the object we are trying to reach
+ finishPt = finishPt - (finishPt - startPt).unit * 2
+ if this:CheckOcclusion(startPt, finishPt, character, Vector3.new(0,0,0)) then
+ local pathResult = {}
+ pathResult.Status = Enum.PathStatus.Success
+ function pathResult:GetPointCoordinates()
+ return {finishPt}
+ end
+ return pathResult
+ end
+ end
+ end
+ end
+
+ local function AllAxisInThreshhold(targetPt, otherPt, threshold)
+ return math.abs(targetPt.X - otherPt.X) <= threshold and
+ math.abs(targetPt.Y - otherPt.Y) <= threshold and
+ math.abs(targetPt.Z - otherPt.Z) <= threshold
+ end
+
+ function this:ComputePath()
+ local smoothed = false
+ local humanoid = findPlayerHumanoid(Player)
+ local torso = humanoid and humanoid.Torso
+ if torso then
+ if this.PathComputed then return end
+ this.PathComputed = true
+ -- Will yield the script since it is an Async script (start, finish, maxDistance)
+ -- Try to use the smooth function, but it may not exist yet :(
+ local success = pcall(function()
+ -- 3 is height from torso cframe to ground
+ this.pathResult = PathfindingService:ComputeSmoothPathAsync(torso.CFrame.p - Vector3.new(0,3,0), point, 400)
+ smoothed = true
+ end)
+ if not success then
+ -- 3 is height from torso cframe to ground
+ this.pathResult = PathfindingService:ComputeRawPathAsync(torso.CFrame.p - Vector3.new(0,3,0), point, 400)
+ smoothed = false
+ end
+ this.pointList = this.pathResult and this.pathResult:GetPointCoordinates()
+ local pathFound = false
+ if this.pathResult.Status == Enum.PathStatus.FailFinishNotEmpty then
+ -- Lets try again with a slightly set back start point; it is ok to do this again so the FailFinishNotEmpty uses little computation
+ local diffVector = point - workspace.CurrentCamera.CoordinateFrame.p
+ if diffVector.magnitude > 2 then
+ local setBackPoint = point - (diffVector).unit * 2.1
+ local success = pcall(function()
+ this.pathResult = PathfindingService:ComputeSmoothPathAsync(torso.CFrame.p, setBackPoint, 400)
+ smoothed = true
+ end)
+ if not success then
+ this.pathResult = PathfindingService:ComputeRawPathAsync(torso.CFrame.p, setBackPoint, 400)
+ smoothed = false
+ end
+ this.pointList = this.pathResult and this.pathResult:GetPointCoordinates()
+ pathFound = true
+ end
+ end
+ if this.pathResult.Status == Enum.PathStatus.ClosestNoPath and #this.pointList >= 1 and pathFound == false then
+ local otherPt = this.pointList[#this.pointList]
+ if AllAxisInThreshhold(point, otherPt, 4) and (torso.CFrame.p - point).magnitude > (otherPt - point).magnitude then
+ local pathResult = {}
+ pathResult.Status = Enum.PathStatus.Success
+ function pathResult:GetPointCoordinates()
+ return {this.pointList}
+ end
+ this.pathResult = pathResult
+ pathFound = true
+ end
+ end
+ if (this.pathResult.Status == Enum.PathStatus.FailStartNotEmpty or this.pathResult.Status == Enum.PathStatus.ClosestNoPath) and pathFound == false then
+ local pathablePoints = this:CheckNeighboringCells(character)
+ for _, otherStart in pairs(pathablePoints) do
+ local pathResult;
+ local success = pcall(function()
+ pathResult = PathfindingService:ComputeSmoothPathAsync(otherStart, point, 400)
+ smoothed = true
+ end)
+ if not success then
+ pathResult = PathfindingService:ComputeRawPathAsync(otherStart, point, 400)
+ smoothed = false
+ end
+ if pathResult and pathResult.Status == Enum.PathStatus.Success then
+ this.pathResult = pathResult
+ if this.pathResult then
+ this.pointList = this.pathResult:GetPointCoordinates()
+ table.insert(this.pointList, 1, otherStart)
+ end
+ break
+ end
+ end
+ end
+ if DirectPathEnabled then
+ if this.pathResult.Status ~= Enum.PathStatus.Success then
+ local directPathResult = this:ComputeDirectPath()
+ if directPathResult and directPathResult.Status == Enum.PathStatus.Success then
+ this.pathResult = directPathResult
+ this.pointList = directPathResult:GetPointCoordinates()
+ end
+ end
+ end
+ end
+ return smoothed
+ end
+
+ function this:IsValidPath()
+ this:ComputePath()
+ local pathStatus = this.pathResult.Status
+ return pathStatus == Enum.PathStatus.Success
+ end
+
+ function this:GetPathStatus()
+ this:ComputePath()
+ return this.pathResult.Status
+ end
+
+ function this:Start()
+ if CurrentSeatPart then
+ return
+ end
+ spawn(function()
+ local humanoid = findPlayerHumanoid(Player)
+ --humanoid.AutoRotate = false
+ local torso = humanoid and humanoid.Torso
+ if torso then
+ if this.Started then return end
+ this.Started = true
+ -- Will yield the script since it is an Async function script (start, finish, maxDistance)
+ local smoothed = this:ComputePath()
+ if this:IsValidPath() then
+ this.PathStarted:fire()
+ -- smooth out zig-zaggy paths
+ local smoothPath = smoothed and this.pointList or this:SmoothPoints(this.pointList)
+ for i, point in pairs(smoothPath) do
+ if humanoid then
+ if this.Cancelled then
+ return
+ end
+
+ local wayPoint = nil
+ if SHOW_PATH then
+ wayPoint = CreateDestinationIndicator(point)
+ wayPoint.BrickColor = BrickColor.new("New Yeller")
+ wayPoint.Parent = workspace
+ print(wayPoint.CFrame.p)
+ end
+
+ humanoid:MoveTo(point)
+
+ local distance = ((torso.CFrame.p - point) * Vector3.new(1,0,1)).magnitude
+ local approxTime = 10
+ if math.abs(humanoid.WalkSpeed) > 0 then
+ approxTime = distance / math.abs(humanoid.WalkSpeed)
+ end
+
+ local yielding = true
+
+ if i == 1 then
+ --local rotatedCFrame = CameraModule:LookAtPreserveHeight(point)
+ if CameraModule then
+ local rotatedCFrame = CameraModule:LookAtPreserveHeight(smoothPath[#smoothPath])
+ local finishedSignal, duration = CameraModule:TweenCameraLook(rotatedCFrame)
+ end
+ --CharacterControl:SetTorsoLookPoint(point)
+ end
+ ---[[
+ if (humanoid.Torso.CFrame.p - point).magnitude > 9 then
+ spawn(function()
+ while yielding and this.Cancelled == false do
+ if CameraModule then
+ local look = CameraModule:GetCameraLook()
+ local squashedLook = (look * Vector3.new(1,0,1)).unit
+ local direction = ((point - CameraModule.cframe.p) * Vector3.new(1,0,1)).unit
+
+ local theta = math.deg(math.acos(squashedLook:Dot(direction)))
+
+ if tick() - Utility.GetLastInput() > 2 and theta > (workspace.CurrentCamera.FieldOfView / 2) then
+ local rotatedCFrame = CameraModule:LookAtPreserveHeight(point)
+ local finishedSignal, duration = CameraModule:TweenCameraLook(rotatedCFrame)
+ --return
+ end
+ end
+ wait(0.1)
+ end
+ end)
+ end
+ --]]
+ local didReach = this:YieldUntilPointReached(character, point, approxTime * 3 + 1)
+
+ yielding = false
+
+ if SHOW_PATH then
+ wayPoint:Destroy()
+ end
+
+ if not didReach then
+ this.PathFailed:fire()
+ return
+ end
+ end
+ end
+
+ this.Finished:fire()
+ return
+ end
+ end
+ this.PathFailed:fire()
+ end)
+ end
+
+ return this
+end
+
+-------------------------------------------------------------------------
+
+local function FlashRed(object)
+ local origColor = object.BrickColor
+ local redColor = BrickColor.new("Really red")
+ local start = tick()
+ local duration = 4
+ spawn(function()
+ while object and tick() - start < duration do
+ object.BrickColor = origColor
+ wait(0.13)
+ if object then
+ object.BrickColor = redColor
+ end
+ wait(0.13)
+ end
+ end)
+end
+
+--local joystickWidth = 250
+--local joystickHeight = 250
+local function IsInBottomLeft(pt)
+ local joystickHeight = math.min(Utility.ViewSizeY() * 0.33, 250)
+ local joystickWidth = joystickHeight
+ return pt.X <= joystickWidth and pt.Y > Utility.ViewSizeY() - joystickHeight
+end
+
+local function IsInBottomRight(pt)
+ local joystickHeight = math.min(Utility.ViewSizeY() * 0.33, 250)
+ local joystickWidth = joystickHeight
+ return pt.X >= Utility.ViewSizeX() - joystickWidth and pt.Y > Utility.ViewSizeY() - joystickHeight
+end
+
+local function CheckAlive(character)
+ local humanoid = findPlayerHumanoid(Player)
+ return humanoid ~= nil and humanoid.Health > 0
+end
+
+local function GetEquippedTool(character)
+ if character ~= nil then
+ for _, child in pairs(character:GetChildren()) do
+ if child:IsA('Tool') then
+ return child
+ end
+ end
+ end
+end
+
+local function ExploreWithRayCast(currentPoint, originDirection)
+ local TestDistance = 40
+ local TestVectors = {}
+ do
+ local forwardVector = originDirection;
+ for i = 0, 15 do
+ table.insert(TestVectors, CFrame.Angles(0, math.pi / 8 * i, 0) * forwardVector)
+ end
+ end
+
+ local testResults = {}
+ -- Heuristic should be something along the lines of distance and closeness to the traveling direction
+ local function ExploreHeuristic()
+ for _, testData in pairs(testResults) do
+ local walkDirection = -1 * originDirection
+ local directionCoeff = (walkDirection:Dot(testData['Vector']) + 1) / 2
+ local distanceCoeff = testData['Distance'] / TestDistance
+ testData["Value"] = directionCoeff * distanceCoeff
+ end
+ end
+
+ for i, vec in pairs(TestVectors) do
+ local hitPart, hitPos = Utility.Raycast(Ray.new(currentPoint, vec * TestDistance), true, {Player.Character})
+ if hitPos then
+ table.insert(testResults, {Vector = vec; Distance = (hitPos - currentPoint).magnitude})
+ else
+ table.insert(testResults, {Vector = vec; Distance = TestDistance})
+ end
+ end
+
+ ExploreHeuristic()
+
+ table.sort(testResults, function(a,b) return a["Value"] > b["Value"] end)
+
+ return testResults
+end
+
+local TapId = 1
+local ExistingPather = nil
+local ExistingIndicator = nil
+local PathCompleteListener = nil
+local PathFailedListener = nil
+
+local function CleanupPath()
+ DrivingTo = nil
+ if ExistingPather then
+ ExistingPather:Cancel()
+ end
+ if PathCompleteListener then
+ PathCompleteListener:disconnect()
+ PathCompleteListener = nil
+ end
+ if PathFailedListener then
+ PathFailedListener:disconnect()
+ PathFailedListener = nil
+ end
+ if ExistingIndicator then
+ DebrisService:AddItem(ExistingIndicator, 0)
+ ExistingIndicator = nil
+ end
+end
+
+local function getExtentsSize(Parts)
+ local maxX = Parts[1].Position.X
+ local maxY = Parts[1].Position.Y
+ local maxZ = Parts[1].Position.Z
+ local minX = Parts[1].Position.X
+ local minY = Parts[1].Position.Y
+ local minZ = Parts[1].Position.Z
+ for i = 2, #Parts do
+ maxX = math.max(maxX, Parts[i].Position.X)
+ maxY = math.max(maxY, Parts[i].Position.Y)
+ maxZ = math.max(maxZ, Parts[i].Position.Z)
+ minX = math.min(minX, Parts[i].Position.X)
+ minY = math.min(minY, Parts[i].Position.Y)
+ minZ = math.min(minZ, Parts[i].Position.Z)
+ end
+ return Region3.new(Vector3.new(minX, minY, minZ), Vector3.new(maxX, maxY, maxZ))
+end
+
+local function inExtents(Extents, Position)
+ if Position.X < (Extents.CFrame.p.X - Extents.Size.X/2) or Position.X > (Extents.CFrame.p.X + Extents.Size.X/2) then
+ return false
+ end
+ if Position.Z < (Extents.CFrame.p.Z - Extents.Size.Z/2) or Position.Z > (Extents.CFrame.p.Z + Extents.Size.Z/2) then
+ return false
+ end
+ --ignoring Y for now
+ return true
+end
+
+local AutoJumperInstance = nil
+local ShootCount = 0
+local FailCount = 0
+local function OnTap(tapPositions, goToPoint)
+ -- Good to remember if this is the latest tap event
+ TapId = TapId + 1
+ local thisTapId = TapId
+
+
+ local camera = workspace.CurrentCamera
+ local character = Player.Character
+
+
+ if not CheckAlive(character) then return end
+
+ -- This is a path tap position
+ if #tapPositions == 1 or goToPoint then
+ if camera then
+ local unitRay = Utility.GetUnitRay(tapPositions[1].x, tapPositions[1].y, MyMouse.ViewSizeX, MyMouse.ViewSizeY, camera)
+ local ray = Ray.new(unitRay.Origin, unitRay.Direction*400)
+ local hitPart, hitPt = Utility.Raycast(ray, true, {character})
+
+ local hitChar, hitHumanoid = Utility.FindChacterAncestor(hitPart)
+ local torso = character and character:FindFirstChild("Humanoid") and character:FindFirstChild("Humanoid").Torso
+ local startPos = torso.CFrame.p
+ if goToPoint then
+ hitPt = goToPoint
+ hitChar = nil
+ end
+ if hitChar and hitHumanoid and hitHumanoid.Torso and (hitHumanoid.Torso.CFrame.p - torso.CFrame.p).magnitude < 7 then
+ CleanupPath()
+
+ local myHumanoid = findPlayerHumanoid(Player)
+ if myHumanoid then
+ myHumanoid:MoveTo(hitPt)
+ end
+
+ ShootCount = ShootCount + 1
+ local thisShoot = ShootCount
+ -- Do shooot
+ local currentWeapon = GetEquippedTool(character)
+ if currentWeapon then
+ currentWeapon:Activate()
+ LastFired = tick()
+ end
+ elseif hitPt and character and not CurrentSeatPart then
+ local thisPather = Pather(character, hitPt)
+ if thisPather:IsValidPath() then
+ FailCount = 0
+ -- TODO: Remove when bug in engine is fixed
+ Player:Move(Vector3.new(1, 0, 0))
+ Player:Move(Vector3.new(0, 0, 0))
+ thisPather:Start()
+ if BindableEvent_OnFailStateChanged then
+ BindableEvent_OnFailStateChanged:Fire(false)
+ end
+ CleanupPath()
+
+ local destinationGlobe = CreateDestinationIndicator(hitPt)
+ destinationGlobe.Parent = camera
+
+ ExistingPather = thisPather
+ ExistingIndicator = destinationGlobe
+
+ if AutoJumperInstance then
+ AutoJumperInstance:Run()
+ end
+
+ PathCompleteListener = thisPather.Finished:connect(function()
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ end
+ if destinationGlobe then
+ if ExistingIndicator == destinationGlobe then
+ ExistingIndicator = nil
+ end
+ DebrisService:AddItem(destinationGlobe, 0)
+ destinationGlobe = nil
+ end
+ if hitChar then
+ local humanoid = findPlayerHumanoid(Player)
+ ShootCount = ShootCount + 1
+ local thisShoot = ShootCount
+ -- Do shoot
+ local currentWeapon = GetEquippedTool(character)
+ if currentWeapon then
+ currentWeapon:Activate()
+ LastFired = tick()
+ end
+ if humanoid then
+ humanoid:MoveTo(hitPt)
+ end
+ end
+ local finishPos = torso and torso.CFrame.p --hitPt
+ if finishPos and startPos and tick() - Utility.GetLastInput() > 2 then
+ local exploreResults = ExploreWithRayCast(finishPos, ((startPos - finishPos) * Vector3.new(1,0,1)).unit)
+ -- Check for Nans etc..
+ if exploreResults[1] and exploreResults[1]["Vector"] and exploreResults[1]["Vector"].magnitude >= 0.5 and exploreResults[1]["Distance"] > 3 then
+ if CameraModule then
+ local rotatedCFrame = CameraModule:LookAtPreserveHeight(finishPos + exploreResults[1]["Vector"] * exploreResults[1]["Distance"])
+ local finishedSignal, duration = CameraModule:TweenCameraLook(rotatedCFrame)
+ end
+ end
+ end
+ end)
+ PathFailedListener = thisPather.PathFailed:connect(function()
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ end
+ if destinationGlobe then
+ FlashRed(destinationGlobe)
+ DebrisService:AddItem(destinationGlobe, 3)
+ end
+ end)
+ else
+ if hitPt then
+ -- Feedback here for when we don't have a good path
+ local failedGlobe = CreateDestinationIndicator(hitPt)
+ FlashRed(failedGlobe)
+ DebrisService:AddItem(failedGlobe, 1)
+ failedGlobe.Parent = camera
+ if ExistingIndicator == nil then
+ FailCount = FailCount + 1
+ if FailCount >= 3 then
+ if BindableEvent_OnFailStateChanged then
+ BindableEvent_OnFailStateChanged:Fire(true)
+ end
+ CleanupPath()
+ end
+ end
+ end
+ end
+ elseif hitPt and character and CurrentSeatPart then
+ local destinationGlobe = CreateDestinationIndicator(hitPt)
+ destinationGlobe.Parent = camera
+ ExistingIndicator = destinationGlobe
+ DrivingTo = hitPt
+ local ConnectedParts = CurrentSeatPart:GetConnectedParts(true)
+
+ while wait() do
+ if CurrentSeatPart and ExistingIndicator == destinationGlobe then
+ local ExtentsSize = getExtentsSize(ConnectedParts)
+ if inExtents(ExtentsSize, destinationGlobe.Position) then
+ DebrisService:AddItem(destinationGlobe, 0)
+ destinationGlobe = nil
+ DrivingTo = nil
+ break
+ end
+ else
+ DebrisService:AddItem(destinationGlobe, 0)
+ if CurrentSeatPart == nil and destinationGlobe == ExistingIndicator then
+ DrivingTo = nil
+ OnTap(tapPositions, hitPt)
+ end
+ destinationGlobe = nil
+ break
+ end
+ end
+
+ else
+ -- no hit pt
+ end
+ end
+ elseif #tapPositions >= 2 then
+ if camera then
+ ShootCount = ShootCount + 1
+ local thisShoot = ShootCount
+ -- Do shoot
+ local avgPoint = Utility.AveragePoints(tapPositions)
+ local unitRay = Utility.GetUnitRay(avgPoint.x, avgPoint.y, MyMouse.ViewSizeX, MyMouse.ViewSizeY, camera)
+ local currentWeapon = GetEquippedTool(character)
+ if currentWeapon then
+ currentWeapon:Activate()
+ LastFired = tick()
+ end
+ end
+ end
+end
+
+
+local function CreateClickToMoveModule()
+ local this = {}
+
+ local LastStateChange = 0
+ local LastState = Enum.HumanoidStateType.Running
+ local FingerTouches = {}
+ local NumUnsunkTouches = 0
+ -- PC simulation
+ local mouse1Down = tick()
+ local mouse1DownPos = Vector2.new()
+ local mouse2Down = tick()
+ local mouse2DownPos = Vector2.new()
+ local mouse2Up = tick()
+
+ local movementKeys = {
+ [Enum.KeyCode.W] = true;
+ [Enum.KeyCode.A] = true;
+ [Enum.KeyCode.S] = true;
+ [Enum.KeyCode.D] = true;
+ [Enum.KeyCode.Up] = true;
+ [Enum.KeyCode.Down] = true;
+ }
+
+ local TapConn = nil
+ local InputBeganConn = nil
+ local InputChangedConn = nil
+ local InputEndedConn = nil
+ local HumanoidDiedConn = nil
+ local CharacterChildAddedConn = nil
+ local OnCharacterAddedConn = nil
+ local CharacterChildRemovedConn = nil
+ local RenderSteppedConn = nil
+ local HumanoidSeatedConn = nil
+
+ local function disconnectEvent(event)
+ if event then
+ event:disconnect()
+ end
+ end
+
+ local function DisconnectEvents()
+ disconnectEvent(TapConn)
+ disconnectEvent(InputBeganConn)
+ disconnectEvent(InputChangedConn)
+ disconnectEvent(InputEndedConn)
+ disconnectEvent(HumanoidDiedConn)
+ disconnectEvent(CharacterChildAddedConn)
+ disconnectEvent(OnCharacterAddedConn)
+ disconnectEvent(RenderSteppedConn)
+ disconnectEvent(CharacterChildRemovedConn)
+ pcall(function() RunService:UnbindFromRenderStep("ClickToMoveRenderUpdate") end)
+ disconnectEvent(HumanoidSeatedConn)
+ end
+
+
+
+ local function IsFinite(num)
+ return num == num and num ~= 1/0 and num ~= -1/0
+ end
+
+ local function findAngleBetweenXZVectors(vec2, vec1)
+ return math.atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z)
+ end
+
+ -- Setup the camera
+ CameraModule = ClassicCameraModule()
+
+ do
+ -- Extend The Camera Module Class
+ function CameraModule:LookAtPreserveHeight(newLookAtPt)
+ local camera = workspace.CurrentCamera
+
+ local focus = camera.Focus.p
+
+ local cameraCFrame = CameraModule.cframe
+ local mag = Vector3.new(cameraCFrame.lookVector.x, 0, cameraCFrame.lookVector.z).magnitude
+ local newLook = (Vector3.new(newLookAtPt.x, focus.y, newLookAtPt.z) - focus).unit * mag
+ local flippedLook = newLook + Vector3.new(0, cameraCFrame.lookVector.y, 0)
+
+ local distance = (focus - cameraCFrame.p).magnitude
+
+ local newCamPos = focus - flippedLook.unit * distance
+ return CFrame.new(newCamPos, newCamPos + flippedLook)
+ end
+
+ function CameraModule:TweenCameraLook(desiredCFrame, speed)
+ local e = 2.718281828459
+ local function SCurve(t)
+ return 1/(1 + e^(-t*1.5))
+ end
+ local function easeOutSine(t, b, c, d)
+ if t >= d then return b + c end
+ return c * math.sin(t/d * (math.pi/2)) + b;
+ end
+
+ local theta, interper = CFrameInterpolator(CFrame.new(Vector3.new(), self:GetCameraLook()), desiredCFrame - desiredCFrame.p)
+ theta = Utility.Clamp(0, math.pi, theta)
+ local duration = 0.65 * SCurve(theta - math.pi/4) + 0.15
+ if speed then
+ duration = theta / speed
+ end
+ local start = tick()
+ local finish = start + duration
+
+ self.UpdateTweenFunction = function()
+ local currTime = tick() - start
+ local alpha = Utility.Clamp(0, 1, easeOutSine(currTime, 0, 1, duration))
+ local newCFrame = interper(alpha)
+ local y = findAngleBetweenXZVectors(newCFrame.lookVector, self:GetCameraLook())
+ if IsFinite(y) and math.abs(y) > 0.0001 then
+ self.RotateInput = self.RotateInput + Vector2.new(y, 0)
+ end
+ return (currTime >= finish or alpha >= 1)
+ end
+ end
+ end
+ --- Done Extending
+
+
+ local function OnTouchBegan(input, processed)
+ if FingerTouches[input] == nil and not processed then
+ NumUnsunkTouches = NumUnsunkTouches + 1
+ end
+ FingerTouches[input] = processed
+ end
+
+ local function OnTouchChanged(input, processed)
+ if FingerTouches[input] == nil then
+ FingerTouches[input] = processed
+ if not processed then
+ NumUnsunkTouches = NumUnsunkTouches + 1
+ end
+ end
+ end
+
+ local function OnTouchEnded(input, processed)
+ --print("Touch tap fake:" , processed)
+ --if not processed then
+ -- OnTap({input.Position})
+ --end
+ if FingerTouches[input] ~= nil and FingerTouches[input] == false then
+ NumUnsunkTouches = NumUnsunkTouches - 1
+ end
+ FingerTouches[input] = nil
+ end
+
+
+ local function OnCharacterAdded(character)
+ DisconnectEvents()
+
+ InputBeganConn = UIS.InputBegan:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchBegan(input, processed)
+
+
+ -- Give back controls when they tap both sticks
+ local wasInBottomLeft = IsInBottomLeft(input.Position)
+ local wasInBottomRight = IsInBottomRight(input.Position)
+ if wasInBottomRight or wasInBottomLeft then
+ for otherInput, _ in pairs(FingerTouches) do
+ if otherInput ~= input then
+ local otherInputInLeft = IsInBottomLeft(otherInput.Position)
+ local otherInputInRight = IsInBottomRight(otherInput.Position)
+ if otherInput.UserInputState ~= Enum.UserInputState.End and ((wasInBottomLeft and otherInputInRight) or (wasInBottomRight and otherInputInLeft)) then
+ if BindableEvent_OnFailStateChanged then
+ BindableEvent_OnFailStateChanged:Fire(true)
+ end
+ return
+ end
+ end
+ end
+ end
+ end
+
+ -- Cancel path when you use the keyboard controls.
+ if processed == false and input.UserInputType == Enum.UserInputType.Keyboard and movementKeys[input.KeyCode] then
+ CleanupPath()
+ end
+ if input.UserInputType == Enum.UserInputType.MouseButton1 then
+ mouse1Down = tick()
+ mouse1DownPos = input.Position
+ end
+ if input.UserInputType == Enum.UserInputType.MouseButton2 then
+ mouse2Down = tick()
+ mouse2DownPos = input.Position
+ end
+ end)
+
+ InputChangedConn = UIS.InputChanged:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchChanged(input, processed)
+ end
+ end)
+
+ InputEndedConn = UIS.InputEnded:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchEnded(input, processed)
+ end
+
+ if input.UserInputType == Enum.UserInputType.MouseButton2 then
+ mouse2Up = tick()
+ local currPos = input.Position
+ if mouse2Up - mouse2Down < 0.25 and (currPos - mouse2DownPos).magnitude < 5 then
+ local positions = {currPos}
+ OnTap(positions)
+ end
+ end
+ end)
+
+ TapConn = UIS.TouchTap:connect(function(touchPositions, processed)
+ if not processed then
+ OnTap(touchPositions)
+ end
+ end)
+
+ if not UIS.TouchEnabled then -- PC
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ AutoJumperInstance = nil
+ end
+ AutoJumperInstance = AutoJumper()
+ end
+
+ local function getThrottleAndSteer(object, point)
+ local lookVector = (point - object.Position)
+ lookVector = Vector3.new(lookVector.X, 0, lookVector.Z).unit
+ local objectVector = Vector3.new(object.CFrame.lookVector.X, 0, object.CFrame.lookVector.Z).unit
+ local dirVector = lookVector - objectVector
+ local mag = dirVector.magnitude
+ local degrees = math.deg(math.acos(lookVector:Dot(objectVector)))
+ local side = (object.CFrame:pointToObjectSpace(point).X > 0)
+ local throttle = 0
+ if mag < 0.25 then
+ throttle = 1
+ end
+ if mag > 1.8 then
+ throttle = -1
+ end
+ local distance = CurrentSeatPart.Position - DrivingTo
+ local velocity = CurrentSeatPart.Velocity
+ if velocity.magnitude*1.5 > distance.magnitude then
+ if velocity.magnitude*0.5 > distance.magnitude then
+ throttle = -throttle
+ else
+ throttle = 0
+ end
+ end
+ local steer = 0
+ if degrees > 5 and degrees < 175 then
+ if side then
+ steer = 1
+ else
+ steer = -1
+ end
+ end
+ local rotatingAt = math.deg(CurrentSeatPart.RotVelocity.magnitude)
+ local degreesAway = math.max(math.min(degrees, 180 - degrees), 10)
+ if (CurrentSeatPart.RotVelocity.X < 0)== (steer < 0) then
+ if rotatingAt*1.5 > degreesAway then
+ if rotatingAt*0.5 > degreesAway then
+ steer = -steer
+ else
+ steer = 0
+ end
+ end
+ end
+ return throttle, steer
+ end
+
+ local function Update()
+ if CameraModule then
+ if CameraModule.UserPanningTheCamera then
+ CameraModule.UpdateTweenFunction = nil
+ else
+ if CameraModule.UpdateTweenFunction then
+ local done = CameraModule.UpdateTweenFunction()
+ if done then
+ CameraModule.UpdateTweenFunction = nil
+ end
+ end
+ end
+ CameraModule:Update()
+ end
+ if CurrentSeatPart then
+ if DrivingTo then
+ local throttle, steer = getThrottleAndSteer(CurrentSeatPart, DrivingTo)
+ CurrentSeatPart.Throttle = throttle
+ CurrentSeatPart.Steer = steer
+ end
+ end
+ end
+
+ local success = pcall(function() RunService:BindToRenderStep("ClickToMoveRenderUpdate",Enum.RenderPriority.Camera.Value - 1,Update) end)
+ if not success then
+ if RenderSteppedConn then
+ RenderSteppedConn:disconnect()
+ end
+ RenderSteppedConn = RunService.RenderStepped:connect(Update)
+ end
+
+ local WasAutoJumper = false
+ local WasAutoJumpMobile = false
+ local function onSeated(child, active, currentSeatPart)
+ if active then
+ if BindableEvent_EnableTouchJump then
+ BindableEvent_EnableTouchJump:Fire(true)
+ end
+ if currentSeatPart.ClassName == "VehicleSeat" then
+ CurrentSeatPart = currentSeatPart
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ AutoJumperInstance = nil
+ WasAutoJumper = true
+ else
+ WasAutoJumper = false
+ end
+ if child.AutoJumpEnabled then
+ WasAutoJumpMobile = true
+ child.AutoJumpEnabled = false
+ end
+ end
+ else
+ CurrentSeatPart = nil
+ if BindableEvent_EnableTouchJump then
+ BindableEvent_EnableTouchJump:Fire(false)
+ end
+ if WasAutoJumper then
+ AutoJumperInstance = AutoJumper()
+ WasAutoJumper = false
+ end
+ if WasAutoJumpMobile then
+ child.AutoJumpEnabled = true
+ WasAutoJumpMobile = false
+ end
+ end
+ end
+
+ local function OnCharacterChildAdded(child)
+ if UIS.TouchEnabled then
+ if child:IsA('Tool') then
+ child.ManualActivationOnly = true
+ end
+ end
+ if child:IsA('Humanoid') then
+ disconnectEvent(HumanoidDiedConn)
+ HumanoidDiedConn = child.Died:connect(function()
+ DebrisService:AddItem(ExistingIndicator, 1)
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ AutoJumperInstance = nil
+ end
+ end)
+ local WasAutoJumper = false
+ local WasAutoJumpMobile = false
+ HumanoidSeatedConn = child.Seated:connect(function(active, seat) onSeated(child, active, seat) end)
+ if child.SeatPart then
+ onSeated(child, true, child.SeatPart)
+ end
+ end
+ end
+
+ CharacterChildAddedConn = character.ChildAdded:connect(function(child)
+ OnCharacterChildAdded(child)
+ end)
+ CharacterChildRemovedConn = character.ChildRemoved:connect(function(child)
+ if UIS.TouchEnabled then
+ if child:IsA('Tool') then
+ child.ManualActivationOnly = false
+ end
+ end
+ end)
+ for _, child in pairs(character:GetChildren()) do
+ OnCharacterChildAdded(child)
+ end
+ end
+
+ local Running = false
+
+ function this:Stop()
+ if Running then
+ DisconnectEvents()
+ CleanupPath()
+ if AutoJumperInstance then
+ AutoJumperInstance:Stop()
+ AutoJumperInstance = nil
+ end
+ if CameraModule then
+ CameraModule.UpdateTweenFunction = nil
+ CameraModule:SetEnabled(false)
+ end
+ -- Restore tool activation on shutdown
+ if UIS.TouchEnabled then
+ local character = Player.Character
+ if character then
+ for _, child in pairs(character:GetChildren()) do
+ if child:IsA('Tool') then
+ child.ManualActivationOnly = false
+ end
+ end
+ end
+ end
+ DrivingTo = nil
+ Running = false
+ end
+ end
+
+ function this:Start()
+ if not Running then
+ if Player.Character then -- retro-listen
+ OnCharacterAdded(Player.Character)
+ end
+ OnCharacterAddedConn = Player.CharacterAdded:connect(OnCharacterAdded)
+ if CameraModule then
+ CameraModule:SetEnabled(true)
+ end
+ Running = true
+ end
+ end
+
+ return this
+end
+
+return CreateClickToMoveModule
+]]>
+
+
+-
+
+ Invisicam
+ originalFade then
+ hit.LocalTransparencyModifier = math.max(originalFade, currentFade - FADE_RATE)
+ else
+ SavedHits[hit] = nil
+ end
+ end
+ end
+end
+
+function Invisicam:SetMode(newMode)
+ AssertTypes(newMode, 'number')
+ for modeName, modeNum in pairs(MODE) do
+ if modeNum == newMode then
+ Mode = newMode
+ return
+ end
+ end
+ error("Invalid mode number")
+end
+
+function Invisicam:SetCustomBehavior(func)
+ AssertTypes(func, 'function')
+ Behaviors[MODE.CUSTOM] = func
+end
+
+-- Want to turn off Invisicam? Be sure to call this after.
+function Invisicam:Cleanup()
+ for hit, originalFade in pairs(SavedHits) do
+ hit.LocalTransparencyModifier = originalFade
+ end
+end
+
+---------------------
+--| Running Logic |--
+---------------------
+
+-- Connect to the current and all future cameras
+workspace.Changed:connect(OnWorkspaceChanged)
+OnWorkspaceChanged('CurrentCamera')
+
+Player.CharacterAdded:connect(OnCharacterAdded)
+if Player.Character then
+ OnCharacterAdded(Player.Character)
+end
+
+Invisicam:SetMode(STARTING_MODE)
+
+Behaviors[MODE.CUSTOM] = function() end -- (Does nothing until SetCustomBehavior)
+Behaviors[MODE.LIMBS] = LimbBehavior
+Behaviors[MODE.MOVEMENT] = MoveBehavior
+Behaviors[MODE.CORNERS] = CornerBehavior
+Behaviors[MODE.CIRCLE1] = CircleBehavior
+Behaviors[MODE.CIRCLE2] = CircleBehavior
+Behaviors[MODE.LIMBMOVE] = LimbMoveBehavior
+
+return Invisicam
+]]>
+
+
+-
+
+
+ PopperCam
+ 0.95 or hitPart.CanCollide == false) then
+ table.insert(ignoreList, hitPart)
+ else
+ return hitPart, hitPoint
+ end
+ until false
+end
+
+local function ScreenToWorld(screenPoint, screenSize, pushDepth)
+ local cameraFOV, cameraCFrame = Camera.FieldOfView, Camera.CoordinateFrame
+ local imagePlaneDepth = screenSize.y / (2 * math.tan(math.rad(cameraFOV) / 2))
+ local direction = Vector3.new(screenPoint.x - (screenSize.x / 2), (screenSize.y / 2) - screenPoint.y, -imagePlaneDepth)
+ local worldDirection = (cameraCFrame:vectorToWorldSpace(direction)).Unit
+ local theta = math.acos(math.min(1, worldDirection:Dot(cameraCFrame.lookVector)))
+ local fixedPushDepth = pushDepth / math.sin((math.pi / 2) - theta)
+ return cameraCFrame.p + worldDirection * fixedPushDepth
+end
+
+local function OnCameraChanged(property)
+ if property == 'CameraSubject' then
+ VehicleParts = {}
+
+ local newSubject = Camera.CameraSubject
+ if newSubject then
+ -- Determine if we should be popping at all
+ PopperEnabled = false
+ for _, subjectType in pairs(VALID_SUBJECTS) do
+ if newSubject:IsA(subjectType) then
+ PopperEnabled = true
+ break
+ end
+ end
+
+ -- Get all parts of the vehicle the player is controlling
+ if newSubject:IsA('VehicleSeat') then
+ VehicleParts = newSubject:GetConnectedParts(true)
+ end
+ end
+ end
+end
+
+local function OnCharacterAdded(player, character)
+ PlayerCharacters[player] = character
+end
+
+local function OnPlayersChildAdded(child)
+ if child:IsA('Player') then
+ child.CharacterAdded:connect(function(character)
+ OnCharacterAdded(child, character)
+ end)
+ if child.Character then
+ OnCharacterAdded(child, child.Character)
+ end
+ end
+end
+
+local function OnPlayersChildRemoved(child)
+ if child:IsA('Player') then
+ PlayerCharacters[child] = nil
+ end
+end
+
+local function OnWorkspaceChanged(property)
+ if property == 'CurrentCamera' then
+ local newCamera = workspace.CurrentCamera
+ if newCamera then
+ Camera = newCamera
+
+ if CameraChangeConn then
+ CameraChangeConn:disconnect()
+ end
+ CameraChangeConn = Camera.Changed:connect(OnCameraChanged)
+ OnCameraChanged('CameraSubject')
+ end
+ end
+end
+
+-------------------------
+--| Exposed Functions |--
+-------------------------
+
+function PopperCam:Update()
+ if PopperEnabled then
+ -- First, prep some intermediate vars
+ local focusPoint = Camera.Focus.p
+ local cameraCFrame = Camera.CoordinateFrame
+ local cameraFrontPoint = cameraCFrame.p + (cameraCFrame.lookVector * NEAR_CLIP_PLANE_OFFSET)
+ local screenSize = Camera.ViewportSize
+ local ignoreList = {}
+ for _, character in pairs(PlayerCharacters) do
+ table.insert(ignoreList, character)
+ end
+ for _, basePart in pairs(VehicleParts) do
+ table.insert(ignoreList, basePart)
+ end
+
+ -- Cast rays at the near clip plane, from corresponding points near the focus point,
+ -- and find the direct line that is the most cut off
+ local largest = 0
+ for _, screenScale in pairs(CAST_SCREEN_SCALES) do
+ local clipWorldPoint = ScreenToWorld(screenSize * screenScale, screenSize, NEAR_CLIP_PLANE_OFFSET)
+ local rayStartPoint = focusPoint + (clipWorldPoint - cameraFrontPoint)
+ local _, hitPoint = PiercingCast(rayStartPoint, clipWorldPoint, ignoreList)
+ local cutoffAmount = (hitPoint - clipWorldPoint).Magnitude
+ if cutoffAmount > largest then
+ largest = cutoffAmount
+ end
+ end
+
+ -- Then check if the player zoomed since the last frame,
+ -- and if so, reset our pop history so we stop tweening
+ local zoomLevel = (cameraCFrame.p - focusPoint).Magnitude
+ if math.abs(zoomLevel - LastZoomLevel) > 0.001 then
+ LastPopAmount = 0
+ end
+
+ -- Finally, zoom the camera in (pop) by that most-cut-off amount, or the last pop amount if that's more
+ local popAmount = math.max(largest, LastPopAmount)
+ if popAmount > 0 then
+ Camera.CoordinateFrame = cameraCFrame + (cameraCFrame.lookVector * popAmount)
+ LastPopAmount = math.max(0, popAmount - POP_RESTORE_RATE) -- Shrink it for the next frame
+ end
+
+ LastZoomLevel = zoomLevel
+ end
+end
+
+--------------------
+--| Script Logic |--
+--------------------
+
+-- Connect to the current and all future cameras
+workspace.Changed:connect(OnWorkspaceChanged)
+OnWorkspaceChanged('CurrentCamera')
+
+-- Connect to all Players so we can ignore their Characters
+PlayersService.ChildRemoved:connect(OnPlayersChildRemoved)
+PlayersService.ChildAdded:connect(OnPlayersChildAdded)
+for _, player in pairs(PlayersService:GetPlayers()) do
+ OnPlayersChildAdded(player)
+end
+
+return PopperCam
+]]>
+
+
+-
+
+
+ RootCamera
+ = 0 then
+ return (k*t) / (k - t + 1)
+ end
+ return -((lowerK*-t) / (lowerK + t + 1))
+ end
+
+ -- DEADZONE
+ local DEADZONE = 0.1
+ local function toSCurveSpace(t)
+ return (1 + DEADZONE) * (2*math.abs(t) - 1) - DEADZONE
+ end
+
+ local function fromSCurveSpace(t)
+ return t/2 + 0.5
+ end
+
+ local function gamepadLinearToCurve(thumbstickPosition)
+ local function onAxis(axisValue)
+ local sign = 1
+ if axisValue < 0 then
+ sign = -1
+ end
+ local point = fromSCurveSpace(SCurveTranform(toSCurveSpace(math.abs(axisValue))))
+ point = point * sign
+ return clamp(-1,1,point)
+ end
+ return Vector2.new(onAxis(thumbstickPosition.x), onAxis(thumbstickPosition.y))
+ end
+
+ function this:UpdateGamepad()
+ local gamepadPan = this.GamepadPanningCamera
+ if gamepadPan then
+ gamepadPan = gamepadLinearToCurve(gamepadPan)
+ local currentTime = tick()
+ if gamepadPan.X ~= 0 or gamepadPan.Y ~= 0 then
+ this.userPanningTheCamera = true
+ elseif gamepadPan == Vector2.new(0,0) then
+ lastThumbstickRotate = nil
+ if lastThumbstickPos == Vector2.new(0,0) then
+ currentSpeed = 0
+ end
+ end
+
+ local finalConstant = 0
+
+ if lastThumbstickRotate then
+ local elapsedTime = (currentTime - lastThumbstickRotate) * 10
+ currentSpeed = currentSpeed + (maxSpeed * ((elapsedTime*elapsedTime)/numOfSeconds))
+
+ if currentSpeed > maxSpeed then currentSpeed = maxSpeed end
+
+ if lastVelocity then
+ local velocity = (gamepadPan - lastThumbstickPos)/(currentTime - lastThumbstickRotate)
+ local velocityDeltaMag = (velocity - lastVelocity).magnitude
+
+ if velocityDeltaMag > 12 then
+ currentSpeed = currentSpeed * (20/velocityDeltaMag)
+ if currentSpeed > maxSpeed then currentSpeed = maxSpeed end
+ end
+ end
+
+ finalConstant = thumbstickSensitivity * currentSpeed
+ lastVelocity = (gamepadPan - lastThumbstickPos)/(currentTime - lastThumbstickRotate)
+ end
+
+ lastThumbstickPos = gamepadPan
+ lastThumbstickRotate = currentTime
+
+ return Vector2.new( gamepadPan.X * finalConstant, gamepadPan.Y * finalConstant * ySensitivity)
+ end
+
+ return Vector2.new(0,0)
+ end
+
+ local InputBeganConn, InputChangedConn, InputEndedConn, ShiftLockToggleConn, GamepadConnectedConn, GamepadDisconnectedConn = nil, nil, nil, nil, nil, nil
+
+ function this:DisconnectInputEvents()
+ if InputBeganConn then
+ InputBeganConn:disconnect()
+ InputBeganConn = nil
+ end
+ if InputChangedConn then
+ InputChangedConn:disconnect()
+ InputChangedConn = nil
+ end
+ if InputEndedConn then
+ InputEndedConn:disconnect()
+ InputEndedConn = nil
+ end
+ if ShiftLockToggleConn then
+ ShiftLockToggleConn:disconnect()
+ ShiftLockToggleConn = nil
+ end
+ if GamepadConnectedConn then
+ GamepadConnectedConn:disconnect()
+ GamepadConnectedConn = nil
+ end
+ if GamepadDisconnectedConn then
+ GamepadDisconnectedConn:disconnect()
+ GamepadDisconnectedConn = nil
+ end
+ this.TurningLeft = false
+ this.TurningRight = false
+ this.LastCameraTransform = nil
+ self.LastSubjectCFrame = nil
+ this.UserPanningTheCamera = false
+ this.RotateInput = Vector2.new()
+ this.GamepadPanningCamera = Vector2.new(0,0)
+
+ -- Reset input states
+ startPos = nil
+ lastPos = nil
+ panBeginLook = nil
+ isRightMouseDown = false
+ isMiddleMouseDown = false
+
+ fingerTouches = {}
+ NumUnsunkTouches = 0
+
+ StartingDiff = nil
+ pinchBeginZoom = nil
+
+ -- Unlock mouse for example if right mouse button was being held down
+ if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then
+ UserInputService.MouseBehavior = Enum.MouseBehavior.Default
+ end
+ end
+
+ function this:ConnectInputEvents()
+ InputBeganConn = UserInputService.InputBegan:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchBegan(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
+ OnMouse2Down(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseButton3 then
+ OnMouse3Down(input, processed)
+ end
+ -- Keyboard
+ if input.UserInputType == Enum.UserInputType.Keyboard then
+ OnKeyDown(input, processed)
+ end
+ end)
+
+ InputChangedConn = UserInputService.InputChanged:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchChanged(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseMovement then
+ OnMouseMoved(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseWheel then
+ OnMouseWheel(input, processed)
+ end
+ end)
+
+ InputEndedConn = UserInputService.InputEnded:connect(function(input, processed)
+ if input.UserInputType == Enum.UserInputType.Touch then
+ OnTouchEnded(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
+ OnMouse2Up(input, processed)
+ elseif input.UserInputType == Enum.UserInputType.MouseButton3 then
+ OnMouse3Up(input, processed)
+ end
+ -- Keyboard
+ if input.UserInputType == Enum.UserInputType.Keyboard then
+ OnKeyUp(input, processed)
+ end
+ end)
+
+ ShiftLockToggleConn = ShiftLockController.OnShiftLockToggled.Event:connect(function()
+ this:UpdateMouseBehavior()
+ end)
+
+ this.RotateInput = Vector2.new()
+
+ local activateGamepad = nil
+ local function assignActivateGamepad()
+ local connectedGamepads = UserInputService:GetConnectedGamepads()
+ if #connectedGamepads > 0 then
+ for i = 1, #connectedGamepads do
+ if activateGamepad == nil then
+ activateGamepad = connectedGamepads[i]
+ elseif connectedGamepads[i].Value < activateGamepad.Value then
+ activateGamepad = connectedGamepads[i]
+ end
+ end
+ end
+
+ if activateGamepad == nil then -- nothing is connected, at least set up for gamepad1
+ activateGamepad = Enum.UserInputType.Gamepad1
+ end
+ end
+
+ GamepadConnectedConn = UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
+ if activateGamepad ~= gamepadEnum then return end
+ activateGamepad = nil
+ assignActivateGamepad()
+ end)
+
+ GamepadDisconnectedConn = UserInputService.GamepadConnected:connect(function(gamepadEnum)
+ if activateGamepad == nil then
+ assignActivateGamepad()
+ end
+ end)
+
+ local getGamepadPan = function(name, state, input)
+ if input.UserInputType == activateGamepad and input.KeyCode == Enum.KeyCode.Thumbstick2 then
+
+ if state == Enum.UserInputState.Cancel then
+ this.GamepadPanningCamera = Vector2.new(0,0)
+ return
+ end
+
+ local inputVector = Vector2.new(input.Position.X, -input.Position.Y)
+ if inputVector.magnitude > THUMBSTICK_DEADZONE then
+ this.GamepadPanningCamera = Vector2.new(input.Position.X, -input.Position.Y)
+ else
+ this.GamepadPanningCamera = Vector2.new(0,0)
+ end
+ end
+ end
+
+ local doGamepadZoom = function(name, state, input)
+ if input.UserInputType == activateGamepad and input.KeyCode == Enum.KeyCode.ButtonR3 and state == Enum.UserInputState.Begin then
+ if this.ZoomEnabled then
+ if this.currentZoom > 0.5 then
+ this:ZoomCamera(0)
+ else
+ this:ZoomCamera(10)
+ end
+ end
+ end
+ end
+
+ game.ContextActionService:BindAction("RootCamGamepadPan", getGamepadPan, false, Enum.KeyCode.Thumbstick2)
+ game.ContextActionService:BindAction("RootCamGamepadZoom", doGamepadZoom, false, Enum.KeyCode.ButtonR3)
+
+ assignActivateGamepad()
+
+ -- set mouse behavior
+ self:UpdateMouseBehavior()
+ end
+
+ function this:SetEnabled(newState)
+ if newState ~= self.Enabled then
+ self.Enabled = newState
+ if self.Enabled then
+ self:ConnectInputEvents()
+ self.cframe = workspace.CurrentCamera.CoordinateFrame
+ else
+ self:DisconnectInputEvents()
+ end
+ end
+ end
+
+ local function OnPlayerAdded(player)
+ player.Changed:connect(function(prop)
+ if this.Enabled then
+ if prop == "CameraMode" or prop == "CameraMaxZoomDistance" or prop == "CameraMinZoomDistance" then
+ this:ZoomCameraFixedBy(0)
+ end
+ end
+ end)
+
+ local function OnCharacterAdded(newCharacter)
+ this:ZoomCamera(12.5)
+ local humanoid = findPlayerHumanoid(player)
+ local start = tick()
+ while tick() - start < 0.3 and (humanoid == nil or humanoid.Torso == nil) do
+ wait()
+ humanoid = findPlayerHumanoid(player)
+ end
+ local function setLookBehindCharacter()
+ if humanoid and humanoid.Torso and player.Character == newCharacter then
+ local newDesiredLook = (humanoid.Torso.CFrame.lookVector - Vector3.new(0,0.23,0)).unit
+ local horizontalShift = findAngleBetweenXZVectors(newDesiredLook, this:GetCameraLook())
+ local vertShift = math.asin(this:GetCameraLook().y) - math.asin(newDesiredLook.y)
+ if not IsFinite(horizontalShift) then
+ horizontalShift = 0
+ end
+ if not IsFinite(vertShift) then
+ vertShift = 0
+ end
+ this.RotateInput = Vector2.new(horizontalShift, vertShift)
+
+ -- reset old camera info so follow cam doesn't rotate us
+ this.LastCameraTransform = nil
+ end
+ end
+ wait()
+ setLookBehindCharacter()
+ end
+
+ player.CharacterAdded:connect(function(character)
+ if this.Enabled or SetCameraOnSpawn then
+ OnCharacterAdded(character)
+ SetCameraOnSpawn = false
+ end
+ end)
+ if player.Character then
+ spawn(function() OnCharacterAdded(player.Character) end)
+ end
+ end
+ if PlayersService.LocalPlayer then
+ OnPlayerAdded(PlayersService.LocalPlayer)
+ end
+ PlayersService.ChildAdded:connect(function(child)
+ if child and PlayersService.LocalPlayer == child then
+ OnPlayerAdded(PlayersService.LocalPlayer)
+ end
+ end)
+
+ return this
+end
+
+return CreateCamera
+]]>
+
+
-
+
+
+ AttachCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ end
+
+ local subjectPosition = self:GetSubjectPosition()
+ if subjectPosition and player and camera then
+ local zoom = self:GetCameraZoom()
+ if zoom <= 0 then
+ zoom = 0.1
+ end
+
+
+ local humanoid = self:GetHumanoid()
+ if lastUpdate and humanoid and humanoid.Torso then
+
+ -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
+ local delta = math.min(0.1, now - lastUpdate)
+ local gamepadRotation = self:UpdateGamepad()
+ self.RotateInput = self.RotateInput + (gamepadRotation * delta)
+
+ local forwardVector = humanoid.Torso.CFrame.lookVector
+
+ local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook())
+ if IsFinite(y) then
+ -- Preserve vertical rotation from user input
+ self.RotateInput = Vector2.new(y, self.RotateInput.Y)
+ end
+ end
+
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+
+
+ camera.Focus = CFrame.new(subjectPosition)
+ camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p)
+ self.LastCameraTransform = camera.CoordinateFrame
+ end
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateAttachCamera
+]]>
+
+
+-
+
+
+ ClassicCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ end
+
+ if lastUpdate then
+ -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
+ local delta = math.min(0.1, now - lastUpdate)
+ local angle = 0
+ if not (isInVehicle or isOnASkateboard) then
+ angle = angle + (self.TurningLeft and -120 or 0)
+ angle = angle + (self.TurningRight and 120 or 0)
+ end
+
+ local gamepadRotation = self:UpdateGamepad()
+ if gamepadRotation ~= Vector2.new(0,0) then
+ userPanningTheCamera = true
+ self.RotateInput = self.RotateInput + (gamepadRotation * delta)
+ end
+
+ if angle ~= 0 then
+ userPanningTheCamera = true
+ self.RotateInput = self.RotateInput + Vector2.new(math.rad(angle * delta), 0)
+ end
+ end
+
+ -- Reset tween speed if user is panning
+ if userPanningTheCamera then
+ tweenSpeed = 0
+ module.LastUserPanCamera = tick()
+ end
+
+ local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate
+ local subjectPosition = self:GetSubjectPosition()
+
+ if subjectPosition and player and camera then
+ local zoom = self:GetCameraZoom()
+ if zoom < 0.5 then
+ zoom = 0.5
+ end
+
+ if self:GetShiftLock() and not self:IsInFirstPerson() then
+ -- We need to use the right vector of the camera after rotation, not before
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ local offset = ((newLookVector * XZ_VECTOR):Cross(UP_VECTOR).unit * 1.75)
+
+ if IsFiniteVector3(offset) then
+ subjectPosition = subjectPosition + offset
+ end
+ else
+ if self.LastCameraTransform and not userPanningTheCamera then
+ local isInFirstPerson = self:IsInFirstPerson()
+ if (isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then
+ if isInFirstPerson then
+ if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then
+ local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector)
+ if IsFinite(y) then
+ self.RotateInput = self.RotateInput + Vector2.new(y, 0)
+ end
+ tweenSpeed = 0
+ end
+ elseif not userRecentlyPannedCamera then
+ local forwardVector = humanoid.Torso.CFrame.lookVector
+ if isOnASkateboard then
+ forwardVector = cameraSubject.CFrame.lookVector
+ end
+ local timeDelta = (now - lastUpdate)
+
+ tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta)
+
+ local percent = clamp(0, 1, tweenSpeed * timeDelta)
+ if self:IsInFirstPerson() then
+ percent = 1
+ end
+
+ local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook())
+ if IsFinite(y) and math.abs(y) > 0.0001 then
+ self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0)
+ end
+ end
+ end
+ end
+ end
+
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+
+ camera.Focus = CFrame.new(subjectPosition)
+ camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p) + Vector3.new(0, self:GetCameraHeight(), 0)
+
+ self.LastCameraTransform = camera.CoordinateFrame
+ if isInVehicle or isOnASkateboard and cameraSubject:IsA('BasePart') then
+ self.LastSubjectCFrame = cameraSubject.CFrame
+ else
+ self.LastSubjectCFrame = nil
+ end
+ end
+
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateClassicCamera]]>
+
+
+-
+
+
+ FixedCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ end
+
+ if lastUpdate then
+ -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
+ local delta = math.min(0.1, now - lastUpdate)
+ local gamepadRotation = self:UpdateGamepad()
+ self.RotateInput = self.RotateInput + (gamepadRotation * delta)
+ end
+
+ local subjectPosition = self:GetSubjectPosition()
+ if subjectPosition and player and camera then
+ local zoom = self:GetCameraZoom()
+ if zoom <= 0 then
+ zoom = 0.1
+ end
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+
+ camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p)
+ self.LastCameraTransform = camera.CoordinateFrame
+ end
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateFixedCamera
+]]>
+
+
+-
+
+
+ FollowCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ end
+
+ if lastUpdate then
+ -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
+ local delta = math.min(0.1, now - lastUpdate)
+ local angle = 0
+ -- NOTE: Traditional follow camera does not rotate with arrow keys
+ if not (isInVehicle or isOnASkateboard) then
+ angle = angle + (self.TurningLeft and -120 or 0)
+ angle = angle + (self.TurningRight and 120 or 0)
+ end
+
+ local gamepadRotation = self:UpdateGamepad()
+ if gamepadRotation ~= Vector2.new(0,0) then
+ userPanningTheCamera = true
+ self.RotateInput = self.RotateInput + (gamepadRotation * delta)
+ end
+
+ if angle ~= 0 then
+ userPanningTheCamera = true
+ self.RotateInput = self.RotateInput + Vector2.new(math.rad(angle * delta), 0)
+ end
+ end
+
+ -- Reset tween speed if user is panning
+ if userPanningTheCamera then
+ tweenSpeed = 0
+ module.LastUserPanCamera = tick()
+ end
+
+ local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate
+
+ local subjectPosition = self:GetSubjectPosition()
+ if subjectPosition and player and camera then
+ local zoom = self:GetCameraZoom()
+ if zoom < 0.5 then
+ zoom = 0.5
+ end
+
+ if self:GetShiftLock() and not self:IsInFirstPerson() then
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ local offset = ((newLookVector * XZ_VECTOR):Cross(UP_VECTOR).unit * 1.75)
+ if IsFiniteVector3(offset) then
+ subjectPosition = subjectPosition + offset
+ end
+ else
+ if self.LastCameraTransform and not userPanningTheCamera then
+ local isInFirstPerson = self:IsInFirstPerson()
+ if (isClimbing or isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then
+ if isInFirstPerson then
+ if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then
+ local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector)
+ if IsFinite(y) then
+ self.RotateInput = self.RotateInput + Vector2.new(y, 0)
+ end
+ tweenSpeed = 0
+ end
+ elseif not userRecentlyPannedCamera then
+ local forwardVector = humanoid.Torso.CFrame.lookVector
+ if isOnASkateboard then
+ forwardVector = cameraSubject.CFrame.lookVector
+ end
+ local timeDelta = (now - lastUpdate)
+
+ tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta)
+
+ local percent = clamp(0, 1, tweenSpeed * timeDelta)
+ if not isClimbing and self:IsInFirstPerson() then
+ percent = 1
+ end
+ local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook())
+ -- Check for NaN
+ if IsFinite(y) and math.abs(y) > 0.0001 then
+ self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0)
+ end
+ end
+ elseif not (isInFirstPerson or userRecentlyPannedCamera) and (HasVRAPI and not UserInputService.VREnabled) then
+ local lastVec = -(self.LastCameraTransform.p - subjectPosition)
+ local y = findAngleBetweenXZVectors(lastVec, self:GetCameraLook())
+ -- Check for NaNs
+ if IsFinite(y) and math.abs(y) > 0.0001 then
+ self.RotateInput = self.RotateInput + Vector2.new(y, 0)
+ end
+ end
+ end
+ end
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+
+ camera.Focus = CFrame.new(subjectPosition)
+ camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p) + Vector3.new(0, self:GetCameraHeight(), 0)
+
+ self.LastCameraTransform = camera.CoordinateFrame
+ if isInVehicle or isOnASkateboard and cameraSubject:IsA('BasePart') then
+ self.LastSubjectCFrame = cameraSubject.CFrame
+ else
+ self.LastSubjectCFrame = nil
+ end
+ end
+
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateFollowCamera
+]]>
+
+
+-
+
+
+ ScriptableCamera
+
+
+
+-
+
+
+ TrackCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ end
+
+ if lastUpdate then
+ -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from
+ local delta = math.min(0.1, now - lastUpdate)
+ local gamepadRotation = self:UpdateGamepad()
+ if gamepadRotation ~= Vector2.new(0,0) then
+ userPanningTheCamera = true
+ self.RotateInput = self.RotateInput + (gamepadRotation * delta)
+ end
+ end
+
+ local subjectPosition = self:GetSubjectPosition()
+ if subjectPosition and player and camera then
+ local zoom = self:GetCameraZoom()
+ if zoom <= 0 then
+ zoom = 0.1
+ end
+ local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+
+ camera.Focus = CFrame.new(subjectPosition)
+ camera.CoordinateFrame = CFrame.new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p)
+ self.LastCameraTransform = camera.CoordinateFrame
+ end
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateTrackCamera
+]]>
+
+
+-
+
+
+ WatchCamera
+ 1 then
+ module:ResetCameraLook()
+ self.LastCameraTransform = nil
+ self.LastZoom = nil
+ end
+
+
+ local subjectPosition = self:GetSubjectPosition()
+ if subjectPosition and player and camera then
+ local cameraLook = nil
+
+ if self.LastCameraTransform then
+ local humanoid = self:GetHumanoid()
+ if humanoid and humanoid.Torso then
+ -- TODO: let the paging buttons move the camera but not the mouse/touch
+ -- currently neither do
+ local diffVector = subjectPosition - self.LastCameraTransform.p
+ cameraLook = diffVector.unit
+
+ if self.LastZoom and self.LastZoom == self:GetCameraZoom() then
+ -- Don't clobber the zoom if they zoomed the camera
+ local zoom = diffVector.magnitude
+ self:ZoomCamera(zoom)
+ end
+ end
+ end
+
+ local zoom = self:GetCameraZoom()
+ if zoom <= 0 then
+ zoom = 0.1
+ end
+
+ local newLookVector = self:RotateVector(cameraLook or self:GetCameraLook(), self.RotateInput)
+ self.RotateInput = Vector2.new()
+ local newFocus = CFrame.new(subjectPosition)
+ local newCamCFrame = CFrame.new(newFocus.p - (zoom * newLookVector), newFocus.p)
+
+ camera.Focus = newFocus
+ camera.CoordinateFrame = newCamCFrame
+ self.LastCameraTransform = newCamCFrame
+ self.LastZoom = zoom
+ end
+ lastUpdate = now
+ end
+
+ return module
+end
+
+return CreateWatchCamera
+]]>
+
+
+
+-
+
+
+ ShiftLockController
+
+
+
+-
+
+
+ TransparencyController
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/characterControlScript.rbxmx b/Client2016/content/fonts/characterControlScript.rbxmx
new file mode 100644
index 0000000..f9a2a5e
--- /dev/null
+++ b/Client2016/content/fonts/characterControlScript.rbxmx
@@ -0,0 +1,2064 @@
+
+ null
+ nil
+-
+
+ false
+
+ ControlScript
+ PlayerScripts.
+
+ // Required Modules:
+ ClickToMove
+ DPad
+ KeyboardMovement
+ Thumbpad
+ Thumbstick
+ TouchJump
+ MasterControl
+ VehicleController
+--]]
+
+local canUseNewControlScript = pcall(function() game:GetService('UserInputService'):GetLastInputType() end)
+local success, value = pcall(function() return UserSettings():IsUserFeatureEnabled("UserUseNewControlScript") end)
+local shouldUseNewControlScript = success and value
+
+if not canUseNewControlScript or not shouldUseNewControlScript then
+
+--[[ Services ]]--
+local ContextActionService = game:GetService('ContextActionService')
+local Players = game:GetService('Players')
+local UserInputService = game:GetService('UserInputService')
+-- Settings and GameSettings are read only
+local Settings = UserSettings()
+local GameSettings = Settings.GameSettings
+
+-- Issue with play solo? (F6)
+while not UserInputService.KeyboardEnabled and not UserInputService.TouchEnabled and not UserInputService.GamepadEnabled do
+ wait()
+end
+
+--[[ Script Variables ]]--
+while not Players.LocalPlayer do
+ wait()
+end
+local LocalPlayer = Players.LocalPlayer
+local PlayerGui = LocalPlayer:WaitForChild('PlayerGui')
+local IsTouchDevice = UserInputService.TouchEnabled
+local IsKeyboardDevice = UserInputService.KeyboardEnabled
+local UserMovementMode = IsTouchDevice and GameSettings.TouchMovementMode or GameSettings.ComputerMovementMode
+local DevMovementMode = IsTouchDevice and LocalPlayer.DevTouchMovementMode or LocalPlayer.DevComputerMovementMode
+local IsUserChoice = (IsTouchDevice and DevMovementMode == Enum.DevTouchMovementMode.UserChoice) or
+ DevMovementMode == Enum.DevComputerMovementMode.UserChoice
+local TouchGui = nil
+local TouchControlFrame = nil
+local TouchJumpModule = nil
+local IsModalEnabled = UserInputService.ModalEnabled
+local BindableEvent_OnFailStateChanged = nil
+local BindableEvent_EnableTouchJump = nil
+local isJumpEnabled = false
+
+
+--[[ Modules ]]--
+local CurrentControlModule = nil
+local ClickToMoveTouchControls = nil
+local ControlModules = {}
+
+local MasterControl = require(script:WaitForChild('MasterControl'))
+
+if IsTouchDevice then
+ ControlModules.Thumbstick = require(script.MasterControl:WaitForChild('Thumbstick'))
+ ControlModules.Thumbpad = require(script.MasterControl:WaitForChild('Thumbpad'))
+ ControlModules.DPad = require(script.MasterControl:WaitForChild('DPad'))
+ ControlModules.Default = ControlModules.Thumbstick
+ TouchJumpModule = require(script.MasterControl:WaitForChild('TouchJump'))
+ BindableEvent_OnFailStateChanged = script.Parent:WaitForChild('OnClickToMoveFailStateChange')
+ BindableEvent_EnableTouchJump = script.Parent:WaitForChild('EnableTouchJump')
+elseif IsKeyboardDevice then
+ ControlModules.Keyboard = require(script.MasterControl:WaitForChild('KeyboardMovement'))
+end
+ControlModules.Gamepad = require(script.MasterControl:WaitForChild('Gamepad'))
+local success, value = pcall(function() return UserSettings():IsUserFeatureEnabled("UserUseLuaVehicleController") end)
+if success and value then
+ local VehicleController = require(script.MasterControl:WaitForChild('VehicleController')) -- Not used, but needs to be required
+end
+
+
+--[[ Initialization/Setup ]]--
+local function createTouchGuiContainer()
+ if TouchGui then TouchGui:Destroy() end
+
+ -- Container for all touch device guis
+ TouchGui = Instance.new('ScreenGui')
+ TouchGui.Name = "TouchGui"
+ TouchGui.Parent = PlayerGui
+
+ TouchControlFrame = Instance.new('Frame')
+ TouchControlFrame.Name = "TouchControlFrame"
+ TouchControlFrame.Size = UDim2.new(1, 0, 1, 0)
+ TouchControlFrame.BackgroundTransparency = 1
+ TouchControlFrame.Parent = TouchGui
+
+ ControlModules.Thumbstick:Create(TouchControlFrame)
+ ControlModules.DPad:Create(TouchControlFrame)
+ ControlModules.Thumbpad:Create(TouchControlFrame)
+ TouchJumpModule:Create(TouchControlFrame)
+end
+
+--[[ Local Functions ]]--
+local function setJumpModule(isEnabled)
+ if not isEnabled then
+ TouchJumpModule:Disable()
+ elseif CurrentControlModule == ControlModules.Thumbpad or CurrentControlModule == ControlModules.Thumbstick or
+ CurrentControlModule == ControlModules.Default then
+ --
+ TouchJumpModule:Enable()
+ end
+end
+
+local function setClickToMove()
+ if DevMovementMode == Enum.DevTouchMovementMode.ClickToMove or DevMovementMode == Enum.DevComputerMovementMode.ClickToMove or
+ UserMovementMode == Enum.ComputerMovementMode.ClickToMove or UserMovementMode == Enum.TouchMovementMode.ClickToMove then
+ --
+ if IsTouchDevice then
+ ClickToMoveTouchControls = CurrentControlModule or ControlModules.Default
+ end
+ else
+ if IsTouchDevice and ClickToMoveTouchControls then
+ ClickToMoveTouchControls:Disable()
+ ClickToMoveTouchControls = nil
+ end
+ end
+end
+
+--[[ Controls State Management ]]--
+local onControlsChanged = nil
+if IsTouchDevice then
+ createTouchGuiContainer()
+ onControlsChanged = function()
+ local newModuleToEnable = nil
+ if not IsUserChoice then
+ if DevMovementMode == Enum.DevTouchMovementMode.Thumbstick then
+ newModuleToEnable = ControlModules.Thumbstick
+ isJumpEnabled = true
+ elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbpad then
+ newModuleToEnable = ControlModules.Thumbpad
+ isJumpEnabled = true
+ elseif DevMovementMode == Enum.DevTouchMovementMode.DPad then
+ newModuleToEnable = ControlModules.DPad
+ isJumpEnabled = false
+ elseif DevMovementMode == Enum.DevTouchMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ newModuleToEnable = nil
+ elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then
+ newModuleToEnable = nil
+ end
+ else
+ if UserMovementMode == Enum.TouchMovementMode.Default or UserMovementMode == Enum.TouchMovementMode.Thumbstick then
+ newModuleToEnable = ControlModules.Thumbstick
+ isJumpEnabled = true
+ elseif UserMovementMode == Enum.TouchMovementMode.Thumbpad then
+ newModuleToEnable = ControlModules.Thumbpad
+ isJumpEnabled = true
+ elseif UserMovementMode == Enum.TouchMovementMode.DPad then
+ newModuleToEnable = ControlModules.DPad
+ isJumpEnabled = false
+ elseif UserMovementMode == Enum.TouchMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ newModuleToEnable = nil
+ end
+ end
+ setClickToMove()
+ if newModuleToEnable ~= CurrentControlModule then
+ if CurrentControlModule then
+ CurrentControlModule:Disable()
+ end
+ setJumpModule(isJumpEnabled)
+ CurrentControlModule = newModuleToEnable
+ if CurrentControlModule and not IsModalEnabled then
+ CurrentControlModule:Enable()
+ if isJumpEnabled then TouchJumpModule:Enable() end
+ end
+ end
+ end
+elseif UserInputService.KeyboardEnabled then
+ onControlsChanged = function()
+ -- NOTE: Click to move still uses keyboard. Leaving cases in case this ever changes.
+ local newModuleToEnable = nil
+ if not IsUserChoice then
+ if DevMovementMode == Enum.DevComputerMovementMode.KeyboardMouse then
+ newModuleToEnable = ControlModules.Keyboard
+ elseif DevMovementMode == Enum.DevComputerMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ newModuleToEnable = ControlModules.Keyboard
+ end
+ else
+ if UserMovementMode == Enum.ComputerMovementMode.KeyboardMouse or UserMovementMode == Enum.ComputerMovementMode.Default then
+ newModuleToEnable = ControlModules.Keyboard
+ elseif UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ newModuleToEnable = ControlModules.Keyboard
+ end
+ end
+ if newModuleToEnable ~= CurrentControlModule then
+ if CurrentControlModule then
+ CurrentControlModule:Disable()
+ end
+ CurrentControlModule = newModuleToEnable
+ if CurrentControlModule then
+ CurrentControlModule:Enable()
+ end
+ end
+ end
+elseif UserInputService.GamepadEnabled then
+ onControlsChanged = function()
+ -- nil for now, probably needs some stuff later
+ end
+end
+
+--[[ Settings Changed Connections ]]--
+LocalPlayer.Changed:connect(function(property)
+ if IsTouchDevice and property == 'DevTouchMovementMode' then
+ DevMovementMode = LocalPlayer.DevTouchMovementMode
+ IsUserChoice = DevMovementMode == Enum.DevTouchMovementMode.UserChoice
+ if IsUserChoice then
+ UserMovementMode = GameSettings.TouchMovementMode
+ end
+ onControlsChanged()
+ elseif not IsTouchDevice and property == 'DevComputerMovementMode' then
+ DevMovementMode = LocalPlayer.DevComputerMovementMode
+ IsUserChoice = DevMovementMode == Enum.DevComputerMovementMode.UserChoice
+ if IsUserChoice then
+ UserMovementMode = GameSettings.ComputerMovementMode
+ end
+ onControlsChanged()
+ end
+end)
+
+GameSettings.Changed:connect(function(property)
+ if not IsUserChoice then return end
+ if property == 'TouchMovementMode' or property == 'ComputerMovementMode' then
+ UserMovementMode = GameSettings[property]
+ onControlsChanged()
+ end
+end)
+
+--[[ Touch Events ]]--
+if IsTouchDevice then
+ -- On touch devices we need to recreate the guis on character load.
+ LocalPlayer.CharacterAdded:connect(function(character)
+ createTouchGuiContainer()
+ if CurrentControlModule then
+ CurrentControlModule:Disable()
+ CurrentControlModule = nil
+ end
+ onControlsChanged()
+ end)
+
+ UserInputService.Changed:connect(function(property)
+ if property == 'ModalEnabled' then
+ IsModalEnabled = UserInputService.ModalEnabled
+ setJumpModule(not UserInputService.ModalEnabled)
+ if UserInputService.ModalEnabled then
+ if CurrentControlModule then
+ CurrentControlModule:Disable()
+ end
+ else
+ if CurrentControlModule then
+ CurrentControlModule:Enable()
+ end
+ end
+ end
+ end)
+
+ BindableEvent_OnFailStateChanged.Event:connect(function(isOn)
+ if ClickToMoveTouchControls then
+ if isOn then
+ ClickToMoveTouchControls:Enable()
+ else
+ ClickToMoveTouchControls:Disable()
+ end
+ if ClickToMoveTouchControls == ControlModules.Thumbpad or ClickToMoveTouchControls == ControlModules.Thumbstick or
+ ClickToMoveTouchControls == ControlModules.Default then
+ --
+ if isOn then
+ TouchJumpModule:Enable()
+ else
+ TouchJumpModule:Disable()
+ end
+ end
+ end
+ end)
+ BindableEvent_EnableTouchJump.Event:connect(function(enable)
+ if enable then
+ TouchJumpModule:Enable()
+ else
+ TouchJumpModule:Disable()
+ end
+ end)
+end
+
+MasterControl:Init()
+onControlsChanged()
+
+-- why do I need a wait here?!?!?!? Sometimes touch controls don't disappear without this
+wait()
+if UserInputService.GamepadEnabled then
+ if CurrentControlModule and IsTouchDevice then
+ CurrentControlModule:Disable()
+ end
+ if isJumpEnabled and IsTouchDevice then TouchJumpModule:Disable() end
+
+ ControlModules.Gamepad:Enable()
+end
+
+UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
+ if UserInputService.GamepadEnabled then return end
+
+ if CurrentControlModule and IsTouchDevice then
+ CurrentControlModule:Enable()
+ end
+ if isJumpEnabled and IsTouchDevice then TouchJumpModule:Enable() end
+
+ ControlModules.Gamepad:Disable()
+end)
+
+UserInputService.GamepadConnected:connect(function(gamepadEnum)
+ if gamepadEnum ~= Enum.UserInputType.Gamepad1 then return end
+
+ if CurrentControlModule and IsTouchDevice then
+ CurrentControlModule:Disable()
+ end
+ if isJumpEnabled and IsTouchDevice then TouchJumpModule:Disable() end
+
+ ControlModules.Gamepad:Enable()
+end)
+
+
+
+
+-- new version of ControlScript below
+else
+
+
+
+
+
+
+
+--[[ Services ]]--
+local ContextActionService = game:GetService('ContextActionService')
+local Players = game:GetService('Players')
+local UserInputService = game:GetService('UserInputService')
+-- Settings and GameSettings are read only
+local Settings = UserSettings()
+local GameSettings = Settings.GameSettings
+
+-- Issue with play solo? (F6)
+while not UserInputService.KeyboardEnabled and not UserInputService.TouchEnabled and not UserInputService.GamepadEnabled do
+ wait()
+end
+
+--[[ Script Variables ]]--
+while not Players.LocalPlayer do
+ wait()
+end
+
+local lastInputType = nil
+local LocalPlayer = Players.LocalPlayer
+local PlayerGui = LocalPlayer:WaitForChild('PlayerGui')
+local IsTouchDevice = UserInputService.TouchEnabled
+local UserMovementMode = IsTouchDevice and GameSettings.TouchMovementMode or GameSettings.ComputerMovementMode
+local DevMovementMode = IsTouchDevice and LocalPlayer.DevTouchMovementMode or LocalPlayer.DevComputerMovementMode
+local IsUserChoice = (IsTouchDevice and DevMovementMode == Enum.DevTouchMovementMode.UserChoice) or (DevMovementMode == Enum.DevComputerMovementMode.UserChoice)
+local TouchGui = nil
+local TouchControlFrame = nil
+local IsModalEnabled = UserInputService.ModalEnabled
+local BindableEvent_OnFailStateChanged = nil
+local isJumpEnabled = false
+
+local ControlState = {}
+ControlState.Current = nil
+function ControlState:SwitchTo(newControl)
+ if ControlState.Current == newControl then return end
+
+ if ControlState.Current then
+ ControlState.Current:Disable()
+ end
+
+ ControlState.Current = newControl
+
+ if ControlState.Current then
+ ControlState.Current:Enable()
+ end
+end
+
+--[[ Modules ]]--
+local ClickToMoveTouchControls = nil
+local ControlModules = {}
+
+local MasterControl = require(script:WaitForChild('MasterControl'))
+
+local ThumbstickModule = require(script.MasterControl:WaitForChild('Thumbstick'))
+local ThumbpadModule = require(script.MasterControl:WaitForChild('Thumbpad'))
+local DPadModule = require(script.MasterControl:WaitForChild('DPad'))
+local DefaultModule = ControlModules.Thumbstick
+local TouchJumpModule = require(script.MasterControl:WaitForChild('TouchJump'))
+
+local keyboardModule = require(script.MasterControl:WaitForChild('KeyboardMovement'))
+ControlModules.Gamepad = require(script.MasterControl:WaitForChild('Gamepad'))
+
+function getTouchModule()
+ local module = nil
+ if not IsUserChoice then
+ if DevMovementMode == Enum.DevTouchMovementMode.Thumbstick then
+ module = ThumbstickModule
+ isJumpEnabled = true
+ elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbpad then
+ module = ThumbpadModule
+ isJumpEnabled = true
+ elseif DevMovementMode == Enum.DevTouchMovementMode.DPad then
+ module = DPadModule
+ isJumpEnabled = false
+ elseif DevMovementMode == Enum.DevTouchMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ module = nil
+ elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then
+ module = nil
+ end
+ else
+ if UserMovementMode == Enum.TouchMovementMode.Default or UserMovementMode == Enum.TouchMovementMode.Thumbstick then
+ module = ThumbstickModule
+ isJumpEnabled = true
+ elseif UserMovementMode == Enum.TouchMovementMode.Thumbpad then
+ module = ThumbpadModule
+ isJumpEnabled = true
+ elseif UserMovementMode == Enum.TouchMovementMode.DPad then
+ module = DPadModule
+ isJumpEnabled = false
+ elseif UserMovementMode == Enum.TouchMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ module = nil
+ end
+ end
+
+ return module
+end
+
+function setJumpModule(isEnabled)
+ if not isEnabled then
+ TouchJumpModule:Disable()
+ elseif ControlState.Current == ControlModules.Touch then
+ TouchJumpModule:Enable()
+ end
+end
+
+function setClickToMove()
+ if DevMovementMode == Enum.DevTouchMovementMode.ClickToMove or DevMovementMode == Enum.DevComputerMovementMode.ClickToMove or
+ UserMovementMode == Enum.ComputerMovementMode.ClickToMove or UserMovementMode == Enum.TouchMovementMode.ClickToMove then
+ --
+ if lastInputType == Enum.UserInputType.Touch then
+ ClickToMoveTouchControls = ControlState.Current
+ end
+ elseif ClickToMoveTouchControls then
+ ClickToMoveTouchControls:Disable()
+ ClickToMoveTouchControls = nil
+ end
+end
+
+ControlModules.Touch = {}
+ControlModules.Touch.Current = nil
+ControlModules.Touch.LocalPlayerChangedCon = nil
+ControlModules.Touch.GameSettingsChangedCon = nil
+
+function ControlModules.Touch:RefreshControlStyle()
+ ControlModules.Touch.Current:Disable()
+ setJumpModule(false)
+ TouchJumpModule:Disable()
+
+ ControlModules.Touch:Enable()
+end
+function ControlModules.Touch:DisconnectEvents()
+ if ControlModules.Touch.LocalPlayerChangedCon then
+ ControlModules.Touch.LocalPlayerChangedCon:disconnect()
+ ControlModules.Touch.LocalPlayerChangedCon = nil
+ end
+ if ControlModules.Touch.GameSettingsChangedCon then
+ ControlModules.Touch.GameSettingsChangedCon:disconnect()
+ ControlModules.Touch.GameSettingsChangedCon = nil
+ end
+end
+function ControlModules.Touch:Enable()
+ DevMovementMode = LocalPlayer.DevTouchMovementMode
+ IsUserChoice = DevMovementMode == Enum.DevTouchMovementMode.UserChoice
+ if IsUserChoice then
+ UserMovementMode = GameSettings.TouchMovementMode
+ end
+
+ local newModuleToEnable = getTouchModule()
+ if newModuleToEnable then
+ setClickToMove()
+ setJumpModule(isJumpEnabled)
+
+ newModuleToEnable:Enable()
+ ControlModules.Touch.Current = newModuleToEnable
+
+ ControlModules.Touch:DisconnectEvents()
+ ControlModules.Touch.LocalPlayerChangedCon = LocalPlayer.Changed:connect(function(property)
+ if property == 'DevTouchMovementMode' then
+ ControlModules.Touch:RefreshControlStyle()
+ end
+ end)
+
+ ControlModules.Touch.GameSettingsChangedCon = GameSettings.Changed:connect(function(property)
+ if property == 'TouchMovementMode' then
+ ControlModules.Touch:RefreshControlStyle()
+ end
+ end)
+
+ if isJumpEnabled then TouchJumpModule:Enable() end
+ end
+end
+function ControlModules.Touch:Disable()
+ ControlModules.Touch:DisconnectEvents()
+
+ local newModuleToDisable = getTouchModule()
+
+ if newModuleToDisable == ThumbstickModule or
+ newModuleToDisable == DPadModule or
+ newModuleToDisable == ThumbpadModule then
+ newModuleToDisable:Disable()
+ setJumpModule(false)
+ TouchJumpModule:Disable()
+ end
+end
+
+local function getKeyboardModule()
+ -- NOTE: Click to move still uses keyboard. Leaving cases in case this ever changes.
+ local whichModule = nil
+ if not IsUserChoice then
+ if DevMovementMode == Enum.DevComputerMovementMode.KeyboardMouse then
+ whichModule = keyboardModule
+ elseif DevMovementMode == Enum.DevComputerMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ whichModule = keyboardModule
+ end
+ else
+ if UserMovementMode == Enum.ComputerMovementMode.KeyboardMouse or UserMovementMode == Enum.ComputerMovementMode.Default then
+ whichModule = keyboardModule
+ elseif UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
+ -- Managed by CameraScript
+ whichModule = keyboardModule
+ end
+ end
+
+ return whichModule
+end
+
+ControlModules.Keyboard = {}
+function ControlModules.Keyboard:Enable()
+ DevMovementMode = LocalPlayer.DevComputerMovementMode
+ IsUserChoice = DevMovementMode == Enum.DevComputerMovementMode.UserChoice
+ if IsUserChoice then
+ UserMovementMode = GameSettings.ComputerMovementMode
+ end
+
+ local newModuleToEnable = getKeyboardModule()
+ if newModuleToEnable then
+ if newModuleToEnable then
+ newModuleToEnable:Enable()
+ end
+ end
+end
+function ControlModules.Keyboard:Disable()
+ local newModuleToDisable = getKeyboardModule()
+ if newModuleToDisable then
+ newModuleToDisable:Disable()
+ end
+end
+
+if IsTouchDevice then
+ BindableEvent_OnFailStateChanged = script.Parent:WaitForChild('OnClickToMoveFailStateChange')
+end
+
+-- not used, but needs to be required
+local VehicleController = require(script.MasterControl:WaitForChild('VehicleController'))
+
+
+--[[ Initialization/Setup ]]--
+local function createTouchGuiContainer()
+ if TouchGui then TouchGui:Destroy() end
+
+ -- Container for all touch device guis
+ TouchGui = Instance.new('ScreenGui')
+ TouchGui.Name = "TouchGui"
+ TouchGui.Parent = PlayerGui
+
+ TouchControlFrame = Instance.new('Frame')
+ TouchControlFrame.Name = "TouchControlFrame"
+ TouchControlFrame.Size = UDim2.new(1, 0, 1, 0)
+ TouchControlFrame.BackgroundTransparency = 1
+ TouchControlFrame.Parent = TouchGui
+
+ ThumbstickModule:Create(TouchControlFrame)
+ DPadModule:Create(TouchControlFrame)
+ ThumbpadModule:Create(TouchControlFrame)
+ TouchJumpModule:Create(TouchControlFrame)
+end
+
+--[[ Settings Changed Connections ]]--
+LocalPlayer.Changed:connect(function(property)
+ if lastInputType == Enum.UserInputType.Touch and property == 'DevTouchMovementMode' then
+ ControlState:SwitchTo(ControlModules.Touch)
+ elseif UserInputService.KeyboardEnabled and property == 'DevComputerMovementMode' then
+ ControlState:SwitchTo(ControlModules.Keyboard)
+ end
+end)
+
+GameSettings.Changed:connect(function(property)
+ if not IsUserChoice then return end
+ if property == 'TouchMovementMode' or property == 'ComputerMovementMode' then
+ UserMovementMode = GameSettings[property]
+ if property == 'TouchMovementMode' then
+ ControlState:SwitchTo(ControlModules.Touch)
+ elseif property == 'ComputerMovementMode' then
+ ControlState:SwitchTo(ControlModules.Keyboard)
+ end
+ end
+end)
+
+--[[ Touch Events ]]--
+-- On touch devices we need to recreate the guis on character load.
+local lastControlState = nil
+LocalPlayer.CharacterAdded:connect(function(character)
+ if UserInputService.TouchEnabled then
+ createTouchGuiContainer()
+ end
+
+ if ControlState.Current == nil then
+ ControlState:SwitchTo(lastControlState)
+ end
+end)
+
+LocalPlayer.CharacterRemoving:connect(function(character)
+ lastControlState = ControlState.Current
+ ControlState:SwitchTo(nil)
+end)
+
+UserInputService.Changed:connect(function(property)
+ if property == 'ModalEnabled' then
+ IsModalEnabled = UserInputService.ModalEnabled
+
+ if lastInputType == Enum.UserInputType.Touch then
+ if ControlState.Current == ControlModules.Touch and IsModalEnabled then
+ ControlState:SwitchTo(nil)
+ elseif ControlState.Current == nil and not IsModalEnabled then
+ ControlState:SwitchTo(ControlModules.Touch)
+ end
+ end
+ end
+end)
+
+if BindableEvent_OnFailStateChanged then
+ BindableEvent_OnFailStateChanged.Event:connect(function(isOn)
+ if lastInputType == Enum.UserInputType.Touch and ClickToMoveTouchControls then
+ if isOn then
+ ControlState:SwitchTo(ClickToMoveTouchControls)
+ else
+ ControlState:SwitchTo(nil)
+ end
+ end
+ end)
+end
+
+local switchToInputType = function(newLastInputType)
+ lastInputType = newLastInputType
+
+ if lastInputType == Enum.UserInputType.Touch then
+ ControlState:SwitchTo(ControlModules.Touch)
+ elseif lastInputType == Enum.UserInputType.Keyboard or
+ lastInputType == Enum.UserInputType.MouseButton1 or
+ lastInputType == Enum.UserInputType.MouseButton2 or
+ lastInputType == Enum.UserInputType.MouseButton3 or
+ lastInputType == Enum.UserInputType.MouseWheel or
+ lastInputType == Enum.UserInputType.MouseMovement then
+ ControlState:SwitchTo(ControlModules.Keyboard)
+ elseif lastInputType == Enum.UserInputType.Gamepad1 or
+ lastInputType == Enum.UserInputType.Gamepad2 or
+ lastInputType == Enum.UserInputType.Gamepad3 or
+ lastInputType == Enum.UserInputType.Gamepad4 then
+ ControlState:SwitchTo(ControlModules.Gamepad)
+ end
+end
+
+if IsTouchDevice then
+ createTouchGuiContainer()
+end
+
+MasterControl:Init()
+
+UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
+ local connectedGamepads = UserInputService:GetConnectedGamepads()
+ if #connectedGamepads > 0 then return end
+
+ if UserInputService.KeyboardEnabled then
+ ControlState:SwitchTo(ControlModules.Keyboard)
+ elseif IsTouchDevice then
+ ControlState:SwitchTo(ControlModules.Touch)
+ end
+end)
+
+UserInputService.GamepadConnected:connect(function(gamepadEnum)
+ ControlState:SwitchTo(ControlModules.Gamepad)
+end)
+
+switchToInputType(UserInputService:GetLastInputType())
+UserInputService.LastInputTypeChanged:connect(switchToInputType)
+
+end -- end of control script flag switch]]>
+
+
-
+
+
+ MasterControl
+
+
+
-
+
+ DPad
+ jumpRadius then
+ local angle = ATAN2(direction.y, direction.x)
+ local octant = (FLOOR(8 * angle / (2 * PI) + 8.5)%8) + 1
+ movementVector = COMPASS_DIR[octant]
+ end
+
+ if not flBtn.Visible and movementVector == COMPASS_DIR[7] then
+ flBtn.Visible = true
+ frBtn.Visible = true
+ end
+ end
+
+ DPadFrame.InputBegan:connect(function(inputObject)
+ if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
+ return
+ end
+
+ MasterControl:AddToPlayerMovement(-movementVector)
+
+ TouchObject = inputObject
+ normalizeDirection(TouchObject.Position)
+
+ MasterControl:AddToPlayerMovement(movementVector)
+ end)
+
+ DPadFrame.InputChanged:connect(function(inputObject)
+ if inputObject == TouchObject then
+ MasterControl:AddToPlayerMovement(-movementVector)
+ normalizeDirection(TouchObject.Position)
+ MasterControl:AddToPlayerMovement(movementVector)
+ MasterControl:SetIsJumping(false)
+ end
+ end)
+
+ OnInputEnded = function()
+ TouchObject = nil
+ flBtn.Visible = false
+ frBtn.Visible = false
+
+ MasterControl:AddToPlayerMovement(-movementVector)
+ movementVector = Vector3.new(0, 0, 0)
+ end
+
+ DPadFrame.InputEnded:connect(function(inputObject)
+ if inputObject == TouchObject then
+ OnInputEnded()
+ end
+ end)
+
+ DPadFrame.Parent = parentFrame
+end
+
+return DPad
+]]>
+
+
+-
+
+
+ Gamepad
+ 0 then
+ for i = 1, #connectedGamepads do
+ if activateGamepad == nil then
+ activateGamepad = connectedGamepads[i]
+ elseif connectedGamepads[i].Value < activateGamepad.Value then
+ activateGamepad = connectedGamepads[i]
+ end
+ end
+ end
+
+ if activateGamepad == nil then -- nothing is connected, at least set up for gamepad1
+ activateGamepad = Enum.UserInputType.Gamepad1
+ end
+end
+
+--[[ Public API ]]--
+function Gamepad:Enable()
+ local forwardValue = 0
+ local backwardValue = 0
+ local leftValue = 0
+ local rightValue = 0
+
+ local moveFunc = LocalPlayer.Move
+ local gamepadSupports = UserInputService.GamepadSupports
+
+ local controlCharacterGamepad = function(actionName, inputState, inputObject)
+ if activateGamepad ~= inputObject.UserInputType then return end
+ if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end
+
+ if inputState == Enum.UserInputState.Cancel then
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+ return
+ end
+
+ if inputObject.Position.magnitude > thumbstickDeadzone then
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(inputObject.Position.X, 0, -inputObject.Position.Y)
+ MasterControl:AddToPlayerMovement(currentMoveVector)
+ else
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+ end
+ end
+
+ local jumpCharacterGamepad = function(actionName, inputState, inputObject)
+ if activateGamepad ~= inputObject.UserInputType then return end
+ if inputObject.KeyCode ~= Enum.KeyCode.ButtonA then return end
+
+ if inputState == Enum.UserInputState.Cancel then
+ MasterControl:SetIsJumping(false)
+ return
+ end
+
+ MasterControl:SetIsJumping(inputObject.UserInputState == Enum.UserInputState.Begin)
+ end
+
+ local doDpadMoveUpdate = function(userInputType)
+ if not gamepadSupports(UserInputService, userInputType, Enum.KeyCode.Thumbstick1) then
+ if LocalPlayer and LocalPlayer.Character then
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(leftValue + rightValue,0,forwardValue + backwardValue)
+ MasterControl:AddToPlayerMovement(currentMoveVector)
+ end
+ end
+ end
+
+ local moveForwardFunc = function(actionName, inputState, inputObject)
+ if inputState == Enum.UserInputState.End then
+ forwardValue = -1
+ elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then
+ forwardValue = 0
+ end
+
+ doDpadMoveUpdate(inputObject.UserInputType)
+ end
+
+ local moveBackwardFunc = function(actionName, inputState, inputObject)
+ if inputState == Enum.UserInputState.End then
+ backwardValue = 1
+ elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then
+ backwardValue = 0
+ end
+
+ doDpadMoveUpdate(inputObject.UserInputType)
+ end
+
+ local moveLeftFunc = function(actionName, inputState, inputObject)
+ if inputState == Enum.UserInputState.End then
+ leftValue = -1
+ elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then
+ leftValue = 0
+ end
+
+ doDpadMoveUpdate(inputObject.UserInputType)
+ end
+
+ local moveRightFunc = function(actionName, inputState, inputObject)
+ if inputState == Enum.UserInputState.End then
+ rightValue = 1
+ elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then
+ rightValue = 0
+ end
+
+ doDpadMoveUpdate(inputObject.UserInputType)
+ end
+
+ local function setActivateGamepad()
+ if activateGamepad then
+ ContextActionService:UnbindActivate(activateGamepad, Enum.KeyCode.ButtonR2)
+ end
+ assignActivateGamepad()
+ if activateGamepad then
+ ContextActionService:BindActivate(activateGamepad, Enum.KeyCode.ButtonR2)
+ end
+ end
+
+ ContextActionService:BindAction("JumpButton",jumpCharacterGamepad, false, Enum.KeyCode.ButtonA)
+ ContextActionService:BindAction("MoveThumbstick",controlCharacterGamepad, false, Enum.KeyCode.Thumbstick1)
+
+ ContextActionService:BindAction("forwardDpad", moveForwardFunc, false, Enum.KeyCode.DPadUp)
+ ContextActionService:BindAction("backwardDpad", moveBackwardFunc, false, Enum.KeyCode.DPadDown)
+ ContextActionService:BindAction("leftDpad", moveLeftFunc, false, Enum.KeyCode.DPadLeft)
+ ContextActionService:BindAction("rightDpad", moveRightFunc, false, Enum.KeyCode.DPadRight)
+
+ setActivateGamepad()
+
+ gamepadConnectedCon = UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
+ if activateGamepad ~= gamepadEnum then return end
+
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+
+ activateGamepad = nil
+ setActivateGamepad()
+ end)
+
+ gamepadDisconnectedCon = UserInputService.GamepadConnected:connect(function(gamepadEnum)
+ if activateGamepad == nil then
+ setActivateGamepad()
+ end
+ end)
+end
+
+function Gamepad:Disable()
+
+ ContextActionService:UnbindAction("forwardDpad")
+ ContextActionService:UnbindAction("backwardDpad")
+ ContextActionService:UnbindAction("leftDpad")
+ ContextActionService:UnbindAction("rightDpad")
+
+ ContextActionService:UnbindAction("MoveThumbstick")
+ ContextActionService:UnbindAction("JumpButton")
+ ContextActionService:UnbindActivate(activateGamepad, Enum.KeyCode.ButtonR2)
+
+ if gamepadConnectedCon then gamepadConnectedCon:disconnect() end
+ if gamepadDisconnectedCon then gamepadDisconnectedCon:disconnect() end
+
+ activateGamepad = nil
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+ MasterControl:SetIsJumping(false)
+end
+
+return Gamepad
+]]>
+
+
+-
+
+
+ KeyboardMovement
+
+
+
+-
+
+ Thumbpad
+ 0.5 then -- UP
+ if not isUp then
+ isUp, isDown = true, false
+ doTween(uArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 0, smImgOffset - smArrowSize.Y.Offset * 1.5))
+ doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
+ end
+ elseif forwardDot < -0.5 then -- DOWN
+ if not isDown then
+ isDown, isUp = true, false
+ doTween(dArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 1, lgImgOffset + smArrowSize.Y.Offset/2))
+ doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
+ end
+ else
+ isUp, isDown = false, false
+ doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
+ doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
+ end
+
+ if rightDot > 0.5 then
+ if not isRight then
+ isRight, isLeft = true, false
+ doTween(rArrow, lgArrowSize, UDim2.new(1, lgImgOffset + smArrowSize.X.Offset/2, 0.5, -smArrowSize.Y.Offset))
+ doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ end
+ elseif rightDot < -0.5 then
+ if not isLeft then
+ isLeft, isRight = true, false
+ doTween(lArrow, lgArrowSize, UDim2.new(0, smImgOffset - smArrowSize.X.Offset * 1.5, 0.5, -smArrowSize.Y.Offset))
+ doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ end
+ else
+ isRight, isLeft = false, false
+ doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ end
+ end
+
+ --input connections
+ ThumbpadFrame.InputBegan:connect(function(inputObject)
+ if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
+ return
+ end
+
+ ThumbpadFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbpadFrame.AbsoluteSize.x/2, 0, inputObject.Position.y - ThumbpadFrame.Size.Y.Offset/2)
+ padOrigin = Vector2.new(ThumbpadFrame.AbsolutePosition.x + ThumbpadFrame.AbsoluteSize.x/2,
+ ThumbpadFrame.AbsolutePosition.y + ThumbpadFrame.AbsoluteSize.y/2)
+ doMove(inputObject.Position)
+ TouchObject = inputObject
+ end)
+
+ OnTouchChangedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
+ if inputObject == TouchObject then
+ doMove(TouchObject.Position)
+ end
+ end)
+
+ OnInputEnded = function()
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+ MasterControl:SetIsJumping(false)
+
+ ThumbpadFrame.Position = position
+ TouchObject = nil
+ isUp, isDown, isLeft, isRight = false, false, false, false
+ doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
+ doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
+ doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
+ end
+
+ OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject)
+ if inputObject == TouchObject then
+ OnInputEnded()
+ end
+ end)
+
+ ThumbpadFrame.Parent = parentFrame
+end
+
+return Thumbpad
+]]>
+
+
+-
+
+
+ Thumbstick
+ maxLength then
+ local offset = relativePosition.unit * maxLength
+ ThumbstickFrame.Position = UDim2.new(
+ 0, pos.x - ThumbstickFrame.AbsoluteSize.x/2 - offset.x,
+ 0, pos.y - ThumbstickFrame.AbsoluteSize.y/2 - offset.y)
+ else
+ length = math.min(length, maxLength)
+ relativePosition = relativePosition.unit * length
+ end
+ StickImage.Position = UDim2.new(0, relativePosition.x + StickImage.AbsoluteSize.x/2, 0, relativePosition.y + StickImage.AbsoluteSize.y/2)
+ end
+
+ -- input connections
+ ThumbstickFrame.InputBegan:connect(function(inputObject)
+ if MoveTouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
+ return
+ end
+
+ MoveTouchObject = inputObject
+ ThumbstickFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbstickFrame.Size.X.Offset/2, 0, inputObject.Position.y - ThumbstickFrame.Size.Y.Offset/2)
+ centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
+ ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2)
+ local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
+ moveStick(inputObject.Position)
+ end)
+
+ OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
+ if inputObject == MoveTouchObject then
+ centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
+ ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2)
+ local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
+ doMove(direction)
+ moveStick(inputObject.Position)
+ end
+ end)
+
+ OnTouchEnded = function()
+ ThumbstickFrame.Position = position
+ StickImage.Position = UDim2.new(0, ThumbstickFrame.Size.X.Offset/2 - thumbstickSize/4, 0, ThumbstickFrame.Size.Y.Offset/2 - thumbstickSize/4)
+ MoveTouchObject = nil
+
+ MasterControl:AddToPlayerMovement(-currentMoveVector)
+ currentMoveVector = Vector3.new(0,0,0)
+ MasterControl:SetIsJumping(false)
+ end
+
+ OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed)
+ if inputObject == MoveTouchObject then
+ OnTouchEnded()
+ end
+ end)
+
+ ThumbstickFrame.Parent = parentFrame
+end
+
+return Thumbstick
+]]>
+
+
+-
+
+ TouchJump
+
+
+
+-
+
+
+ VehicleController
+ 0.5 then
+ return 1
+ elseif value < -0.5 then
+ return -1
+ end
+ return 0
+end
+
+local function onRenderStepped()
+ if CurrentVehicleSeat then
+ local moveValue = MasterControl:GetMoveVector()
+ if game:GetService("UserInputService"):GetGamepadConnected(Enum.UserInputType.Gamepad1) and onlyTriggersForThrottle and useTriggersForThrottle then
+ CurrentVehicleSeat.Throttle = -CurrentThrottle
+ else
+ CurrentVehicleSeat.Throttle = getClosestFittingValue(-moveValue.z)
+ end
+ CurrentVehicleSeat.Steer = getClosestFittingValue(moveValue.x)
+ end
+end
+
+local function onSeated(active, currentSeatPart)
+ if active then
+ if currentSeatPart and currentSeatPart:IsA('VehicleSeat') then
+ CurrentVehicleSeat = currentSeatPart
+ if useTriggersForThrottle then
+ ContextActionService:BindAction("throttleAccel", onThrottleAccel, false, Enum.KeyCode.ButtonR2)
+ ContextActionService:BindAction("throttleDeccel", onThrottleDeccel, false, Enum.KeyCode.ButtonL2)
+ end
+ ContextActionService:BindAction("arrowSteerRight", onSteerRight, false, Enum.KeyCode.Right)
+ ContextActionService:BindAction("arrowSteerLeft", onSteerLeft, false, Enum.KeyCode.Left)
+ local success = pcall(function() RunService:BindToRenderStep("VehicleControlStep", Enum.RenderPriority.Input.Value, onRenderStepped) end)
+
+ if not success then
+ if RenderSteppedCn then return end
+ RenderSteppedCn = RunService.RenderStepped:connect(onRenderStepped)
+ end
+ end
+ else
+ CurrentVehicleSeat = nil
+ if useTriggersForThrottle then
+ ContextActionService:UnbindAction("throttleAccel")
+ ContextActionService:UnbindAction("throttleDeccel")
+ end
+ ContextActionService:UnbindAction("arrowSteerRight")
+ ContextActionService:UnbindAction("arrowSteerLeft")
+ MasterControl:AddToPlayerMovement(Vector3.new(-CurrentSteer, 0, -CurrentThrottle))
+ CurrentThrottle = 0
+ CurrentSteer = 0
+ local success = pcall(function() RunService:UnbindFromRenderStep("VehicleControlStep") end)
+ if not success and RenderSteppedCn then
+ RenderSteppedCn:disconnect()
+ RenderSteppedCn = nil
+ end
+ end
+end
+
+local function CharacterAdded(character)
+ local humanoid = getHumanoid()
+ while not humanoid do
+ wait()
+ humanoid = getHumanoid()
+ end
+ --
+ if HumanoidSeatedCn then
+ HumanoidSeatedCn:disconnect()
+ HumanoidSeatedCn = nil
+ end
+ HumanoidSeatedCn = humanoid.Seated:connect(onSeated)
+end
+
+if LocalPlayer.Character then
+ CharacterAdded(LocalPlayer.Character)
+end
+LocalPlayer.CharacterAdded:connect(CharacterAdded)
+
+return VehicleController
+]]>
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/characterR15.rbxm b/Client2016/content/fonts/characterR15.rbxm
new file mode 100644
index 0000000..6b9045b
Binary files /dev/null and b/Client2016/content/fonts/characterR15.rbxm differ
diff --git a/Client2016/content/fonts/comics.fnt b/Client2016/content/fonts/comics.fnt
new file mode 100644
index 0000000..6b71c7e
Binary files /dev/null and b/Client2016/content/fonts/comics.fnt differ
diff --git a/Client2016/content/fonts/diogenes.fnt b/Client2016/content/fonts/diogenes.fnt
new file mode 100644
index 0000000..e69de29
diff --git a/Client2016/content/fonts/fonts.dds b/Client2016/content/fonts/fonts.dds
new file mode 100644
index 0000000..30e4474
Binary files /dev/null and b/Client2016/content/fonts/fonts.dds differ
diff --git a/Client2016/content/fonts/gamecontrollerdb.txt b/Client2016/content/fonts/gamecontrollerdb.txt
new file mode 100644
index 0000000..dd49836
--- /dev/null
+++ b/Client2016/content/fonts/gamecontrollerdb.txt
@@ -0,0 +1,89 @@
+# Windows - DINPUT
+8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
+4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
+25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
+4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,
+4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,
+00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
+00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
+28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
+ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,
+8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,
+79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,
+4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,
+d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,
+8f0e0300000000000000504944564944,Trust GTX 28,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+
+# OS X
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
+4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,Platform:Mac OS X,
+5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
+4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,
+8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+
+# Linux
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux,
+03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
+03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,
+030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
+030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,
+030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
+030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,
+030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
+030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,
+0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
+0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
+030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,
+030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,
+030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
+03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
+03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,
+05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
+05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
+030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
\ No newline at end of file
diff --git a/Client2016/content/fonts/head.mesh b/Client2016/content/fonts/head.mesh
new file mode 100644
index 0000000..26db950
Binary files /dev/null and b/Client2016/content/fonts/head.mesh differ
diff --git a/Client2016/content/fonts/headA.mesh b/Client2016/content/fonts/headA.mesh
new file mode 100644
index 0000000..76b2e72
Binary files /dev/null and b/Client2016/content/fonts/headA.mesh differ
diff --git a/Client2016/content/fonts/headB.mesh b/Client2016/content/fonts/headB.mesh
new file mode 100644
index 0000000..7705a05
Binary files /dev/null and b/Client2016/content/fonts/headB.mesh differ
diff --git a/Client2016/content/fonts/headC.mesh b/Client2016/content/fonts/headC.mesh
new file mode 100644
index 0000000..4672c59
Binary files /dev/null and b/Client2016/content/fonts/headC.mesh differ
diff --git a/Client2016/content/fonts/headD.mesh b/Client2016/content/fonts/headD.mesh
new file mode 100644
index 0000000..ff6cd6c
Binary files /dev/null and b/Client2016/content/fonts/headD.mesh differ
diff --git a/Client2016/content/fonts/headE.mesh b/Client2016/content/fonts/headE.mesh
new file mode 100644
index 0000000..d722d29
Binary files /dev/null and b/Client2016/content/fonts/headE.mesh differ
diff --git a/Client2016/content/fonts/headF.mesh b/Client2016/content/fonts/headF.mesh
new file mode 100644
index 0000000..7c0b311
Binary files /dev/null and b/Client2016/content/fonts/headF.mesh differ
diff --git a/Client2016/content/fonts/headG.mesh b/Client2016/content/fonts/headG.mesh
new file mode 100644
index 0000000..38db235
Binary files /dev/null and b/Client2016/content/fonts/headG.mesh differ
diff --git a/Client2016/content/fonts/headH.mesh b/Client2016/content/fonts/headH.mesh
new file mode 100644
index 0000000..fe7365b
Binary files /dev/null and b/Client2016/content/fonts/headH.mesh differ
diff --git a/Client2016/content/fonts/headI.mesh b/Client2016/content/fonts/headI.mesh
new file mode 100644
index 0000000..8ff7ba1
Binary files /dev/null and b/Client2016/content/fonts/headI.mesh differ
diff --git a/Client2016/content/fonts/headJ.mesh b/Client2016/content/fonts/headJ.mesh
new file mode 100644
index 0000000..ff76d44
Binary files /dev/null and b/Client2016/content/fonts/headJ.mesh differ
diff --git a/Client2016/content/fonts/headK.mesh b/Client2016/content/fonts/headK.mesh
new file mode 100644
index 0000000..b08bffc
Binary files /dev/null and b/Client2016/content/fonts/headK.mesh differ
diff --git a/Client2016/content/fonts/headL.mesh b/Client2016/content/fonts/headL.mesh
new file mode 100644
index 0000000..645531b
Binary files /dev/null and b/Client2016/content/fonts/headL.mesh differ
diff --git a/Client2016/content/fonts/headM.mesh b/Client2016/content/fonts/headM.mesh
new file mode 100644
index 0000000..ba144e8
Binary files /dev/null and b/Client2016/content/fonts/headM.mesh differ
diff --git a/Client2016/content/fonts/headN.mesh b/Client2016/content/fonts/headN.mesh
new file mode 100644
index 0000000..6fc4620
Binary files /dev/null and b/Client2016/content/fonts/headN.mesh differ
diff --git a/Client2016/content/fonts/headO.mesh b/Client2016/content/fonts/headO.mesh
new file mode 100644
index 0000000..a41f85f
Binary files /dev/null and b/Client2016/content/fonts/headO.mesh differ
diff --git a/Client2016/content/fonts/headP.mesh b/Client2016/content/fonts/headP.mesh
new file mode 100644
index 0000000..cdb1647
Binary files /dev/null and b/Client2016/content/fonts/headP.mesh differ
diff --git a/Client2016/content/fonts/humanoidAnimate.rbxm b/Client2016/content/fonts/humanoidAnimate.rbxm
new file mode 100644
index 0000000..7a59cb9
--- /dev/null
+++ b/Client2016/content/fonts/humanoidAnimate.rbxm
@@ -0,0 +1,296 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+ -- Now with exciting TeamColors HACK!
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+-- TEAM COLORS
+
+
+function onTeamChanged(player)
+
+ wait(1)
+
+ local char = player.Character
+ if char == nil then return end
+
+ if player.Neutral then
+ -- Replacing the current BodyColor object will force a reset
+ local old = char:findFirstChild("Body Colors")
+ if not old then return end
+ old:clone().Parent = char
+ old.Parent = nil
+ else
+ local head = char:findFirstChild("Head")
+ local torso = char:findFirstChild("Torso")
+ local left_arm = char:findFirstChild("Left Arm")
+ local right_arm = char:findFirstChild("Right Arm")
+ local left_leg = char:findFirstChild("Left Leg")
+ local right_leg = char:findFirstChild("Right Leg")
+
+ if head then head.BrickColor = BrickColor.new(24) end
+ if torso then torso.BrickColor = player.TeamColor end
+ if left_arm then left_arm.BrickColor = BrickColor.new(26) end
+ if right_arm then right_arm.BrickColor = BrickColor.new(26) end
+ if left_leg then left_leg.BrickColor = BrickColor.new(26) end
+ if right_leg then right_leg.BrickColor = BrickColor.new(26) end
+ end
+end
+
+function onPlayerPropChanged(property, player)
+ if property == "Character" then
+ onTeamChanged(player)
+ end
+ if property== "TeamColor" or property == "Neutral" then
+ onTeamChanged(player)
+ end
+end
+
+
+local cPlayer = game.Players:GetPlayerFromCharacter(script.Parent)
+cPlayer.Changed:connect(function(property) onPlayerPropChanged(property, cPlayer) end )
+onTeamChanged(cPlayer)
+
+
+-- ANIMATION
+
+-- declarations
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local toolAnim = "None"
+local toolAnimTime = 0
+
+-- functions
+
+function onRunning(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ pose = "Jumping"
+end
+
+function onClimbing()
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function moveJump()
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+
+-- same as jump for now
+
+function moveFreeFall()
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ RightShoulder:SetDesiredAngle(1.57)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ RightShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(0)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightHip.MaxVelocity = 0.5
+ LeftHip.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(1.57)
+ LeftShoulder:SetDesiredAngle(1.0)
+ RightHip:SetDesiredAngle(1.57)
+ LeftHip:SetDesiredAngle(1.0)
+ return
+ end
+end
+
+function move(time)
+ local amplitude
+ local frequency
+
+ if (pose == "Jumping") then
+ moveJump()
+ return
+ end
+
+ if (pose == "FreeFall") then
+ moveFreeFall()
+ return
+ end
+
+ if (pose == "Seated") then
+ moveSit()
+ return
+ end
+
+ local climbFudge = 0
+
+ if (pose == "Running") then
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ amplitude = 1
+ frequency = 9
+ elseif (pose == "Climbing") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ amplitude = 1
+ frequency = 9
+ climbFudge = 3.14
+ else
+ amplitude = 0.1
+ frequency = 1
+ end
+
+ desiredAngle = amplitude * math.sin(time*frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+
+
+ local tool = getTool()
+
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+
+
+ else
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+
+-- connect events
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+
+-- main program
+
+local runService = game:service("RunService");
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidAnimateLocal.rbxm b/Client2016/content/fonts/humanoidAnimateLocal.rbxm
new file mode 100644
index 0000000..5c18211
--- /dev/null
+++ b/Client2016/content/fonts/humanoidAnimateLocal.rbxm
@@ -0,0 +1,336 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+
+
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+-- ANIMATION
+
+-- declarations
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local toolAnim = "None"
+local toolAnimTime = 0
+
+local jumpMaxLimbVelocity = 0.75
+
+-- functions
+
+function onRunning(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ pose = "Jumping"
+end
+
+function onClimbing()
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function onSwimming(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function moveJump()
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+
+-- same as jump for now
+
+function moveFreeFall()
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ RightShoulder:SetDesiredAngle(3.14)
+ LeftShoulder:SetDesiredAngle(-3.14)
+ RightHip:SetDesiredAngle(0)
+ LeftHip:SetDesiredAngle(0)
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ RightShoulder:SetDesiredAngle(1.57)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ RightShoulder.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(0)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ RightHip.MaxVelocity = 0.5
+ LeftHip.MaxVelocity = 0.5
+ RightShoulder:SetDesiredAngle(1.57)
+ LeftShoulder:SetDesiredAngle(1.0)
+ RightHip:SetDesiredAngle(1.57)
+ LeftHip:SetDesiredAngle(1.0)
+ return
+ end
+end
+
+function move(time)
+ local amplitude
+ local frequency
+
+ if (pose == "Jumping") then
+ moveJump()
+ return
+ end
+
+ if (pose == "FreeFall") then
+ moveFreeFall()
+ return
+ end
+
+ if (pose == "Seated") then
+ moveSit()
+ return
+ end
+
+ local climbFudge = 0
+
+ if (pose == "Running") then
+ if (RightShoulder.CurrentAngle > 1.5 or RightShoulder.CurrentAngle < -1.5) then
+ RightShoulder.MaxVelocity = jumpMaxLimbVelocity
+ else
+ RightShoulder.MaxVelocity = 0.15
+ end
+ if (LeftShoulder.CurrentAngle > 1.5 or LeftShoulder.CurrentAngle < -1.5) then
+ LeftShoulder.MaxVelocity = jumpMaxLimbVelocity
+ else
+ LeftShoulder.MaxVelocity = 0.15
+ end
+ amplitude = 1
+ frequency = 9
+ elseif (pose == "Climbing") then
+ RightShoulder.MaxVelocity = 0.5
+ LeftShoulder.MaxVelocity = 0.5
+ amplitude = 1
+ frequency = 9
+ climbFudge = 3.14
+ else
+ amplitude = 0.1
+ frequency = 1
+ end
+
+ desiredAngle = amplitude * math.sin(time*frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+
+
+ local tool = getTool()
+
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+
+
+ else
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+
+-- connect events
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+Humanoid.Swimming:connect(onSwimming)
+-- main program
+
+local runService = game:service("RunService");
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+ true
+
+
+ -
+
+ false
+
+
+
+ RobloxTeam
+
+ -- Now with exciting TeamColors HACK!
+
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+ end
+
+ -- TEAM COLORS
+
+
+ function onTeamChanged(player)
+
+ wait(1)
+
+ local char = player.Character
+ if char == nil then return end
+
+ if player.Neutral then
+ -- Replacing the current BodyColor object will force a reset
+ local old = char:findFirstChild("Body Colors")
+ if not old then return end
+ old:clone().Parent = char
+ old.Parent = nil
+ else
+ local head = char:findFirstChild("Head")
+ local torso = char:findFirstChild("Torso")
+ local left_arm = char:findFirstChild("Left Arm")
+ local right_arm = char:findFirstChild("Right Arm")
+ local left_leg = char:findFirstChild("Left Leg")
+ local right_leg = char:findFirstChild("Right Leg")
+
+ if head then head.BrickColor = BrickColor.new(24) end
+ if torso then torso.BrickColor = player.TeamColor end
+ if left_arm then left_arm.BrickColor = BrickColor.new(26) end
+ if right_arm then right_arm.BrickColor = BrickColor.new(26) end
+ if left_leg then left_leg.BrickColor = BrickColor.new(26) end
+ if right_leg then right_leg.BrickColor = BrickColor.new(26) end
+ end
+ end
+
+ function onPlayerPropChanged(property, player)
+ if property == "Character" then
+ onTeamChanged(player)
+ end
+ if property== "TeamColor" or property == "Neutral" then
+ onTeamChanged(player)
+ end
+ end
+
+
+ local cPlayer = game.Players:GetPlayerFromCharacter(script.Parent)
+ cPlayer.Changed:connect(function(property) onPlayerPropChanged(property, cPlayer) end )
+ onTeamChanged(cPlayer)
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidAnimateLocalKeyframe.rbxm b/Client2016/content/fonts/humanoidAnimateLocalKeyframe.rbxm
new file mode 100644
index 0000000..fc12d22
--- /dev/null
+++ b/Client2016/content/fonts/humanoidAnimateLocalKeyframe.rbxm
@@ -0,0 +1,649 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+ function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+local Figure = script.Parent
+local Torso = waitForChild(Figure, "Torso")
+local RightShoulder = waitForChild(Torso, "Right Shoulder")
+local LeftShoulder = waitForChild(Torso, "Left Shoulder")
+local RightHip = waitForChild(Torso, "Right Hip")
+local LeftHip = waitForChild(Torso, "Left Hip")
+local Neck = waitForChild(Torso, "Neck")
+local Humanoid = waitForChild(Figure, "Humanoid")
+local pose = "Standing"
+
+local currentAnim = ""
+local currentAnimTrack = nil
+local currentAnimKeyframeHandler = nil
+local currentAnimSpeed = 1.0
+local animTable = {}
+local animNames = {
+ idle = {
+ { id = "http://www.roblox.com/asset/?id=125750544", weight = 9 },
+ { id = "http://www.roblox.com/asset/?id=125750618", weight = 1 }
+ },
+ walk = {
+ { id = "http://www.roblox.com/asset/?id=125749145", weight = 10 }
+ },
+ run = {
+ { id = "run.xml", weight = 10 }
+ },
+ jump = {
+ { id = "http://www.roblox.com/asset/?id=125750702", weight = 10 }
+ },
+ fall = {
+ { id = "http://www.roblox.com/asset/?id=125750759", weight = 10 }
+ },
+ climb = {
+ { id = "http://www.roblox.com/asset/?id=125750800", weight = 10 }
+ },
+ sit = {
+ { id = "http://www.roblox.com/asset/?id=178130996", weight = 10 }
+ },
+ toolnone = {
+ { id = "http://www.roblox.com/asset/?id=125750867", weight = 10 }
+ },
+ toolslash = {
+ { id = "http://www.roblox.com/asset/?id=129967390", weight = 10 }
+-- { id = "slash.xml", weight = 10 }
+ },
+ toollunge = {
+ { id = "http://www.roblox.com/asset/?id=129967478", weight = 10 }
+ },
+ wave = {
+ { id = "http://www.roblox.com/asset/?id=128777973", weight = 10 }
+ },
+ point = {
+ { id = "http://www.roblox.com/asset/?id=128853357", weight = 10 }
+ },
+ dance = {
+ { id = "http://www.roblox.com/asset/?id=130018893", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=132546839", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=132546884", weight = 10 }
+ },
+ dance2 = {
+ { id = "http://www.roblox.com/asset/?id=160934142", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=160934298", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=160934376", weight = 10 }
+ },
+ dance3 = {
+ { id = "http://www.roblox.com/asset/?id=160934458", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=160934530", weight = 10 },
+ { id = "http://www.roblox.com/asset/?id=160934593", weight = 10 }
+ },
+ laugh = {
+ { id = "http://www.roblox.com/asset/?id=129423131", weight = 10 }
+ },
+ cheer = {
+ { id = "http://www.roblox.com/asset/?id=129423030", weight = 10 }
+ },
+}
+
+-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
+local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}
+
+math.randomseed(tick())
+
+function configureAnimationSet(name, fileList)
+ if (animTable[name] ~= nil) then
+ for _, connection in pairs(animTable[name].connections) do
+ connection:disconnect()
+ end
+ end
+ animTable[name] = {}
+ animTable[name].count = 0
+ animTable[name].totalWeight = 0
+ animTable[name].connections = {}
+
+ -- check for config values
+ local config = script:FindFirstChild(name)
+ if (config ~= nil) then
+-- print("Loading anims " .. name)
+ table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))
+ table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))
+ local idx = 1
+ for _, childPart in pairs(config:GetChildren()) do
+ if (childPart:IsA("Animation")) then
+ table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
+ animTable[name][idx] = {}
+ animTable[name][idx].anim = childPart
+ local weightObject = childPart:FindFirstChild("Weight")
+ if (weightObject == nil) then
+ animTable[name][idx].weight = 1
+ else
+ animTable[name][idx].weight = weightObject.Value
+ end
+ animTable[name].count = animTable[name].count + 1
+ animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
+ -- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")")
+ idx = idx + 1
+ end
+ end
+ end
+
+ -- fallback to defaults
+ if (animTable[name].count <= 0) then
+ for idx, anim in pairs(fileList) do
+ animTable[name][idx] = {}
+ animTable[name][idx].anim = Instance.new("Animation")
+ animTable[name][idx].anim.Name = name
+ animTable[name][idx].anim.AnimationId = anim.id
+ animTable[name][idx].weight = anim.weight
+ animTable[name].count = animTable[name].count + 1
+ animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
+-- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
+ end
+ end
+end
+
+-- Setup animation objects
+function scriptChildModified(child)
+ local fileList = animNames[child.Name]
+ if (fileList ~= nil) then
+ configureAnimationSet(child.Name, fileList)
+ end
+end
+
+script.ChildAdded:connect(scriptChildModified)
+script.ChildRemoved:connect(scriptChildModified)
+
+
+for name, fileList in pairs(animNames) do
+ configureAnimationSet(name, fileList)
+end
+
+-- ANIMATION
+
+-- declarations
+local toolAnim = "None"
+local toolAnimTime = 0
+
+local jumpAnimTime = 0
+local jumpAnimDuration = 0.3
+
+local toolTransitionTime = 0.1
+local fallTransitionTime = 0.3
+local jumpMaxLimbVelocity = 0.75
+
+-- functions
+
+function stopAllAnimations()
+ local oldAnim = currentAnim
+
+ -- return to idle if finishing an emote
+ if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then
+ oldAnim = "idle"
+ end
+
+ currentAnim = ""
+ if (currentAnimKeyframeHandler ~= nil) then
+ currentAnimKeyframeHandler:disconnect()
+ end
+
+ if (currentAnimTrack ~= nil) then
+ currentAnimTrack:Stop()
+ currentAnimTrack:Destroy()
+ currentAnimTrack = nil
+ end
+ return oldAnim
+end
+
+function setAnimationSpeed(speed)
+ if speed ~= currentAnimSpeed then
+ currentAnimSpeed = speed
+ currentAnimTrack:AdjustSpeed(currentAnimSpeed)
+ end
+end
+
+function keyFrameReachedFunc(frameName)
+ if (frameName == "End") then
+-- print("Keyframe : ".. frameName)
+ local repeatAnim = stopAllAnimations()
+ local animSpeed = currentAnimSpeed
+ playAnimation(repeatAnim, 0.0, Humanoid)
+ setAnimationSpeed(animSpeed)
+ end
+end
+
+-- Preload animations
+function playAnimation(animName, transitionTime, humanoid)
+ local idleFromEmote = (animName == "idle" and emoteNames[currentAnim] ~= nil)
+ if (animName ~= currentAnim and not idleFromEmote) then
+
+ if (currentAnimTrack ~= nil) then
+ currentAnimTrack:Stop(transitionTime)
+ currentAnimTrack:Destroy()
+ end
+
+ currentAnimSpeed = 1.0
+ local roll = math.random(1, animTable[animName].totalWeight)
+ local origRoll = roll
+ local idx = 1
+ while (roll > animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ -- load it to the humanoid; get AnimationTrack
+ currentAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ currentAnimTrack:Play(transitionTime)
+ currentAnim = animName
+
+ -- set up keyframe name triggers
+ if (currentAnimKeyframeHandler ~= nil) then
+ currentAnimKeyframeHandler:disconnect()
+ end
+ currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
+ end
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+local toolAnimName = ""
+local toolAnimTrack = nil
+local currentToolAnimKeyframeHandler = nil
+
+function toolKeyFrameReachedFunc(frameName)
+ if (frameName == "End") then
+-- print("Keyframe : ".. frameName)
+ local repeatAnim = stopToolAnimations()
+ playToolAnimation(repeatAnim, 0.0, Humanoid)
+ end
+end
+
+
+function playToolAnimation(animName, transitionTime, humanoid)
+ if (animName ~= toolAnimName) then
+
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ transitionTime = 0
+ end
+
+ local roll = math.random(1, animTable[animName].totalWeight)
+ local origRoll = roll
+ local idx = 1
+ while (roll > animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ -- load it to the humanoid; get AnimationTrack
+ toolAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ toolAnimTrack:Play(transitionTime)
+ toolAnimName = animName
+
+ currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
+ end
+end
+
+function stopToolAnimations()
+ local oldAnim = toolAnimName
+
+ if (currentToolAnimKeyframeHandler ~= nil) then
+ currentToolAnimKeyframeHandler:disconnect()
+ end
+
+ toolAnimName = ""
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ toolAnimTrack = nil
+ end
+
+
+ return oldAnim
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+
+function onRunning(speed)
+ if speed>0.5 then
+ playAnimation("walk", 0.1, Humanoid)
+ pose = "Running"
+ else
+ playAnimation("idle", 0.1, Humanoid)
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ playAnimation("jump", 0.1, Humanoid)
+ jumpAnimTime = jumpAnimDuration
+ pose = "Jumping"
+end
+
+function onClimbing(speed)
+ playAnimation("climb", 0.1, Humanoid)
+ setAnimationSpeed(speed / 12.0)
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ if (jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ end
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function onSwimming(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ playToolAnimation("toolnone", toolTransitionTime, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ playToolAnimation("toolslash", 0, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ playToolAnimation("toollunge", 0, Humanoid)
+ return
+ end
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+local lastTick = 0
+
+function move(time)
+ local amplitude = 1
+ local frequency = 1
+ local deltaTime = time - lastTick
+ lastTick = time
+
+ local climbFudge = 0
+ local setAngles = false
+
+ if (jumpAnimTime > 0) then
+ jumpAnimTime = jumpAnimTime - deltaTime
+ end
+
+ if (pose == "FreeFall" and jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ elseif (pose == "Seated") then
+ playAnimation("sit", 0.5, Humanoid)
+ return
+ elseif (pose == "Running") then
+ playAnimation("walk", 0.1, Humanoid)
+ elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
+-- print("Wha " .. pose)
+ stopAllAnimations()
+ amplitude = 0.1
+ frequency = 1
+ setAngles = true
+ end
+
+ if (setAngles) then
+ desiredAngle = amplitude * math.sin(time * frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+ end
+
+ -- Tool Animation handling
+ local tool = getTool()
+ if tool then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+ else
+ stopToolAnimations()
+ toolAnim = "None"
+ toolAnimTime = 0
+ end
+end
+
+-- connect events
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+Humanoid.Swimming:connect(onSwimming)
+
+-- setup emote chat hook
+Game.Players.LocalPlayer.Chatted:connect(function(msg)
+ local emote = ""
+ if (string.sub(msg, 1, 3) == "/e ") then
+ emote = string.sub(msg, 4)
+ elseif (string.sub(msg, 1, 7) == "/emote ") then
+ emote = string.sub(msg, 8)
+ end
+
+ if (pose == "Standing" and emoteNames[emote] ~= nil) then
+ playAnimation(emote, 0.1, Humanoid)
+ end
+-- print("===> " .. string.sub(msg, 1, 3) .. "(" .. emote .. ")")
+end)
+
+
+-- main program
+
+local runService = game:service("RunService");
+
+-- initialize to idle
+playAnimation("idle", 0.1, Humanoid)
+pose = "Standing"
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+
+
+
+
-
+
+ idle
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750544
+ Animation1
+
+
-
+
+ Weight
+ 9
+
+
+
+ -
+
+ http://www.roblox.com/asset/?id=125750618
+ Animation2
+
+
-
+
+ Weight
+ 1
+
+
+
+
+ -
+
+ walk
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125749145
+ WalkAnim
+
+
+
+ -
+
+ run
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125749145
+ RunAnim
+
+
+
+ -
+
+ jump
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750702
+ JumpAnim
+
+
+
+ -
+
+ climb
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750800
+ ClimbAnim
+
+
+
+ -
+
+ toolnone
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750867
+ ToolNoneAnim
+
+
+
+ -
+
+ fall
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750759
+ FallAnim
+
+
+
+ -
+
+ sit
+
+
+
-
+
+ http://www.roblox.com/asset/?id=178130996
+ SitAnim
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidAnimateLocalKeyframe2.rbxm b/Client2016/content/fonts/humanoidAnimateLocalKeyframe2.rbxm
new file mode 100644
index 0000000..7753644
--- /dev/null
+++ b/Client2016/content/fonts/humanoidAnimateLocalKeyframe2.rbxm
@@ -0,0 +1,669 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Animate
+ animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ -- switch animation
+ if (anim ~= currentAnimInstance) then
+
+ if (currentAnimTrack ~= nil) then
+ currentAnimTrack:Stop(transitionTime)
+ currentAnimTrack:Destroy()
+ end
+
+ currentAnimSpeed = 1.0
+
+ -- load it to the humanoid; get AnimationTrack
+ currentAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ currentAnimTrack:Play(transitionTime)
+ currentAnim = animName
+ currentAnimInstance = anim
+
+ -- set up keyframe name triggers
+ if (currentAnimKeyframeHandler ~= nil) then
+ currentAnimKeyframeHandler:disconnect()
+ end
+ currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
+
+ end
+
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+local toolAnimName = ""
+local toolAnimTrack = nil
+local toolAnimInstance = nil
+local currentToolAnimKeyframeHandler = nil
+
+function toolKeyFrameReachedFunc(frameName)
+ if (frameName == "End") then
+-- print("Keyframe : ".. frameName)
+ playToolAnimation(toolAnimName, 0.0, Humanoid)
+ end
+end
+
+
+function playToolAnimation(animName, transitionTime, humanoid)
+
+ local roll = math.random(1, animTable[animName].totalWeight)
+ local origRoll = roll
+ local idx = 1
+ while (roll > animTable[animName][idx].weight) do
+ roll = roll - animTable[animName][idx].weight
+ idx = idx + 1
+ end
+-- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
+ local anim = animTable[animName][idx].anim
+
+ if (toolAnimInstance ~= anim) then
+
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ transitionTime = 0
+ end
+
+ -- load it to the humanoid; get AnimationTrack
+ toolAnimTrack = humanoid:LoadAnimation(anim)
+
+ -- play the animation
+ toolAnimTrack:Play(transitionTime)
+ toolAnimName = animName
+ toolAnimInstance = anim
+
+ currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
+ end
+end
+
+function stopToolAnimations()
+ local oldAnim = toolAnimName
+
+ if (currentToolAnimKeyframeHandler ~= nil) then
+ currentToolAnimKeyframeHandler:disconnect()
+ end
+
+ toolAnimName = ""
+ toolAnimInstance = nil
+ if (toolAnimTrack ~= nil) then
+ toolAnimTrack:Stop()
+ toolAnimTrack:Destroy()
+ toolAnimTrack = nil
+ end
+
+
+ return oldAnim
+end
+
+-------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------
+
+
+function onRunning(speed)
+ if speed>0.01 then
+ playAnimation("walk", 0.1, Humanoid)
+ if currentAnimInstance and currentAnimInstance.AnimationId == "http://www.roblox.com/asset/?id=180426354" then
+ setAnimationSpeed(speed / 14.5)
+ end
+ pose = "Running"
+ else
+ playAnimation("idle", 0.1, Humanoid)
+ pose = "Standing"
+ end
+end
+
+function onDied()
+ pose = "Dead"
+end
+
+function onJumping()
+ playAnimation("jump", 0.1, Humanoid)
+ jumpAnimTime = jumpAnimDuration
+ pose = "Jumping"
+end
+
+function onClimbing(speed)
+ playAnimation("climb", 0.1, Humanoid)
+ setAnimationSpeed(speed / 12.0)
+ pose = "Climbing"
+end
+
+function onGettingUp()
+ pose = "GettingUp"
+end
+
+function onFreeFall()
+ if (jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ end
+ pose = "FreeFall"
+end
+
+function onFallingDown()
+ pose = "FallingDown"
+end
+
+function onSeated()
+ pose = "Seated"
+end
+
+function onPlatformStanding()
+ pose = "PlatformStanding"
+end
+
+function onSwimming(speed)
+ if speed>0 then
+ pose = "Running"
+ else
+ pose = "Standing"
+ end
+end
+
+function getTool()
+ for _, kid in ipairs(Figure:GetChildren()) do
+ if kid.className == "Tool" then return kid end
+ end
+ return nil
+end
+
+function getToolAnim(tool)
+ for _, c in ipairs(tool:GetChildren()) do
+ if c.Name == "toolanim" and c.className == "StringValue" then
+ return c
+ end
+ end
+ return nil
+end
+
+function animateTool()
+
+ if (toolAnim == "None") then
+ playToolAnimation("toolnone", toolTransitionTime, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Slash") then
+ playToolAnimation("toolslash", 0, Humanoid)
+ return
+ end
+
+ if (toolAnim == "Lunge") then
+ playToolAnimation("toollunge", 0, Humanoid)
+ return
+ end
+end
+
+function moveSit()
+ RightShoulder.MaxVelocity = 0.15
+ LeftShoulder.MaxVelocity = 0.15
+ RightShoulder:SetDesiredAngle(3.14 /2)
+ LeftShoulder:SetDesiredAngle(-3.14 /2)
+ RightHip:SetDesiredAngle(3.14 /2)
+ LeftHip:SetDesiredAngle(-3.14 /2)
+end
+
+local lastTick = 0
+
+function move(time)
+ local amplitude = 1
+ local frequency = 1
+ local deltaTime = time - lastTick
+ lastTick = time
+
+ local climbFudge = 0
+ local setAngles = false
+
+ if (jumpAnimTime > 0) then
+ jumpAnimTime = jumpAnimTime - deltaTime
+ end
+
+ if (pose == "FreeFall" and jumpAnimTime <= 0) then
+ playAnimation("fall", fallTransitionTime, Humanoid)
+ elseif (pose == "Seated") then
+ playAnimation("sit", 0.5, Humanoid)
+ return
+ elseif (pose == "Running") then
+ playAnimation("walk", 0.1, Humanoid)
+ elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
+-- print("Wha " .. pose)
+ stopAllAnimations()
+ amplitude = 0.1
+ frequency = 1
+ setAngles = true
+ end
+
+ if (setAngles) then
+ desiredAngle = amplitude * math.sin(time * frequency)
+
+ RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
+ LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
+ RightHip:SetDesiredAngle(-desiredAngle)
+ LeftHip:SetDesiredAngle(-desiredAngle)
+ end
+
+ -- Tool Animation handling
+ local tool = getTool()
+ if tool and tool:FindFirstChild("Handle") then
+
+ animStringValueObject = getToolAnim(tool)
+
+ if animStringValueObject then
+ toolAnim = animStringValueObject.Value
+ -- message recieved, delete StringValue
+ animStringValueObject.Parent = nil
+ toolAnimTime = time + .3
+ end
+
+ if time > toolAnimTime then
+ toolAnimTime = 0
+ toolAnim = "None"
+ end
+
+ animateTool()
+ else
+ stopToolAnimations()
+ toolAnim = "None"
+ toolAnimInstance = nil
+ toolAnimTime = 0
+ end
+end
+
+-- connect events
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(onJumping)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.GettingUp:connect(onGettingUp)
+Humanoid.FreeFalling:connect(onFreeFall)
+Humanoid.FallingDown:connect(onFallingDown)
+Humanoid.Seated:connect(onSeated)
+Humanoid.PlatformStanding:connect(onPlatformStanding)
+Humanoid.Swimming:connect(onSwimming)
+
+-- setup emote chat hook
+game.Players.LocalPlayer.Chatted:connect(function(msg)
+ local emote = ""
+ if msg == "/e dance" then
+ emote = dances[math.random(1, #dances)]
+ elseif (string.sub(msg, 1, 3) == "/e ") then
+ emote = string.sub(msg, 4)
+ elseif (string.sub(msg, 1, 7) == "/emote ") then
+ emote = string.sub(msg, 8)
+ end
+
+ if (pose == "Standing" and emoteNames[emote] ~= nil) then
+ playAnimation(emote, 0.1, Humanoid)
+ end
+
+end)
+
+
+-- main program
+
+local runService = game:service("RunService");
+
+-- initialize to idle
+playAnimation("idle", 0.1, Humanoid)
+pose = "Standing"
+
+while Figure.Parent~=nil do
+ local _, time = wait(0.1)
+ move(time)
+end
+
+
+]]>
+
+
-
+
+ idle
+
+
+
-
+
+ http://www.roblox.com/asset/?id=180435571
+ Animation1
+
+
-
+
+ Weight
+ 9
+
+
+
+ -
+
+ http://www.roblox.com/asset/?id=180435792
+ Animation2
+
+
-
+
+ Weight
+ 1
+
+
+
+
+ -
+
+ walk
+
+
+
-
+
+ http://www.roblox.com/asset/?id=180426354
+ WalkAnim
+
+
+
+ -
+
+ run
+
+
+
-
+
+ http://www.roblox.com/asset/?id=180426354
+ RunAnim
+
+
+
+ -
+
+ jump
+
+
+
-
+
+ http://www.roblox.com/asset/?id=125750702
+ JumpAnim
+
+
+
+ -
+
+ climb
+
+
+
-
+
+ http://www.roblox.com/asset/?id=180436334
+ ClimbAnim
+
+
+
+ -
+
+ toolnone
+
+
+
-
+
+ http://www.roblox.com/asset/?id=182393478
+ ToolNoneAnim
+
+
+
+ -
+
+ fall
+
+
+
-
+
+ http://www.roblox.com/asset/?id=180436148
+ FallAnim
+
+
+
+ -
+
+ sit
+
+
+
-
+
+ http://www.roblox.com/asset/?id=178130996
+ SitAnim
+
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidAnimateR15.rbxm b/Client2016/content/fonts/humanoidAnimateR15.rbxm
new file mode 100644
index 0000000..ebae470
Binary files /dev/null and b/Client2016/content/fonts/humanoidAnimateR15.rbxm differ
diff --git a/Client2016/content/fonts/humanoidExtra.rbxm b/Client2016/content/fonts/humanoidExtra.rbxm
new file mode 100644
index 0000000..ea08e27
--- /dev/null
+++ b/Client2016/content/fonts/humanoidExtra.rbxm
@@ -0,0 +1,11 @@
+
+ null
+ nil
+ -
+
+ false
+ Script
+
while script.Parent.Head==nil do
wait(0.05)
end
function newSound(id)
local sound = Instance.new("Sound")
sound.SoundId = id
sound.Parent = script.Parent.Head
return sound
end
sDied = newSound("rbxasset://sounds/uuhhh.wav")
sFallingDown = newSound("rbxasset://sounds/splat.wav")
sFreeFalling = newSound("rbxasset://sounds/swoosh.wav")
sGettingUp = newSound("rbxasset://sounds/hit.wav")
sJumping = newSound("rbxasset://sounds/button.wav")
sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3")
sRunning.Looped = true
function onDied()
sDied:play()
end
function onState(state, sound)
if state then
sound:play()
else
sound:pause()
end
end
function onRunning(speed)
if speed>0 then
sRunning:play()
else
sRunning:pause()
end
end
while script.Parent.Humanoid==nil do
wait(0.05)
end
h = script.Parent.Humanoid
h.Died:connect(onDied)
h.Running:connect(onRunning)
h.Jumping:connect(function(state) onState(state, sJumping) end)
h.GettingUp:connect(function(state) onState(state, sGettingUp) end)
h.FreeFalling:connect(function(state) onState(state, sFreeFalling) end)
h.FallingDown:connect(function(state) onState(state, sFallingDown) end)
-- regeneration
while true do
local s = wait(1)
local health=h.Health
if health>0 and health<h.MaxHealth then
health = health + 0.01*s*h.MaxHealth
if health*1.05 < h.MaxHealth then
h.Health = health
else
h.Health = h.MaxHealth
end
end
end
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidSound.rbxm b/Client2016/content/fonts/humanoidSound.rbxm
new file mode 100644
index 0000000..8968b16
--- /dev/null
+++ b/Client2016/content/fonts/humanoidSound.rbxm
@@ -0,0 +1,75 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ -- util
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+function newSound(id)
+ local sound = Instance.new("Sound")
+ sound.SoundId = id
+ sound.archivable = false
+ sound.Parent = script.Parent.Head
+ return sound
+end
+
+-- declarations
+
+local sDied = newSound("rbxasset://sounds/uuhhh.wav")
+local sFallingDown = newSound("rbxasset://sounds/splat.wav")
+local sFreeFalling = newSound("rbxasset://sounds/swoosh.wav")
+local sGettingUp = newSound("rbxasset://sounds/hit.wav")
+local sJumping = newSound("rbxasset://sounds/button.wav")
+local sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3")
+sRunning.Looped = true
+
+local Figure = script.Parent
+local Head = waitForChild(Figure, "Head")
+local Humanoid = waitForChild(Figure, "Humanoid")
+
+-- functions
+
+function onDied()
+ sDied:Play()
+end
+
+function onState(state, sound)
+ if state then
+ sound:Play()
+ else
+ sound:Pause()
+ end
+end
+
+function onRunning(speed)
+ if speed>0.01 then
+ sRunning:Play()
+ else
+ sRunning:Pause()
+ end
+end
+
+-- connect up
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Jumping:connect(function(state) onState(state, sJumping) end)
+Humanoid.GettingUp:connect(function(state) onState(state, sGettingUp) end)
+Humanoid.FreeFalling:connect(function(state) onState(state, sFreeFalling) end)
+Humanoid.FallingDown:connect(function(state) onState(state, sFallingDown) end)
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidSound2.rbxm b/Client2016/content/fonts/humanoidSound2.rbxm
new file mode 100644
index 0000000..01591b3
--- /dev/null
+++ b/Client2016/content/fonts/humanoidSound2.rbxm
@@ -0,0 +1,43 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ -- util
+
+function waitForChild(parent, childName)
+ local child = parent:findFirstChild(childName)
+ if child then return child end
+ while true do
+ child = parent.ChildAdded:wait()
+ if child.Name==childName then return child end
+ end
+end
+
+function newSound(id, name)
+ local sound = Instance.new("Sound")
+ sound.SoundId = id
+ sound.archivable = false
+ sound.Parent = script.Parent.Head
+ sound.Name = name
+ return sound
+end
+
+-- declarations
+local Figure = script.Parent
+local Head = waitForChild(Figure, "Head")
+local Humanoid = waitForChild(Figure, "Humanoid")
+
+local sDied = newSound("rbxasset://sounds/uuhhh.wav", "DiedSound")
+local sFallingDown = newSound("rbxasset://sounds/splat.wav", "FallingDownSound")
+local sFreeFalling = newSound("rbxasset://sounds/swoosh.wav", "FreeFallingSound")
+local sGettingUp = newSound("rbxasset://sounds/hit.wav", "GettingUpSound")
+local sJumping = newSound("rbxasset://sounds/button.wav", "JumpingSound")
+local sRunning = newSound("rbxasset://sounds/bfsl-minifigfoots1.mp3", "RunningSound")
+sRunning.Looped = true
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidSoundNew.rbxm b/Client2016/content/fonts/humanoidSoundNew.rbxm
new file mode 100644
index 0000000..abb6eec
--- /dev/null
+++ b/Client2016/content/fonts/humanoidSoundNew.rbxm
@@ -0,0 +1,160 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ 0.1) then
+ local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
+ sLanding.Volume = vol
+ sLanding:Play()
+ fallSpeed = 0
+ end
+ if speed>0.5 then
+ sRunning:Play()
+ sRunning.Pitch = speed / 8.0
+ else
+ sRunning:Stop()
+ end
+ prevState = "Run"
+end
+
+function onSwimming(speed)
+ if (prevState ~= "Swim" and speed > 0.1) then
+ local volume = math.min(1.0, speed / 350)
+ sSplash.Volume = volume
+ sSplash:Play()
+ prevState = "Swim"
+ end
+ sClimbing:Stop()
+ sRunning:Stop()
+ sSwimming.Pitch = 1.6
+ sSwimming:Play()
+end
+
+function onClimbing(speed)
+ sRunning:Stop()
+ sSwimming:Stop()
+ if speed>0.01 then
+ sClimbing:Play()
+ sClimbing.Pitch = speed / 5.5
+ else
+ sClimbing:Stop()
+ end
+ prevState = "Climb"
+end
+-- connect up
+
+function stopLoopedSounds()
+ sRunning:Stop()
+ sClimbing:Stop()
+ sSwimming:Stop()
+end
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Swimming:connect(onSwimming)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.Jumping:connect(function(state) onStateNoStop(state, sJumping) prevState = "Jump" end)
+Humanoid.GettingUp:connect(function(state) stopLoopedSounds() onStateNoStop(state, sGettingUp) prevState = "GetUp" end)
+Humanoid.FreeFalling:connect(function(state) stopLoopedSounds() onStateFall(state, sFreeFalling) prevState = "FreeFall" end)
+Humanoid.FallingDown:connect(function(state) stopLoopedSounds() end)
+Humanoid.StateChanged:connect(function(old, new)
+ if not (new.Name == "Dead" or
+ new.Name == "Running" or
+ new.Name == "RunningNoPhysics" or
+ new.Name == "Swimming" or
+ new.Name == "Jumping" or
+ new.Name == "GettingUp" or
+ new.Name == "Freefall" or
+ new.Name == "FallingDown") then
+ stopLoopedSounds()
+ end
+end)
+]]>
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidSoundNewLocal.rbxmx b/Client2016/content/fonts/humanoidSoundNewLocal.rbxmx
new file mode 100644
index 0000000..8100552
--- /dev/null
+++ b/Client2016/content/fonts/humanoidSoundNewLocal.rbxmx
@@ -0,0 +1,317 @@
+
+ null
+ nil
+ -
+
+ false
+
+ Sound
+ 0.1) then
+ local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
+ sLanding.Volume = vol
+ sLanding:Play()
+ fallSpeed = 0
+ end
+ if speed>0.5 then
+ sRunning:Play()
+ sRunning.Pitch = speed / 8.0
+ else
+ sRunning:Stop()
+ end
+ prevState = "Run"
+end
+
+function onSwimming(speed)
+ if (prevState ~= "Swim" and speed > 0.1) then
+ local volume = math.min(1.0, speed / 350)
+ sSplash.Volume = volume
+ sSplash:Play()
+ prevState = "Swim"
+ end
+ sClimbing:Stop()
+ sRunning:Stop()
+ sSwimming.Pitch = 1.6
+ sSwimming:Play()
+end
+
+function onClimbing(speed)
+ sRunning:Stop()
+ sSwimming:Stop()
+ if speed>0.01 then
+ sClimbing:Play()
+ sClimbing.Pitch = speed / 5.5
+ else
+ sClimbing:Stop()
+ end
+ prevState = "Climb"
+end
+-- connect up
+
+function stopLoopedSounds()
+ sRunning:Stop()
+ sClimbing:Stop()
+ sSwimming:Stop()
+end
+
+if hasPlayer == nil then
+ Humanoid.Died:connect(onDied)
+ Humanoid.Running:connect(onRunning)
+ Humanoid.Swimming:connect(onSwimming)
+ Humanoid.Climbing:connect(onClimbing)
+ Humanoid.Jumping:connect(function(state) onStateNoStop(state, sJumping) prevState = "Jump" end)
+ Humanoid.GettingUp:connect(function(state) stopLoopedSounds() onStateNoStop(state, sGettingUp) prevState = "GetUp" end)
+ Humanoid.FreeFalling:connect(function(state) stopLoopedSounds() onStateFall(state, sFreeFalling) prevState = "FreeFall" end)
+ Humanoid.FallingDown:connect(function(state) stopLoopedSounds() end)
+ Humanoid.StateChanged:connect(function(old, new)
+ if not (new.Name == "Dead" or
+ new.Name == "Running" or
+ new.Name == "RunningNoPhysics" or
+ new.Name == "Swimming" or
+ new.Name == "Jumping" or
+ new.Name == "GettingUp" or
+ new.Name == "Freefall" or
+ new.Name == "FallingDown") then
+ stopLoopedSounds()
+ end
+ end)
+end
+]]>
+
+
-
+
+ false
+
+ LocalSound
+ 0.1) then
+ local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
+ sLanding.Volume = vol
+ sLanding:Play()
+ fallSpeed = 0
+ end
+ if speed>0.5 then
+ sRunning:Play()
+ sRunning.Pitch = speed / 8.0
+ else
+ sRunning:Stop()
+ end
+ prevState = "Run"
+end
+
+function onSwimming(speed)
+ if (prevState ~= "Swim" and speed > 0.1) then
+ local volume = math.min(1.0, speed / 350)
+ sSplash.Volume = volume
+ sSplash:Play()
+ prevState = "Swim"
+ end
+ sClimbing:Stop()
+ sRunning:Stop()
+ sSwimming.Pitch = 1.6
+ sSwimming:Play()
+end
+
+function onClimbing(speed)
+ sRunning:Stop()
+ sSwimming:Stop()
+ if speed>0.01 then
+ sClimbing:Play()
+ sClimbing.Pitch = speed / 5.5
+ else
+ sClimbing:Stop()
+ end
+ prevState = "Climb"
+end
+-- connect up
+
+function stopLoopedSounds()
+ sRunning:Stop()
+ sClimbing:Stop()
+ sSwimming:Stop()
+end
+
+Humanoid.Died:connect(onDied)
+Humanoid.Running:connect(onRunning)
+Humanoid.Swimming:connect(onSwimming)
+Humanoid.Climbing:connect(onClimbing)
+Humanoid.Jumping:connect(function(state) onStateNoStop(state, sJumping) prevState = "Jump" end)
+Humanoid.GettingUp:connect(function(state) stopLoopedSounds() onStateNoStop(state, sGettingUp) prevState = "GetUp" end)
+Humanoid.FreeFalling:connect(function(state) stopLoopedSounds() onStateFall(state, sFreeFalling) prevState = "FreeFall" end)
+Humanoid.FallingDown:connect(function(state) stopLoopedSounds() end)
+Humanoid.StateChanged:connect(function(old, new)
+ if not (new.Name == "Dead" or
+ new.Name == "Running" or
+ new.Name == "RunningNoPhysics" or
+ new.Name == "Swimming" or
+ new.Name == "Jumping" or
+ new.Name == "GettingUp" or
+ new.Name == "Freefall" or
+ new.Name == "FallingDown") then
+ stopLoopedSounds()
+ end
+end)
+
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/humanoidStatic.rbxm b/Client2016/content/fonts/humanoidStatic.rbxm
new file mode 100644
index 0000000..1c9fcb7
--- /dev/null
+++ b/Client2016/content/fonts/humanoidStatic.rbxm
@@ -0,0 +1,12 @@
+
+ null
+ nil
+ -
+
+ false
+ Static
+ local Figure = script.Parent
local Torso = Figure:findFirstChild("Torso")
Torso:makeJoints()
+ true
+
+
+
\ No newline at end of file
diff --git a/Client2016/content/fonts/leftarm.mesh b/Client2016/content/fonts/leftarm.mesh
new file mode 100644
index 0000000..6e8bb63
Binary files /dev/null and b/Client2016/content/fonts/leftarm.mesh differ
diff --git a/Client2016/content/fonts/leftleg.mesh b/Client2016/content/fonts/leftleg.mesh
new file mode 100644
index 0000000..aba3a29
Binary files /dev/null and b/Client2016/content/fonts/leftleg.mesh differ
diff --git a/Client2016/content/fonts/rightarm.mesh b/Client2016/content/fonts/rightarm.mesh
new file mode 100644
index 0000000..14a52a4
Binary files /dev/null and b/Client2016/content/fonts/rightarm.mesh differ
diff --git a/Client2016/content/fonts/rightleg.mesh b/Client2016/content/fonts/rightleg.mesh
new file mode 100644
index 0000000..dab065d
Binary files /dev/null and b/Client2016/content/fonts/rightleg.mesh differ
diff --git a/Client2016/content/fonts/safechat.xml b/Client2016/content/fonts/safechat.xml
new file mode 100644
index 0000000..199e3b2
--- /dev/null
+++ b/Client2016/content/fonts/safechat.xml
@@ -0,0 +1,737 @@
+
+ null
+ nil
+ Use the Chat menu to talk to me.
+ I can only see menu chats.
+
+ Hello
+
+ Hi
+ Hi there!
+ Hi everyone
+
+
+ Howdy
+ Howdy partner!
+
+
+ Greetings
+ Greetings everyone
+ Greetings Robloxians!
+ Seasons greetings!
+
+
+ Welcome
+ Welcome to my place
+ Welcome to our base
+ Welcome to my barbeque
+
+ Hey there!
+
+ What's up?
+ How are you doing?
+ How's it going?
+ What's new?
+
+
+ Good day
+ Good morning
+ Good afternoon
+ Good evening
+ Good night
+
+
+ Silly
+ Waaaaaaaz up?!
+ Hullo!
+ Behold greatness, mortals!
+ Pardon me, is this Sparta?
+ THIS IS SPARTAAAA!
+
+
+ Happy Holidays!
+ Happy New Year!
+ Happy Valentine's Day!
+ Beware the Ides of March!
+ Happy St. Patrick's Day!
+ Happy Easter!
+ Happy Earth Day!
+ Happy 4th of July!
+ Happy Thanksgiving!
+ Happy Halloween!
+ Happy Hanukkah!
+ Merry Christmas!
+ Happy Halloween!
+ Happy Earth Day!
+ Happy May Day!
+ Happy Towel Day!
+ Happy ROBLOX Day!
+ Happy LOL Day!
+
+
+
+ Goodbye
+
+ Good Night
+ Sweet dreams
+ Go to sleep!
+ Lights out!
+ Bedtime
+ Going to bed now
+
+
+ Later
+ See ya later
+ Later gator!
+ See you tomorrow
+
+
+ Bye
+ Hasta la bye bye!
+
+ I'll be right back
+ I have to go
+
+ Farewell
+ Take care
+ Have a nice day
+ Goodluck!
+ Ta-ta for now!
+
+
+ Peace
+ Peace out!
+ Peace dudes!
+ Rest in pieces!
+
+
+ Silly
+ To the batcave!
+ Over and out!
+ Happy trails!
+ I've got to book it!
+ Tootles!
+ Smell you later!
+ GG!
+ My house is on fire! gtg.
+
+
+
+ Friend
+ Wanna be friends?
+
+ Follow me
+ Come to my place!
+ Come to my base!
+ Follow me, team!
+ Follow me
+
+
+ Your place is cool
+ Your place is fun
+ Your place is awesome
+ Your place looks good
+ This place is awesome!
+
+
+ Thank you
+ Thanks for playing
+ Thanks for visiting
+ Thanks for everything
+ No, thank you
+ Thanx
+
+
+ No problem
+ Don't worry
+ That's ok
+ np
+
+
+ You are ...
+ You are great!
+ You are good!
+ You are cool!
+ You are funny!
+ You are silly!
+ You are awesome!
+ You are doing something I don't like, please stop
+
+
+ I like ...
+ I like your name
+ I like your shirt
+ I like your place
+ I like your style
+ I like you
+ I like items
+ I like money
+
+
+ Sorry
+ My bad!
+ I'm sorry
+ Whoops!
+ Please forgive me.
+ I forgive you.
+ I didn't mean to do that.
+ Sorry, I'll stop now.
+
+
+
+ Questions
+
+ Who?
+ Who wants to be my friend?
+ Who wants to be on my team?
+ Who made this brilliant game?
+ LOLWHO?
+
+
+ What?
+ What is your favorite animal?
+ What is your favorite game?
+ What is your favorite movie?
+ What is your favorite TV show?
+ What is your favorite music?
+ What are your hobbies?
+ LOLWUT?
+
+
+ When?
+ When are you online?
+ When is the new version coming out?
+ When can we play again?
+ When will your place be done?
+
+
+ Where?
+ Where do you want to go?
+ Where are you going?
+ Where am I?!
+ Where did you go?
+
+
+ How?
+ How are you today?
+ How did you make this cool place?
+ LOLHOW?
+
+
+ Can I...
+ Can I have a tour?
+ Can I be on your team?
+ Can I be your friend?
+ Can I try something?
+ Can I have that please?
+ Can I have that back please?
+ Can I have borrow your hat?
+ Can I have borrow your gear?
+
+
+
+ Answers
+
+ You need help?
+ Check out the news section
+ Check out the help section
+ Read the wiki!
+ All the answers are in the wiki!
+ I will help you with this.
+
+
+ Some people ...
+ Me
+ Not me
+ You
+ All of us
+ Everyone but you
+ Builderman!
+ Telamon!
+ My team
+ My group
+ Mom
+ Dad
+ Sister
+ Brother
+ Cousin
+ Grandparent
+ Friend
+
+
+ Time ...
+ In the morning
+ In the afternoon
+ At night
+ Tomorrow
+ This week
+ This month
+ Sometime
+ Sometimes
+ Whenever you want
+ Never
+ After this
+ In 10 minutes
+ In a couple hours
+ In a couple days
+
+
+ Animals
+
+ Cats
+ Lion
+ Tiger
+ Leopard
+ Cheetah
+
+
+ Dogs
+ Wolves
+ Beagle
+ Collie
+ Dalmatian
+ Poodle
+ Spaniel
+ Shepherd
+ Terrier
+ Retriever
+
+
+ Horses
+ Ponies
+ Stallions
+ Pwnyz
+
+
+ Reptiles
+ Dinosaurs
+ Lizards
+ Snakes
+ Turtles!
+
+ Hamster
+ Monkey
+ Bears
+
+ Fish
+ Goldfish
+ Sharks
+ Sea Bass
+ Halibut
+ Tropical Fish
+
+
+ Birds
+ Eagles
+ Penguins
+ Parakeets
+ Owls
+ Hawks
+ Pidgeons
+
+ Elephants
+
+ Mythical Beasts
+ Dragons
+ Unicorns
+ Sea Serpents
+ Sphinx
+ Cyclops
+ Minotaurs
+ Goblins
+ Honest Politicians
+ Ghosts
+ Scylla and Charybdis
+
+
+
+ Games
+
+ Roblox
+ BrickBattle
+ Community Building
+ Roblox Minigames
+ Contest Place
+
+ Action
+ Puzzle
+ Strategy
+ Racing
+ RPG
+ Obstacle Course
+ Tycoon
+
+ Board games
+ Chess
+ Checkers
+ Settlers of Catan
+ Tigris and Euphrates
+ El Grande
+ Stratego
+ Carcassonne
+
+
+
+ Sports
+ Hockey
+ Soccer
+ Football
+ Baseball
+ Basketball
+ Volleyball
+ Tennis
+ Sports team practice
+
+ Watersports
+ Surfing
+ Swimming
+ Water Polo
+
+
+ Winter sports
+ Skiing
+ Snowboarding
+ Sledding
+ Skating
+
+
+ Adventure
+ Rock climbing
+ Hiking
+ Fishing
+ Horseback riding
+
+
+ Wacky
+ Foosball
+ Calvinball
+ Croquet
+ Cricket
+ Dodgeball
+ Squash
+ Trampoline
+
+
+
+ Movies/TV
+ Science Fiction
+
+ Animated
+ Anime
+
+ Comedy
+ Romantic
+ Action
+ Fantasy
+
+
+ Music
+ Country
+ Jazz
+ Rap
+ Hip-hop
+ Techno
+ Classical
+ Pop
+ Rock
+
+
+ Hobbies
+
+ Computers
+ Building computers
+ Videogames
+ Coding
+ Hacking
+
+
+ The Internet
+ lol. teh internets!
+ Watching vids
+
+ Dance
+ Gymnastics
+
+ Martial Arts
+ Karate
+ Judo
+ Taikwon Do
+ Wushu
+ Street fighting
+
+ Listening to music
+
+ Music lessons
+ Playing in my band
+ Playing piano
+ Playing guitar
+ Playing violin
+ Playing drums
+ Playing a weird instrument
+
+ Arts and crafts
+
+
+ Location
+
+ USA
+
+ West
+ Alaska
+ Arizona
+ California
+ Colorado
+ Hawaii
+ Idaho
+ Montana
+ Nevada
+ New Mexico
+ Oregon
+ Utah
+ Washington
+ Wyoming
+
+
+ Midwest
+ Illinois
+ Indiana
+ Iowa
+ Kansas
+ Michigan
+ Minnesota
+ Missouri
+ Nebraska
+ North Dakota
+ Ohio
+ South Dakota
+ Wisconsin
+
+
+ Northeast
+ Connecticut
+ Delaware
+ Maine
+ Maryland
+ Massachusetts
+ New Hampshire
+ New Jersey
+ New York
+ Pennsylvania
+ Rhode Island
+ Vermont
+
+
+ South
+ Alabama
+ Arkansas
+ Florida
+ Georgia
+ Kentucky
+ Louisiana
+ Mississippi
+ North Carolina
+ Oklahoma
+ South Carolina
+ Tennessee
+ Texas
+ Virginia
+ West Virginia
+
+
+
+ Canada
+ Alberta
+ British Columbia
+ Manitoba
+ New Brunswick
+ Newfoundland
+ Northwest Territories
+ Nova Scotia
+ Nunavut
+ Ontario
+ Prince Edward Island
+ Quebec
+ Saskatchewan
+ Yukon
+
+ Mexico
+ Central America
+
+ Europe
+
+ Great Britain
+ England
+ Scotland
+ Wales
+ Northern Ireland
+
+ France
+ Germany
+ Spain
+ Italy
+ Poland
+ Switzerland
+ Greece
+ Romania
+ Netherlands
+
+
+ Asia
+ China
+ India
+ Japan
+ Korea
+ Russia
+ Vietnam
+
+
+ South America
+ Argentina
+ Brazil
+
+
+ Africa
+ Eygpt
+ Swaziland
+
+ Australia
+ Middle East
+ Antarctica
+ New Zealand
+
+
+ Age
+ Rugrat
+ Kid
+ Tween
+ Teen
+ Twenties
+ Old
+ Ancient
+ Mesozoic
+ I don't want to say my age. Don't ask.
+
+
+ Mood
+ Good
+ Great!
+ Not bad
+ Sad
+ Hyper
+ Chill
+ Happy
+ Kind of mad
+
+ Boy
+ Girl
+ I don't want to say boy or girl. Don't ask.
+
+
+ Game
+ Let's build
+ Let's battle
+ Nice one!
+ So far so good!
+ Lucky shot!
+ Oh man!
+ I challenge you to a fight!
+ Help me with this
+ Let's go to your game
+ Can you show me how do to that?
+ Backflip!
+ Frontflip!
+ Dance!
+ I'm on your side!
+
+ Game Commands
+ regen
+ reset
+ go
+ fix
+ respawn
+
+
+
+ Silly
+ Muahahahaha!
+ all your base are belong to me!
+ GET OFF MAH LAWN
+ TEH EPIK DUCK IS COMING!!!
+ ROFL
+
+ 1337
+ i r teh pwnz0r!
+ w00t!
+ z0mg h4x!
+ ub3rR0xXorzage!
+
+
+
+ Yes
+ Absolutely!
+ Rock on!
+ Totally!
+ Juice!
+ Yay!
+ Yesh
+
+
+ No
+ Ummm. No.
+ ...
+ Stop!
+ Go away!
+ Don't do that
+ Stop breaking the rules
+ I don't want to
+
+
+ Ok
+ Well... ok
+ Sure
+
+
+ Uncertain
+ Maybe
+ I don't know
+ idk
+ I can't decide
+ Hmm...
+
+
+
+ :-)
+ :-(
+ :D
+ :-O
+ lol
+ =D
+ D=
+ XD
+ ;D
+ ;)
+ O_O
+ =)
+ @_@
+ >_<
+ T_T
+ ^_^
+ <(0_0<) <(0_0)> (>0_0)> KIRBY DANCE
+ )';
+ :3
+
+
+ Ratings
+ Rate it!
+ I give it a 1 out of 10
+ I give it a 2 out of 10
+ I give it a 3 out of 10
+ I give it a 4 out of 10
+ I give it a 5 out of 10
+ I give it a 6 out of 10
+ I give it a 7 out of 10
+ I give it a 8 out of 10
+ I give it a 9 out of 10
+ I give it a 10 out of 10!
+
+
diff --git a/Client2016/content/fonts/torso.mesh b/Client2016/content/fonts/torso.mesh
new file mode 100644
index 0000000..43d58d1
Binary files /dev/null and b/Client2016/content/fonts/torso.mesh differ
diff --git a/Client2016/content/music/bass.wav b/Client2016/content/music/bass.wav
new file mode 100644
index 0000000..5f4b791
Binary files /dev/null and b/Client2016/content/music/bass.wav differ
diff --git a/Client2016/content/music/ufofly.wav b/Client2016/content/music/ufofly.wav
new file mode 100644
index 0000000..359710b
Binary files /dev/null and b/Client2016/content/music/ufofly.wav differ
diff --git a/Client2016/content/particles/explosion.particle b/Client2016/content/particles/explosion.particle
new file mode 100644
index 0000000..a7c5e1f
--- /dev/null
+++ b/Client2016/content/particles/explosion.particle
@@ -0,0 +1,192 @@
+/////////////////////////////////////////////////////////
+// The fast rising center plume of the explosion.
+// Grows and rotates.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionPlume
+{
+ quota 40
+ material explosion/explosionMatl
+ particle_width 6
+ particle_height 6
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Ellipsoid
+ {
+ angle 16
+ colour 1.0 0.4 0.2 1.0
+ colour_range_start 1.0 0.4 0.2 1.0
+ colour_range_end 0.7 0.2 0.1 0.6
+ direction 0 1 0
+ emission_rate 100
+ position 0 6 0
+ velocity 25
+ velocity_min 25
+ velocity_max 38
+ time_to_live 1.5
+ time_to_live_min 1.5
+ time_to_live_max 1.5
+ duration 0.2
+ duration_min 0.2
+ duration_max 0.2
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ width 3
+ height 3
+ depth 3
+ }
+
+ affector ColourFader
+ {
+ red -0.9
+ green -0.5
+ blue -0.3
+ alpha -1.0
+ }
+ affector Scaler
+ {
+ rate 13
+ }
+ affector Rotator
+ {
+ rotation_speed_range_start 100
+ rotation_speed_range_end 200
+ rotation_range_start 100
+ rotation_range_end 300
+ }
+}
+
+
+/////////////////////////////////////////////////////////
+//The slow moving base of the explosion.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionBase
+{
+ quota 40
+ material explosion/explosionMatl
+ particle_width 20
+ particle_height 20
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Ellipsoid
+ {
+ angle 100
+ colour 1.0 0.4 0.2 1.0
+ colour_range_start 1.0 0.4 0.2 1.0
+ colour_range_end 0.7 0.2 0.1 0.6
+ direction 0 1 0
+ emission_rate 80
+ position 0 0 0
+ velocity 11
+ velocity_min 11
+ velocity_max 16
+ time_to_live 1.5
+ time_to_live_min 1.5
+ time_to_live_max 1.5
+ duration 0.2
+ duration_min 0.2
+ duration_max 0.2
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ width 15
+ height 15
+ depth 15
+ }
+
+ affector ColourFader
+ {
+ red -0.9
+ green -0.5
+ blue -0.3
+ alpha -1.0
+ }
+ affector Scaler
+ {
+ rate 5
+ }
+}
+
+
+/////////////////////////////////////////////////////////
+// The fast flying sparks of the explosion.
+/////////////////////////////////////////////////////////
+particle_system explosion/explosionSparks
+{
+ quota 120
+ material explosion/explosparkMatl
+ particle_width 3
+ particle_height 3
+ cull_each false
+ renderer billboard
+ billboard_type point
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Point
+ {
+ angle 120
+ colour 1.0 0.6 0.4 1.0
+ colour_range_start 1.0 0.6 0.4 1.0
+ colour_range_end 1.0 0.6 0.4 1.0
+ direction 0 1 0
+ emission_rate 900
+ position 0 0 0
+ velocity 30
+ velocity_min 30
+ velocity_max 60
+ time_to_live 1.2
+ time_to_live_min 1.2
+ time_to_live_max 1.2
+ duration 0.2
+ duration_min 0.1
+ duration_max 0.1
+ repeat_delay 10000
+ repeat_delay_min 10000
+ repeat_delay_max 10000
+ }
+
+ affector ColourFader
+ {
+ red -0.7
+ green -0.6
+ blue -0.4
+ alpha -0.7
+ }
+ affector Scaler
+ {
+ rate -3
+ }
+}
diff --git a/Client2016/content/particles/fire.particle b/Client2016/content/particles/fire.particle
new file mode 100644
index 0000000..442fe8e
--- /dev/null
+++ b/Client2016/content/particles/fire.particle
@@ -0,0 +1,59 @@
+/////////////////////////////////////////////////////////
+// Fire
+/////////////////////////////////////////////////////////
+
+// height and width modified by RbxParticleFactory for user input size
+particle_system FireTemplate
+{
+ material fireMat1
+ particle_width 5
+ particle_height 5
+ cull_each false
+ quota 40
+ renderer billboard
+ billboard_type point
+ point_rendering false
+ accurate_facing false
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+
+ // emission rate is modified by RbxParticleManager for throttling
+ // of particle systems
+ emitter Point
+ {
+ colour_range_start 240 240 240
+ colour_range_end 240 240 240
+ angle 18
+ emission_rate 35
+ time_to_live_min 1
+ time_to_live_max 1
+ direction 0 1 0
+ velocity_min 2.33
+ velocity_max 7.0
+ }
+ affector Rotator
+ {
+ rotation_range_start 0
+ rotation_range_end 365
+ rotation_speed_range_start 0
+ rotation_speed_range_end 100
+ }
+ // modified in RbxParticleFactory for user input size
+ affector Scaler
+ {
+ rate -5.0
+ }
+ // modified in RbxParticleFactory for user input colors
+ affector ColourInterpolator
+ {
+ time0 0
+ colour0 240 240 240 1
+
+ time1 1
+ colour1 240 240 240 1
+
+ }
+
+}
diff --git a/Client2016/content/particles/forceFieldBeam.particle b/Client2016/content/particles/forceFieldBeam.particle
new file mode 100644
index 0000000..22914a9
--- /dev/null
+++ b/Client2016/content/particles/forceFieldBeam.particle
@@ -0,0 +1,55 @@
+/////////////////////////////////////////////////////////
+// Beam
+/////////////////////////////////////////////////////////
+particle_system forceField/beam
+{
+ quota 40
+ material PE/lensflare
+ particle_width 0.5
+ particle_height 2
+ cull_each false
+ billboard_type oriented_common
+ common_direction 0 1 0
+
+ emitter Ring
+ {
+ colour 1 1 1 0
+ angle 0
+ direction 0 1 0
+ emission_rate 20
+ position 0 -2 0
+ velocity_min 2
+ velocity_max 5
+ time_to_live 2
+ duration 0
+ duration_min 0
+ duration_max 0
+ repeat_delay 0
+ repeat_delay_min 0
+ repeat_delay_max 0
+ width 5
+ height 5
+ depth 1
+ inner_width 0.8
+ inner_height 0.8
+ }
+
+ //affector LinearForce
+// {
+ // force_vector 0 -1 0
+ // force_application add
+ //}
+
+ affector ColourFader2
+ {
+ red1 0
+ green1 0
+ blue1 0
+ alpha1 1
+ red2 0
+ green2 0
+ blue2 0
+ alpha2 -1
+ state_change 1
+ }
+}
diff --git a/Client2016/content/particles/forceFieldRadial.particle b/Client2016/content/particles/forceFieldRadial.particle
new file mode 100644
index 0000000..807f93d
--- /dev/null
+++ b/Client2016/content/particles/forceFieldRadial.particle
@@ -0,0 +1,51 @@
+/////////////////////////////////////////////////////////
+// Radial
+/////////////////////////////////////////////////////////
+particle_system forceField/radial
+{
+ material PE/lensflare
+ particle_width 5
+ particle_height 5
+ cull_each false
+ quota 6
+ renderer billboard
+ billboard_type point
+ point_rendering false
+ accurate_facing false
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+
+ // emission rate is modified by RbxParticleManager for throttling
+ // of particle systems
+ emitter Point
+ {
+ angle 18
+ emission_rate 2
+ time_to_live_min 2
+ time_to_live_max 2
+ direction 0 1 0
+ velocity_min 0
+ velocity_max 0.1
+ }
+ affector Rotator
+ {
+ rotation_range_start 0
+ rotation_range_end 365
+ rotation_speed_range_start 4
+ rotation_speed_range_end 100
+ }
+ // modified in RbxParticleFactory for user input size
+ affector Scaler
+ {
+ rate 6.0
+ }
+ affector ColourFader
+ {
+ red 0
+ green 0
+ blue 0
+ alpha -0.5
+ }
+}
diff --git a/Client2016/content/particles/smoke.particle b/Client2016/content/particles/smoke.particle
new file mode 100644
index 0000000..79c6c16
--- /dev/null
+++ b/Client2016/content/particles/smoke.particle
@@ -0,0 +1,57 @@
+particle_system SmokeTemplate
+{
+ quota 70
+ material PE/smoke
+ particle_width 1
+ particle_height 1
+ cull_each false
+ renderer billboard
+ billboard_type point
+
+ emitter Box
+ {
+ angle 180
+ colour 0.8 0.8 0.8 0.3
+ colour_range_start 0.8 0.8 0.8 0.3
+ colour_range_end 0.8 0.8 0.8 0.3
+ direction 0 1 0
+ emission_rate 6
+ position 0 0 0
+ velocity 0.1
+ velocity_min 0
+ velocity_max 0.1
+ time_to_live 4
+ time_to_live_min 4
+ time_to_live_max 6
+ duration 0
+ duration_min 0
+ duration_max 0
+ repeat_delay 0
+ repeat_delay_min 0
+ repeat_delay_max 0
+ width 1
+ height 1
+ depth 1
+ }
+
+ affector ColourFader
+ {
+ red -0.11
+ green -0.11
+ blue -0.11
+ alpha -0.1
+ }
+
+ affector Scaler
+ {
+ rate 1.5
+ }
+
+ affector Rotator
+ {
+ rotation_speed_range_start 0
+ rotation_speed_range_end 0
+ rotation_range_start 0
+ rotation_range_end 0
+ }
+}
diff --git a/Client2016/content/particles/sparkles.particle b/Client2016/content/particles/sparkles.particle
new file mode 100644
index 0000000..60102d0
--- /dev/null
+++ b/Client2016/content/particles/sparkles.particle
@@ -0,0 +1,49 @@
+/////////////////////////////////////////////////////////
+// Sparkles
+/////////////////////////////////////////////////////////
+particle_system SparklesTemplate
+{
+ quota 40
+ material sparkle/sparkleMatl
+ particle_width 0.8
+ particle_height 1
+ cull_each false
+ renderer billboard
+ sorted false
+ local_space false
+ iteration_interval 0
+ nonvisible_update_timeout 0
+ billboard_type point
+ billboard_origin center
+ billboard_rotation_type vertex
+ common_up_vector 0 1 0
+ point_rendering false
+ accurate_facing false
+
+ emitter Point
+ {
+ angle 180
+ direction 0 -1 0
+ emission_rate 35
+ position 0 0 0
+ velocity_min 4
+ velocity_max 8
+ duration 0.0
+ time_to_live 1.1
+ //repeat_delay 2.0
+ }
+ affector Rotator
+ {
+ rotation_speed_range_end 360
+ rotation_range_start 0
+ rotation_range_end 360
+ }
+ affector ColourFader
+ {
+ red 0
+ green 0
+ blue 0
+ alpha -1
+ }
+}
+
diff --git a/Client2016/content/sky/lensflare.jpg b/Client2016/content/sky/lensflare.jpg
new file mode 100644
index 0000000..c53f2ec
Binary files /dev/null and b/Client2016/content/sky/lensflare.jpg differ
diff --git a/Client2016/content/sky/moon-alpha.jpg b/Client2016/content/sky/moon-alpha.jpg
new file mode 100644
index 0000000..5e193d5
Binary files /dev/null and b/Client2016/content/sky/moon-alpha.jpg differ
diff --git a/Client2016/content/sky/moon.jpg b/Client2016/content/sky/moon.jpg
new file mode 100644
index 0000000..247b6cd
Binary files /dev/null and b/Client2016/content/sky/moon.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_bk.jpg b/Client2016/content/sky/null_plainsky512_bk.jpg
new file mode 100644
index 0000000..a01c9ef
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_bk.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_dn.jpg b/Client2016/content/sky/null_plainsky512_dn.jpg
new file mode 100644
index 0000000..75f16c1
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_dn.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_ft.jpg b/Client2016/content/sky/null_plainsky512_ft.jpg
new file mode 100644
index 0000000..253cb31
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_ft.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_lf.jpg b/Client2016/content/sky/null_plainsky512_lf.jpg
new file mode 100644
index 0000000..aa3626b
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_lf.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_rt.jpg b/Client2016/content/sky/null_plainsky512_rt.jpg
new file mode 100644
index 0000000..45b5071
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_rt.jpg differ
diff --git a/Client2016/content/sky/null_plainsky512_up.jpg b/Client2016/content/sky/null_plainsky512_up.jpg
new file mode 100644
index 0000000..49940da
Binary files /dev/null and b/Client2016/content/sky/null_plainsky512_up.jpg differ
diff --git a/Client2016/content/sky/skyspheremap.jpg b/Client2016/content/sky/skyspheremap.jpg
new file mode 100644
index 0000000..947a7ee
Binary files /dev/null and b/Client2016/content/sky/skyspheremap.jpg differ
diff --git a/Client2016/content/sky/sun-rays.jpg b/Client2016/content/sky/sun-rays.jpg
new file mode 100644
index 0000000..a76a4d5
Binary files /dev/null and b/Client2016/content/sky/sun-rays.jpg differ
diff --git a/Client2016/content/sky/sun.jpg b/Client2016/content/sky/sun.jpg
new file mode 100644
index 0000000..12b3829
Binary files /dev/null and b/Client2016/content/sky/sun.jpg differ
diff --git a/Client2016/content/sounds/Kerplunk.mp3 b/Client2016/content/sounds/Kerplunk.mp3
new file mode 100644
index 0000000..1211b02
Binary files /dev/null and b/Client2016/content/sounds/Kerplunk.mp3 differ
diff --git a/Client2016/content/sounds/Kid saying Ouch.mp3 b/Client2016/content/sounds/Kid saying Ouch.mp3
new file mode 100644
index 0000000..b3f87e0
Binary files /dev/null and b/Client2016/content/sounds/Kid saying Ouch.mp3 differ
diff --git a/Client2016/content/sounds/Rubber band sling shot.mp3 b/Client2016/content/sounds/Rubber band sling shot.mp3
new file mode 100644
index 0000000..430f96c
Binary files /dev/null and b/Client2016/content/sounds/Rubber band sling shot.mp3 differ
diff --git a/Client2016/content/sounds/Rubber band.mp3 b/Client2016/content/sounds/Rubber band.mp3
new file mode 100644
index 0000000..f815a17
Binary files /dev/null and b/Client2016/content/sounds/Rubber band.mp3 differ
diff --git a/Client2016/content/sounds/SWITCH3.mp3 b/Client2016/content/sounds/SWITCH3.mp3
new file mode 100644
index 0000000..0132c84
Binary files /dev/null and b/Client2016/content/sounds/SWITCH3.mp3 differ
diff --git a/Client2016/content/sounds/action_falling.mp3 b/Client2016/content/sounds/action_falling.mp3
new file mode 100644
index 0000000..6408717
Binary files /dev/null and b/Client2016/content/sounds/action_falling.mp3 differ
diff --git a/Client2016/content/sounds/action_footsteps_plastic.mp3 b/Client2016/content/sounds/action_footsteps_plastic.mp3
new file mode 100644
index 0000000..6804420
Binary files /dev/null and b/Client2016/content/sounds/action_footsteps_plastic.mp3 differ
diff --git a/Client2016/content/sounds/action_get_up.mp3 b/Client2016/content/sounds/action_get_up.mp3
new file mode 100644
index 0000000..ababd77
Binary files /dev/null and b/Client2016/content/sounds/action_get_up.mp3 differ
diff --git a/Client2016/content/sounds/action_jump.mp3 b/Client2016/content/sounds/action_jump.mp3
new file mode 100644
index 0000000..7159074
Binary files /dev/null and b/Client2016/content/sounds/action_jump.mp3 differ
diff --git a/Client2016/content/sounds/action_jump_land.mp3 b/Client2016/content/sounds/action_jump_land.mp3
new file mode 100644
index 0000000..3d68ce1
Binary files /dev/null and b/Client2016/content/sounds/action_jump_land.mp3 differ
diff --git a/Client2016/content/sounds/action_swim.mp3 b/Client2016/content/sounds/action_swim.mp3
new file mode 100644
index 0000000..95dd2d5
Binary files /dev/null and b/Client2016/content/sounds/action_swim.mp3 differ
diff --git a/Client2016/content/sounds/bass.mp3 b/Client2016/content/sounds/bass.mp3
new file mode 100644
index 0000000..ffd6286
Binary files /dev/null and b/Client2016/content/sounds/bass.mp3 differ
diff --git a/Client2016/content/sounds/bfsl-minifigfoots1.mp3 b/Client2016/content/sounds/bfsl-minifigfoots1.mp3
new file mode 100644
index 0000000..ca2e697
Binary files /dev/null and b/Client2016/content/sounds/bfsl-minifigfoots1.mp3 differ
diff --git a/Client2016/content/sounds/bfsl-minifigfoots2.mp3 b/Client2016/content/sounds/bfsl-minifigfoots2.mp3
new file mode 100644
index 0000000..113ad8f
Binary files /dev/null and b/Client2016/content/sounds/bfsl-minifigfoots2.mp3 differ
diff --git a/Client2016/content/sounds/button.mp3 b/Client2016/content/sounds/button.mp3
new file mode 100644
index 0000000..1136b2b
Binary files /dev/null and b/Client2016/content/sounds/button.mp3 differ
diff --git a/Client2016/content/sounds/clickfast.mp3 b/Client2016/content/sounds/clickfast.mp3
new file mode 100644
index 0000000..12bfbff
Binary files /dev/null and b/Client2016/content/sounds/clickfast.mp3 differ
diff --git a/Client2016/content/sounds/collide.mp3 b/Client2016/content/sounds/collide.mp3
new file mode 100644
index 0000000..8f69cf0
Binary files /dev/null and b/Client2016/content/sounds/collide.mp3 differ
diff --git a/Client2016/content/sounds/electronicpingshort.mp3 b/Client2016/content/sounds/electronicpingshort.mp3
new file mode 100644
index 0000000..bfb3eb0
Binary files /dev/null and b/Client2016/content/sounds/electronicpingshort.mp3 differ
diff --git a/Client2016/content/sounds/flashbulb.mp3 b/Client2016/content/sounds/flashbulb.mp3
new file mode 100644
index 0000000..fdcf7f6
Binary files /dev/null and b/Client2016/content/sounds/flashbulb.mp3 differ
diff --git a/Client2016/content/sounds/grass.mp3 b/Client2016/content/sounds/grass.mp3
new file mode 100644
index 0000000..e79fb5b
Binary files /dev/null and b/Client2016/content/sounds/grass.mp3 differ
diff --git a/Client2016/content/sounds/grass2.mp3 b/Client2016/content/sounds/grass2.mp3
new file mode 100644
index 0000000..1a1ad7a
Binary files /dev/null and b/Client2016/content/sounds/grass2.mp3 differ
diff --git a/Client2016/content/sounds/grass3.mp3 b/Client2016/content/sounds/grass3.mp3
new file mode 100644
index 0000000..131602a
Binary files /dev/null and b/Client2016/content/sounds/grass3.mp3 differ
diff --git a/Client2016/content/sounds/grassstone.mp3 b/Client2016/content/sounds/grassstone.mp3
new file mode 100644
index 0000000..4e9397c
Binary files /dev/null and b/Client2016/content/sounds/grassstone.mp3 differ
diff --git a/Client2016/content/sounds/grassstone2.mp3 b/Client2016/content/sounds/grassstone2.mp3
new file mode 100644
index 0000000..0a5f1c1
Binary files /dev/null and b/Client2016/content/sounds/grassstone2.mp3 differ
diff --git a/Client2016/content/sounds/grassstone3.mp3 b/Client2016/content/sounds/grassstone3.mp3
new file mode 100644
index 0000000..51df635
Binary files /dev/null and b/Client2016/content/sounds/grassstone3.mp3 differ
diff --git a/Client2016/content/sounds/hit.mp3 b/Client2016/content/sounds/hit.mp3
new file mode 100644
index 0000000..a299c1a
Binary files /dev/null and b/Client2016/content/sounds/hit.mp3 differ
diff --git a/Client2016/content/sounds/ice.mp3 b/Client2016/content/sounds/ice.mp3
new file mode 100644
index 0000000..db528cc
Binary files /dev/null and b/Client2016/content/sounds/ice.mp3 differ
diff --git a/Client2016/content/sounds/ice2.mp3 b/Client2016/content/sounds/ice2.mp3
new file mode 100644
index 0000000..dc4cb7b
Binary files /dev/null and b/Client2016/content/sounds/ice2.mp3 differ
diff --git a/Client2016/content/sounds/ice3.mp3 b/Client2016/content/sounds/ice3.mp3
new file mode 100644
index 0000000..7f3e5b1
Binary files /dev/null and b/Client2016/content/sounds/ice3.mp3 differ
diff --git a/Client2016/content/sounds/icegrass.mp3 b/Client2016/content/sounds/icegrass.mp3
new file mode 100644
index 0000000..2561aff
Binary files /dev/null and b/Client2016/content/sounds/icegrass.mp3 differ
diff --git a/Client2016/content/sounds/icegrass2.mp3 b/Client2016/content/sounds/icegrass2.mp3
new file mode 100644
index 0000000..db6f6d2
Binary files /dev/null and b/Client2016/content/sounds/icegrass2.mp3 differ
diff --git a/Client2016/content/sounds/icegrass3.mp3 b/Client2016/content/sounds/icegrass3.mp3
new file mode 100644
index 0000000..b72c2db
Binary files /dev/null and b/Client2016/content/sounds/icegrass3.mp3 differ
diff --git a/Client2016/content/sounds/icemetal.mp3 b/Client2016/content/sounds/icemetal.mp3
new file mode 100644
index 0000000..5c9d2d4
Binary files /dev/null and b/Client2016/content/sounds/icemetal.mp3 differ
diff --git a/Client2016/content/sounds/icemetal2.mp3 b/Client2016/content/sounds/icemetal2.mp3
new file mode 100644
index 0000000..60f9e4d
Binary files /dev/null and b/Client2016/content/sounds/icemetal2.mp3 differ
diff --git a/Client2016/content/sounds/icemetal3.mp3 b/Client2016/content/sounds/icemetal3.mp3
new file mode 100644
index 0000000..2ee4312
Binary files /dev/null and b/Client2016/content/sounds/icemetal3.mp3 differ
diff --git a/Client2016/content/sounds/icestone.mp3 b/Client2016/content/sounds/icestone.mp3
new file mode 100644
index 0000000..37b99bb
Binary files /dev/null and b/Client2016/content/sounds/icestone.mp3 differ
diff --git a/Client2016/content/sounds/icestone2.mp3 b/Client2016/content/sounds/icestone2.mp3
new file mode 100644
index 0000000..1f5e264
Binary files /dev/null and b/Client2016/content/sounds/icestone2.mp3 differ
diff --git a/Client2016/content/sounds/icestone3.mp3 b/Client2016/content/sounds/icestone3.mp3
new file mode 100644
index 0000000..e51ce3d
Binary files /dev/null and b/Client2016/content/sounds/icestone3.mp3 differ
diff --git a/Client2016/content/sounds/impact_bodyfall.mp3 b/Client2016/content/sounds/impact_bodyfall.mp3
new file mode 100644
index 0000000..d7bf3ae
Binary files /dev/null and b/Client2016/content/sounds/impact_bodyfall.mp3 differ
diff --git a/Client2016/content/sounds/impact_explosion_01.mp3 b/Client2016/content/sounds/impact_explosion_01.mp3
new file mode 100644
index 0000000..3e03015
Binary files /dev/null and b/Client2016/content/sounds/impact_explosion_01.mp3 differ
diff --git a/Client2016/content/sounds/impact_explosion_02.mp3 b/Client2016/content/sounds/impact_explosion_02.mp3
new file mode 100644
index 0000000..df33b3b
Binary files /dev/null and b/Client2016/content/sounds/impact_explosion_02.mp3 differ
diff --git a/Client2016/content/sounds/impact_explosion_03.mp3 b/Client2016/content/sounds/impact_explosion_03.mp3
new file mode 100644
index 0000000..4501c83
Binary files /dev/null and b/Client2016/content/sounds/impact_explosion_03.mp3 differ
diff --git a/Client2016/content/sounds/impact_water.mp3 b/Client2016/content/sounds/impact_water.mp3
new file mode 100644
index 0000000..741862b
Binary files /dev/null and b/Client2016/content/sounds/impact_water.mp3 differ
diff --git a/Client2016/content/sounds/metal.mp3 b/Client2016/content/sounds/metal.mp3
new file mode 100644
index 0000000..32473b1
Binary files /dev/null and b/Client2016/content/sounds/metal.mp3 differ
diff --git a/Client2016/content/sounds/metal2.mp3 b/Client2016/content/sounds/metal2.mp3
new file mode 100644
index 0000000..023273f
Binary files /dev/null and b/Client2016/content/sounds/metal2.mp3 differ
diff --git a/Client2016/content/sounds/metal3.mp3 b/Client2016/content/sounds/metal3.mp3
new file mode 100644
index 0000000..e407be0
Binary files /dev/null and b/Client2016/content/sounds/metal3.mp3 differ
diff --git a/Client2016/content/sounds/metalgrass.mp3 b/Client2016/content/sounds/metalgrass.mp3
new file mode 100644
index 0000000..46fdef4
Binary files /dev/null and b/Client2016/content/sounds/metalgrass.mp3 differ
diff --git a/Client2016/content/sounds/metalgrass2.mp3 b/Client2016/content/sounds/metalgrass2.mp3
new file mode 100644
index 0000000..3a7dad2
Binary files /dev/null and b/Client2016/content/sounds/metalgrass2.mp3 differ
diff --git a/Client2016/content/sounds/metalgrass3.mp3 b/Client2016/content/sounds/metalgrass3.mp3
new file mode 100644
index 0000000..e8172ad
Binary files /dev/null and b/Client2016/content/sounds/metalgrass3.mp3 differ
diff --git a/Client2016/content/sounds/metalstone.mp3 b/Client2016/content/sounds/metalstone.mp3
new file mode 100644
index 0000000..6910e46
Binary files /dev/null and b/Client2016/content/sounds/metalstone.mp3 differ
diff --git a/Client2016/content/sounds/metalstone2.mp3 b/Client2016/content/sounds/metalstone2.mp3
new file mode 100644
index 0000000..0dd924e
Binary files /dev/null and b/Client2016/content/sounds/metalstone2.mp3 differ
diff --git a/Client2016/content/sounds/metalstone3.mp3 b/Client2016/content/sounds/metalstone3.mp3
new file mode 100644
index 0000000..37e1198
Binary files /dev/null and b/Client2016/content/sounds/metalstone3.mp3 differ
diff --git a/Client2016/content/sounds/plasticgrass.mp3 b/Client2016/content/sounds/plasticgrass.mp3
new file mode 100644
index 0000000..579d4ab
Binary files /dev/null and b/Client2016/content/sounds/plasticgrass.mp3 differ
diff --git a/Client2016/content/sounds/plasticgrass2.mp3 b/Client2016/content/sounds/plasticgrass2.mp3
new file mode 100644
index 0000000..f77843a
Binary files /dev/null and b/Client2016/content/sounds/plasticgrass2.mp3 differ
diff --git a/Client2016/content/sounds/plasticgrass3.mp3 b/Client2016/content/sounds/plasticgrass3.mp3
new file mode 100644
index 0000000..9274ff0
Binary files /dev/null and b/Client2016/content/sounds/plasticgrass3.mp3 differ
diff --git a/Client2016/content/sounds/plasticice.mp3 b/Client2016/content/sounds/plasticice.mp3
new file mode 100644
index 0000000..668ba91
Binary files /dev/null and b/Client2016/content/sounds/plasticice.mp3 differ
diff --git a/Client2016/content/sounds/plasticice2.mp3 b/Client2016/content/sounds/plasticice2.mp3
new file mode 100644
index 0000000..041e4ca
Binary files /dev/null and b/Client2016/content/sounds/plasticice2.mp3 differ
diff --git a/Client2016/content/sounds/plasticice3.mp3 b/Client2016/content/sounds/plasticice3.mp3
new file mode 100644
index 0000000..180b476
Binary files /dev/null and b/Client2016/content/sounds/plasticice3.mp3 differ
diff --git a/Client2016/content/sounds/plasticmetal.mp3 b/Client2016/content/sounds/plasticmetal.mp3
new file mode 100644
index 0000000..1eadf0c
Binary files /dev/null and b/Client2016/content/sounds/plasticmetal.mp3 differ
diff --git a/Client2016/content/sounds/plasticmetal2.mp3 b/Client2016/content/sounds/plasticmetal2.mp3
new file mode 100644
index 0000000..6d4119a
Binary files /dev/null and b/Client2016/content/sounds/plasticmetal2.mp3 differ
diff --git a/Client2016/content/sounds/plasticmetal3.mp3 b/Client2016/content/sounds/plasticmetal3.mp3
new file mode 100644
index 0000000..c777ee4
Binary files /dev/null and b/Client2016/content/sounds/plasticmetal3.mp3 differ
diff --git a/Client2016/content/sounds/plasticplastic.mp3 b/Client2016/content/sounds/plasticplastic.mp3
new file mode 100644
index 0000000..7283013
Binary files /dev/null and b/Client2016/content/sounds/plasticplastic.mp3 differ
diff --git a/Client2016/content/sounds/plasticplastic2.mp3 b/Client2016/content/sounds/plasticplastic2.mp3
new file mode 100644
index 0000000..f9710c7
Binary files /dev/null and b/Client2016/content/sounds/plasticplastic2.mp3 differ
diff --git a/Client2016/content/sounds/plasticplastic3.mp3 b/Client2016/content/sounds/plasticplastic3.mp3
new file mode 100644
index 0000000..c7cd1ca
Binary files /dev/null and b/Client2016/content/sounds/plasticplastic3.mp3 differ
diff --git a/Client2016/content/sounds/plasticstone.mp3 b/Client2016/content/sounds/plasticstone.mp3
new file mode 100644
index 0000000..d33e553
Binary files /dev/null and b/Client2016/content/sounds/plasticstone.mp3 differ
diff --git a/Client2016/content/sounds/plasticstone2.mp3 b/Client2016/content/sounds/plasticstone2.mp3
new file mode 100644
index 0000000..cd33d00
Binary files /dev/null and b/Client2016/content/sounds/plasticstone2.mp3 differ
diff --git a/Client2016/content/sounds/plasticstone3.mp3 b/Client2016/content/sounds/plasticstone3.mp3
new file mode 100644
index 0000000..5732f38
Binary files /dev/null and b/Client2016/content/sounds/plasticstone3.mp3 differ
diff --git a/Client2016/content/sounds/snap.mp3 b/Client2016/content/sounds/snap.mp3
new file mode 100644
index 0000000..8dd8d5a
Binary files /dev/null and b/Client2016/content/sounds/snap.mp3 differ
diff --git a/Client2016/content/sounds/splat.mp3 b/Client2016/content/sounds/splat.mp3
new file mode 100644
index 0000000..934a634
Binary files /dev/null and b/Client2016/content/sounds/splat.mp3 differ
diff --git a/Client2016/content/sounds/stone.mp3 b/Client2016/content/sounds/stone.mp3
new file mode 100644
index 0000000..e9dd548
Binary files /dev/null and b/Client2016/content/sounds/stone.mp3 differ
diff --git a/Client2016/content/sounds/stone2.mp3 b/Client2016/content/sounds/stone2.mp3
new file mode 100644
index 0000000..f582a22
Binary files /dev/null and b/Client2016/content/sounds/stone2.mp3 differ
diff --git a/Client2016/content/sounds/stone3.mp3 b/Client2016/content/sounds/stone3.mp3
new file mode 100644
index 0000000..b8bfa31
Binary files /dev/null and b/Client2016/content/sounds/stone3.mp3 differ
diff --git a/Client2016/content/sounds/switch.mp3 b/Client2016/content/sounds/switch.mp3
new file mode 100644
index 0000000..69e9442
Binary files /dev/null and b/Client2016/content/sounds/switch.mp3 differ
diff --git a/Client2016/content/sounds/swoosh.mp3 b/Client2016/content/sounds/swoosh.mp3
new file mode 100644
index 0000000..99014d0
Binary files /dev/null and b/Client2016/content/sounds/swoosh.mp3 differ
diff --git a/Client2016/content/sounds/swordlunge.mp3 b/Client2016/content/sounds/swordlunge.mp3
new file mode 100644
index 0000000..c5b017a
Binary files /dev/null and b/Client2016/content/sounds/swordlunge.mp3 differ
diff --git a/Client2016/content/sounds/swordslash.mp3 b/Client2016/content/sounds/swordslash.mp3
new file mode 100644
index 0000000..cf5b902
Binary files /dev/null and b/Client2016/content/sounds/swordslash.mp3 differ
diff --git a/Client2016/content/sounds/unsheath.mp3 b/Client2016/content/sounds/unsheath.mp3
new file mode 100644
index 0000000..6913873
Binary files /dev/null and b/Client2016/content/sounds/unsheath.mp3 differ
diff --git a/Client2016/content/sounds/uuhhh.mp3 b/Client2016/content/sounds/uuhhh.mp3
new file mode 100644
index 0000000..81b3565
Binary files /dev/null and b/Client2016/content/sounds/uuhhh.mp3 differ
diff --git a/Client2016/content/sounds/victory.mp3 b/Client2016/content/sounds/victory.mp3
new file mode 100644
index 0000000..793b1ba
Binary files /dev/null and b/Client2016/content/sounds/victory.mp3 differ
diff --git a/Client2016/content/sounds/woodgrass.mp3 b/Client2016/content/sounds/woodgrass.mp3
new file mode 100644
index 0000000..f70237c
Binary files /dev/null and b/Client2016/content/sounds/woodgrass.mp3 differ
diff --git a/Client2016/content/sounds/woodgrass2.mp3 b/Client2016/content/sounds/woodgrass2.mp3
new file mode 100644
index 0000000..0d12b62
Binary files /dev/null and b/Client2016/content/sounds/woodgrass2.mp3 differ
diff --git a/Client2016/content/sounds/woodgrass3.mp3 b/Client2016/content/sounds/woodgrass3.mp3
new file mode 100644
index 0000000..f234835
Binary files /dev/null and b/Client2016/content/sounds/woodgrass3.mp3 differ
diff --git a/Client2016/content/sounds/woodice.mp3 b/Client2016/content/sounds/woodice.mp3
new file mode 100644
index 0000000..5604dcf
Binary files /dev/null and b/Client2016/content/sounds/woodice.mp3 differ
diff --git a/Client2016/content/sounds/woodice2.mp3 b/Client2016/content/sounds/woodice2.mp3
new file mode 100644
index 0000000..dc3a586
Binary files /dev/null and b/Client2016/content/sounds/woodice2.mp3 differ
diff --git a/Client2016/content/sounds/woodice3.mp3 b/Client2016/content/sounds/woodice3.mp3
new file mode 100644
index 0000000..300dea9
Binary files /dev/null and b/Client2016/content/sounds/woodice3.mp3 differ
diff --git a/Client2016/content/sounds/woodmetal.mp3 b/Client2016/content/sounds/woodmetal.mp3
new file mode 100644
index 0000000..666db63
Binary files /dev/null and b/Client2016/content/sounds/woodmetal.mp3 differ
diff --git a/Client2016/content/sounds/woodmetal2.mp3 b/Client2016/content/sounds/woodmetal2.mp3
new file mode 100644
index 0000000..60e87dc
Binary files /dev/null and b/Client2016/content/sounds/woodmetal2.mp3 differ
diff --git a/Client2016/content/sounds/woodmetal3.mp3 b/Client2016/content/sounds/woodmetal3.mp3
new file mode 100644
index 0000000..29ec64a
Binary files /dev/null and b/Client2016/content/sounds/woodmetal3.mp3 differ
diff --git a/Client2016/content/sounds/woodplastic.mp3 b/Client2016/content/sounds/woodplastic.mp3
new file mode 100644
index 0000000..d909b8a
Binary files /dev/null and b/Client2016/content/sounds/woodplastic.mp3 differ
diff --git a/Client2016/content/sounds/woodplastic2.mp3 b/Client2016/content/sounds/woodplastic2.mp3
new file mode 100644
index 0000000..c4e9b19
Binary files /dev/null and b/Client2016/content/sounds/woodplastic2.mp3 differ
diff --git a/Client2016/content/sounds/woodplastic3.mp3 b/Client2016/content/sounds/woodplastic3.mp3
new file mode 100644
index 0000000..4398179
Binary files /dev/null and b/Client2016/content/sounds/woodplastic3.mp3 differ
diff --git a/Client2016/content/sounds/woodstone.mp3 b/Client2016/content/sounds/woodstone.mp3
new file mode 100644
index 0000000..3f7c071
Binary files /dev/null and b/Client2016/content/sounds/woodstone.mp3 differ
diff --git a/Client2016/content/sounds/woodstone2.mp3 b/Client2016/content/sounds/woodstone2.mp3
new file mode 100644
index 0000000..1b4505a
Binary files /dev/null and b/Client2016/content/sounds/woodstone2.mp3 differ
diff --git a/Client2016/content/sounds/woodstone3.mp3 b/Client2016/content/sounds/woodstone3.mp3
new file mode 100644
index 0000000..6e04dec
Binary files /dev/null and b/Client2016/content/sounds/woodstone3.mp3 differ
diff --git a/Client2016/content/sounds/woodwood.mp3 b/Client2016/content/sounds/woodwood.mp3
new file mode 100644
index 0000000..8279e0c
Binary files /dev/null and b/Client2016/content/sounds/woodwood.mp3 differ
diff --git a/Client2016/content/sounds/woodwood2.mp3 b/Client2016/content/sounds/woodwood2.mp3
new file mode 100644
index 0000000..ad29d7f
Binary files /dev/null and b/Client2016/content/sounds/woodwood2.mp3 differ
diff --git a/Client2016/content/sounds/woodwood3.mp3 b/Client2016/content/sounds/woodwood3.mp3
new file mode 100644
index 0000000..e8bf04f
Binary files /dev/null and b/Client2016/content/sounds/woodwood3.mp3 differ
diff --git a/Client2016/content/textures/AnchorCursor.png b/Client2016/content/textures/AnchorCursor.png
new file mode 100644
index 0000000..5c4cac7
Binary files /dev/null and b/Client2016/content/textures/AnchorCursor.png differ
diff --git a/Client2016/content/textures/ArrowCursor.png b/Client2016/content/textures/ArrowCursor.png
new file mode 100644
index 0000000..0f839d0
Binary files /dev/null and b/Client2016/content/textures/ArrowCursor.png differ
diff --git a/Client2016/content/textures/ArrowCursorDecalDrag.png b/Client2016/content/textures/ArrowCursorDecalDrag.png
new file mode 100644
index 0000000..0f839d0
Binary files /dev/null and b/Client2016/content/textures/ArrowCursorDecalDrag.png differ
diff --git a/Client2016/content/textures/ArrowFarCursor.png b/Client2016/content/textures/ArrowFarCursor.png
new file mode 100644
index 0000000..c3ce391
Binary files /dev/null and b/Client2016/content/textures/ArrowFarCursor.png differ
diff --git a/Client2016/content/textures/BWGradient.png b/Client2016/content/textures/BWGradient.png
new file mode 100644
index 0000000..0a5edb5
Binary files /dev/null and b/Client2016/content/textures/BWGradient.png differ
diff --git a/Client2016/content/textures/BackgroundImage.png b/Client2016/content/textures/BackgroundImage.png
new file mode 100644
index 0000000..9f76324
Binary files /dev/null and b/Client2016/content/textures/BackgroundImage.png differ
diff --git a/Client2016/content/textures/Blank.png b/Client2016/content/textures/Blank.png
new file mode 100644
index 0000000..d8860f6
Binary files /dev/null and b/Client2016/content/textures/Blank.png differ
diff --git a/Client2016/content/textures/Clone.png b/Client2016/content/textures/Clone.png
new file mode 100644
index 0000000..31915a9
Binary files /dev/null and b/Client2016/content/textures/Clone.png differ
diff --git a/Client2016/content/textures/CloneCursor.png b/Client2016/content/textures/CloneCursor.png
new file mode 100644
index 0000000..afe32c0
Binary files /dev/null and b/Client2016/content/textures/CloneCursor.png differ
diff --git a/Client2016/content/textures/CloneDownCursor.png b/Client2016/content/textures/CloneDownCursor.png
new file mode 100644
index 0000000..b33240d
Binary files /dev/null and b/Client2016/content/textures/CloneDownCursor.png differ
diff --git a/Client2016/content/textures/CloneOverCursor.png b/Client2016/content/textures/CloneOverCursor.png
new file mode 100644
index 0000000..5c97ee1
Binary files /dev/null and b/Client2016/content/textures/CloneOverCursor.png differ
diff --git a/Client2016/content/textures/Cursors/Gamepad/Pointer.png b/Client2016/content/textures/Cursors/Gamepad/Pointer.png
new file mode 100644
index 0000000..d14627c
Binary files /dev/null and b/Client2016/content/textures/Cursors/Gamepad/Pointer.png differ
diff --git a/Client2016/content/textures/Cursors/Gamepad/Pointer@2x.png b/Client2016/content/textures/Cursors/Gamepad/Pointer@2x.png
new file mode 100644
index 0000000..cd8c978
Binary files /dev/null and b/Client2016/content/textures/Cursors/Gamepad/Pointer@2x.png differ
diff --git a/Client2016/content/textures/Cursors/Gamepad/PointerOver.png b/Client2016/content/textures/Cursors/Gamepad/PointerOver.png
new file mode 100644
index 0000000..61fee5d
Binary files /dev/null and b/Client2016/content/textures/Cursors/Gamepad/PointerOver.png differ
diff --git a/Client2016/content/textures/Cursors/Gamepad/PointerOver@2x.png b/Client2016/content/textures/Cursors/Gamepad/PointerOver@2x.png
new file mode 100644
index 0000000..54f37cc
Binary files /dev/null and b/Client2016/content/textures/Cursors/Gamepad/PointerOver@2x.png differ
diff --git a/Client2016/content/textures/DialogHelp.png b/Client2016/content/textures/DialogHelp.png
new file mode 100644
index 0000000..073e3b7
Binary files /dev/null and b/Client2016/content/textures/DialogHelp.png differ
diff --git a/Client2016/content/textures/DialogQuest.png b/Client2016/content/textures/DialogQuest.png
new file mode 100644
index 0000000..0eb475c
Binary files /dev/null and b/Client2016/content/textures/DialogQuest.png differ
diff --git a/Client2016/content/textures/DialogShop.png b/Client2016/content/textures/DialogShop.png
new file mode 100644
index 0000000..5e5d503
Binary files /dev/null and b/Client2016/content/textures/DialogShop.png differ
diff --git a/Client2016/content/textures/DragCursor.png b/Client2016/content/textures/DragCursor.png
new file mode 100644
index 0000000..a8f1894
Binary files /dev/null and b/Client2016/content/textures/DragCursor.png differ
diff --git a/Client2016/content/textures/DropperCursor.png b/Client2016/content/textures/DropperCursor.png
new file mode 100644
index 0000000..d98bcb6
Binary files /dev/null and b/Client2016/content/textures/DropperCursor.png differ
diff --git a/Client2016/content/textures/Exit.png b/Client2016/content/textures/Exit.png
new file mode 100644
index 0000000..523d2c5
Binary files /dev/null and b/Client2016/content/textures/Exit.png differ
diff --git a/Client2016/content/textures/Exit_dn.png b/Client2016/content/textures/Exit_dn.png
new file mode 100644
index 0000000..b2359c5
Binary files /dev/null and b/Client2016/content/textures/Exit_dn.png differ
diff --git a/Client2016/content/textures/Exit_ovr.png b/Client2016/content/textures/Exit_ovr.png
new file mode 100644
index 0000000..b2359c5
Binary files /dev/null and b/Client2016/content/textures/Exit_ovr.png differ
diff --git a/Client2016/content/textures/FillCursor.png b/Client2016/content/textures/FillCursor.png
new file mode 100644
index 0000000..752cebc
Binary files /dev/null and b/Client2016/content/textures/FillCursor.png differ
diff --git a/Client2016/content/textures/FlagCursor.png b/Client2016/content/textures/FlagCursor.png
new file mode 100644
index 0000000..59c3798
Binary files /dev/null and b/Client2016/content/textures/FlagCursor.png differ
diff --git a/Client2016/content/textures/FlatCursor.png b/Client2016/content/textures/FlatCursor.png
new file mode 100644
index 0000000..feba33a
Binary files /dev/null and b/Client2016/content/textures/FlatCursor.png differ
diff --git a/Client2016/content/textures/GrabCursor.png b/Client2016/content/textures/GrabCursor.png
new file mode 100644
index 0000000..d411bae
Binary files /dev/null and b/Client2016/content/textures/GrabCursor.png differ
diff --git a/Client2016/content/textures/GrabRotateCursor.png b/Client2016/content/textures/GrabRotateCursor.png
new file mode 100644
index 0000000..0cd0c13
Binary files /dev/null and b/Client2016/content/textures/GrabRotateCursor.png differ
diff --git a/Client2016/content/textures/Grass_Texture.jpg b/Client2016/content/textures/Grass_Texture.jpg
new file mode 100644
index 0000000..cd273dc
Binary files /dev/null and b/Client2016/content/textures/Grass_Texture.jpg differ
diff --git a/Client2016/content/textures/GunCursor.png b/Client2016/content/textures/GunCursor.png
new file mode 100644
index 0000000..d1b6afc
Binary files /dev/null and b/Client2016/content/textures/GunCursor.png differ
diff --git a/Client2016/content/textures/GunWaitCursor.png b/Client2016/content/textures/GunWaitCursor.png
new file mode 100644
index 0000000..0c812be
Binary files /dev/null and b/Client2016/content/textures/GunWaitCursor.png differ
diff --git a/Client2016/content/textures/HammerCursor.png b/Client2016/content/textures/HammerCursor.png
new file mode 100644
index 0000000..ad2b622
Binary files /dev/null and b/Client2016/content/textures/HammerCursor.png differ
diff --git a/Client2016/content/textures/HammerDownCursor.png b/Client2016/content/textures/HammerDownCursor.png
new file mode 100644
index 0000000..cdbcfe2
Binary files /dev/null and b/Client2016/content/textures/HammerDownCursor.png differ
diff --git a/Client2016/content/textures/HammerOverCursor.png b/Client2016/content/textures/HammerOverCursor.png
new file mode 100644
index 0000000..4182d69
Binary files /dev/null and b/Client2016/content/textures/HammerOverCursor.png differ
diff --git a/Client2016/content/textures/HingeCursor.png b/Client2016/content/textures/HingeCursor.png
new file mode 100644
index 0000000..e507cd3
Binary files /dev/null and b/Client2016/content/textures/HingeCursor.png differ
diff --git a/Client2016/content/textures/LockCursor.png b/Client2016/content/textures/LockCursor.png
new file mode 100644
index 0000000..4c4c6b2
Binary files /dev/null and b/Client2016/content/textures/LockCursor.png differ
diff --git a/Client2016/content/textures/MotorCursor.png b/Client2016/content/textures/MotorCursor.png
new file mode 100644
index 0000000..c363ab6
Binary files /dev/null and b/Client2016/content/textures/MotorCursor.png differ
diff --git a/Client2016/content/textures/MouseLockedCursor.png b/Client2016/content/textures/MouseLockedCursor.png
new file mode 100644
index 0000000..c3b44db
Binary files /dev/null and b/Client2016/content/textures/MouseLockedCursor.png differ
diff --git a/Client2016/content/textures/ResizeCursor.png b/Client2016/content/textures/ResizeCursor.png
new file mode 100644
index 0000000..e9e06f5
Binary files /dev/null and b/Client2016/content/textures/ResizeCursor.png differ
diff --git a/Client2016/content/textures/Roblox-loading-glow.png b/Client2016/content/textures/Roblox-loading-glow.png
new file mode 100644
index 0000000..bc757b1
Binary files /dev/null and b/Client2016/content/textures/Roblox-loading-glow.png differ
diff --git a/Client2016/content/textures/Roblox-loading-glow@2x.png b/Client2016/content/textures/Roblox-loading-glow@2x.png
new file mode 100644
index 0000000..a1107c4
Binary files /dev/null and b/Client2016/content/textures/Roblox-loading-glow@2x.png differ
diff --git a/Client2016/content/textures/Roblox-loading.png b/Client2016/content/textures/Roblox-loading.png
new file mode 100644
index 0000000..c4d13ae
Binary files /dev/null and b/Client2016/content/textures/Roblox-loading.png differ
diff --git a/Client2016/content/textures/Roblox-loading@2x.png b/Client2016/content/textures/Roblox-loading@2x.png
new file mode 100644
index 0000000..0530a1a
Binary files /dev/null and b/Client2016/content/textures/Roblox-loading@2x.png differ
diff --git a/Client2016/content/textures/Roblox.bmp b/Client2016/content/textures/Roblox.bmp
new file mode 100644
index 0000000..362aa34
Binary files /dev/null and b/Client2016/content/textures/Roblox.bmp differ
diff --git a/Client2016/content/textures/RustGradient.png b/Client2016/content/textures/RustGradient.png
new file mode 100644
index 0000000..0180253
Binary files /dev/null and b/Client2016/content/textures/RustGradient.png differ
diff --git a/Client2016/content/textures/Smoke.png b/Client2016/content/textures/Smoke.png
new file mode 100644
index 0000000..b86df5d
Binary files /dev/null and b/Client2016/content/textures/Smoke.png differ
diff --git a/Client2016/content/textures/SpawnCursor.png b/Client2016/content/textures/SpawnCursor.png
new file mode 100644
index 0000000..37fb08e
Binary files /dev/null and b/Client2016/content/textures/SpawnCursor.png differ
diff --git a/Client2016/content/textures/SpawnLocation.png b/Client2016/content/textures/SpawnLocation.png
new file mode 100644
index 0000000..049c2d3
Binary files /dev/null and b/Client2016/content/textures/SpawnLocation.png differ
diff --git a/Client2016/content/textures/SurfacesDefault.png b/Client2016/content/textures/SurfacesDefault.png
new file mode 100644
index 0000000..53b1505
Binary files /dev/null and b/Client2016/content/textures/SurfacesDefault.png differ
diff --git a/Client2016/content/textures/UnAnchorCursor.png b/Client2016/content/textures/UnAnchorCursor.png
new file mode 100644
index 0000000..fa4e9cb
Binary files /dev/null and b/Client2016/content/textures/UnAnchorCursor.png differ
diff --git a/Client2016/content/textures/UnlockCursor.png b/Client2016/content/textures/UnlockCursor.png
new file mode 100644
index 0000000..052a07a
Binary files /dev/null and b/Client2016/content/textures/UnlockCursor.png differ
diff --git a/Client2016/content/textures/WeldCursor.png b/Client2016/content/textures/WeldCursor.png
new file mode 100644
index 0000000..c2a4292
Binary files /dev/null and b/Client2016/content/textures/WeldCursor.png differ
diff --git a/Client2016/content/textures/WhiteCircle.png b/Client2016/content/textures/WhiteCircle.png
new file mode 100644
index 0000000..78f4075
Binary files /dev/null and b/Client2016/content/textures/WhiteCircle.png differ
diff --git a/Client2016/content/textures/advClosed-hand-no-weld.png b/Client2016/content/textures/advClosed-hand-no-weld.png
new file mode 100644
index 0000000..beb2fd4
Binary files /dev/null and b/Client2016/content/textures/advClosed-hand-no-weld.png differ
diff --git a/Client2016/content/textures/advClosed-hand-weld.png b/Client2016/content/textures/advClosed-hand-weld.png
new file mode 100644
index 0000000..b79d71b
Binary files /dev/null and b/Client2016/content/textures/advClosed-hand-weld.png differ
diff --git a/Client2016/content/textures/advClosed-hand.png b/Client2016/content/textures/advClosed-hand.png
new file mode 100644
index 0000000..38fcea4
Binary files /dev/null and b/Client2016/content/textures/advClosed-hand.png differ
diff --git a/Client2016/content/textures/advCursor-default.png b/Client2016/content/textures/advCursor-default.png
new file mode 100644
index 0000000..58c115b
Binary files /dev/null and b/Client2016/content/textures/advCursor-default.png differ
diff --git a/Client2016/content/textures/advCursor-openedHand.png b/Client2016/content/textures/advCursor-openedHand.png
new file mode 100644
index 0000000..c972e29
Binary files /dev/null and b/Client2016/content/textures/advCursor-openedHand.png differ
diff --git a/Client2016/content/textures/advCursor-white.png b/Client2016/content/textures/advCursor-white.png
new file mode 100644
index 0000000..8a68e4f
Binary files /dev/null and b/Client2016/content/textures/advCursor-white.png differ
diff --git a/Client2016/content/textures/advancedMove.png b/Client2016/content/textures/advancedMove.png
new file mode 100644
index 0000000..da15757
Binary files /dev/null and b/Client2016/content/textures/advancedMove.png differ
diff --git a/Client2016/content/textures/advancedMoveResize.png b/Client2016/content/textures/advancedMoveResize.png
new file mode 100644
index 0000000..8b1264a
Binary files /dev/null and b/Client2016/content/textures/advancedMoveResize.png differ
diff --git a/Client2016/content/textures/advancedMove_joint.png b/Client2016/content/textures/advancedMove_joint.png
new file mode 100644
index 0000000..17079e0
Binary files /dev/null and b/Client2016/content/textures/advancedMove_joint.png differ
diff --git a/Client2016/content/textures/advancedMove_keysOnly.png b/Client2016/content/textures/advancedMove_keysOnly.png
new file mode 100644
index 0000000..36eb233
Binary files /dev/null and b/Client2016/content/textures/advancedMove_keysOnly.png differ
diff --git a/Client2016/content/textures/advancedMove_noJoint.png b/Client2016/content/textures/advancedMove_noJoint.png
new file mode 100644
index 0000000..62752c4
Binary files /dev/null and b/Client2016/content/textures/advancedMove_noJoint.png differ
diff --git a/Client2016/content/textures/blackBkg_round.png b/Client2016/content/textures/blackBkg_round.png
new file mode 100644
index 0000000..7070a7c
Binary files /dev/null and b/Client2016/content/textures/blackBkg_round.png differ
diff --git a/Client2016/content/textures/blackBkg_square.png b/Client2016/content/textures/blackBkg_square.png
new file mode 100644
index 0000000..dc97acf
Binary files /dev/null and b/Client2016/content/textures/blackBkg_square.png differ
diff --git a/Client2016/content/textures/chatBubble_botBlue_bkg.png b/Client2016/content/textures/chatBubble_botBlue_bkg.png
new file mode 100644
index 0000000..9f0b008
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botBlue_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botBlue_notify_bkg.png b/Client2016/content/textures/chatBubble_botBlue_notify_bkg.png
new file mode 100644
index 0000000..0b03982
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botBlue_notify_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botBlue_tail.png b/Client2016/content/textures/chatBubble_botBlue_tail.png
new file mode 100644
index 0000000..316bc9d
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botBlue_tail.png differ
diff --git a/Client2016/content/textures/chatBubble_botBlue_tailRight.png b/Client2016/content/textures/chatBubble_botBlue_tailRight.png
new file mode 100644
index 0000000..da047a8
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botBlue_tailRight.png differ
diff --git a/Client2016/content/textures/chatBubble_botGreen_bkg.png b/Client2016/content/textures/chatBubble_botGreen_bkg.png
new file mode 100644
index 0000000..e158c85
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botGreen_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botGreen_notify_bkg.png b/Client2016/content/textures/chatBubble_botGreen_notify_bkg.png
new file mode 100644
index 0000000..d0a0c47
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botGreen_notify_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botGreen_tail.png b/Client2016/content/textures/chatBubble_botGreen_tail.png
new file mode 100644
index 0000000..01e6a00
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botGreen_tail.png differ
diff --git a/Client2016/content/textures/chatBubble_botGreen_tailRight.png b/Client2016/content/textures/chatBubble_botGreen_tailRight.png
new file mode 100644
index 0000000..8cd6293
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botGreen_tailRight.png differ
diff --git a/Client2016/content/textures/chatBubble_botRed_bkg.png b/Client2016/content/textures/chatBubble_botRed_bkg.png
new file mode 100644
index 0000000..66e411f
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botRed_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botRed_notify_bkg.png b/Client2016/content/textures/chatBubble_botRed_notify_bkg.png
new file mode 100644
index 0000000..e7376eb
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botRed_notify_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_botRed_tail.png b/Client2016/content/textures/chatBubble_botRed_tail.png
new file mode 100644
index 0000000..b29c2af
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botRed_tail.png differ
diff --git a/Client2016/content/textures/chatBubble_botRed_tailRight.png b/Client2016/content/textures/chatBubble_botRed_tailRight.png
new file mode 100644
index 0000000..1e39788
Binary files /dev/null and b/Client2016/content/textures/chatBubble_botRed_tailRight.png differ
diff --git a/Client2016/content/textures/chatBubble_bot_notifyGray_dotDotDot.png b/Client2016/content/textures/chatBubble_bot_notifyGray_dotDotDot.png
new file mode 100644
index 0000000..f5b017d
Binary files /dev/null and b/Client2016/content/textures/chatBubble_bot_notifyGray_dotDotDot.png differ
diff --git a/Client2016/content/textures/chatBubble_bot_notify_bang.png b/Client2016/content/textures/chatBubble_bot_notify_bang.png
new file mode 100644
index 0000000..1ccef6c
Binary files /dev/null and b/Client2016/content/textures/chatBubble_bot_notify_bang.png differ
diff --git a/Client2016/content/textures/chatBubble_bot_notify_dotDotDot.png b/Client2016/content/textures/chatBubble_bot_notify_dotDotDot.png
new file mode 100644
index 0000000..4318458
Binary files /dev/null and b/Client2016/content/textures/chatBubble_bot_notify_dotDotDot.png differ
diff --git a/Client2016/content/textures/chatBubble_bot_notify_money.png b/Client2016/content/textures/chatBubble_bot_notify_money.png
new file mode 100644
index 0000000..54f58c5
Binary files /dev/null and b/Client2016/content/textures/chatBubble_bot_notify_money.png differ
diff --git a/Client2016/content/textures/chatBubble_bot_notify_question.png b/Client2016/content/textures/chatBubble_bot_notify_question.png
new file mode 100644
index 0000000..0a91c4f
Binary files /dev/null and b/Client2016/content/textures/chatBubble_bot_notify_question.png differ
diff --git a/Client2016/content/textures/chatBubble_white_bkg.png b/Client2016/content/textures/chatBubble_white_bkg.png
new file mode 100644
index 0000000..7e6648c
Binary files /dev/null and b/Client2016/content/textures/chatBubble_white_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_white_notify_bkg.png b/Client2016/content/textures/chatBubble_white_notify_bkg.png
new file mode 100644
index 0000000..828e362
Binary files /dev/null and b/Client2016/content/textures/chatBubble_white_notify_bkg.png differ
diff --git a/Client2016/content/textures/chatBubble_white_tail.png b/Client2016/content/textures/chatBubble_white_tail.png
new file mode 100644
index 0000000..77d1bd4
Binary files /dev/null and b/Client2016/content/textures/chatBubble_white_tail.png differ
diff --git a/Client2016/content/textures/dirt.jpg b/Client2016/content/textures/dirt.jpg
new file mode 100644
index 0000000..05f5c94
Binary files /dev/null and b/Client2016/content/textures/dirt.jpg differ
diff --git a/Client2016/content/textures/explosion.png b/Client2016/content/textures/explosion.png
new file mode 100644
index 0000000..5124cb2
Binary files /dev/null and b/Client2016/content/textures/explosion.png differ
diff --git a/Client2016/content/textures/face.png b/Client2016/content/textures/face.png
new file mode 100644
index 0000000..e57e342
Binary files /dev/null and b/Client2016/content/textures/face.png differ
diff --git a/Client2016/content/textures/fire_0.png b/Client2016/content/textures/fire_0.png
new file mode 100644
index 0000000..bbada0f
Binary files /dev/null and b/Client2016/content/textures/fire_0.png differ
diff --git a/Client2016/content/textures/glow.png b/Client2016/content/textures/glow.png
new file mode 100644
index 0000000..db4a99e
Binary files /dev/null and b/Client2016/content/textures/glow.png differ
diff --git a/Client2016/content/textures/gradient.png b/Client2016/content/textures/gradient.png
new file mode 100644
index 0000000..4278521
Binary files /dev/null and b/Client2016/content/textures/gradient.png differ
diff --git a/Client2016/content/textures/loading/cancelButton.png b/Client2016/content/textures/loading/cancelButton.png
new file mode 100644
index 0000000..4020631
Binary files /dev/null and b/Client2016/content/textures/loading/cancelButton.png differ
diff --git a/Client2016/content/textures/loading/darkLoadingTexture.png b/Client2016/content/textures/loading/darkLoadingTexture.png
new file mode 100644
index 0000000..1cae38f
Binary files /dev/null and b/Client2016/content/textures/loading/darkLoadingTexture.png differ
diff --git a/Client2016/content/textures/loading/loadingCircle.png b/Client2016/content/textures/loading/loadingCircle.png
new file mode 100644
index 0000000..aa1c650
Binary files /dev/null and b/Client2016/content/textures/loading/loadingCircle.png differ
diff --git a/Client2016/content/textures/loading/loadingTexture.png b/Client2016/content/textures/loading/loadingTexture.png
new file mode 100644
index 0000000..ba9b60d
Binary files /dev/null and b/Client2016/content/textures/loading/loadingTexture.png differ
diff --git a/Client2016/content/textures/loading/loadingvignette.png b/Client2016/content/textures/loading/loadingvignette.png
new file mode 100644
index 0000000..1398ef7
Binary files /dev/null and b/Client2016/content/textures/loading/loadingvignette.png differ
diff --git a/Client2016/content/textures/loading/robloxlogo.png b/Client2016/content/textures/loading/robloxlogo.png
new file mode 100644
index 0000000..180233d
Binary files /dev/null and b/Client2016/content/textures/loading/robloxlogo.png differ
diff --git a/Client2016/content/textures/lua.png b/Client2016/content/textures/lua.png
new file mode 100644
index 0000000..2791c43
Binary files /dev/null and b/Client2016/content/textures/lua.png differ
diff --git a/Client2016/content/textures/particles/common_alpha.dds b/Client2016/content/textures/particles/common_alpha.dds
new file mode 100644
index 0000000..2cc9c9c
Binary files /dev/null and b/Client2016/content/textures/particles/common_alpha.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_core_alpha.png b/Client2016/content/textures/particles/explosion01_core_alpha.png
new file mode 100644
index 0000000..2dbf12f
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_core_alpha.png differ
diff --git a/Client2016/content/textures/particles/explosion01_core_main.dds b/Client2016/content/textures/particles/explosion01_core_main.dds
new file mode 100644
index 0000000..44fd908
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_core_main.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_implosion_color.png b/Client2016/content/textures/particles/explosion01_implosion_color.png
new file mode 100644
index 0000000..385bed7
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_implosion_color.png differ
diff --git a/Client2016/content/textures/particles/explosion01_implosion_main.dds b/Client2016/content/textures/particles/explosion01_implosion_main.dds
new file mode 100644
index 0000000..a5bf1b5
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_implosion_main.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_shockwave_main.dds b/Client2016/content/textures/particles/explosion01_shockwave_main.dds
new file mode 100644
index 0000000..7a30ca6
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_shockwave_main.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_smoke_alpha.dds b/Client2016/content/textures/particles/explosion01_smoke_alpha.dds
new file mode 100644
index 0000000..99807c7
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_smoke_alpha.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_smoke_color_new.dds b/Client2016/content/textures/particles/explosion01_smoke_color_new.dds
new file mode 100644
index 0000000..fd4df8f
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_smoke_color_new.dds differ
diff --git a/Client2016/content/textures/particles/explosion01_smoke_main.dds b/Client2016/content/textures/particles/explosion01_smoke_main.dds
new file mode 100644
index 0000000..c37f99a
Binary files /dev/null and b/Client2016/content/textures/particles/explosion01_smoke_main.dds differ
diff --git a/Client2016/content/textures/particles/explosion_alpha.dds b/Client2016/content/textures/particles/explosion_alpha.dds
new file mode 100644
index 0000000..add095f
Binary files /dev/null and b/Client2016/content/textures/particles/explosion_alpha.dds differ
diff --git a/Client2016/content/textures/particles/explosion_color.dds b/Client2016/content/textures/particles/explosion_color.dds
new file mode 100644
index 0000000..f69e2cc
Binary files /dev/null and b/Client2016/content/textures/particles/explosion_color.dds differ
diff --git a/Client2016/content/textures/particles/fire_alpha.dds b/Client2016/content/textures/particles/fire_alpha.dds
new file mode 100644
index 0000000..812a506
Binary files /dev/null and b/Client2016/content/textures/particles/fire_alpha.dds differ
diff --git a/Client2016/content/textures/particles/fire_color.dds b/Client2016/content/textures/particles/fire_color.dds
new file mode 100644
index 0000000..5d569ad
Binary files /dev/null and b/Client2016/content/textures/particles/fire_color.dds differ
diff --git a/Client2016/content/textures/particles/fire_main.dds b/Client2016/content/textures/particles/fire_main.dds
new file mode 100644
index 0000000..bd398ae
Binary files /dev/null and b/Client2016/content/textures/particles/fire_main.dds differ
diff --git a/Client2016/content/textures/particles/fire_sparks_color.dds b/Client2016/content/textures/particles/fire_sparks_color.dds
new file mode 100644
index 0000000..8876db1
Binary files /dev/null and b/Client2016/content/textures/particles/fire_sparks_color.dds differ
diff --git a/Client2016/content/textures/particles/fire_sparks_main.dds b/Client2016/content/textures/particles/fire_sparks_main.dds
new file mode 100644
index 0000000..4468e5a
Binary files /dev/null and b/Client2016/content/textures/particles/fire_sparks_main.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_alpha.dds b/Client2016/content/textures/particles/forcefield_alpha.dds
new file mode 100644
index 0000000..03fdac0
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_alpha.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_glow_alpha.dds b/Client2016/content/textures/particles/forcefield_glow_alpha.dds
new file mode 100644
index 0000000..326310f
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_glow_alpha.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_glow_color.dds b/Client2016/content/textures/particles/forcefield_glow_color.dds
new file mode 100644
index 0000000..39dfb8e
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_glow_color.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_glow_main.dds b/Client2016/content/textures/particles/forcefield_glow_main.dds
new file mode 100644
index 0000000..d1a6472
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_glow_main.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_vortex_color.dds b/Client2016/content/textures/particles/forcefield_vortex_color.dds
new file mode 100644
index 0000000..fe33e22
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_vortex_color.dds differ
diff --git a/Client2016/content/textures/particles/forcefield_vortex_main.dds b/Client2016/content/textures/particles/forcefield_vortex_main.dds
new file mode 100644
index 0000000..d67cf49
Binary files /dev/null and b/Client2016/content/textures/particles/forcefield_vortex_main.dds differ
diff --git a/Client2016/content/textures/particles/legacy_fire_alpha_color.dds b/Client2016/content/textures/particles/legacy_fire_alpha_color.dds
new file mode 100644
index 0000000..da0fb05
Binary files /dev/null and b/Client2016/content/textures/particles/legacy_fire_alpha_color.dds differ
diff --git a/Client2016/content/textures/particles/smoke_color.dds b/Client2016/content/textures/particles/smoke_color.dds
new file mode 100644
index 0000000..a4d0a4f
Binary files /dev/null and b/Client2016/content/textures/particles/smoke_color.dds differ
diff --git a/Client2016/content/textures/particles/smoke_main.dds b/Client2016/content/textures/particles/smoke_main.dds
new file mode 100644
index 0000000..1aaef8d
Binary files /dev/null and b/Client2016/content/textures/particles/smoke_main.dds differ
diff --git a/Client2016/content/textures/particles/sparkles_color.dds b/Client2016/content/textures/particles/sparkles_color.dds
new file mode 100644
index 0000000..4fd1f85
Binary files /dev/null and b/Client2016/content/textures/particles/sparkles_color.dds differ
diff --git a/Client2016/content/textures/particles/sparkles_main.dds b/Client2016/content/textures/particles/sparkles_main.dds
new file mode 100644
index 0000000..d1875fd
Binary files /dev/null and b/Client2016/content/textures/particles/sparkles_main.dds differ
diff --git a/Client2016/content/textures/roblox-logo.png b/Client2016/content/textures/roblox-logo.png
new file mode 100644
index 0000000..cf5d0c2
Binary files /dev/null and b/Client2016/content/textures/roblox-logo.png differ
diff --git a/Client2016/content/textures/rotationArrow.png b/Client2016/content/textures/rotationArrow.png
new file mode 100644
index 0000000..427aa20
Binary files /dev/null and b/Client2016/content/textures/rotationArrow.png differ
diff --git a/Client2016/content/textures/script.png b/Client2016/content/textures/script.png
new file mode 100644
index 0000000..0f9ed4d
Binary files /dev/null and b/Client2016/content/textures/script.png differ
diff --git a/Client2016/content/textures/shadowmask.png b/Client2016/content/textures/shadowmask.png
new file mode 100644
index 0000000..47ed550
Binary files /dev/null and b/Client2016/content/textures/shadowmask.png differ
diff --git a/Client2016/content/textures/spark.png b/Client2016/content/textures/spark.png
new file mode 100644
index 0000000..486f47c
Binary files /dev/null and b/Client2016/content/textures/spark.png differ
diff --git a/Client2016/content/textures/sparkle.png b/Client2016/content/textures/sparkle.png
new file mode 100644
index 0000000..5fa5e2a
Binary files /dev/null and b/Client2016/content/textures/sparkle.png differ
diff --git a/Client2016/content/textures/transformFiveDegrees.png b/Client2016/content/textures/transformFiveDegrees.png
new file mode 100644
index 0000000..542315f
Binary files /dev/null and b/Client2016/content/textures/transformFiveDegrees.png differ
diff --git a/Client2016/content/textures/transformNinetyDegrees.png b/Client2016/content/textures/transformNinetyDegrees.png
new file mode 100644
index 0000000..8f6f8fe
Binary files /dev/null and b/Client2016/content/textures/transformNinetyDegrees.png differ
diff --git a/Client2016/content/textures/transformOneDegree.png b/Client2016/content/textures/transformOneDegree.png
new file mode 100644
index 0000000..aa93f1e
Binary files /dev/null and b/Client2016/content/textures/transformOneDegree.png differ
diff --git a/Client2016/content/textures/transformTwentyTwoDegrees.png b/Client2016/content/textures/transformTwentyTwoDegrees.png
new file mode 100644
index 0000000..cf9e6a1
Binary files /dev/null and b/Client2016/content/textures/transformTwentyTwoDegrees.png differ
diff --git a/Client2016/content/textures/ui/Backpack/Backpack.png b/Client2016/content/textures/ui/Backpack/Backpack.png
new file mode 100644
index 0000000..3aab561
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack/Backpack.png differ
diff --git a/Client2016/content/textures/ui/Backpack/Backpack@2x.png b/Client2016/content/textures/ui/Backpack/Backpack@2x.png
new file mode 100644
index 0000000..c13f00b
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack/Backpack@2x.png differ
diff --git a/Client2016/content/textures/ui/Backpack/Backpack_Down.png b/Client2016/content/textures/ui/Backpack/Backpack_Down.png
new file mode 100644
index 0000000..c2f0fdd
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack/Backpack_Down.png differ
diff --git a/Client2016/content/textures/ui/Backpack/Backpack_Down@2x.png b/Client2016/content/textures/ui/Backpack/Backpack_Down@2x.png
new file mode 100644
index 0000000..56e9c4b
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack/Backpack_Down@2x.png differ
diff --git a/Client2016/content/textures/ui/Backpack_Close.png b/Client2016/content/textures/ui/Backpack_Close.png
new file mode 100644
index 0000000..ed2442b
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack_Close.png differ
diff --git a/Client2016/content/textures/ui/Backpack_Close@2x.png b/Client2016/content/textures/ui/Backpack_Close@2x.png
new file mode 100644
index 0000000..73098da
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack_Close@2x.png differ
diff --git a/Client2016/content/textures/ui/Backpack_Open.png b/Client2016/content/textures/ui/Backpack_Open.png
new file mode 100644
index 0000000..d6ddd0b
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack_Open.png differ
diff --git a/Client2016/content/textures/ui/Backpack_Open@2x.png b/Client2016/content/textures/ui/Backpack_Open@2x.png
new file mode 100644
index 0000000..d3a58cd
Binary files /dev/null and b/Client2016/content/textures/ui/Backpack_Open@2x.png differ
diff --git a/Client2016/content/textures/ui/ButtonLeft.png b/Client2016/content/textures/ui/ButtonLeft.png
new file mode 100644
index 0000000..3ccafc8
Binary files /dev/null and b/Client2016/content/textures/ui/ButtonLeft.png differ
diff --git a/Client2016/content/textures/ui/ButtonLeftDown.png b/Client2016/content/textures/ui/ButtonLeftDown.png
new file mode 100644
index 0000000..a17d93c
Binary files /dev/null and b/Client2016/content/textures/ui/ButtonLeftDown.png differ
diff --git a/Client2016/content/textures/ui/ButtonRight.png b/Client2016/content/textures/ui/ButtonRight.png
new file mode 100644
index 0000000..e6f3e3e
Binary files /dev/null and b/Client2016/content/textures/ui/ButtonRight.png differ
diff --git a/Client2016/content/textures/ui/ButtonRightDown.png b/Client2016/content/textures/ui/ButtonRightDown.png
new file mode 100644
index 0000000..70f1bc7
Binary files /dev/null and b/Client2016/content/textures/ui/ButtonRightDown.png differ
diff --git a/Client2016/content/textures/ui/Chat/Chat.png b/Client2016/content/textures/ui/Chat/Chat.png
new file mode 100644
index 0000000..4a81845
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/Chat.png differ
diff --git a/Client2016/content/textures/ui/Chat/Chat@2x.png b/Client2016/content/textures/ui/Chat/Chat@2x.png
new file mode 100644
index 0000000..52cdff1
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/Chat@2x.png differ
diff --git a/Client2016/content/textures/ui/Chat/ChatDown.png b/Client2016/content/textures/ui/Chat/ChatDown.png
new file mode 100644
index 0000000..a8e354f
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ChatDown.png differ
diff --git a/Client2016/content/textures/ui/Chat/ChatDown@2x.png b/Client2016/content/textures/ui/Chat/ChatDown@2x.png
new file mode 100644
index 0000000..1bc47fd
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ChatDown@2x.png differ
diff --git a/Client2016/content/textures/ui/Chat/MessageCounter.png b/Client2016/content/textures/ui/Chat/MessageCounter.png
new file mode 100644
index 0000000..ad062c4
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/MessageCounter.png differ
diff --git a/Client2016/content/textures/ui/Chat/MessageCounter@2x.png b/Client2016/content/textures/ui/Chat/MessageCounter@2x.png
new file mode 100644
index 0000000..d978e2e
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/MessageCounter@2x.png differ
diff --git a/Client2016/content/textures/ui/Chat/ToggleChat.png b/Client2016/content/textures/ui/Chat/ToggleChat.png
new file mode 100644
index 0000000..49a4eb1
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ToggleChat.png differ
diff --git a/Client2016/content/textures/ui/Chat/ToggleChat@2x.png b/Client2016/content/textures/ui/Chat/ToggleChat@2x.png
new file mode 100644
index 0000000..20bdca8
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ToggleChat@2x.png differ
diff --git a/Client2016/content/textures/ui/Chat/ToggleChatDown.png b/Client2016/content/textures/ui/Chat/ToggleChatDown.png
new file mode 100644
index 0000000..16c5acb
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ToggleChatDown.png differ
diff --git a/Client2016/content/textures/ui/Chat/ToggleChatDown@2x.png b/Client2016/content/textures/ui/Chat/ToggleChatDown@2x.png
new file mode 100644
index 0000000..9f07a8d
Binary files /dev/null and b/Client2016/content/textures/ui/Chat/ToggleChatDown@2x.png differ
diff --git a/Client2016/content/textures/ui/CloneButton.png b/Client2016/content/textures/ui/CloneButton.png
new file mode 100644
index 0000000..7e24cc6
Binary files /dev/null and b/Client2016/content/textures/ui/CloneButton.png differ
diff --git a/Client2016/content/textures/ui/CloneButton_dn.png b/Client2016/content/textures/ui/CloneButton_dn.png
new file mode 100644
index 0000000..adbfe60
Binary files /dev/null and b/Client2016/content/textures/ui/CloneButton_dn.png differ
diff --git a/Client2016/content/textures/ui/CloseButton.png b/Client2016/content/textures/ui/CloseButton.png
new file mode 100644
index 0000000..59d62c0
Binary files /dev/null and b/Client2016/content/textures/ui/CloseButton.png differ
diff --git a/Client2016/content/textures/ui/CloseButton_dn.png b/Client2016/content/textures/ui/CloseButton_dn.png
new file mode 100644
index 0000000..2a92663
Binary files /dev/null and b/Client2016/content/textures/ui/CloseButton_dn.png differ
diff --git a/Client2016/content/textures/ui/Concrete.png b/Client2016/content/textures/ui/Concrete.png
new file mode 100644
index 0000000..79ee458
Binary files /dev/null and b/Client2016/content/textures/ui/Concrete.png differ
diff --git a/Client2016/content/textures/ui/CorrodedMetal.png b/Client2016/content/textures/ui/CorrodedMetal.png
new file mode 100644
index 0000000..76483c7
Binary files /dev/null and b/Client2016/content/textures/ui/CorrodedMetal.png differ
diff --git a/Client2016/content/textures/ui/DPadSheet.png b/Client2016/content/textures/ui/DPadSheet.png
new file mode 100644
index 0000000..dbef643
Binary files /dev/null and b/Client2016/content/textures/ui/DPadSheet.png differ
diff --git a/Client2016/content/textures/ui/DeleteButton.png b/Client2016/content/textures/ui/DeleteButton.png
new file mode 100644
index 0000000..7f5757c
Binary files /dev/null and b/Client2016/content/textures/ui/DeleteButton.png differ
diff --git a/Client2016/content/textures/ui/DeleteButton_dn.png b/Client2016/content/textures/ui/DeleteButton_dn.png
new file mode 100644
index 0000000..184a615
Binary files /dev/null and b/Client2016/content/textures/ui/DeleteButton_dn.png differ
diff --git a/Client2016/content/textures/ui/DiamondPlate.png b/Client2016/content/textures/ui/DiamondPlate.png
new file mode 100644
index 0000000..ad9d4d0
Binary files /dev/null and b/Client2016/content/textures/ui/DiamondPlate.png differ
diff --git a/Client2016/content/textures/ui/ErrorIcon.png b/Client2016/content/textures/ui/ErrorIcon.png
new file mode 100644
index 0000000..e69c486
Binary files /dev/null and b/Client2016/content/textures/ui/ErrorIcon.png differ
diff --git a/Client2016/content/textures/ui/ErrorIconSmall.png b/Client2016/content/textures/ui/ErrorIconSmall.png
new file mode 100644
index 0000000..16a49a7
Binary files /dev/null and b/Client2016/content/textures/ui/ErrorIconSmall.png differ
diff --git a/Client2016/content/textures/ui/Foil.png b/Client2016/content/textures/ui/Foil.png
new file mode 100644
index 0000000..7cf51fc
Binary files /dev/null and b/Client2016/content/textures/ui/Foil.png differ
diff --git a/Client2016/content/textures/ui/Gear.png b/Client2016/content/textures/ui/Gear.png
new file mode 100644
index 0000000..de60a6a
Binary files /dev/null and b/Client2016/content/textures/ui/Gear.png differ
diff --git a/Client2016/content/textures/ui/Gear_dn.png b/Client2016/content/textures/ui/Gear_dn.png
new file mode 100644
index 0000000..53c8366
Binary files /dev/null and b/Client2016/content/textures/ui/Gear_dn.png differ
diff --git a/Client2016/content/textures/ui/Glue.png b/Client2016/content/textures/ui/Glue.png
new file mode 100644
index 0000000..3ceed9c
Binary files /dev/null and b/Client2016/content/textures/ui/Glue.png differ
diff --git a/Client2016/content/textures/ui/Grass.png b/Client2016/content/textures/ui/Grass.png
new file mode 100644
index 0000000..fd390c4
Binary files /dev/null and b/Client2016/content/textures/ui/Grass.png differ
diff --git a/Client2016/content/textures/ui/GroupMoveButton.png b/Client2016/content/textures/ui/GroupMoveButton.png
new file mode 100644
index 0000000..61a48b4
Binary files /dev/null and b/Client2016/content/textures/ui/GroupMoveButton.png differ
diff --git a/Client2016/content/textures/ui/GroupMoveButton_dn.png b/Client2016/content/textures/ui/GroupMoveButton_dn.png
new file mode 100644
index 0000000..7500d53
Binary files /dev/null and b/Client2016/content/textures/ui/GroupMoveButton_dn.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Center.png b/Client2016/content/textures/ui/Health-BKG-Center.png
new file mode 100644
index 0000000..eb0f3a4
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Center.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Center@2x.png b/Client2016/content/textures/ui/Health-BKG-Center@2x.png
new file mode 100644
index 0000000..e875086
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Center@2x.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Left-Cap.png b/Client2016/content/textures/ui/Health-BKG-Left-Cap.png
new file mode 100644
index 0000000..4437d29
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Left-Cap.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Left-Cap@2x.png b/Client2016/content/textures/ui/Health-BKG-Left-Cap@2x.png
new file mode 100644
index 0000000..1f7c652
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Left-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Right-Cap.png b/Client2016/content/textures/ui/Health-BKG-Right-Cap.png
new file mode 100644
index 0000000..12db34b
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Right-Cap.png differ
diff --git a/Client2016/content/textures/ui/Health-BKG-Right-Cap@2x.png b/Client2016/content/textures/ui/Health-BKG-Right-Cap@2x.png
new file mode 100644
index 0000000..49a0e50
Binary files /dev/null and b/Client2016/content/textures/ui/Health-BKG-Right-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Hinge.png b/Client2016/content/textures/ui/Hinge.png
new file mode 100644
index 0000000..c2ab9c9
Binary files /dev/null and b/Client2016/content/textures/ui/Hinge.png differ
diff --git a/Client2016/content/textures/ui/Ice.png b/Client2016/content/textures/ui/Ice.png
new file mode 100644
index 0000000..e9d0a32
Binary files /dev/null and b/Client2016/content/textures/ui/Ice.png differ
diff --git a/Client2016/content/textures/ui/Inlets.png b/Client2016/content/textures/ui/Inlets.png
new file mode 100644
index 0000000..cac89e3
Binary files /dev/null and b/Client2016/content/textures/ui/Inlets.png differ
diff --git a/Client2016/content/textures/ui/InsertButton.png b/Client2016/content/textures/ui/InsertButton.png
new file mode 100644
index 0000000..4058f36
Binary files /dev/null and b/Client2016/content/textures/ui/InsertButton.png differ
diff --git a/Client2016/content/textures/ui/InsertButton_dn.png b/Client2016/content/textures/ui/InsertButton_dn.png
new file mode 100644
index 0000000..03e72b2
Binary files /dev/null and b/Client2016/content/textures/ui/InsertButton_dn.png differ
diff --git a/Client2016/content/textures/ui/LoadingBKG.png b/Client2016/content/textures/ui/LoadingBKG.png
new file mode 100644
index 0000000..212468c
Binary files /dev/null and b/Client2016/content/textures/ui/LoadingBKG.png differ
diff --git a/Client2016/content/textures/ui/MaterialButton.png b/Client2016/content/textures/ui/MaterialButton.png
new file mode 100644
index 0000000..4191aab
Binary files /dev/null and b/Client2016/content/textures/ui/MaterialButton.png differ
diff --git a/Client2016/content/textures/ui/MaterialButton_dn.png b/Client2016/content/textures/ui/MaterialButton_dn.png
new file mode 100644
index 0000000..d61978c
Binary files /dev/null and b/Client2016/content/textures/ui/MaterialButton_dn.png differ
diff --git a/Client2016/content/textures/ui/MaterialMenu.png b/Client2016/content/textures/ui/MaterialMenu.png
new file mode 100644
index 0000000..c4a1c73
Binary files /dev/null and b/Client2016/content/textures/ui/MaterialMenu.png differ
diff --git a/Client2016/content/textures/ui/Menu/Hamburger.png b/Client2016/content/textures/ui/Menu/Hamburger.png
new file mode 100644
index 0000000..29520b8
Binary files /dev/null and b/Client2016/content/textures/ui/Menu/Hamburger.png differ
diff --git a/Client2016/content/textures/ui/Menu/Hamburger@2x.png b/Client2016/content/textures/ui/Menu/Hamburger@2x.png
new file mode 100644
index 0000000..e17c15f
Binary files /dev/null and b/Client2016/content/textures/ui/Menu/Hamburger@2x.png differ
diff --git a/Client2016/content/textures/ui/Menu/HamburgerDown.png b/Client2016/content/textures/ui/Menu/HamburgerDown.png
new file mode 100644
index 0000000..6d4fe9c
Binary files /dev/null and b/Client2016/content/textures/ui/Menu/HamburgerDown.png differ
diff --git a/Client2016/content/textures/ui/Menu/HamburgerDown@2x.png b/Client2016/content/textures/ui/Menu/HamburgerDown@2x.png
new file mode 100644
index 0000000..b788db9
Binary files /dev/null and b/Client2016/content/textures/ui/Menu/HamburgerDown@2x.png differ
diff --git a/Client2016/content/textures/ui/Modal.png b/Client2016/content/textures/ui/Modal.png
new file mode 100644
index 0000000..ff98cf8
Binary files /dev/null and b/Client2016/content/textures/ui/Modal.png differ
diff --git a/Client2016/content/textures/ui/Motor.png b/Client2016/content/textures/ui/Motor.png
new file mode 100644
index 0000000..e9b63eb
Binary files /dev/null and b/Client2016/content/textures/ui/Motor.png differ
diff --git a/Client2016/content/textures/ui/PaintButton.png b/Client2016/content/textures/ui/PaintButton.png
new file mode 100644
index 0000000..03b99a7
Binary files /dev/null and b/Client2016/content/textures/ui/PaintButton.png differ
diff --git a/Client2016/content/textures/ui/PaintButton_dn.png b/Client2016/content/textures/ui/PaintButton_dn.png
new file mode 100644
index 0000000..af4c64d
Binary files /dev/null and b/Client2016/content/textures/ui/PaintButton_dn.png differ
diff --git a/Client2016/content/textures/ui/PartMoveButton.png b/Client2016/content/textures/ui/PartMoveButton.png
new file mode 100644
index 0000000..a8f8fce
Binary files /dev/null and b/Client2016/content/textures/ui/PartMoveButton.png differ
diff --git a/Client2016/content/textures/ui/PartMoveButton_dn.png b/Client2016/content/textures/ui/PartMoveButton_dn.png
new file mode 100644
index 0000000..3c866db
Binary files /dev/null and b/Client2016/content/textures/ui/PartMoveButton_dn.png differ
diff --git a/Client2016/content/textures/ui/Plastic.png b/Client2016/content/textures/ui/Plastic.png
new file mode 100644
index 0000000..8f8bbf3
Binary files /dev/null and b/Client2016/content/textures/ui/Plastic.png differ
diff --git a/Client2016/content/textures/ui/PlayerList/BlockedIcon.png b/Client2016/content/textures/ui/PlayerList/BlockedIcon.png
new file mode 100644
index 0000000..6505f14
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerList/BlockedIcon.png differ
diff --git a/Client2016/content/textures/ui/PlayerList/CharacterImageBackground.png b/Client2016/content/textures/ui/PlayerList/CharacterImageBackground.png
new file mode 100644
index 0000000..624bc78
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerList/CharacterImageBackground.png differ
diff --git a/Client2016/content/textures/ui/PlayerList/TileShadowMissingTop.png b/Client2016/content/textures/ui/PlayerList/TileShadowMissingTop.png
new file mode 100644
index 0000000..64b90fc
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerList/TileShadowMissingTop.png differ
diff --git a/Client2016/content/textures/ui/PlayerListFriendRequestReceivedIcon.png b/Client2016/content/textures/ui/PlayerListFriendRequestReceivedIcon.png
new file mode 100644
index 0000000..ab292da
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerListFriendRequestReceivedIcon.png differ
diff --git a/Client2016/content/textures/ui/PlayerListFriendRequestSentIcon.png b/Client2016/content/textures/ui/PlayerListFriendRequestSentIcon.png
new file mode 100644
index 0000000..e10634b
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerListFriendRequestSentIcon.png differ
diff --git a/Client2016/content/textures/ui/PlayerlistFriendIcon.png b/Client2016/content/textures/ui/PlayerlistFriendIcon.png
new file mode 100644
index 0000000..21619a5
Binary files /dev/null and b/Client2016/content/textures/ui/PlayerlistFriendIcon.png differ
diff --git a/Client2016/content/textures/ui/PropertyButton.png b/Client2016/content/textures/ui/PropertyButton.png
new file mode 100644
index 0000000..254e00d
Binary files /dev/null and b/Client2016/content/textures/ui/PropertyButton.png differ
diff --git a/Client2016/content/textures/ui/PropertyButton_dn.png b/Client2016/content/textures/ui/PropertyButton_dn.png
new file mode 100644
index 0000000..c95ec8d
Binary files /dev/null and b/Client2016/content/textures/ui/PropertyButton_dn.png differ
diff --git a/Client2016/content/textures/ui/RecordDown.png b/Client2016/content/textures/ui/RecordDown.png
new file mode 100644
index 0000000..0e815a2
Binary files /dev/null and b/Client2016/content/textures/ui/RecordDown.png differ
diff --git a/Client2016/content/textures/ui/RecordStop.png b/Client2016/content/textures/ui/RecordStop.png
new file mode 100644
index 0000000..6b86baf
Binary files /dev/null and b/Client2016/content/textures/ui/RecordStop.png differ
diff --git a/Client2016/content/textures/ui/ResetIcon.png b/Client2016/content/textures/ui/ResetIcon.png
new file mode 100644
index 0000000..b9558d4
Binary files /dev/null and b/Client2016/content/textures/ui/ResetIcon.png differ
diff --git a/Client2016/content/textures/ui/RobuxIcon.png b/Client2016/content/textures/ui/RobuxIcon.png
new file mode 100644
index 0000000..ce39cb5
Binary files /dev/null and b/Client2016/content/textures/ui/RobuxIcon.png differ
diff --git a/Client2016/content/textures/ui/ScaleButton.png b/Client2016/content/textures/ui/ScaleButton.png
new file mode 100644
index 0000000..05ab151
Binary files /dev/null and b/Client2016/content/textures/ui/ScaleButton.png differ
diff --git a/Client2016/content/textures/ui/ScaleButton_dn.png b/Client2016/content/textures/ui/ScaleButton_dn.png
new file mode 100644
index 0000000..c5010fa
Binary files /dev/null and b/Client2016/content/textures/ui/ScaleButton_dn.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-bottom.png b/Client2016/content/textures/ui/Scroll/scroll-bottom.png
new file mode 100644
index 0000000..74b6f8e
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-bottom.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-bottom@2x.png b/Client2016/content/textures/ui/Scroll/scroll-bottom@2x.png
new file mode 100644
index 0000000..351081f
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-bottom@2x.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-middle.png b/Client2016/content/textures/ui/Scroll/scroll-middle.png
new file mode 100644
index 0000000..0702f1e
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-middle.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-middle@2x.png b/Client2016/content/textures/ui/Scroll/scroll-middle@2x.png
new file mode 100644
index 0000000..86ffc6f
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-middle@2x.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-top.png b/Client2016/content/textures/ui/Scroll/scroll-top.png
new file mode 100644
index 0000000..dd426d1
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-top.png differ
diff --git a/Client2016/content/textures/ui/Scroll/scroll-top@2x.png b/Client2016/content/textures/ui/Scroll/scroll-top@2x.png
new file mode 100644
index 0000000..29f9243
Binary files /dev/null and b/Client2016/content/textures/ui/Scroll/scroll-top@2x.png differ
diff --git a/Client2016/content/textures/ui/SearchIcon.png b/Client2016/content/textures/ui/SearchIcon.png
new file mode 100644
index 0000000..d72741c
Binary files /dev/null and b/Client2016/content/textures/ui/SearchIcon.png differ
diff --git a/Client2016/content/textures/ui/SelectionBox.png b/Client2016/content/textures/ui/SelectionBox.png
new file mode 100644
index 0000000..ab76dee
Binary files /dev/null and b/Client2016/content/textures/ui/SelectionBox.png differ
diff --git a/Client2016/content/textures/ui/SelectionBox@2x.png b/Client2016/content/textures/ui/SelectionBox@2x.png
new file mode 100644
index 0000000..54621f5
Binary files /dev/null and b/Client2016/content/textures/ui/SelectionBox@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/DropDown/DropDown.png b/Client2016/content/textures/ui/Settings/DropDown/DropDown.png
new file mode 100644
index 0000000..6088030
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/DropDown/DropDown.png differ
diff --git a/Client2016/content/textures/ui/Settings/DropDown/DropDown@2x.png b/Client2016/content/textures/ui/Settings/DropDown/DropDown@2x.png
new file mode 100644
index 0000000..0d82f2b
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/DropDown/DropDown@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/AButtonDark.png b/Client2016/content/textures/ui/Settings/Help/AButtonDark.png
new file mode 100644
index 0000000..5b761d0
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/AButtonDark.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/AButtonDark@2x.png b/Client2016/content/textures/ui/Settings/Help/AButtonDark@2x.png
new file mode 100644
index 0000000..b913a96
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/AButtonDark@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/AButtonLight.png b/Client2016/content/textures/ui/Settings/Help/AButtonLight.png
new file mode 100644
index 0000000..344af4c
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/AButtonLight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/AButtonLight@2x.png b/Client2016/content/textures/ui/Settings/Help/AButtonLight@2x.png
new file mode 100644
index 0000000..436be8e
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/AButtonLight@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/AButtonLightSmall.png b/Client2016/content/textures/ui/Settings/Help/AButtonLightSmall.png
new file mode 100644
index 0000000..5f95aa4
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/AButtonLightSmall.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/BButtonDark.png b/Client2016/content/textures/ui/Settings/Help/BButtonDark.png
new file mode 100644
index 0000000..f00a6db
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/BButtonDark.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/BButtonDark@2x.png b/Client2016/content/textures/ui/Settings/Help/BButtonDark@2x.png
new file mode 100644
index 0000000..22d6007
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/BButtonDark@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/BButtonLight.png b/Client2016/content/textures/ui/Settings/Help/BButtonLight.png
new file mode 100644
index 0000000..6314785
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/BButtonLight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/BButtonLight@2x.png b/Client2016/content/textures/ui/Settings/Help/BButtonLight@2x.png
new file mode 100644
index 0000000..46737cf
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/BButtonLight@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/EscapeIcon.png b/Client2016/content/textures/ui/Settings/Help/EscapeIcon.png
new file mode 100644
index 0000000..e49636e
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/EscapeIcon.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/GenericController.png b/Client2016/content/textures/ui/Settings/Help/GenericController.png
new file mode 100644
index 0000000..c92f1e1
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/GenericController.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/GenericController@2x.png b/Client2016/content/textures/ui/Settings/Help/GenericController@2x.png
new file mode 100644
index 0000000..3b82e31
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/GenericController@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/LeaveIcon.png b/Client2016/content/textures/ui/Settings/Help/LeaveIcon.png
new file mode 100644
index 0000000..cbe8d88
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/LeaveIcon.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/ResetIcon.png b/Client2016/content/textures/ui/Settings/Help/ResetIcon.png
new file mode 100644
index 0000000..64fedc8
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/ResetIcon.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/RotateCameraGesture.png b/Client2016/content/textures/ui/Settings/Help/RotateCameraGesture.png
new file mode 100644
index 0000000..53fd54e
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/RotateCameraGesture.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/UseToolGesture.png b/Client2016/content/textures/ui/Settings/Help/UseToolGesture.png
new file mode 100644
index 0000000..1e4124b
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/UseToolGesture.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/XButtonDark.png b/Client2016/content/textures/ui/Settings/Help/XButtonDark.png
new file mode 100644
index 0000000..83e45cd
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/XButtonDark.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/XButtonDark@2x.png b/Client2016/content/textures/ui/Settings/Help/XButtonDark@2x.png
new file mode 100644
index 0000000..cd15ff2
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/XButtonDark@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/XButtonLight.png b/Client2016/content/textures/ui/Settings/Help/XButtonLight.png
new file mode 100644
index 0000000..fd294c8
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/XButtonLight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/XButtonLight@2x.png b/Client2016/content/textures/ui/Settings/Help/XButtonLight@2x.png
new file mode 100644
index 0000000..efffae4
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/XButtonLight@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/XboxController.png b/Client2016/content/textures/ui/Settings/Help/XboxController.png
new file mode 100644
index 0000000..ae478c4
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/XboxController.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/YButtonDark.png b/Client2016/content/textures/ui/Settings/Help/YButtonDark.png
new file mode 100644
index 0000000..46d4284
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/YButtonDark.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/YButtonDark@2x.png b/Client2016/content/textures/ui/Settings/Help/YButtonDark@2x.png
new file mode 100644
index 0000000..81aaf13
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/YButtonDark@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/YButtonLight.png b/Client2016/content/textures/ui/Settings/Help/YButtonLight.png
new file mode 100644
index 0000000..b8130fb
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/YButtonLight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/YButtonLight@2x.png b/Client2016/content/textures/ui/Settings/Help/YButtonLight@2x.png
new file mode 100644
index 0000000..b19c89e
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/YButtonLight@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Help/ZoomGesture.png b/Client2016/content/textures/ui/Settings/Help/ZoomGesture.png
new file mode 100644
index 0000000..23a8f62
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Help/ZoomGesture.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuBackground.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuBackground.png
new file mode 100644
index 0000000..825c316
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuBackground.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton.png
new file mode 100644
index 0000000..ca1fb48
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton@2x.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton@2x.png
new file mode 100644
index 0000000..1406ca9
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButton@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected.png
new file mode 100644
index 0000000..298a952
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected@2x.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected@2x.png
new file mode 100644
index 0000000..4e25b24
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuButtonSelected@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection.png
new file mode 100644
index 0000000..0e79bfe
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection@2x.png b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection@2x.png
new file mode 100644
index 0000000..da1a3a3
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarAssets/MenuSelection@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab.png
new file mode 100644
index 0000000..81df477
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab@2x.png
new file mode 100644
index 0000000..8fa963f
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/GameSettingsTab@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab.png
new file mode 100644
index 0000000..2658eea
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab@2x.png
new file mode 100644
index 0000000..2910461
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/HelpTab@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab.png
new file mode 100644
index 0000000..f05200f
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab@2x.png
new file mode 100644
index 0000000..7fe7075
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/HomeTab@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon.png
new file mode 100644
index 0000000..9405151
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon@2x.png
new file mode 100644
index 0000000..1e32cfd
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/PlayersTabIcon@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab.png
new file mode 100644
index 0000000..4020a78
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab@2x.png
new file mode 100644
index 0000000..63a7411
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/RecordTab@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab.png
new file mode 100644
index 0000000..bddb28b
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab.png differ
diff --git a/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab@2x.png b/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab@2x.png
new file mode 100644
index 0000000..abb6674
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/MenuBarIcons/ReportAbuseTab@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Alert.png b/Client2016/content/textures/ui/Settings/Radial/Alert.png
new file mode 100644
index 0000000..4165e5c
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Alert.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Alert@2x.png b/Client2016/content/textures/ui/Settings/Radial/Alert@2x.png
new file mode 100644
index 0000000..c4fd032
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Alert@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Backpack.png b/Client2016/content/textures/ui/Settings/Radial/Backpack.png
new file mode 100644
index 0000000..fe7ed08
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Backpack.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Backpack@2x.png b/Client2016/content/textures/ui/Settings/Radial/Backpack@2x.png
new file mode 100644
index 0000000..70aa912
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Backpack@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Bottom.png b/Client2016/content/textures/ui/Settings/Radial/Bottom.png
new file mode 100644
index 0000000..deb9a5d
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Bottom.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/BottomLeft.png b/Client2016/content/textures/ui/Settings/Radial/BottomLeft.png
new file mode 100644
index 0000000..9606a32
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/BottomLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/BottomLeftSelected.png b/Client2016/content/textures/ui/Settings/Radial/BottomLeftSelected.png
new file mode 100644
index 0000000..c695162
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/BottomLeftSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/BottomRight.png b/Client2016/content/textures/ui/Settings/Radial/BottomRight.png
new file mode 100644
index 0000000..470101a
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/BottomRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/BottomRightSelected.png b/Client2016/content/textures/ui/Settings/Radial/BottomRightSelected.png
new file mode 100644
index 0000000..9752011
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/BottomRightSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/BottomSelected.png b/Client2016/content/textures/ui/Settings/Radial/BottomSelected.png
new file mode 100644
index 0000000..8503642
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/BottomSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Chat.png b/Client2016/content/textures/ui/Settings/Radial/Chat.png
new file mode 100644
index 0000000..de382f9
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Chat.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Chat@2x.png b/Client2016/content/textures/ui/Settings/Radial/Chat@2x.png
new file mode 100644
index 0000000..7d2f835
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Chat@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyBottom.png b/Client2016/content/textures/ui/Settings/Radial/EmptyBottom.png
new file mode 100644
index 0000000..65bfc6a
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyBottom.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyBottomLeft.png b/Client2016/content/textures/ui/Settings/Radial/EmptyBottomLeft.png
new file mode 100644
index 0000000..6944d53
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyBottomLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyBottomRight.png b/Client2016/content/textures/ui/Settings/Radial/EmptyBottomRight.png
new file mode 100644
index 0000000..6ec4168
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyBottomRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyTop.png b/Client2016/content/textures/ui/Settings/Radial/EmptyTop.png
new file mode 100644
index 0000000..bd0bdda
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyTop.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyTopLeft.png b/Client2016/content/textures/ui/Settings/Radial/EmptyTopLeft.png
new file mode 100644
index 0000000..fcb0312
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyTopLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/EmptyTopRight.png b/Client2016/content/textures/ui/Settings/Radial/EmptyTopRight.png
new file mode 100644
index 0000000..5b17865
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/EmptyTopRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Leave.png b/Client2016/content/textures/ui/Settings/Radial/Leave.png
new file mode 100644
index 0000000..90ee842
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Leave.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Leave@2x.png b/Client2016/content/textures/ui/Settings/Radial/Leave@2x.png
new file mode 100644
index 0000000..e9d11ad
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Leave@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Menu.png b/Client2016/content/textures/ui/Settings/Radial/Menu.png
new file mode 100644
index 0000000..c414691
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Menu.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Menu@2x.png b/Client2016/content/textures/ui/Settings/Radial/Menu@2x.png
new file mode 100644
index 0000000..5c65bd0
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Menu@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/PlayerList.png b/Client2016/content/textures/ui/Settings/Radial/PlayerList.png
new file mode 100644
index 0000000..b8da356
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/PlayerList.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/PlayerList@2x.png b/Client2016/content/textures/ui/Settings/Radial/PlayerList@2x.png
new file mode 100644
index 0000000..3ca6d5f
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/PlayerList@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/RadialLabel.png b/Client2016/content/textures/ui/Settings/Radial/RadialLabel.png
new file mode 100644
index 0000000..420552f
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/RadialLabel.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/RadialLabel@2x.png b/Client2016/content/textures/ui/Settings/Radial/RadialLabel@2x.png
new file mode 100644
index 0000000..a75f44d
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/RadialLabel@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/Top.png b/Client2016/content/textures/ui/Settings/Radial/Top.png
new file mode 100644
index 0000000..e3cc6eb
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/Top.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/TopLeft.png b/Client2016/content/textures/ui/Settings/Radial/TopLeft.png
new file mode 100644
index 0000000..b58730f
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/TopLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/TopLeftSelected.png b/Client2016/content/textures/ui/Settings/Radial/TopLeftSelected.png
new file mode 100644
index 0000000..03e85ff
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/TopLeftSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/TopRight.png b/Client2016/content/textures/ui/Settings/Radial/TopRight.png
new file mode 100644
index 0000000..120dcbf
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/TopRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/TopRightSelected.png b/Client2016/content/textures/ui/Settings/Radial/TopRightSelected.png
new file mode 100644
index 0000000..2b447f0
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/TopRightSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Radial/TopSelected.png b/Client2016/content/textures/ui/Settings/Radial/TopSelected.png
new file mode 100644
index 0000000..6e94eed
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Radial/TopSelected.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/BarLeft.png b/Client2016/content/textures/ui/Settings/Slider/BarLeft.png
new file mode 100644
index 0000000..7c77f60
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/BarLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/BarLeft@2x.png b/Client2016/content/textures/ui/Settings/Slider/BarLeft@2x.png
new file mode 100644
index 0000000..f116856
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/BarLeft@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/BarRight.png b/Client2016/content/textures/ui/Settings/Slider/BarRight.png
new file mode 100644
index 0000000..52256d6
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/BarRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/BarRight@2x.png b/Client2016/content/textures/ui/Settings/Slider/BarRight@2x.png
new file mode 100644
index 0000000..41bfe69
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/BarRight@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/Left.png b/Client2016/content/textures/ui/Settings/Slider/Left.png
new file mode 100644
index 0000000..a742728
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/Left.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/Left@2x.png b/Client2016/content/textures/ui/Settings/Slider/Left@2x.png
new file mode 100644
index 0000000..582699d
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/Left@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/Right.png b/Client2016/content/textures/ui/Settings/Slider/Right.png
new file mode 100644
index 0000000..0d47c0a
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/Right.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/Right@2x.png b/Client2016/content/textures/ui/Settings/Slider/Right@2x.png
new file mode 100644
index 0000000..fb86118
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/Right@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft.png b/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft.png
new file mode 100644
index 0000000..42cbddf
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft@2x.png b/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft@2x.png
new file mode 100644
index 0000000..8c97cda
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/SelectedBarLeft@2x.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight.png b/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight.png
new file mode 100644
index 0000000..c1b3f78
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight.png differ
diff --git a/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight@2x.png b/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight@2x.png
new file mode 100644
index 0000000..56010f0
Binary files /dev/null and b/Client2016/content/textures/ui/Settings/Slider/SelectedBarRight@2x.png differ
diff --git a/Client2016/content/textures/ui/SettingsButton.png b/Client2016/content/textures/ui/SettingsButton.png
new file mode 100644
index 0000000..196cf23
Binary files /dev/null and b/Client2016/content/textures/ui/SettingsButton.png differ
diff --git a/Client2016/content/textures/ui/SettingsButton_dn.png b/Client2016/content/textures/ui/SettingsButton_dn.png
new file mode 100644
index 0000000..e6f4799
Binary files /dev/null and b/Client2016/content/textures/ui/SettingsButton_dn.png differ
diff --git a/Client2016/content/textures/ui/SettingsButton_ds.png b/Client2016/content/textures/ui/SettingsButton_ds.png
new file mode 100644
index 0000000..2aca460
Binary files /dev/null and b/Client2016/content/textures/ui/SettingsButton_ds.png differ
diff --git a/Client2016/content/textures/ui/SettingsButton_ovr.png b/Client2016/content/textures/ui/SettingsButton_ovr.png
new file mode 100644
index 0000000..e6f4799
Binary files /dev/null and b/Client2016/content/textures/ui/SettingsButton_ovr.png differ
diff --git a/Client2016/content/textures/ui/SingleButton.png b/Client2016/content/textures/ui/SingleButton.png
new file mode 100644
index 0000000..6bf0fa0
Binary files /dev/null and b/Client2016/content/textures/ui/SingleButton.png differ
diff --git a/Client2016/content/textures/ui/SingleButtonDown.png b/Client2016/content/textures/ui/SingleButtonDown.png
new file mode 100644
index 0000000..b72335b
Binary files /dev/null and b/Client2016/content/textures/ui/SingleButtonDown.png differ
diff --git a/Client2016/content/textures/ui/Slate.png b/Client2016/content/textures/ui/Slate.png
new file mode 100644
index 0000000..4f90fb8
Binary files /dev/null and b/Client2016/content/textures/ui/Slate.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Center.png b/Client2016/content/textures/ui/Slider-BKG-Center.png
new file mode 100644
index 0000000..34f9c13
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Center.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Center@2x.png b/Client2016/content/textures/ui/Slider-BKG-Center@2x.png
new file mode 100644
index 0000000..4c4e650
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Center@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Left-Cap.png b/Client2016/content/textures/ui/Slider-BKG-Left-Cap.png
new file mode 100644
index 0000000..ae0ba4e
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Left-Cap.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Left-Cap@2x.png b/Client2016/content/textures/ui/Slider-BKG-Left-Cap@2x.png
new file mode 100644
index 0000000..e97552f
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Left-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Right-Cap.png b/Client2016/content/textures/ui/Slider-BKG-Right-Cap.png
new file mode 100644
index 0000000..19ef545
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Right-Cap.png differ
diff --git a/Client2016/content/textures/ui/Slider-BKG-Right-Cap@2x.png b/Client2016/content/textures/ui/Slider-BKG-Right-Cap@2x.png
new file mode 100644
index 0000000..614b0f4
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-BKG-Right-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Center.png b/Client2016/content/textures/ui/Slider-Fill-Center.png
new file mode 100644
index 0000000..6f45d7a
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Center.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Center@2x.png b/Client2016/content/textures/ui/Slider-Fill-Center@2x.png
new file mode 100644
index 0000000..9bf9420
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Center@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Left-Cap.png b/Client2016/content/textures/ui/Slider-Fill-Left-Cap.png
new file mode 100644
index 0000000..1c1ccdc
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Left-Cap.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Left-Cap@2x.png b/Client2016/content/textures/ui/Slider-Fill-Left-Cap@2x.png
new file mode 100644
index 0000000..cfd7689
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Left-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Right-Cap.png b/Client2016/content/textures/ui/Slider-Fill-Right-Cap.png
new file mode 100644
index 0000000..7e74df5
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Right-Cap.png differ
diff --git a/Client2016/content/textures/ui/Slider-Fill-Right-Cap@2x.png b/Client2016/content/textures/ui/Slider-Fill-Right-Cap@2x.png
new file mode 100644
index 0000000..31b7fc1
Binary files /dev/null and b/Client2016/content/textures/ui/Slider-Fill-Right-Cap@2x.png differ
diff --git a/Client2016/content/textures/ui/Slider.png b/Client2016/content/textures/ui/Slider.png
new file mode 100644
index 0000000..63c4dea
Binary files /dev/null and b/Client2016/content/textures/ui/Slider.png differ
diff --git a/Client2016/content/textures/ui/Slider_dn.png b/Client2016/content/textures/ui/Slider_dn.png
new file mode 100644
index 0000000..d98cb85
Binary files /dev/null and b/Client2016/content/textures/ui/Slider_dn.png differ
diff --git a/Client2016/content/textures/ui/Slider_sel.png b/Client2016/content/textures/ui/Slider_sel.png
new file mode 100644
index 0000000..d98cb85
Binary files /dev/null and b/Client2016/content/textures/ui/Slider_sel.png differ
diff --git a/Client2016/content/textures/ui/Smooth.png b/Client2016/content/textures/ui/Smooth.png
new file mode 100644
index 0000000..e4d6c4d
Binary files /dev/null and b/Client2016/content/textures/ui/Smooth.png differ
diff --git a/Client2016/content/textures/ui/StampToolButton.png b/Client2016/content/textures/ui/StampToolButton.png
new file mode 100644
index 0000000..34e7994
Binary files /dev/null and b/Client2016/content/textures/ui/StampToolButton.png differ
diff --git a/Client2016/content/textures/ui/StampToolButton_dn.png b/Client2016/content/textures/ui/StampToolButton_dn.png
new file mode 100644
index 0000000..affebf4
Binary files /dev/null and b/Client2016/content/textures/ui/StampToolButton_dn.png differ
diff --git a/Client2016/content/textures/ui/Studs.png b/Client2016/content/textures/ui/Studs.png
new file mode 100644
index 0000000..194a02b
Binary files /dev/null and b/Client2016/content/textures/ui/Studs.png differ
diff --git a/Client2016/content/textures/ui/SurfaceButton.png b/Client2016/content/textures/ui/SurfaceButton.png
new file mode 100644
index 0000000..78c90f0
Binary files /dev/null and b/Client2016/content/textures/ui/SurfaceButton.png differ
diff --git a/Client2016/content/textures/ui/SurfaceButton_dn.png b/Client2016/content/textures/ui/SurfaceButton_dn.png
new file mode 100644
index 0000000..850e099
Binary files /dev/null and b/Client2016/content/textures/ui/SurfaceButton_dn.png differ
diff --git a/Client2016/content/textures/ui/SurfaceMenu.png b/Client2016/content/textures/ui/SurfaceMenu.png
new file mode 100644
index 0000000..1582479
Binary files /dev/null and b/Client2016/content/textures/ui/SurfaceMenu.png differ
diff --git a/Client2016/content/textures/ui/TinyBcIcon.png b/Client2016/content/textures/ui/TinyBcIcon.png
new file mode 100644
index 0000000..1e2c7ef
Binary files /dev/null and b/Client2016/content/textures/ui/TinyBcIcon.png differ
diff --git a/Client2016/content/textures/ui/TinyObcIcon.png b/Client2016/content/textures/ui/TinyObcIcon.png
new file mode 100644
index 0000000..f12104d
Binary files /dev/null and b/Client2016/content/textures/ui/TinyObcIcon.png differ
diff --git a/Client2016/content/textures/ui/TinyTbcIcon.png b/Client2016/content/textures/ui/TinyTbcIcon.png
new file mode 100644
index 0000000..d5c37fe
Binary files /dev/null and b/Client2016/content/textures/ui/TinyTbcIcon.png differ
diff --git a/Client2016/content/textures/ui/TixIcon.png b/Client2016/content/textures/ui/TixIcon.png
new file mode 100644
index 0000000..852d976
Binary files /dev/null and b/Client2016/content/textures/ui/TixIcon.png differ
diff --git a/Client2016/content/textures/ui/ToggleFullScreen_ds.png b/Client2016/content/textures/ui/ToggleFullScreen_ds.png
new file mode 100644
index 0000000..07d7de0
Binary files /dev/null and b/Client2016/content/textures/ui/ToggleFullScreen_ds.png differ
diff --git a/Client2016/content/textures/ui/ToolButton.png b/Client2016/content/textures/ui/ToolButton.png
new file mode 100644
index 0000000..ca9a395
Binary files /dev/null and b/Client2016/content/textures/ui/ToolButton.png differ
diff --git a/Client2016/content/textures/ui/ToolButton_dn.png b/Client2016/content/textures/ui/ToolButton_dn.png
new file mode 100644
index 0000000..e53c826
Binary files /dev/null and b/Client2016/content/textures/ui/ToolButton_dn.png differ
diff --git a/Client2016/content/textures/ui/ToolButton_ds.png b/Client2016/content/textures/ui/ToolButton_ds.png
new file mode 100644
index 0000000..016ae9c
Binary files /dev/null and b/Client2016/content/textures/ui/ToolButton_ds.png differ
diff --git a/Client2016/content/textures/ui/TopBar/dropshadow.png b/Client2016/content/textures/ui/TopBar/dropshadow.png
new file mode 100644
index 0000000..8147254
Binary files /dev/null and b/Client2016/content/textures/ui/TopBar/dropshadow.png differ
diff --git a/Client2016/content/textures/ui/TopBar/dropshadow@2x.png b/Client2016/content/textures/ui/TopBar/dropshadow@2x.png
new file mode 100644
index 0000000..5b97175
Binary files /dev/null and b/Client2016/content/textures/ui/TopBar/dropshadow@2x.png differ
diff --git a/Client2016/content/textures/ui/TouchControlsSheet.png b/Client2016/content/textures/ui/TouchControlsSheet.png
new file mode 100644
index 0000000..d3b740e
Binary files /dev/null and b/Client2016/content/textures/ui/TouchControlsSheet.png differ
diff --git a/Client2016/content/textures/ui/Universal.png b/Client2016/content/textures/ui/Universal.png
new file mode 100644
index 0000000..508fac8
Binary files /dev/null and b/Client2016/content/textures/ui/Universal.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBar.png b/Client2016/content/textures/ui/Vehicle/SpeedBar.png
new file mode 100644
index 0000000..0bd0fb6
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBar.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBar@2x.png b/Client2016/content/textures/ui/Vehicle/SpeedBar@2x.png
new file mode 100644
index 0000000..403883b
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBar@2x.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBarBKG.png b/Client2016/content/textures/ui/Vehicle/SpeedBarBKG.png
new file mode 100644
index 0000000..67cf7dd
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBarBKG.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBarBKG@2x.png b/Client2016/content/textures/ui/Vehicle/SpeedBarBKG@2x.png
new file mode 100644
index 0000000..93f3e60
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBarBKG@2x.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty.png b/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty.png
new file mode 100644
index 0000000..23cef24
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty.png differ
diff --git a/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty@2x.png b/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty@2x.png
new file mode 100644
index 0000000..fe7f6d6
Binary files /dev/null and b/Client2016/content/textures/ui/Vehicle/SpeedBarEmpty@2x.png differ
diff --git a/Client2016/content/textures/ui/Weld.png b/Client2016/content/textures/ui/Weld.png
new file mode 100644
index 0000000..d45375b
Binary files /dev/null and b/Client2016/content/textures/ui/Weld.png differ
diff --git a/Client2016/content/textures/ui/Wood.png b/Client2016/content/textures/ui/Wood.png
new file mode 100644
index 0000000..93898de
Binary files /dev/null and b/Client2016/content/textures/ui/Wood.png differ
diff --git a/Client2016/content/textures/ui/btn_grey.png b/Client2016/content/textures/ui/btn_grey.png
new file mode 100644
index 0000000..5e46696
Binary files /dev/null and b/Client2016/content/textures/ui/btn_grey.png differ
diff --git a/Client2016/content/textures/ui/btn_greyTransp.png b/Client2016/content/textures/ui/btn_greyTransp.png
new file mode 100644
index 0000000..df5989b
Binary files /dev/null and b/Client2016/content/textures/ui/btn_greyTransp.png differ
diff --git a/Client2016/content/textures/ui/btn_newBlue.png b/Client2016/content/textures/ui/btn_newBlue.png
new file mode 100644
index 0000000..5a08d4b
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newBlue.png differ
diff --git a/Client2016/content/textures/ui/btn_newBlue@2x.png b/Client2016/content/textures/ui/btn_newBlue@2x.png
new file mode 100644
index 0000000..d20d595
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newBlue@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_newBlueGlow.png b/Client2016/content/textures/ui/btn_newBlueGlow.png
new file mode 100644
index 0000000..9376645
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newBlueGlow.png differ
diff --git a/Client2016/content/textures/ui/btn_newBlueGlow@2x.png b/Client2016/content/textures/ui/btn_newBlueGlow@2x.png
new file mode 100644
index 0000000..b559d35
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newBlueGlow@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_newGrey.png b/Client2016/content/textures/ui/btn_newGrey.png
new file mode 100644
index 0000000..3868d8c
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newGrey.png differ
diff --git a/Client2016/content/textures/ui/btn_newGrey@2x.png b/Client2016/content/textures/ui/btn_newGrey@2x.png
new file mode 100644
index 0000000..967c988
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newGrey@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_newGreyGlow.png b/Client2016/content/textures/ui/btn_newGreyGlow.png
new file mode 100644
index 0000000..6782b53
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newGreyGlow.png differ
diff --git a/Client2016/content/textures/ui/btn_newGreyGlow@2x.png b/Client2016/content/textures/ui/btn_newGreyGlow@2x.png
new file mode 100644
index 0000000..aba488a
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newGreyGlow@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_newWhite.png b/Client2016/content/textures/ui/btn_newWhite.png
new file mode 100644
index 0000000..bd5efaf
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newWhite.png differ
diff --git a/Client2016/content/textures/ui/btn_newWhite@2x.png b/Client2016/content/textures/ui/btn_newWhite@2x.png
new file mode 100644
index 0000000..35c6494
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newWhite@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_newWhiteGlow.png b/Client2016/content/textures/ui/btn_newWhiteGlow.png
new file mode 100644
index 0000000..857274f
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newWhiteGlow.png differ
diff --git a/Client2016/content/textures/ui/btn_newWhiteGlow@2x.png b/Client2016/content/textures/ui/btn_newWhiteGlow@2x.png
new file mode 100644
index 0000000..f0dbb9d
Binary files /dev/null and b/Client2016/content/textures/ui/btn_newWhiteGlow@2x.png differ
diff --git a/Client2016/content/textures/ui/btn_red.png b/Client2016/content/textures/ui/btn_red.png
new file mode 100644
index 0000000..17666e6
Binary files /dev/null and b/Client2016/content/textures/ui/btn_red.png differ
diff --git a/Client2016/content/textures/ui/btn_redGlow.png b/Client2016/content/textures/ui/btn_redGlow.png
new file mode 100644
index 0000000..5cf7081
Binary files /dev/null and b/Client2016/content/textures/ui/btn_redGlow.png differ
diff --git a/Client2016/content/textures/ui/btn_white.png b/Client2016/content/textures/ui/btn_white.png
new file mode 100644
index 0000000..d2a1cf2
Binary files /dev/null and b/Client2016/content/textures/ui/btn_white.png differ
diff --git a/Client2016/content/textures/ui/chatBubble_blue_notify_bkg.png b/Client2016/content/textures/ui/chatBubble_blue_notify_bkg.png
new file mode 100644
index 0000000..75871f9
Binary files /dev/null and b/Client2016/content/textures/ui/chatBubble_blue_notify_bkg.png differ
diff --git a/Client2016/content/textures/ui/chatBubble_green_notify_bkg.png b/Client2016/content/textures/ui/chatBubble_green_notify_bkg.png
new file mode 100644
index 0000000..5dd7ce5
Binary files /dev/null and b/Client2016/content/textures/ui/chatBubble_green_notify_bkg.png differ
diff --git a/Client2016/content/textures/ui/chatBubble_red_notify_bkg.png b/Client2016/content/textures/ui/chatBubble_red_notify_bkg.png
new file mode 100644
index 0000000..92ffa3b
Binary files /dev/null and b/Client2016/content/textures/ui/chatBubble_red_notify_bkg.png differ
diff --git a/Client2016/content/textures/ui/chatBubble_white_notify_bkg.png b/Client2016/content/textures/ui/chatBubble_white_notify_bkg.png
new file mode 100644
index 0000000..45158ce
Binary files /dev/null and b/Client2016/content/textures/ui/chatBubble_white_notify_bkg.png differ
diff --git a/Client2016/content/textures/ui/chat_teamButton.png b/Client2016/content/textures/ui/chat_teamButton.png
new file mode 100644
index 0000000..ad390aa
Binary files /dev/null and b/Client2016/content/textures/ui/chat_teamButton.png differ
diff --git a/Client2016/content/textures/ui/chat_teamButton@2x.png b/Client2016/content/textures/ui/chat_teamButton@2x.png
new file mode 100644
index 0000000..b38e73f
Binary files /dev/null and b/Client2016/content/textures/ui/chat_teamButton@2x.png differ
diff --git a/Client2016/content/textures/ui/dialog_blue.png b/Client2016/content/textures/ui/dialog_blue.png
new file mode 100644
index 0000000..734129b
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_blue.png differ
diff --git a/Client2016/content/textures/ui/dialog_blue@2x.png b/Client2016/content/textures/ui/dialog_blue@2x.png
new file mode 100644
index 0000000..7d17ee8
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_blue@2x.png differ
diff --git a/Client2016/content/textures/ui/dialog_ellipses.png b/Client2016/content/textures/ui/dialog_ellipses.png
new file mode 100644
index 0000000..845c727
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_ellipses.png differ
diff --git a/Client2016/content/textures/ui/dialog_green.png b/Client2016/content/textures/ui/dialog_green.png
new file mode 100644
index 0000000..b3b655c
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_green.png differ
diff --git a/Client2016/content/textures/ui/dialog_green@2x.png b/Client2016/content/textures/ui/dialog_green@2x.png
new file mode 100644
index 0000000..2daaacf
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_green@2x.png differ
diff --git a/Client2016/content/textures/ui/dialog_purpose_help.png b/Client2016/content/textures/ui/dialog_purpose_help.png
new file mode 100644
index 0000000..04c7c71
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_purpose_help.png differ
diff --git a/Client2016/content/textures/ui/dialog_purpose_quest.png b/Client2016/content/textures/ui/dialog_purpose_quest.png
new file mode 100644
index 0000000..1fb351d
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_purpose_quest.png differ
diff --git a/Client2016/content/textures/ui/dialog_purpose_shop.png b/Client2016/content/textures/ui/dialog_purpose_shop.png
new file mode 100644
index 0000000..5e14018
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_purpose_shop.png differ
diff --git a/Client2016/content/textures/ui/dialog_red.png b/Client2016/content/textures/ui/dialog_red.png
new file mode 100644
index 0000000..0cfce4d
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_red.png differ
diff --git a/Client2016/content/textures/ui/dialog_red@2x.png b/Client2016/content/textures/ui/dialog_red@2x.png
new file mode 100644
index 0000000..7c63527
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_red@2x.png differ
diff --git a/Client2016/content/textures/ui/dialog_tail.png b/Client2016/content/textures/ui/dialog_tail.png
new file mode 100644
index 0000000..34e7d89
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_tail.png differ
diff --git a/Client2016/content/textures/ui/dialog_tail@2x.png b/Client2016/content/textures/ui/dialog_tail@2x.png
new file mode 100644
index 0000000..461718b
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_tail@2x.png differ
diff --git a/Client2016/content/textures/ui/dialog_white.png b/Client2016/content/textures/ui/dialog_white.png
new file mode 100644
index 0000000..92cc922
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_white.png differ
diff --git a/Client2016/content/textures/ui/dialog_white@2x.png b/Client2016/content/textures/ui/dialog_white@2x.png
new file mode 100644
index 0000000..3935a05
Binary files /dev/null and b/Client2016/content/textures/ui/dialog_white@2x.png differ
diff --git a/Client2016/content/textures/ui/dropdown_arrow.png b/Client2016/content/textures/ui/dropdown_arrow.png
new file mode 100644
index 0000000..e428280
Binary files /dev/null and b/Client2016/content/textures/ui/dropdown_arrow.png differ
diff --git a/Client2016/content/textures/ui/dropdown_arrow@2x.png b/Client2016/content/textures/ui/dropdown_arrow@2x.png
new file mode 100644
index 0000000..fec2bf9
Binary files /dev/null and b/Client2016/content/textures/ui/dropdown_arrow@2x.png differ
diff --git a/Client2016/content/textures/ui/expandPlayerList.png b/Client2016/content/textures/ui/expandPlayerList.png
new file mode 100644
index 0000000..beff417
Binary files /dev/null and b/Client2016/content/textures/ui/expandPlayerList.png differ
diff --git a/Client2016/content/textures/ui/expandPlayerList@2x.png b/Client2016/content/textures/ui/expandPlayerList@2x.png
new file mode 100644
index 0000000..6766d2a
Binary files /dev/null and b/Client2016/content/textures/ui/expandPlayerList@2x.png differ
diff --git a/Client2016/content/textures/ui/homeButton.png b/Client2016/content/textures/ui/homeButton.png
new file mode 100644
index 0000000..0ad7744
Binary files /dev/null and b/Client2016/content/textures/ui/homeButton.png differ
diff --git a/Client2016/content/textures/ui/homeButton@2x.png b/Client2016/content/textures/ui/homeButton@2x.png
new file mode 100644
index 0000000..b0b5a0f
Binary files /dev/null and b/Client2016/content/textures/ui/homeButton@2x.png differ
diff --git a/Client2016/content/textures/ui/icon_BC-16.png b/Client2016/content/textures/ui/icon_BC-16.png
new file mode 100644
index 0000000..57f0ce1
Binary files /dev/null and b/Client2016/content/textures/ui/icon_BC-16.png differ
diff --git a/Client2016/content/textures/ui/icon_OBC-16.png b/Client2016/content/textures/ui/icon_OBC-16.png
new file mode 100644
index 0000000..3d9b177
Binary files /dev/null and b/Client2016/content/textures/ui/icon_OBC-16.png differ
diff --git a/Client2016/content/textures/ui/icon_TBC-16.png b/Client2016/content/textures/ui/icon_TBC-16.png
new file mode 100644
index 0000000..ea803fe
Binary files /dev/null and b/Client2016/content/textures/ui/icon_TBC-16.png differ
diff --git a/Client2016/content/textures/ui/icon_follower-16.png b/Client2016/content/textures/ui/icon_follower-16.png
new file mode 100644
index 0000000..f5c057a
Binary files /dev/null and b/Client2016/content/textures/ui/icon_follower-16.png differ
diff --git a/Client2016/content/textures/ui/icon_following-16.png b/Client2016/content/textures/ui/icon_following-16.png
new file mode 100644
index 0000000..3810904
Binary files /dev/null and b/Client2016/content/textures/ui/icon_following-16.png differ
diff --git a/Client2016/content/textures/ui/icon_friendrequestrecieved-16.png b/Client2016/content/textures/ui/icon_friendrequestrecieved-16.png
new file mode 100644
index 0000000..2e45d38
Binary files /dev/null and b/Client2016/content/textures/ui/icon_friendrequestrecieved-16.png differ
diff --git a/Client2016/content/textures/ui/icon_friendrequestsent_16.png b/Client2016/content/textures/ui/icon_friendrequestsent_16.png
new file mode 100644
index 0000000..fa7c6bd
Binary files /dev/null and b/Client2016/content/textures/ui/icon_friendrequestsent_16.png differ
diff --git a/Client2016/content/textures/ui/icon_friends_16.png b/Client2016/content/textures/ui/icon_friends_16.png
new file mode 100644
index 0000000..649067e
Binary files /dev/null and b/Client2016/content/textures/ui/icon_friends_16.png differ
diff --git a/Client2016/content/textures/ui/icon_mutualfollowing-16.png b/Client2016/content/textures/ui/icon_mutualfollowing-16.png
new file mode 100644
index 0000000..e08ba52
Binary files /dev/null and b/Client2016/content/textures/ui/icon_mutualfollowing-16.png differ
diff --git a/Client2016/content/textures/ui/icon_placeowner.png b/Client2016/content/textures/ui/icon_placeowner.png
new file mode 100644
index 0000000..1feb020
Binary files /dev/null and b/Client2016/content/textures/ui/icon_placeowner.png differ
diff --git a/Client2016/content/textures/ui/mouseLock_off.png b/Client2016/content/textures/ui/mouseLock_off.png
new file mode 100644
index 0000000..27b1272
Binary files /dev/null and b/Client2016/content/textures/ui/mouseLock_off.png differ
diff --git a/Client2016/content/textures/ui/mouseLock_off@2x.png b/Client2016/content/textures/ui/mouseLock_off@2x.png
new file mode 100644
index 0000000..4fdd594
Binary files /dev/null and b/Client2016/content/textures/ui/mouseLock_off@2x.png differ
diff --git a/Client2016/content/textures/ui/mouseLock_on.png b/Client2016/content/textures/ui/mouseLock_on.png
new file mode 100644
index 0000000..250c42a
Binary files /dev/null and b/Client2016/content/textures/ui/mouseLock_on.png differ
diff --git a/Client2016/content/textures/ui/mouseLock_on@2x.png b/Client2016/content/textures/ui/mouseLock_on@2x.png
new file mode 100644
index 0000000..9614f3e
Binary files /dev/null and b/Client2016/content/textures/ui/mouseLock_on@2x.png differ
diff --git a/Client2016/content/textures/ui/newBkg_square.png b/Client2016/content/textures/ui/newBkg_square.png
new file mode 100644
index 0000000..923826c
Binary files /dev/null and b/Client2016/content/textures/ui/newBkg_square.png differ
diff --git a/Client2016/content/textures/ui/newBkg_square@2x.png b/Client2016/content/textures/ui/newBkg_square@2x.png
new file mode 100644
index 0000000..ab0e64c
Binary files /dev/null and b/Client2016/content/textures/ui/newBkg_square@2x.png differ
diff --git a/Client2016/content/textures/ui/scroll-bottom.png b/Client2016/content/textures/ui/scroll-bottom.png
new file mode 100644
index 0000000..2db02a8
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-bottom.png differ
diff --git a/Client2016/content/textures/ui/scroll-bottom@2x.png b/Client2016/content/textures/ui/scroll-bottom@2x.png
new file mode 100644
index 0000000..713ade5
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-bottom@2x.png differ
diff --git a/Client2016/content/textures/ui/scroll-middle.png b/Client2016/content/textures/ui/scroll-middle.png
new file mode 100644
index 0000000..7ef7495
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-middle.png differ
diff --git a/Client2016/content/textures/ui/scroll-middle@2x.png b/Client2016/content/textures/ui/scroll-middle@2x.png
new file mode 100644
index 0000000..9162507
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-middle@2x.png differ
diff --git a/Client2016/content/textures/ui/scroll-top.png b/Client2016/content/textures/ui/scroll-top.png
new file mode 100644
index 0000000..2bcfd00
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-top.png differ
diff --git a/Client2016/content/textures/ui/scroll-top@2x.png b/Client2016/content/textures/ui/scroll-top@2x.png
new file mode 100644
index 0000000..50e5389
Binary files /dev/null and b/Client2016/content/textures/ui/scroll-top@2x.png differ
diff --git a/Client2016/content/textures/ui/scrollbar.png b/Client2016/content/textures/ui/scrollbar.png
new file mode 100644
index 0000000..9d7a4ff
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbar.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonDown.png b/Client2016/content/textures/ui/scrollbuttonDown.png
new file mode 100644
index 0000000..a3e6539
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonDown.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonDown_dn.png b/Client2016/content/textures/ui/scrollbuttonDown_dn.png
new file mode 100644
index 0000000..f7002ce
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonDown_dn.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonDown_ds.png b/Client2016/content/textures/ui/scrollbuttonDown_ds.png
new file mode 100644
index 0000000..eac4eb9
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonDown_ds.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonDown_ovr.png b/Client2016/content/textures/ui/scrollbuttonDown_ovr.png
new file mode 100644
index 0000000..f7002ce
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonDown_ovr.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonUp.png b/Client2016/content/textures/ui/scrollbuttonUp.png
new file mode 100644
index 0000000..5754f55
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonUp.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonUp_dn.png b/Client2016/content/textures/ui/scrollbuttonUp_dn.png
new file mode 100644
index 0000000..f12d690
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonUp_dn.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonUp_ds.png b/Client2016/content/textures/ui/scrollbuttonUp_ds.png
new file mode 100644
index 0000000..1e1b9db
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonUp_ds.png differ
diff --git a/Client2016/content/textures/ui/scrollbuttonUp_ovr.png b/Client2016/content/textures/ui/scrollbuttonUp_ovr.png
new file mode 100644
index 0000000..f12d690
Binary files /dev/null and b/Client2016/content/textures/ui/scrollbuttonUp_ovr.png differ
diff --git a/Client2016/content/textures/ui/slider_new_tab.png b/Client2016/content/textures/ui/slider_new_tab.png
new file mode 100644
index 0000000..8ecb85a
Binary files /dev/null and b/Client2016/content/textures/ui/slider_new_tab.png differ
diff --git a/Client2016/content/textures/ui/slider_new_tab@2x.png b/Client2016/content/textures/ui/slider_new_tab@2x.png
new file mode 100644
index 0000000..674c6ff
Binary files /dev/null and b/Client2016/content/textures/ui/slider_new_tab@2x.png differ
diff --git a/Client2016/content/textures/water_Subsurface.dds b/Client2016/content/textures/water_Subsurface.dds
new file mode 100644
index 0000000..0435f14
Binary files /dev/null and b/Client2016/content/textures/water_Subsurface.dds differ
diff --git a/Client2016/content/textures/water_Wave.dds b/Client2016/content/textures/water_Wave.dds
new file mode 100644
index 0000000..fc2f7a0
Binary files /dev/null and b/Client2016/content/textures/water_Wave.dds differ
diff --git a/Client2016/content/textures/wrench.png b/Client2016/content/textures/wrench.png
new file mode 100644
index 0000000..5c8213f
Binary files /dev/null and b/Client2016/content/textures/wrench.png differ
diff --git a/Client2016/d3dcompiler_47.dll b/Client2016/d3dcompiler_47.dll
new file mode 100644
index 0000000..e5bf5cf
Binary files /dev/null and b/Client2016/d3dcompiler_47.dll differ
diff --git a/Client2016/d3dx9_35.dll b/Client2016/d3dx9_35.dll
new file mode 100644
index 0000000..48e487b
Binary files /dev/null and b/Client2016/d3dx9_35.dll differ
diff --git a/Client2016/fmod64.dll b/Client2016/fmod64.dll
new file mode 100644
index 0000000..ee3f58f
Binary files /dev/null and b/Client2016/fmod64.dll differ
diff --git a/Client2016/openvr_api.dll b/Client2016/openvr_api.dll
new file mode 100644
index 0000000..8494ad3
Binary files /dev/null and b/Client2016/openvr_api.dll differ
diff --git a/Client2016/shaders/shaders.json b/Client2016/shaders/shaders.json
new file mode 100644
index 0000000..874ac86
--- /dev/null
+++ b/Client2016/shaders/shaders.json
@@ -0,0 +1,152 @@
+[
+ { "name": "AdornAALineVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornAALineVS"},
+ { "name": "AdornAALineFS", "source": "adorn.hlsl", "target": "ps_2_0", "entrypoint": "AdornAALinePS" },
+ { "name": "AdornVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornVS" },
+ { "name": "AdornSelfLitVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornSelfLitVS" },
+ { "name": "AdornSelfLitHighlightVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornSelfLitHighlightVS" },
+ { "name": "AdornLightingVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornVS", "defines": "PIN_LIGHTING" },
+ { "name": "AdornFS", "source": "adorn.hlsl", "target": "ps_2_0", "entrypoint": "AdornPS" },
+ { "name": "AdornOutlineVS", "source": "adorn.hlsl", "target": "vs_2_0", "entrypoint": "AdornOutlineVS"},
+ { "name": "AdornOutlineFS", "source": "adorn.hlsl", "target": "ps_2_0", "entrypoint": "AdornOutlinePS" },
+ { "name": "DefaultStaticVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS" },
+ { "name": "DefaultStaticHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_HQ" },
+ { "name": "DefaultSkinnedVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED" },
+ { "name": "DefaultSkinnedHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_HQ" },
+ { "name": "DefaultStaticDebugVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_DEBUG" },
+ { "name": "DefaultSkinnedDebugVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_DEBUG" },
+ { "name": "DefaultFS", "source": "default.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultHQFS", "source": "default.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultHQGBufferFS", "source": "default.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultStaticReflectionVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultSkinnedReflectionVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_REFLECTION" },
+ { "name": "DefaultStaticSurfaceHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SURFACE PIN_HQ" },
+ { "name": "DefaultSkinnedSurfaceHQVS", "source": "default.hlsl", "target": "vs_2_0", "entrypoint": "DefaultVS", "defines": "PIN_SKINNED PIN_SURFACE PIN_HQ" },
+
+ { "name": "LowQMaterialFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_LOWQMAT" },
+ { "name": "LowQMaterialWangFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_LOWQMAT PIN_WANG" },
+ { "name": "LowQMaterialWangFallbackFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_LOWQMAT PIN_WANG_FALLBACK" },
+
+ { "name": "DefaultShadowStaticVS", "source": "shadow.hlsl", "target": "vs_2_0", "entrypoint": "ShadowVS" },
+ { "name": "DefaultShadowSkinnedVS", "source": "shadow.hlsl", "target": "vs_2_0", "entrypoint": "ShadowVS", "defines": "PIN_SKINNED" },
+ { "name": "DefaultShadowFS", "source": "shadow.hlsl", "target": "ps_2_0", "entrypoint": "ShadowPS" },
+
+ { "name": "DefaultPlasticFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultNeonFS", "source": "neon.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultPlasticHQFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultPlasticHQGBufferFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultPlasticReflectionFS", "source": "plastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultPlasticReflectionHQFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ" },
+ { "name": "DefaultPlasticReflectionHQGBufferFS", "source": "plastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSmoothPlasticFS", "source": "smoothplastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS" },
+ { "name": "DefaultSmoothPlasticHQFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSmoothPlasticHQGBufferFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSmoothPlasticReflectionFS", "source": "smoothplastic.hlsl", "target": "ps_2_0", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION" },
+ { "name": "DefaultSmoothPlasticReflectionHQFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ" },
+ { "name": "DefaultSmoothPlasticReflectionHQGBufferFS", "source": "smoothplastic.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_REFLECTION PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultWoodHQFS", "source": "wood.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultWoodHQGBufferFS", "source": "wood.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultMarbleHQFS", "source": "marble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultMarbleHQGBufferFS", "source": "marble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSlateHQFS", "source": "slate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSlateHQGBufferFS", "source": "slate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultGraniteHQFS", "source": "granite.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultGraniteHQGBufferFS", "source": "granite.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultConcreteHQFS", "source": "concrete.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultConcreteHQGBufferFS", "source": "concrete.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultPebbleHQFS", "source": "pebble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultPebbleHQGBufferFS", "source": "pebble.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultBrickHQFS", "source": "brick.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultBrickHQGBufferFS", "source": "brick.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultRustHQFS", "source": "rust.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultRustHQGBufferFS", "source": "rust.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultDiamondplateHQFS", "source": "diamondplate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultDiamondplateHQGBufferFS", "source": "diamondplate.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultAluminumHQFS", "source": "aluminum.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultAluminumHQGBufferFS", "source": "aluminum.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultGrassHQFS", "source": "grass.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultGrassHQGBufferFS", "source": "grass.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultSandHQFS", "source": "sand.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultSandHQGBufferFS", "source": "sand.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultFabricHQFS", "source": "fabric.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultFabricHQGBufferFS", "source": "fabric.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultIceHQFS", "source": "ice.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultIceHQGBufferFS", "source": "ice.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultCobblestoneHQFS", "source": "cobblestone.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultCobblestoneHQGBufferFS", "source": "cobblestone.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultMetalHQFS", "source": "metal.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultMetalHQGBufferFS", "source": "metal.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultWoodPlanksHQFS", "source": "woodplanks.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultWoodPlanksHQGBufferFS", "source": "woodplanks.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+ { "name": "DefaultNeonHQFS", "source": "neon.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ" },
+ { "name": "DefaultNeonHQGBufferFS", "source": "neon.hlsl", "target": "ps_2_a", "entrypoint": "DefaultPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+
+ { "name": "MegaClusterVS", "source": "megacluster.hlsl", "target": "vs_2_0", "entrypoint": "MegaClusterVS" },
+ { "name": "MegaClusterHQVS", "source": "megacluster.hlsl", "target": "vs_2_0", "entrypoint": "MegaClusterVS", "defines": "PIN_HQ" },
+ { "name": "MegaClusterFS", "source": "megacluster.hlsl", "target": "ps_2_0", "entrypoint": "MegaClusterPS" },
+ { "name": "MegaClusterHQFS", "source": "megacluster.hlsl", "target": "ps_2_a", "entrypoint": "MegaClusterPS", "defines": "PIN_HQ" },
+ { "name": "MegaClusterHQGBufferFS", "source": "megacluster.hlsl", "target": "ps_2_a", "entrypoint": "MegaClusterPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+
+ { "name": "SmoothClusterVS", "source": "smoothcluster.hlsl", "target": "vs_2_0", "entrypoint": "TerrainVS" },
+ { "name": "SmoothClusterHQVS", "source": "smoothcluster.hlsl", "target": "vs_3_0", "entrypoint": "TerrainVS", "defines": "PIN_HQ" },
+ { "name": "SmoothClusterFS", "source": "smoothcluster.hlsl", "target": "ps_2_0", "entrypoint": "TerrainPS" },
+ { "name": "SmoothClusterHQFS", "source": "smoothcluster.hlsl", "target": "ps_3_0", "entrypoint": "TerrainPS", "defines": "PIN_HQ" },
+ { "name": "SmoothClusterHQGBufferFS", "source": "smoothcluster.hlsl", "target": "ps_3_0", "entrypoint": "TerrainPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+
+ { "name": "ParticleVS", "source": "particle.hlsl", "target": "vs_1_1", "entrypoint": "vs" },
+ { "name": "ParticleAddFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psAdd" },
+ { "name": "ParticleModulateFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psModulate" },
+ { "name": "ParticleCrazyFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psCrazy" },
+ { "name": "ParticleCrazySparklesFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psCrazySparkles" },
+
+ { "name": "ParticleCustomVS", "source": "particle.hlsl", "target": "vs_1_1", "entrypoint": "vsCustom" },
+ { "name": "ParticleCustomFS", "source": "particle.hlsl", "target": "ps_2_0", "entrypoint": "psCustom" },
+
+ { "name": "SkyVS", "source": "sky.hlsl", "target": "vs_1_1", "entrypoint": "SkyVS" },
+ { "name": "SkyFS", "source": "sky.hlsl", "target": "ps_2_0", "entrypoint": "SkyPS" },
+ { "name": "TexCompVS", "source": "texcomp.hlsl", "target": "vs_1_1", "entrypoint": "TexCompVS" },
+ { "name": "TexCompFS", "source": "texcomp.hlsl", "target": "ps_2_0", "entrypoint": "TexCompPS" },
+ { "name": "TexCompPMAFS", "source": "texcomp.hlsl", "target": "ps_2_0", "entrypoint": "TexCompPMAPS" },
+ { "name": "UIVS", "source": "ui.hlsl", "target": "vs_1_1", "entrypoint": "UIVS" },
+ { "name": "UIFogVS", "source": "ui.hlsl", "target": "vs_1_1", "entrypoint": "UIVS", "defines": "PIN_FOG" },
+ { "name": "UIFS", "source": "ui.hlsl", "target": "ps_2_0", "entrypoint": "UIPS" },
+ { "name": "UIFogFS", "source": "ui.hlsl", "target": "ps_2_0", "entrypoint": "UIPS", "defines": "PIN_FOG" },
+
+ { "name": "WaterVS", "source": "water.hlsl", "target": "vs_2_0", "entrypoint": "water_vs" },
+ { "name": "WaterHQVS", "source": "water.hlsl", "target": "vs_2_0", "entrypoint": "water_vs", "defines": "PIN_HQ" },
+ { "name": "WaterFS", "source": "water.hlsl", "target": "ps_2_0", "entrypoint": "water_ps" },
+ { "name": "WaterHQFS", "source": "water.hlsl", "target": "ps_2_a", "entrypoint": "water_ps", "defines": "PIN_HQ" },
+
+ { "name": "SmoothWaterVS", "source": "smoothwater.hlsl", "target": "vs_2_0", "entrypoint": "WaterVS" },
+ { "name": "SmoothWaterHQVS", "source": "smoothwater.hlsl", "target": "vs_3_0", "entrypoint": "WaterVS", "defines": "PIN_HQ" },
+ { "name": "SmoothWaterFS", "source": "smoothwater.hlsl", "target": "ps_2_0", "entrypoint": "WaterPS" },
+ { "name": "SmoothWaterHQFS", "source": "smoothwater.hlsl", "target": "ps_3_0", "entrypoint": "WaterPS", "defines": "PIN_HQ" },
+ { "name": "SmoothWaterHQGBufferFS", "source": "smoothwater.hlsl", "target": "ps_3_0", "entrypoint": "WaterPS", "defines": "PIN_HQ PIN_GBUFFER", "exclude": "glsles" },
+
+ { "name": "SSAOFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssao_ps", "exclude": "glsles" },
+ { "name": "SSAODepthDownVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoDepthDown_vs", "exclude": "glsles" },
+ { "name": "SSAODepthDownFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoDepthDown_ps", "exclude": "glsles" },
+ { "name": "SSAOBlurXVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoBlurX_vs", "exclude": "glsles" },
+ { "name": "SSAOBlurXFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoBlurX_ps", "exclude": "glsles" },
+ { "name": "SSAOBlurYVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoBlurY_vs", "exclude": "glsles" },
+ { "name": "SSAOBlurYFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoBlurY_ps", "exclude": "glsles" },
+ { "name": "SSAOCompositVS", "source": "ssao.hlsl", "target": "vs_1_1", "entrypoint": "ssaoComposit_vs", "exclude": "glsles" },
+ { "name": "SSAOCompositFS", "source": "ssao.hlsl", "target": "ps_2_a", "entrypoint": "ssaoComposit_ps", "exclude": "glsles" },
+
+ { "name": "PassThroughVS", "source": "screenspace.hlsl", "target": "vs_1_1", "entrypoint": "passThrough_vs"},
+ { "name": "PassThroughFS", "source": "screenspace.hlsl", "target": "ps_2_0", "entrypoint": "passThrough_ps"},
+ { "name": "GlowApplyFS", "source": "screenspace.hlsl", "target": "ps_2_a", "entrypoint": "glowApply_ps", "exclude": "glsles" },
+ { "name": "DownSample4x4VS", "source": "screenspace.hlsl", "target": "vs_1_1", "entrypoint": "downsample4x4_vs", "exclude": "glsles" },
+ { "name": "DownSample4x4GlowFS", "source": "screenspace.hlsl", "target": "ps_2_0", "entrypoint": "downSample4x4Glow_ps", "exclude": "glsles" },
+ { "name": "ShadowBlurFS", "source": "screenspace.hlsl", "target": "ps_2_0", "entrypoint": "ShadowBlurPS" },
+
+ { "name": "Blur3FS", "source": "screenspace.hlsl", "target": "ps_2_a", "entrypoint": "blur3_ps", "exclude": "glsles" },
+ { "name": "Blur5FS", "source": "screenspace.hlsl", "target": "ps_2_a", "entrypoint": "blur5_ps", "exclude": "glsles" },
+ { "name": "Blur7FS", "source": "screenspace.hlsl", "target": "ps_2_a", "entrypoint": "blur7_ps", "exclude": "glsles" },
+ { "name": "ImageProcessFS", "source": "screenspace.hlsl", "target": "ps_2_0", "entrypoint": "imageProcess_ps", "exclude": "glsles" },
+
+ { "name": "GBufferResolveVS", "source" : "gbuffer.hlsl", "target" : "vs_2_0", "entrypoint" : "gbufferVS" },
+ { "name": "GBufferResolveFS", "source" : "gbuffer.hlsl", "target" : "ps_2_0", "entrypoint" : "gbufferPS" },
+
+ { "name": "ProfilerVS", "source": "profiler.hlsl", "target": "vs_1_1", "entrypoint": "ProfilerVS" },
+ { "name": "ProfilerFS", "source": "profiler.hlsl", "target": "ps_2_0", "entrypoint": "ProfilerPS" }
+]
diff --git a/Client2016/shaders/shaders_d3d11.pack b/Client2016/shaders/shaders_d3d11.pack
new file mode 100644
index 0000000..e94eeaa
Binary files /dev/null and b/Client2016/shaders/shaders_d3d11.pack differ
diff --git a/Client2016/shaders/shaders_d3d11_durango.pack b/Client2016/shaders/shaders_d3d11_durango.pack
new file mode 100644
index 0000000..52d5392
Binary files /dev/null and b/Client2016/shaders/shaders_d3d11_durango.pack differ
diff --git a/Client2016/shaders/shaders_d3d9.pack b/Client2016/shaders/shaders_d3d9.pack
new file mode 100644
index 0000000..21eafb1
Binary files /dev/null and b/Client2016/shaders/shaders_d3d9.pack differ
diff --git a/Client2016/shaders/shaders_glsl.pack b/Client2016/shaders/shaders_glsl.pack
new file mode 100644
index 0000000..66b2a99
Binary files /dev/null and b/Client2016/shaders/shaders_glsl.pack differ
diff --git a/Client2016/shaders/shaders_glsl3.pack b/Client2016/shaders/shaders_glsl3.pack
new file mode 100644
index 0000000..cab9fea
Binary files /dev/null and b/Client2016/shaders/shaders_glsl3.pack differ
diff --git a/Client2016/shaders/shaders_glsles.pack b/Client2016/shaders/shaders_glsles.pack
new file mode 100644
index 0000000..940b565
Binary files /dev/null and b/Client2016/shaders/shaders_glsles.pack differ
diff --git a/Client2016/shaders/shaders_glsles3.pack b/Client2016/shaders/shaders_glsles3.pack
new file mode 100644
index 0000000..9f5f176
Binary files /dev/null and b/Client2016/shaders/shaders_glsles3.pack differ
diff --git a/Client2016/shaders/source/adorn.hlsl b/Client2016/shaders/source/adorn.hlsl
new file mode 100644
index 0000000..991e248
--- /dev/null
+++ b/Client2016/shaders/source/adorn.hlsl
@@ -0,0 +1,249 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float3 Normal : NORMAL0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+
+ float FogFactor : TEXCOORD1;
+};
+
+struct AALineVertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float4 Position : TEXCOORD1;
+ float4 Color : COLOR0;
+
+ float FogFactor : COLOR1;
+ float4 Start : TEXCOORD2;
+ float4 End : TEXCOORD3;
+};
+
+struct OutlineVertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float4 Color : COLOR0;
+ float4 Position : TEXCOORD0;
+
+ float4 CenterRadius : TEXCOORD1;
+};
+
+WORLD_MATRIX(WorldMatrix);
+
+uniform float4 Color;
+// pixel info is for AA line
+// x -> Fov * 0.5f / screenSize.y;
+// y -> ScreenWidth
+// z -> ScreenWidth / ScreenHeight
+// w -> Line thickness
+uniform float4 PixelInfo;
+
+
+VertexOutput AdornSelfLitVSGeneric(Appdata IN, float ambient)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+ float3 normal = normalize(mul((float3x3)WorldMatrix, IN.Normal));
+
+ float3 light = normalize(G(CameraPosition).xyz - position.xyz);
+ float ndotl = saturate(dot(normal, light));
+
+ float lighting = ambient + (1 - ambient) * ndotl;
+ float specular = pow(ndotl, 64.0);
+
+ OUT.HPosition = mul(G(ViewProjection), mul(WorldMatrix, IN.Position));
+ OUT.Uv = IN.Uv;
+ OUT.Color = float4(Color.rgb * lighting + specular, Color.a);
+
+ OUT.FogFactor = (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w;
+
+ return OUT;
+}
+
+VertexOutput AdornSelfLitVS(Appdata IN)
+{
+ return AdornSelfLitVSGeneric(IN, 0.5f);
+}
+
+VertexOutput AdornSelfLitHighlightVS(Appdata IN)
+{
+ return AdornSelfLitVSGeneric(IN, 0.75f);
+}
+
+VertexOutput AdornVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+
+#ifdef PIN_LIGHTING
+ float3 normal = normalize(mul((float3x3)WorldMatrix, IN.Normal));
+ float ndotl = dot(normal, -G(Lamp0Dir));
+ float3 lighting = G(AmbientColor) + saturate(ndotl) * G(Lamp0Color) + saturate(-ndotl) * G(Lamp1Color);
+#else
+ float3 lighting = 1;
+#endif
+
+ OUT.HPosition = mul(G(ViewProjection), position);
+ OUT.Uv = IN.Uv;
+ OUT.Color = float4(Color.rgb * lighting, Color.a);
+
+ OUT.FogFactor = (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w;
+
+ return OUT;
+}
+
+TEX_DECLARE2D(DiffuseMap, 0);
+
+float4 AdornPS(VertexOutput IN): COLOR0
+{
+ float4 result = tex2D(DiffuseMap, IN.Uv) * IN.Color;
+
+ result.rgb = lerp(G(FogColor), result.rgb, saturate(IN.FogFactor));
+
+ return result;
+}
+
+AALineVertexOutput AdornAALineVS(Appdata IN)
+{
+ AALineVertexOutput OUT = (AALineVertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+ float3 normal = normalize(mul((float3x3)WorldMatrix, IN.Normal));
+
+ // line start and end position in world space
+ float4 startPosW = mul(WorldMatrix, float4(1, 0, 0, 1));
+ float4 endPosW = mul(WorldMatrix, float4(-1, 0, 0, 1));
+
+ // Compute view-space w
+ float w = dot(G(ViewProjection)[3], float4(position.xyz, 1.0f));
+
+ // radius in pixels + constant because line has to be little bit bigget to perform anti aliasing
+ float radius = PixelInfo.w + 2;
+
+ // scale the way that line has same size on screen
+ if (length(position - startPosW) < length(position - endPosW))
+ {
+ float w = dot(G(ViewProjection)[3], float4(startPosW.xyz, 1.0f));
+ float pixel_radius = radius * w * PixelInfo.x;
+ position.xyz = startPosW.xyz + normal * pixel_radius;
+ }
+ else
+ {
+ float w = dot(G(ViewProjection)[3], float4(endPosW.xyz, 1.0f));
+ float pixel_radius = radius * w * PixelInfo.x;
+ position.xyz = endPosW.xyz + normal * pixel_radius;
+ }
+
+ // output for PS
+ OUT.HPosition = mul(G(ViewProjection), position);
+ OUT.Position = OUT.HPosition;
+ OUT.Start = mul(G(ViewProjection), startPosW);
+ OUT.End = mul(G(ViewProjection), endPosW);
+ OUT.FogFactor = (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w;
+
+ // screen ratio
+ OUT.Position.y *= PixelInfo.z;
+ OUT.Start.y *= PixelInfo.z;
+ OUT.End.y *= PixelInfo.z;
+
+ return OUT;
+}
+
+float4 AdornAALinePS(AALineVertexOutput IN): COLOR0
+{
+ IN.Position /= IN.Position.w ;
+ IN.Start /= IN.Start.w;
+ IN.End /= IN.End.w;
+
+ float4 result = 1;
+
+ float2 lineDir = normalize(IN.End.xy - IN.Start.xy);
+ float2 fragToPoint = IN.Position.xy - IN.Start.xy;
+
+ // tips of the line are not Anti-Aliesed, they are just cut
+ // discard as soon as we can
+ float startDist = dot(lineDir, fragToPoint);
+ float endDist = dot(lineDir, -IN.Position.xy + IN.End.xy);
+
+ if (startDist < 0)
+ discard;
+
+ if (endDist < 0)
+ discard;
+
+ float2 perpLineDir = float2(lineDir.y, -lineDir.x);
+
+ float dist = abs(dot(perpLineDir, fragToPoint));
+
+ // high point serves to compute the function which is described bellow.
+ float highPoint = 1 + (PixelInfo.w - 1) * 0.5;
+
+ // this is function that has this shape /¯¯¯\, it is symetric, centered around 0 on X axis
+ // slope parts are +- 45 degree and are 1px thick. Area of the shape sums to line thickness in pixels
+ // funtion for 1px would be /\, func for 2px is /¯\ and so on...
+ result.a = saturate(highPoint - (dist * 0.5 * PixelInfo.y));
+
+ result *= Color;
+
+ // convert to sRGB, its not perfect for non-black backgrounds, but its the best we can get
+ result.a = pow( saturate(1 - result.a), 1/2.2);
+ result.a = 1 - result.a;
+
+ result.rgb = lerp(G(FogColor), result.rgb, saturate(IN.FogFactor));
+ return result;
+
+}
+
+OutlineVertexOutput AdornOutlineVS(Appdata IN)
+{
+ OutlineVertexOutput OUT = (OutlineVertexOutput)0;
+
+ float4 position = mul(WorldMatrix, IN.Position);
+
+ OUT.HPosition = mul(G(ViewProjection), position);
+
+ OUT.Color = Color;
+ OUT.Position = position;
+
+ OUT.CenterRadius = float4(mul(WorldMatrix, float4(0, 0, 0, 1)).xyz, length(mul(WorldMatrix, float4(1, 0, 0, 0))));
+
+ return OUT;
+}
+
+float4 AdornOutlinePS(OutlineVertexOutput IN): COLOR0
+{
+ float3 rayO = IN.Position.xyz - IN.CenterRadius.xyz;
+ float3 rayD = normalize(IN.Position.xyz - G(CameraPosition));
+
+ // magnitude(rayO + t * rayD) = radius
+ // t^2 + bt + c = radius
+ float thickness = 1;
+
+ float r0 = IN.CenterRadius.w;
+ float r1 = max(0, IN.CenterRadius.w - thickness);
+
+ float b = 2 * dot(rayO, rayD);
+ float c0 = dot(rayO, rayO) - r0 * r0;
+ float c1 = dot(rayO, rayO) - r1 * r1;
+
+ if (b * b < 4 * c0)
+ discard;
+
+ if (b * b > 4 * c1)
+ discard;
+
+ return IN.Color;
+}
diff --git a/Client2016/shaders/source/aluminum.hlsl b/Client2016/shaders/source/aluminum.hlsl
new file mode 100644
index 0000000..f327503
--- /dev/null
+++ b/Client2016/shaders/source/aluminum.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0.6
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.94
+#define CFG_GLOSS_LOD 240
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0.75
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_DIFFUSE_CONST
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/brick.hlsl b/Client2016/shaders/source/brick.hlsl
new file mode 100644
index 0000000..4b9c574
--- /dev/null
+++ b/Client2016/shaders/source/brick.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.3
+#define CFG_GLOSS_SCALE 64
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.13
+#define CFG_GLOSS_LOD 44
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/cobblestone.hlsl b/Client2016/shaders/source/cobblestone.hlsl
new file mode 100644
index 0000000..560e18d
--- /dev/null
+++ b/Client2016/shaders/source/cobblestone.hlsl
@@ -0,0 +1,22 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 3
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.3
+
+#define CFG_SPECULAR_LOD 0.21
+#define CFG_GLOSS_LOD 22
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#define CFG_WANG_TILES
+#define CFG_WANG_TILES_SCALE 1
+
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/common.h b/Client2016/shaders/source/common.h
new file mode 100644
index 0000000..2fd3e6d
--- /dev/null
+++ b/Client2016/shaders/source/common.h
@@ -0,0 +1,252 @@
+#include "globals.h"
+
+// GLSLES has limited number of vertex shader registers so we have to use less bones
+#if defined(GLSLES) && !defined(GL3)
+#define MAX_BONE_COUNT 32
+#else
+#define MAX_BONE_COUNT 72
+#endif
+
+// PowerVR saturate() is compiled to min/max pair
+// These are cross-platform specialized saturates that are free on PC and only cost 1 cycle on PowerVR
+#ifdef GLSLES
+float saturate0(float v) { return max(v, 0); }
+float saturate1(float v) { return min(v, 1); }
+#define WANG_SUBSET_SCALE 2
+#else
+float saturate0(float v) { return saturate(v); }
+float saturate1(float v) { return saturate(v); }
+#define WANG_SUBSET_SCALE 1
+#endif
+
+#define GBUFFER_MAX_DEPTH 500.0f
+
+
+#ifndef DX11
+ #define TEX_DECLARE2D(name, reg) sampler2D name: register(s##reg)
+ #define TEX_DECLARE3D(name, reg) sampler3D name: register(s##reg)
+ #define TEX_DECLARECUBE(name, reg) samplerCUBE name: register(s##reg)
+
+ #define TEXTURE(name) name
+ #define TEXTURE_IN_2D(name) sampler2D name
+ #define TEXTURE_IN_3D(name) sampler3D name
+ #define TEXTURE_IN_CUBE(name) samplerCUBE name
+
+ #define WORLD_MATRIX(name) uniform float4x4 name;
+ #define WORLD_MATRIX_ARRAY(name, count) uniform float4 name [ count ];
+
+ #ifdef GLSL
+ #define ATTR_INT4 float4
+ #define ATTR_INT3 float3
+ #define ATTR_INT2 float2
+ #define ATTR_INT float
+ #else
+ #define ATTR_INT4 int4
+ #define ATTR_INT3 int3
+ #define ATTR_INT2 int2
+ #define ATTR_INT int
+ #endif
+#else
+ #define TEX_DECLARE2D(name, reg) SamplerState name##Sampler: register(s##reg); Texture2D name##Texture: register(t##reg)
+ #define TEX_DECLARE3D(name, reg) SamplerState name##Sampler: register(s##reg); Texture3D name##Texture: register(t##reg)
+ #define TEX_DECLARECUBE(name, reg) SamplerState name##Sampler: register(s##reg); TextureCube name##Texture: register(t##reg)
+
+ #define tex2D(tex, uv) tex##Texture.Sample(tex##Sampler, uv)
+ #define tex3D(tex, uv) tex##Texture.Sample(tex##Sampler, uv)
+ #define texCUBE(tex, uv) tex##Texture.Sample(tex##Sampler, uv)
+ #define tex2Dgrad(tex, uv, DDX, DDY) tex##Texture.SampleGrad(tex##Sampler, uv, DDX, DDY)
+ #define tex2Dbias(tex, uv) tex##Texture.SampleBias(tex##Sampler, uv.xy, uv.w)
+ #define texCUBEbias(tex, uv) tex##Texture.SampleBias(tex##Sampler, uv.xyz, uv.w)
+
+ #define TEXTURE(name) name##Sampler, name##Texture
+ #define TEXTURE_IN_2D(name) SamplerState name##Sampler, Texture2D name##Texture
+ #define TEXTURE_IN_3D(name) SamplerState name##Sampler, Texture3D name##Texture
+ #define TEXTURE_IN_CUBE(name) SamplerState name##Sampler, TextureCube name##Texture
+
+ #define WORLD_MATRIX(name) cbuffer WorldMatrixCB : register( b1 ) { float4x4 name; }
+ #define WORLD_MATRIX_ARRAY(name, count) cbuffer WorldMatrixCB : register( b1 ) { float4 name[ count ]; }
+
+ #define ATTR_INT4 int4
+ #define ATTR_INT3 int3
+ #define ATTR_INT2 int2
+ #define ATTR_INT int
+#endif
+
+#if defined(GLSLES) || defined(PIN_WANG_FALLBACK)
+ #define TEXTURE_WANG(name) 0
+ void getWang(float unused, float2 uv, float tiling, out float2 wangUv, out float4 wangUVDerivatives)
+ {
+ wangUv = uv * WANG_SUBSET_SCALE;
+ wangUVDerivatives = float4(0,0,0,0); // not used in this mode
+ }
+ float4 sampleWang(TEXTURE_IN_2D(s), float2 uv, float4 wangUVDerivatives)
+ {
+ return tex2D(s,uv);
+ }
+#else
+ #define TEXTURE_WANG(name) TEXTURE(name)
+ void getWang(TEXTURE_IN_2D(s), float2 uv, float tiling, out float2 wangUv, out float4 wangUVDerivatives)
+ {
+ #ifndef WIN_MOBILE
+ float idxTexSize = 128;
+ #else
+ float idxTexSize = 32;
+ #endif
+
+ float2 wangBase = uv * tiling * 4;
+
+ #if defined(DX11) && !defined(WIN_MOBILE)
+ // compensate the precision problem of Point Sampling on some cards. (We do it just at DX11 for performance reasons)
+ float2 wangUV = (floor(wangBase) + 0.5) / idxTexSize;
+ #else
+ float2 wangUV = wangBase / idxTexSize;
+ #endif
+
+ #if defined(DX11) || defined(GL3)
+ float2 wang = tex2D(s, wangUV).rg;
+ #else
+ float2 wang = tex2D(s, wangUV).ba;
+ #endif
+
+ wangUVDerivatives = float4(ddx(wangBase*0.25), ddy(wangBase*0.25));
+
+ wang *= 255.0/256.0;
+ wangUv = wang + frac(wangBase)*0.25;
+ }
+ float4 sampleWang(TEXTURE_IN_2D(s), float2 uv, float4 derivates)
+ {
+ return tex2Dgrad(s, uv, derivates.xy, derivates.zw);
+ }
+#endif
+
+float4 gbufferPack(float depth, float3 diffuse, float3 specular, float fog)
+{
+ depth = saturate(depth / GBUFFER_MAX_DEPTH);
+
+ const float3 bitSh = float3(255*255, 255, 1);
+ const float3 lumVec = float3(0.299, 0.587, 0.114);
+
+ float2 comp;
+ comp = depth*float2(255,255*256);
+ comp = frac(comp);
+ comp = float2(depth,comp.x*256/255) - float2(comp.x, comp.y)/255;
+
+ float4 result;
+
+ result.r = lerp(1, dot(specular, lumVec), saturate(3 * fog));
+ result.g = lerp(0, dot(diffuse, lumVec), saturate(3 * fog));
+ result.ba = comp.yx;
+
+ return result;
+}
+
+float3 lgridOffset(float3 v, float3 n)
+{
+ // cells are 4 studs in size
+ // offset in normal direction to prevent self-occlusion
+ // the offset has to be 1.5 cells in order to fully eliminate the influence of the source cell with trilinear filtering
+ // (i.e. 1 cell is enough for point filtering, but is not enough for trilinear filtering)
+ return v + n * (1.5f * 4.f);
+}
+
+float3 lgridPrepareSample(float3 c)
+{
+ // yxz swizzle is necessary for GLSLES sampling to work efficiently
+ // (having .y as the first component allows to do the LUT lookup as a non-dependent texture fetch)
+ return c.yxz * G(LightConfig0).xyz + G(LightConfig1).xyz;
+}
+
+#if defined(GLSLES) && !defined(GL3)
+#define LGRID_SAMPLER(name, register) TEX_DECLARE2D(name, register)
+
+float4 lgridSample(TEXTURE_IN_2D(t), TEXTURE_IN_2D(lut), float3 data)
+{
+ float4 offsets = tex2D(lut, data.xy);
+
+ // texture is 64 pixels high
+ // let's compute slice lerp coeff
+ float slicef = frac(data.x * 64);
+
+ // texture has 64 slices with 8x8 atlas setup
+ float2 base = saturate(data.yz) * 0.125;
+
+ float4 s0 = tex2D(t, base + offsets.xy);
+ float4 s1 = tex2D(t, base + offsets.zw);
+
+ return lerp(s0, s1, slicef);
+}
+#else
+#define LGRID_SAMPLER(name, register) TEX_DECLARE3D(name, register)
+
+float4 lgridSample(TEXTURE_IN_3D(t), TEXTURE_IN_2D(lut), float3 data)
+{
+ float3 edge = step(G(LightConfig3).xyz, abs(data - G(LightConfig2).xyz));
+ float edgef = saturate1(dot(edge, 1));
+
+ // replace data with 0 on edges to minimize texture cache misses
+ float4 light = tex3D(t, data.yzx - data.yzx * edgef);
+
+ return lerp(light, G(LightBorder), edgef);
+}
+#endif
+
+#ifdef GLSLES
+float3 nmapUnpack(float4 value)
+{
+ return value.rgb * 2 - 1;
+}
+#else
+float3 nmapUnpack(float4 value)
+{
+ float2 xy = value.ag * 2 - 1;
+
+ return float3(xy, sqrt(saturate(1 + dot(-xy, xy))));
+}
+#endif
+
+float3 terrainNormal(float4 tnp0, float4 tnp1, float4 tnp2, float3 w, float3 normal, float3 tsel)
+{
+ // Inspired by "Voxel-Based Terrain for Real-Time Virtual Simulations" [Lengyel2010] 5.5.2
+ float3 tangentTop = float3(normal.y, -normal.x, 0);
+ float3 tangentSide = float3(normal.z, 0, -normal.x);
+
+ float3 bitangentTop = float3(0, -normal.z, normal.y);
+ float3 bitangentSide = float3(0, -1, 0);
+
+ // Blend pre-unpack to save cycles
+ float3 tn = nmapUnpack(tnp0 * w.x + tnp1 * w.y + tnp2 * w.z);
+
+ // We blend all tangent frames together as a faster approximation to the correct world normal blend
+ float tselw = dot(tsel, w);
+
+ float3 tangent = lerp(tangentSide, tangentTop, tselw);
+ float3 bitangent = lerp(bitangentSide, bitangentTop, tselw);
+
+ return normalize(tangent * tn.x + bitangent * tn.y + normal * tn.z);
+}
+
+float3 shadowPrepareSample(float3 p)
+{
+ float4 c = float4(p, 1);
+
+ return float3(dot(G(ShadowMatrix0), c), dot(G(ShadowMatrix1), c), dot(G(ShadowMatrix2), c));
+}
+
+float shadowDepth(float3 lpos)
+{
+ return lpos.z;
+}
+
+float shadowStep(float d, float z)
+{
+ // saturate returns 1 for z in [0.1..0.9]; it fades to 0 as z approaches 0 or 1
+ return step(d, z) * saturate(9 - 20 * abs(z - 0.5));
+}
+
+float shadowSample(TEXTURE_IN_2D(map), float3 lpos, float lightShadow)
+{
+ float2 smDepth = tex2D(map, lpos.xy).rg;
+ float smShadow = shadowStep(smDepth.x, shadowDepth(lpos));
+
+ return (1 - smShadow * smDepth.y * G(OutlineBrightness_ShadowInfo).w) * lightShadow;
+}
diff --git a/Client2016/shaders/source/concrete.hlsl b/Client2016/shaders/source/concrete.hlsl
new file mode 100644
index 0000000..e068502
--- /dev/null
+++ b/Client2016/shaders/source/concrete.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.3
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.07
+#define CFG_GLOSS_LOD 22
+
+#define CFG_NORMAL_DETAIL_TILING 10
+#define CFG_NORMAL_DETAIL_SCALE 1
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/default.hlsl b/Client2016/shaders/source/default.hlsl
new file mode 100644
index 0000000..60058df
--- /dev/null
+++ b/Client2016/shaders/source/default.hlsl
@@ -0,0 +1,329 @@
+#include "common.h"
+
+#define LQMAT_FADE_FACTOR (1.0f/300.0f)
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float2 Uv : TEXCOORD0;
+ float2 UvStuds : TEXCOORD1;
+
+ float4 Color : COLOR0;
+ ATTR_INT4 Extra : COLOR1;
+
+#ifdef PIN_SURFACE
+ float3 Tangent : TEXCOORD2;
+#endif
+ float4 EdgeDistances : TEXCOORD3;
+};
+
+struct VertexOutput
+{
+ float4 Uv_EdgeDistance1 : TEXCOORD0;
+ float4 UvStuds_EdgeDistance2 : TEXCOORD1;
+
+ float4 Color : COLOR0;
+ float4 LightPosition_Fog : TEXCOORD2;
+
+ float4 View_Depth : TEXCOORD3;
+ #if defined(PIN_HQ) || defined(PIN_REFLECTION)
+ float4 Normal_SpecPower : TEXCOORD4;
+ #endif
+
+ #ifdef PIN_SURFACE
+ float3 Tangent : TEXCOORD5;
+ #else
+ float4 Diffuse_Specular : COLOR1;
+ #endif
+
+ float4 PosLightSpace_Reflectance: TEXCOORD6;
+};
+
+#ifdef PIN_SKINNED
+ WORLD_MATRIX_ARRAY(WorldMatrixArray, MAX_BONE_COUNT * 3);
+#endif
+
+#ifdef PIN_DEBUG
+uniform float4 DebugColor;
+#endif
+
+VertexOutput DefaultVS(Appdata IN, out float4 HPosition: POSITION)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ // Transform position and normal to world space
+#ifdef PIN_SKINNED
+ int boneIndex = IN.Extra.r;
+
+ float4 worldRow0 = WorldMatrixArray[boneIndex * 3 + 0];
+ float4 worldRow1 = WorldMatrixArray[boneIndex * 3 + 1];
+ float4 worldRow2 = WorldMatrixArray[boneIndex * 3 + 2];
+
+ float3 posWorld = float3(dot(worldRow0, IN.Position), dot(worldRow1, IN.Position), dot(worldRow2, IN.Position));
+ float3 normalWorld = float3(dot(worldRow0.xyz, IN.Normal), dot(worldRow1.xyz, IN.Normal), dot(worldRow2.xyz, IN.Normal));
+#else
+ float3 posWorld = IN.Position.xyz;
+ float3 normalWorld = IN.Normal;
+#endif
+
+ // Decode diffuse/specular parameters; encoding depends on the skinned flag due to vertex declaration differences
+#if defined(PIN_DEBUG)
+ float4 color = DebugColor;
+#else
+ float4 color = IN.Color;
+#endif
+
+ float specularIntensity = IN.Extra.g / 255.f;
+ float specularPower = IN.Extra.b;
+
+ float ndotl = dot(normalWorld, -G(Lamp0Dir));
+
+#ifdef PIN_HQ
+ // We'll calculate specular in pixel shader
+ float2 lt = float2(saturate(ndotl), (ndotl > 0));
+#else
+ // Using lit here improves performance on software vertex shader implementations
+ float2 lt = lit(ndotl, dot(normalize(-G(Lamp0Dir) + normalize(G(CameraPosition).xyz - posWorld.xyz)), normalWorld), specularPower).yz;
+#endif
+
+ HPosition = mul(G(ViewProjection), float4(posWorld, 1));
+
+ OUT.Uv_EdgeDistance1.xy = IN.Uv;
+ OUT.UvStuds_EdgeDistance2.xy = IN.UvStuds;
+
+ OUT.Color = color;
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - HPosition.w) * G(FogParams).w);
+
+ OUT.View_Depth = float4(G(CameraPosition).xyz - posWorld, HPosition.w);
+
+ #if defined(PIN_HQ) || defined(PIN_REFLECTION)
+ float4 edgeDistances = IN.EdgeDistances*G(FadeDistance_GlowFactor).z + 0.5 * OUT.View_Depth.w * G(FadeDistance_GlowFactor).y;
+
+ OUT.Uv_EdgeDistance1.zw = edgeDistances.xy;
+ OUT.UvStuds_EdgeDistance2.zw = edgeDistances.zw;
+ OUT.Normal_SpecPower = float4(normalWorld, specularPower);
+ OUT.PosLightSpace_Reflectance.w = IN.Extra.a / 255.f;
+ #endif
+
+ #ifdef PIN_SURFACE
+ #ifdef PIN_SKINNED
+ float3 tangent = float3(dot(worldRow0.xyz, IN.Tangent), dot(worldRow1.xyz, IN.Tangent), dot(worldRow2.xyz, IN.Tangent));
+ #else
+ float3 tangent = IN.Tangent;
+ #endif
+
+ OUT.Tangent = tangent;
+ #else
+ float3 diffuse = lt.x * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
+
+ OUT.Diffuse_Specular = float4(diffuse, lt.y * specularIntensity);
+ #endif
+
+ OUT.PosLightSpace_Reflectance.xyz = shadowPrepareSample(posWorld);
+
+ return OUT;
+}
+
+#ifdef PIN_SURFACE
+struct SurfaceInput
+{
+ float4 Color;
+ float2 Uv;
+ float2 UvStuds;
+
+#ifdef PIN_REFLECTION
+ float Reflectance;
+#endif
+};
+
+struct Surface
+{
+ float3 albedo;
+ float3 normal;
+ float specular;
+ float gloss;
+ float reflectance;
+};
+
+Surface surfaceShader(SurfaceInput IN, float2 fade);
+
+Surface surfaceShaderExec(VertexOutput IN)
+{
+ SurfaceInput SIN;
+ SIN.Color = IN.Color;
+ SIN.Uv = IN.Uv_EdgeDistance1.xy;
+ SIN.UvStuds = IN.UvStuds_EdgeDistance2.xy;
+
+ #ifdef PIN_REFLECTION
+ SIN.Reflectance = IN.PosLightSpace_Reflectance.w;
+ #endif
+
+ float2 fade;
+ fade.x = saturate0(1 - IN.View_Depth.w * LQMAT_FADE_FACTOR );
+ fade.y = saturate0(1 - IN.View_Depth.w * G(FadeDistance_GlowFactor).y );
+
+ return surfaceShader(SIN, fade);
+}
+#endif
+
+TEX_DECLARE2D(StudsMap, 0);
+
+LGRID_SAMPLER(LightMap, 1);
+TEX_DECLARE2D(LightMapLookup, 2);
+
+TEX_DECLARE2D(ShadowMap, 3);
+
+TEX_DECLARECUBE(EnvironmentMap, 4);
+
+TEX_DECLARE2D(DiffuseMap, 5);
+TEX_DECLARE2D(NormalMap, 6);
+TEX_DECLARE2D(SpecularMap, 7);
+
+#ifndef GLSLES
+TEX_DECLARE2D(NormalDetailMap, 8);
+#endif
+
+uniform float4 LqmatFarTilingFactor; // material tiling factor for low-quality shader, must be the same as CFG_FAR_TILING
+
+
+float4 sampleFar1(TEXTURE_IN_2D(s), float2 uv, float fade, float cutoff)
+{
+#ifdef GLSLES
+ return tex2D(s, uv);
+#else
+ if (cutoff == 0)
+ return tex2D(s, uv);
+ else
+ {
+ float cscale = 1 / (1 - cutoff);
+
+ return lerp(tex2D(s, uv * (LqmatFarTilingFactor.xy) ), tex2D(s, uv ), saturate0(fade * cscale - cutoff * cscale));
+ }
+#endif
+}
+
+#if defined(PIN_WANG) || defined(PIN_WANG_FALLBACK)
+float4 sampleWangSimple(TEXTURE_IN_2D(s), float2 uv)
+{
+ float2 wangUv;
+ float4 wangUVDerivatives;
+ getWang(TEXTURE_WANG(NormalDetailMap), uv, 1, wangUv, wangUVDerivatives);
+ return sampleWang(TEXTURE(s), wangUv, wangUVDerivatives);
+}
+#endif
+
+void DefaultPS(VertexOutput IN,
+#ifdef PIN_GBUFFER
+ out float4 oColor1: COLOR1,
+#endif
+ out float4 oColor0: COLOR0)
+{
+ // Compute albedo term
+#ifdef PIN_SURFACE
+ Surface surface = surfaceShaderExec(IN);
+
+ float4 albedo = float4(surface.albedo, IN.Color.a);
+
+ float3 bitangent = cross(IN.Normal_SpecPower.xyz, IN.Tangent.xyz);
+ float3 normal = normalize(surface.normal.x * IN.Tangent.xyz + surface.normal.y * bitangent + surface.normal.z * IN.Normal_SpecPower.xyz);
+
+ float ndotl = dot(normal, -G(Lamp0Dir));
+
+ float3 diffuseIntensity = saturate0(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
+ float specularIntensity = step(0, ndotl) * surface.specular;
+ float specularPower = surface.gloss;
+
+ float reflectance = surface.reflectance;
+#elif PIN_LOWQMAT
+
+#ifndef CFG_FAR_DIFFUSE_CUTOFF
+#define CFG_FAR_DIFFUSE_CUTOFF (0.6f)
+#endif
+
+#if defined(PIN_WANG) || defined(PIN_WANG_FALLBACK)
+ float4 albedo = sampleWangSimple(TEXTURE(DiffuseMap), IN.Uv_EdgeDistance1.xy);
+#else
+ float fade = saturate0(1 - IN.View_Depth.w * LQMAT_FADE_FACTOR);
+ float4 albedo = sampleFar1(TEXTURE(DiffuseMap), IN.Uv_EdgeDistance1.xy, fade, CFG_FAR_DIFFUSE_CUTOFF);
+#endif
+
+ albedo.rgb = lerp(float3(1, 1, 1), IN.Color.rgb, albedo.a ) * albedo.rgb;
+ albedo.a = IN.Color.a;
+
+ float3 diffuseIntensity = IN.Diffuse_Specular.xyz;
+ float specularIntensity = IN.Diffuse_Specular.w;
+ float reflectance = 0;
+
+#else
+ #ifdef PIN_PLASTIC
+ float4 studs = tex2D(StudsMap, IN.UvStuds_EdgeDistance2.xy);
+ float4 albedo = float4(IN.Color.rgb * (studs.r * 2), IN.Color.a);
+ #else
+ float4 albedo = tex2D(DiffuseMap, IN.Uv_EdgeDistance1.xy) * IN.Color;
+ #endif
+
+ #ifdef PIN_HQ
+ float3 normal = normalize(IN.Normal_SpecPower.xyz);
+ float specularPower = IN.Normal_SpecPower.w;
+ #elif defined(PIN_REFLECTION)
+ float3 normal = IN.Normal_SpecPower.xyz;
+ #endif
+
+ float3 diffuseIntensity = IN.Diffuse_Specular.xyz;
+ float specularIntensity = IN.Diffuse_Specular.w;
+
+ #ifdef PIN_REFLECTION
+ float reflectance = IN.PosLightSpace_Reflectance.w;
+ #endif
+
+#endif
+
+ float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
+ float shadow = shadowSample(TEXTURE(ShadowMap), IN.PosLightSpace_Reflectance.xyz, light.a);
+
+ // Compute reflection term
+#if defined(PIN_SURFACE) || defined(PIN_REFLECTION)
+ float3 reflection = texCUBE(EnvironmentMap, reflect(-IN.View_Depth.xyz, normal)).rgb;
+
+ albedo.rgb = lerp(albedo.rgb, reflection.rgb, reflectance);
+#endif
+
+ // Compute diffuse term
+ float3 diffuse = (G(AmbientColor) + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
+
+ // Compute specular term
+#ifdef PIN_HQ
+ float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + normalize(IN.View_Depth.xyz)))), specularPower));
+#else
+ float3 specular = G(Lamp0Color) * (specularIntensity * shadow);
+#endif
+
+ // Combine
+ oColor0.rgb = diffuse.rgb + specular.rgb;
+ oColor0.a = albedo.a;
+
+#ifdef PIN_HQ
+ float ViewDepthMul = IN.View_Depth.w * G(FadeDistance_GlowFactor).y;
+ float outlineFade = saturate1( ViewDepthMul * G(OutlineBrightness_ShadowInfo).x + G(OutlineBrightness_ShadowInfo).y);
+ float2 minIntermediate = min(IN.Uv_EdgeDistance1.wz, IN.UvStuds_EdgeDistance2.wz);
+ float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / ViewDepthMul;
+ oColor0.rgb *= saturate1(outlineFade *(1.5 - minEdgesPlus) + minEdgesPlus);
+#endif
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+#ifdef PIN_NEON
+ oColor0.rgb = IN.Color.rgb * G(FadeDistance_GlowFactor).w;
+ oColor0.a = 1 - fogAlpha * IN.Color.a;
+ diffuse.rgb = 0;
+ specular.rgb = 0;
+#endif
+
+ oColor0.rgb = lerp(G(FogColor), oColor0.rgb, fogAlpha);
+
+#ifdef PIN_GBUFFER
+ oColor1 = gbufferPack(IN.View_Depth.w, diffuse.rgb, specular.rgb, fogAlpha);
+#endif
+
+}
diff --git a/Client2016/shaders/source/diamondplate.hlsl b/Client2016/shaders/source/diamondplate.hlsl
new file mode 100644
index 0000000..6b0c8f8
--- /dev/null
+++ b/Client2016/shaders/source/diamondplate.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2.7
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.9
+#define CFG_GLOSS_LOD 160
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/fabric.hlsl b/Client2016/shaders/source/fabric.hlsl
new file mode 100644
index 0000000..86a06e0
--- /dev/null
+++ b/Client2016/shaders/source/fabric.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.2
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.2
+
+#define CFG_SPECULAR_LOD 0.03
+#define CFG_GLOSS_LOD 16
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/gbuffer.hlsl b/Client2016/shaders/source/gbuffer.hlsl
new file mode 100644
index 0000000..b3b710c
--- /dev/null
+++ b/Client2016/shaders/source/gbuffer.hlsl
@@ -0,0 +1,52 @@
+#include "common.h"
+
+// .xy = gbuffer width/height, .zw = inverse gbuffer width/height
+uniform float4 TextureSize;
+
+TEX_DECLARE2D(tex, 0);
+
+struct v2f
+{
+ float4 pos : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+#if defined(GLSL) || defined(DX11)
+float4 convertPosition(float4 p)
+{
+ return p;
+}
+#else
+float4 convertPosition(float4 p)
+{
+ // half-pixel offset
+ return p + float4(-TextureSize.z, TextureSize.w, 0, 0);
+}
+#endif
+
+#if defined(GLSL)
+float2 convertUv(float4 p)
+{
+ return p.xy * 0.5 + 0.5;
+}
+#else
+float2 convertUv(float4 p)
+{
+ return p.xy * float2(0.5, -0.5) + 0.5;
+}
+#endif
+
+
+v2f gbufferVS( in float4 pos : POSITION )
+{
+ v2f o;
+ o.pos = convertPosition(pos);
+ o.uv = convertUv(pos);
+ return o;
+}
+
+
+float4 gbufferPS( v2f i ) : COLOR0
+{
+ return tex2D( tex, i.uv );
+}
diff --git a/Client2016/shaders/source/globals.h b/Client2016/shaders/source/globals.h
new file mode 100644
index 0000000..e4f3621
--- /dev/null
+++ b/Client2016/shaders/source/globals.h
@@ -0,0 +1,44 @@
+#ifndef GLSL
+struct Globals
+{
+#endif
+ float4x4 ViewProjection;
+
+ float4 ViewRight;
+ float4 ViewUp;
+ float4 ViewDir;
+ float3 CameraPosition;
+
+ float3 AmbientColor;
+ float3 Lamp0Color;
+ float3 Lamp0Dir;
+ float3 Lamp1Color;
+
+ float3 FogColor;
+ float4 FogParams;
+
+ float4 LightBorder;
+ float4 LightConfig0;
+ float4 LightConfig1;
+ float4 LightConfig2;
+ float4 LightConfig3;
+
+ float4 FadeDistance_GlowFactor;
+ float4 OutlineBrightness_ShadowInfo;
+
+ float4 ShadowMatrix0;
+ float4 ShadowMatrix1;
+ float4 ShadowMatrix2;
+#ifndef GLSL
+};
+
+#ifdef DX11
+cbuffer Globals: register( b0 ) { Globals _G; };
+#else
+uniform Globals _G: register(c0);
+#endif
+
+#define G(x) _G.x
+#else
+#define G(x) x
+#endif
diff --git a/Client2016/shaders/source/granite.hlsl b/Client2016/shaders/source/granite.hlsl
new file mode 100644
index 0000000..39541a7
--- /dev/null
+++ b/Client2016/shaders/source/granite.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.5
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0.2
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.19
+#define CFG_GLOSS_LOD 24
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.6
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/grass.hlsl b/Client2016/shaders/source/grass.hlsl
new file mode 100644
index 0000000..7b4480a
--- /dev/null
+++ b/Client2016/shaders/source/grass.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.17
+#define CFG_GLOSS_LOD 18
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.6
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/ice.hlsl b/Client2016/shaders/source/ice.hlsl
new file mode 100644
index 0000000..493698a
--- /dev/null
+++ b/Client2016/shaders/source/ice.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1.0
+#define CFG_SPECULAR_SCALE 1.2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0.3
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 1
+#define CFG_GLOSS_LOD 190
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0.75
+
+#define CFG_OPT_DIFFUSE_CONST
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/marble.hlsl b/Client2016/shaders/source/marble.hlsl
new file mode 100644
index 0000000..4447ca8
--- /dev/null
+++ b/Client2016/shaders/source/marble.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1.0
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0.2
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+#define CFG_SPECULAR_LOD 0.7
+#define CFG_GLOSS_LOD 54
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_NORMAL_CONST
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/material.hlsl b/Client2016/shaders/source/material.hlsl
new file mode 100644
index 0000000..17dc3ed
--- /dev/null
+++ b/Client2016/shaders/source/material.hlsl
@@ -0,0 +1,100 @@
+#define PIN_SURFACE
+#include "default.hlsl"
+
+#ifndef CFG_WANG_TILES
+float4 sampleFar(TEXTURE_IN_2D(s), float2 uv, float fade, float cutoff)
+{
+#ifdef GLSLES
+ return tex2D(s, uv);
+#else
+ if (cutoff == 0)
+ return tex2D(s, uv);
+ else
+ {
+ float cscale = 1 / (1 - cutoff);
+
+ return lerp(tex2D(s, uv * (CFG_FAR_TILING) ), tex2D(s, uv ), saturate0(fade * cscale - cutoff * cscale));
+ }
+#endif
+}
+#endif
+
+Surface surfaceShader(SurfaceInput IN, float2 fade2)
+{
+#ifdef CFG_WANG_TILES
+ float2 wangUv;
+ float4 wangUVDerivatives;
+ getWang(TEXTURE_WANG(NormalDetailMap), IN.Uv, CFG_TEXTURE_TILING, wangUv, wangUVDerivatives);
+#endif
+
+ float2 uv = IN.Uv * (CFG_TEXTURE_TILING);
+
+ float fadeDiffuse = fade2.x;
+ float fade = fade2.y;
+
+#ifdef CFG_OPT_DIFFUSE_CONST
+ float4 diffuse = 1;
+#else
+
+ #ifdef CFG_WANG_TILES
+ float4 diffuse = sampleWang(TEXTURE(DiffuseMap), wangUv, wangUVDerivatives);
+ #else
+ float4 diffuse = sampleFar(TEXTURE(DiffuseMap), uv, fadeDiffuse, CFG_FAR_DIFFUSE_CUTOFF);
+ #endif
+
+ diffuse.rgba = diffuse.rgba * (CFG_DIFFUSE_SCALE);
+
+#endif
+
+#ifdef CFG_OPT_NORMAL_CONST
+ float3 normal = float3(0, 0, 1);
+#else
+ #ifdef CFG_WANG_TILES
+ float3 normal = nmapUnpack(sampleWang(TEXTURE(NormalMap), wangUv, wangUVDerivatives));
+ #else
+ float3 normal = nmapUnpack(sampleFar(TEXTURE(NormalMap), uv, fade, CFG_FAR_NORMAL_CUTOFF));
+ #endif
+#endif
+
+#ifndef GLSLES
+ #ifndef CFG_WANG_TILES // normal detail unavailable when running wang tiles
+ float3 normalDetail = nmapUnpack(tex2D(NormalDetailMap, uv * (CFG_NORMAL_DETAIL_TILING)));
+ normal.xy += normalDetail.xy * (CFG_NORMAL_DETAIL_SCALE);
+ #endif
+#endif
+
+ normal.xy *= fade;
+
+ float shadowFactor = 1 + normal.x * (CFG_NORMAL_SHADOW_SCALE);
+
+#ifdef CFG_OPT_BLEND_COLOR
+ float3 albedo = lerp(float3(1, 1, 1), IN.Color.rgb, diffuse.a) * diffuse.rgb * shadowFactor;
+#else
+ float3 albedo = IN.Color.rgb * diffuse.rgb * shadowFactor;
+#endif
+
+#ifndef GLSLES
+ float4 studs = tex2D(StudsMap, IN.UvStuds);
+
+ albedo *= studs.r * 2;
+#endif
+
+#ifdef CFG_WANG_TILES
+ float2 specular = sampleWang(TEXTURE(SpecularMap), wangUv, wangUVDerivatives).rg;
+#else
+ float2 specular = sampleFar(TEXTURE(SpecularMap), uv, fade, CFG_FAR_SPECULAR_CUTOFF).rg;
+#endif
+
+ // make sure glossiness is never 0 to avoid fp specials
+ float2 specbase = specular * float2(CFG_SPECULAR_SCALE, CFG_GLOSS_SCALE) + float2(0, 0.01);
+ float2 specfade = lerp(float2(CFG_SPECULAR_LOD, CFG_GLOSS_LOD), specbase, fade);
+
+ Surface surface = (Surface)0;
+ surface.albedo = albedo;
+ surface.normal = normal;
+ surface.specular = specfade.r;
+ surface.gloss = specfade.g;
+ surface.reflectance = specular.g * fade * (CFG_REFLECTION_SCALE);
+
+ return surface;
+}
diff --git a/Client2016/shaders/source/megacluster.hlsl b/Client2016/shaders/source/megacluster.hlsl
new file mode 100644
index 0000000..7b7d369
--- /dev/null
+++ b/Client2016/shaders/source/megacluster.hlsl
@@ -0,0 +1,151 @@
+#include "common.h"
+
+struct Appdata
+{
+ ATTR_INT4 Position : POSITION;
+ ATTR_INT3 Normal : NORMAL;
+ ATTR_INT4 Uv : TEXCOORD0;
+#ifdef PIN_HQ
+ ATTR_INT4 EdgeDistances : TEXCOORD1;
+ ATTR_INT3 Tangent : TEXCOORD2;
+#endif
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float4 UvHigh_EdgeDistance1 : TEXCOORD0;
+ float4 UvLow_EdgeDistance2 : TEXCOORD1;
+
+ float4 LightPosition_Fog : TEXCOORD2;
+
+#ifdef PIN_HQ
+ float4 View_Depth : TEXCOORD3;
+ float4 Normal_Blend : TEXCOORD4;
+ float3 Tangent : TEXCOORD5;
+#else
+ float4 Diffuse_Blend : COLOR0;
+#endif
+
+ float3 PosLightSpace : TEXCOORD7;
+};
+
+WORLD_MATRIX(WorldMatrix);
+
+VertexOutput MegaClusterVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ // Decode vertex data
+ float3 Normal = (IN.Normal - 127.0) / 127.0;
+ float4 UV = IN.Uv / 2048.0;
+
+ // Transform position and normal to world space
+ // Note: world matrix does not contain rotation/scale for static geometry so we can avoid transforming normal
+ float3 posWorld = mul(WorldMatrix, IN.Position).xyz;
+ float3 normalWorld = Normal;
+
+ OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
+
+ float blend = OUT.HPosition.w / 200;
+
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w);
+
+ OUT.UvHigh_EdgeDistance1.xy = UV.xy;
+ OUT.UvLow_EdgeDistance2.xy = UV.zw;
+
+#ifdef PIN_HQ
+ OUT.View_Depth = float4(posWorld, OUT.HPosition.w * G(FadeDistance_GlowFactor).y);
+ float4 edgeDistances = IN.EdgeDistances*G(FadeDistance_GlowFactor).z + 0.5 * OUT.View_Depth.w;
+
+ OUT.UvHigh_EdgeDistance1.zw = edgeDistances.xy;
+ OUT.UvLow_EdgeDistance2.zw = edgeDistances.zw;
+
+ OUT.View_Depth.xyz = G(CameraPosition).xyz - posWorld;
+ OUT.Normal_Blend = float4(Normal, blend);
+ // decode tangent
+ OUT.Tangent = (IN.Tangent - 127.0) / 127.0;
+#else
+ // IF LQ shading is performed in VS
+ float ndotl = dot(normalWorld, -G(Lamp0Dir));
+ float3 diffuse = saturate(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
+
+ OUT.Diffuse_Blend = float4(diffuse, blend);
+#endif
+
+ OUT.PosLightSpace = shadowPrepareSample(posWorld);
+
+ return OUT;
+}
+
+TEX_DECLARE2D(DiffuseHighMap, 0);
+TEX_DECLARE2D(DiffuseLowMap, 1);
+TEX_DECLARE2D(NormalMap, 2);
+TEX_DECLARE2D(SpecularMap, 3);
+LGRID_SAMPLER(LightMap, 4);
+TEX_DECLARE2D(LightMapLookup, 5);
+TEX_DECLARE2D(ShadowMap, 6);
+
+void MegaClusterPS(VertexOutput IN,
+#ifdef PIN_GBUFFER
+ out float4 oColor1: COLOR1,
+#endif
+ out float4 oColor0: COLOR0)
+{
+ float4 high = tex2D(DiffuseHighMap, IN.UvHigh_EdgeDistance1.xy);
+ float4 low = tex2D(DiffuseLowMap, IN.UvLow_EdgeDistance2.xy);
+
+ float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
+ float shadow = shadowSample(TEXTURE(ShadowMap), IN.PosLightSpace, light.a);
+
+#ifdef PIN_HQ
+ float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Normal_Blend.a));
+
+ // sample normal map and specular map
+ float4 normalMapSample = tex2D(NormalMap, IN.UvHigh_EdgeDistance1.xy);
+ float4 specularMapSample = tex2D(SpecularMap, IN.UvHigh_EdgeDistance1.xy);
+
+ // compute bitangent and world space normal
+ float3 bitangent = cross(IN.Normal_Blend.xyz, IN.Tangent.xyz);
+ float3 nmap = nmapUnpack(normalMapSample);
+ float3 normal = normalize(nmap.x * IN.Tangent.xyz + nmap.y * bitangent + nmap.z * IN.Normal_Blend.xyz);
+
+ float ndotl = dot(normal, -G(Lamp0Dir));
+ float3 diffuseIntensity = saturate0(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
+ float specularIntensity = step(0, ndotl) * specularMapSample.r;
+ float specularPower = specularMapSample.g * 255 + 0.01;
+
+ // Compute diffuse and specular and combine them
+ float3 diffuse = (G(AmbientColor) + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
+ float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + normalize(IN.View_Depth.xyz)))), specularPower));
+ oColor0.rgb = diffuse + specular;
+
+ // apply outlines
+ float outlineFade = saturate1(IN.View_Depth.w * G(OutlineBrightness_ShadowInfo).x + G(OutlineBrightness_ShadowInfo).y);
+ float2 minIntermediate = min(IN.UvHigh_EdgeDistance1.wz, IN.UvLow_EdgeDistance2.wz);
+ float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / IN.View_Depth.w;
+ oColor0.rgb *= saturate1(outlineFade * (1.5 - minEdgesPlus) + minEdgesPlus);
+
+ oColor0.a = 1;
+
+#else
+ float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Diffuse_Blend.a));
+
+ // Compute diffuse term
+ float3 diffuse = (G(AmbientColor) + IN.Diffuse_Blend.rgb * shadow + light.rgb) * albedo.rgb;
+
+ // Combine
+ oColor0.rgb = diffuse;
+ oColor0.a = 1;
+
+#endif
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+ oColor0.rgb = lerp(G(FogColor), oColor0.rgb, fogAlpha);
+
+#ifdef PIN_GBUFFER
+ oColor1 = gbufferPack(IN.View_Depth.w*G(FadeDistance_GlowFactor).x, diffuse.rgb, 0, fogAlpha);
+#endif
+}
diff --git a/Client2016/shaders/source/metal.hlsl b/Client2016/shaders/source/metal.hlsl
new file mode 100644
index 0000000..ad92d37
--- /dev/null
+++ b/Client2016/shaders/source/metal.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.3
+
+#define CFG_SPECULAR_LOD 0.8
+#define CFG_GLOSS_LOD 120
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0.75
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/neon.hlsl b/Client2016/shaders/source/neon.hlsl
new file mode 100644
index 0000000..60c7186
--- /dev/null
+++ b/Client2016/shaders/source/neon.hlsl
@@ -0,0 +1,3 @@
+#define PIN_PLASTIC
+#define PIN_NEON
+#include "default.hlsl"
diff --git a/Client2016/shaders/source/particle.hlsl b/Client2016/shaders/source/particle.hlsl
new file mode 100644
index 0000000..367ef8f
--- /dev/null
+++ b/Client2016/shaders/source/particle.hlsl
@@ -0,0 +1,240 @@
+#include "common.h"
+
+TEX_DECLARE2D(tex, 0);
+TEX_DECLARE2D(cstrip, 1);
+TEX_DECLARE2D(astrip, 2);
+
+uniform float4 throttleFactor; // .x = alpha cutoff, .y = alpha boost (clamp), .w - additive/alpha ratio for Crazy shaders
+uniform float4 modulateColor;
+uniform float4 zOffset;
+
+struct VS_INPUT
+{
+ float4 pos : POSITION;
+ ATTR_INT4 scaleRotLife : TEXCOORD0; // transform matrix
+ ATTR_INT2 disp : TEXCOORD1; // .xy = corner, either (0,0), (1,0), (0,1), or (1,1)
+ ATTR_INT2 cline: TEXCOORD2; // .x = color line [0...32767]
+};
+
+struct VS_OUTPUT
+{
+ float4 pos : POSITION;
+ float3 uvFog : TEXCOORD0;
+ float2 colorLookup : TEXCOORD1;
+};
+
+float4 rotScale( float4 scaleRotLife )
+{
+ float cr = cos( scaleRotLife.z );
+ float sr = sin( scaleRotLife.z );
+
+ float4 r;
+ r.x = cr * scaleRotLife.x;
+ r.y = -sr * scaleRotLife.x;
+ r.z = sr * scaleRotLife.y;
+ r.w = cr * scaleRotLife.y;
+
+ return r;
+}
+
+float4 mulq( float4 a, float4 b )
+{
+ float3 i = cross( a.xyz, b.xyz ) + a.w * b.xyz + b.w * a.xyz;
+ float r = a.w * b.w - dot( a.xyz, b.xyz );
+ return float4( i, r );
+}
+
+float4 conj( float4 a ) { return float4( -a.xyz, a.w ); }
+
+float4 rotate( float4 v, float4 q )
+{
+ return mulq( mulq( q, v ), conj( q ) );
+}
+
+float4 axis_angle( float3 axis, float angle )
+{
+ return float4( sin(angle/2) * axis, cos(angle/2) );
+}
+
+VS_OUTPUT vs( VS_INPUT input )
+{
+ VS_OUTPUT o;
+
+ float4 pos = float4( input.pos.xyz, 1 );
+ float2 disp = input.disp.xy * 2 - 1; // -1..1
+
+ float4 scaleRotLifeFlt = (float4)input.scaleRotLife * float4( 1.0f/256.0f, 1.0f/256.0f, 2.0 * 3.1415926f / 32767.0f, 1.0f / 32767.0f );
+ scaleRotLifeFlt.xy += 127.0f;
+
+ float4 rs = rotScale( scaleRotLifeFlt );
+
+ pos += G(ViewRight) * dot( disp, rs.xy );
+ pos += G(ViewUp) * dot( disp, rs.zw );
+
+ float4 pos2 = pos + G(ViewDir)*zOffset.x; // Z-offset position in world space
+
+ o.pos = mul( G(ViewProjection), pos );
+
+ o.uvFog.xy = input.disp.xy;
+ o.uvFog.y = 1 - o.uvFog.y;
+ o.uvFog.z = (G(FogParams).z - o.pos.w) * G(FogParams).w;
+
+ o.colorLookup.x = 1 - max( 0, min(1, scaleRotLifeFlt.w ) );
+ o.colorLookup.y = (float)input.cline.x * (1.0 / 32767.0f);
+
+
+ pos2 = mul( G(ViewProjection), pos2 ); // Z-offset position in clip space
+ o.pos.z = pos2.z * o.pos.w/pos2.w; // Only need z
+
+
+ return o;
+}
+
+
+float4 psAdd( VS_OUTPUT input ) : COLOR0 // #0
+{
+ float4 texcolor = tex2D( tex, input.uvFog.xy );
+ float4 vcolor = tex2D( cstrip, input.colorLookup.xy );
+ vcolor.a = tex2D( astrip, input.colorLookup.xy ).r;
+
+ float4 result;
+
+ result.rgb = (texcolor.rgb + vcolor.rgb) * modulateColor.rgb;
+ result.a = texcolor.a * vcolor.a;
+ result.rgb *= result.a;
+
+ result.rgb = lerp( 0.0f.xxx, result.rgb, saturate( input.uvFog.zzz ) );
+ return result;
+}
+
+float4 psModulate( VS_OUTPUT input ) : COLOR0 // #1
+{
+
+ float4 texcolor = tex2D( tex, input.uvFog.xy );
+ float4 vcolor = tex2D( cstrip, input.colorLookup.xy ) * modulateColor;
+ vcolor.a = tex2D( astrip, input.colorLookup.xy ).r * modulateColor.a;
+
+ float4 result;
+
+ result.rgb = texcolor.rgb * vcolor.rgb;
+ result.a = texcolor.a * vcolor.a;
+
+ result.rgb = lerp( G(FogColor).rgb, result.rgb, saturate( input.uvFog.zzz ) );
+ return result;
+}
+
+
+// - this shader is crazy
+// - used instead of additive particles to help see bright particles (e.g. fire) on top of extremely bright backgrounds
+// - requires ONE | INVSRCALPHA blend mode, useless otherwise
+// - does not use color strip texture
+// - outputs a blend between additive blend and alpha blend in fragment alpha
+// - ratio multiplier is in throttleFactor.w
+float4 psCrazy( VS_OUTPUT input ) : COLOR0
+{
+ float4 texcolor = tex2D( tex, input.uvFog.xy );
+ float4 vcolor = float4(1,0,0,0); //tex2D( cstrip, input.colorLookup.xy ); // not actually used
+ vcolor.a = tex2D( astrip, input.colorLookup.xy ).r;
+ float blendRatio = throttleFactor.w; // yeah yeah
+
+ float4 result;
+
+ result.rgb = (texcolor.rgb ) * modulateColor.rgb * vcolor.a * texcolor.a;
+ result.a = blendRatio * texcolor.a * vcolor.a;
+
+ result = lerp( 0.0f.xxxx, result, saturate( input.uvFog.zzzz ) );
+ return result;
+}
+
+float4 psCrazySparkles( VS_OUTPUT input ) : COLOR0
+{
+ float4 texcolor = tex2D( tex, input.uvFog.xy );
+ float4 vcolor = tex2D( cstrip, input.colorLookup.xy );
+ vcolor.a = tex2D( astrip, input.colorLookup.xy ).r;
+ float blendRatio = throttleFactor.w;
+
+ float4 result;
+
+ if( texcolor.a < 0.5f )
+ {
+ result.rgb = vcolor.rgb * modulateColor.rgb * (2 * texcolor.a);
+ }
+ else
+ {
+ result.rgb = lerp( vcolor.rgb * modulateColor.rgb, texcolor.rgb, 2*texcolor.a-1 );
+ }
+
+ //vcolor.a *= modulateColor.a;
+ result.rgb *= vcolor.a;
+ result.a = blendRatio * texcolor.a * vcolor.a;
+
+ result = lerp( 0.0f.xxxx, result, saturate( input.uvFog.zzzz ) );
+ return result;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////
+
+struct VS_INPUT2
+{
+ float4 pos : POSITION;
+ ATTR_INT4 scaleRotLife : TEXCOORD0; // transform matrix
+ ATTR_INT2 disp : TEXCOORD1; // .xy = corner, either (0,0), (1,0), (0,1), or (1,1)
+ ATTR_INT2 cline: TEXCOORD2; // .x = color line [0...32767]
+ ATTR_INT4 color: TEXCOORD3; // .xyzw
+};
+
+struct VS_OUTPUT2
+{
+ float4 pos : POSITION;
+ float3 uvFog : TEXCOORD0;
+ float4 color : TEXCOORD1;
+};
+
+VS_OUTPUT2 vsCustom( VS_INPUT2 input )
+{
+ VS_OUTPUT2 o;
+
+ float4 pos = input.pos;
+ float2 disp = input.disp.xy * 2 - 1; // -1..1
+
+ float4 scaleRotLifeFlt = (float4)input.scaleRotLife * float4( 1.0/256.0f, 1.0/256.0f, 2.0 * 3.1415926f / 32767.0, 1.0 / 32767.0f );
+ scaleRotLifeFlt.xy += 127.0f;
+
+ float4 rs = rotScale( scaleRotLifeFlt );
+
+ pos += G(ViewRight) * dot( disp, rs.xy );
+ pos += G(ViewUp) * dot( disp, rs.zw );
+
+ float4 pos2 = pos + G(ViewDir)*zOffset.x; // Z-offset position in world space
+
+ o.pos = mul( G(ViewProjection), pos );
+
+ o.uvFog.xy = input.disp.xy;
+ o.uvFog.y = 1 - o.uvFog.y;
+ o.uvFog.z = (G(FogParams).z - o.pos.w) * G(FogParams).w;
+
+ o.color = input.color * (1/255.0f);
+
+ pos2 = mul( G(ViewProjection), pos2 ); // Z-offset position in clip space
+ o.pos.z = pos2.z * o.pos.w/pos2.w; // Only need z
+
+
+ return o;
+}
+
+float4 psCustom( VS_OUTPUT2 input ) : COLOR0 // #1
+{
+ float4 texcolor = tex2D( tex, input.uvFog.xy );
+ float4 vcolor = input.color;
+
+ float blendRatio = throttleFactor.w; // yeah yeah
+
+ float4 result;
+
+ result.rgb = texcolor.rgb * vcolor.rgb * vcolor.a * texcolor.a;
+ result.a = blendRatio * texcolor.a * vcolor.a;
+
+ result = lerp( 0.0f.xxxx, result, saturate( input.uvFog.zzzz ) );
+ return result;
+}
diff --git a/Client2016/shaders/source/pebble.hlsl b/Client2016/shaders/source/pebble.hlsl
new file mode 100644
index 0000000..9e35fe9
--- /dev/null
+++ b/Client2016/shaders/source/pebble.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2.5
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.15
+#define CFG_GLOSS_LOD 22
+
+#define CFG_NORMAL_DETAIL_TILING 6
+#define CFG_NORMAL_DETAIL_SCALE 1.5
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/plastic.hlsl b/Client2016/shaders/source/plastic.hlsl
new file mode 100644
index 0000000..905a540
--- /dev/null
+++ b/Client2016/shaders/source/plastic.hlsl
@@ -0,0 +1,52 @@
+#if defined(PIN_HQ)
+#define PIN_SURFACE
+#include "default.hlsl"
+
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_BUMP_INTENSITY 0.5
+
+#define CFG_SPECULAR 0.4
+#define CFG_GLOSS 9
+
+#define CFG_NORMAL_SHADOW_SCALE 0.1
+
+Surface surfaceShader(SurfaceInput IN, float2 fade2)
+{
+ float fade = fade2.y;
+
+ float4 studs = tex2D(DiffuseMap, IN.UvStuds);
+ float3 normal = nmapUnpack(tex2D(NormalMap, IN.UvStuds));
+
+#ifdef GLSLES
+ float3 noise = float3(0, 0, 1);
+#else
+ float3 noise = nmapUnpack(tex2D(NormalDetailMap, IN.Uv * (CFG_TEXTURE_TILING)));
+#endif
+
+ float noiseScale = saturate0(IN.Color.a * 2 * (CFG_BUMP_INTENSITY) - 1 * (CFG_BUMP_INTENSITY));
+
+#ifdef PIN_REFLECTION
+ noiseScale *= saturate(1 - 2 * IN.Reflectance);
+#endif
+
+ normal.xy += noise.xy * noiseScale;
+
+ normal.xy *= fade;
+
+ Surface surface = (Surface)0;
+ surface.albedo = IN.Color.rgb * (studs.r * 2);
+ surface.normal = normal;
+ surface.specular = (CFG_SPECULAR);
+ surface.gloss = (CFG_GLOSS);
+
+#ifdef PIN_REFLECTION
+ surface.reflectance = IN.Reflectance;
+#endif
+
+ return surface;
+}
+#else
+#define PIN_PLASTIC
+#include "default.hlsl"
+#endif
diff --git a/Client2016/shaders/source/profiler.hlsl b/Client2016/shaders/source/profiler.hlsl
new file mode 100644
index 0000000..ec6001f
--- /dev/null
+++ b/Client2016/shaders/source/profiler.hlsl
@@ -0,0 +1,40 @@
+#include "common.h"
+
+
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+VertexOutput ProfilerVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = mul(G(ViewProjection), IN.Position);
+ OUT.HPosition.y = -OUT.HPosition.y;
+
+ OUT.Uv = IN.Uv;
+ OUT.Color = IN.Color;
+
+ return OUT;
+}
+
+TEX_DECLARE2D(DiffuseMap, 0);
+
+float4 ProfilerPS(VertexOutput IN): COLOR0
+{
+ float4 c0 = tex2D(DiffuseMap, IN.Uv);
+ float4 c1 = tex2D(DiffuseMap, IN.Uv + float2(0, 1.f / 9.f));
+
+ return c0.a < 0.5 ? float4(0, 0, 0, c1.a) : c0 * IN.Color;
+}
diff --git a/Client2016/shaders/source/rust.hlsl b/Client2016/shaders/source/rust.hlsl
new file mode 100644
index 0000000..9be4823
--- /dev/null
+++ b/Client2016/shaders/source/rust.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 1
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.35
+#define CFG_GLOSS_LOD 103
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0.5
+#define CFG_FAR_DIFFUSE_CUTOFF 0.6
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/sand.hlsl b/Client2016/shaders/source/sand.hlsl
new file mode 100644
index 0000000..f64f6c1
--- /dev/null
+++ b/Client2016/shaders/source/sand.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.4
+#define CFG_GLOSS_SCALE 32
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0
+
+#define CFG_SPECULAR_LOD 0.07
+#define CFG_GLOSS_LOD 6
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/screenspace.hlsl b/Client2016/shaders/source/screenspace.hlsl
new file mode 100644
index 0000000..825c8ba
--- /dev/null
+++ b/Client2016/shaders/source/screenspace.hlsl
@@ -0,0 +1,211 @@
+#include "common.h"
+
+TEX_DECLARE2D(Texture, 0);
+TEX_DECLARE2D(Mask, 1);
+
+// .xy = gbuffer width/height, .zw = inverse gbuffer width/height
+uniform float4 TextureSize;
+uniform float4 Params1;
+uniform float4 Params2;
+
+#if defined(GLSL) || defined(DX11)
+float4 convertPosition(float4 p, float scale)
+{
+ return p;
+}
+#else
+float4 convertPosition(float4 p, float scale)
+{
+ // half-pixel offset
+ return p + float4(-TextureSize.z, TextureSize.w, 0, 0) * scale;
+}
+#endif
+
+#ifndef GLSL
+float2 convertUv(float4 p)
+{
+ return p.xy * float2(0.5, -0.5) + 0.5;
+}
+#else
+float2 convertUv(float4 p)
+{
+ return p.xy * 0.5 + 0.5;
+}
+#endif
+
+
+// simple pass through structure
+struct VertexOutput
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+};
+
+// position and tex coord + 4 additional tex coords
+struct VertexOutput_4uv
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+ float4 uv12 : TEXCOORD1;
+ float4 uv34 : TEXCOORD2;
+};
+
+// position and tex coord + 8 additional tex coords
+struct VertexOutput_8uv
+{
+ float4 p : POSITION;
+ float2 uv : TEXCOORD0;
+ float4 uv12 : TEXCOORD1;
+ float4 uv34 : TEXCOORD2;
+ float4 uv56 : TEXCOORD3;
+ float4 uv78 : TEXCOORD4;
+};
+
+VertexOutput passThrough_vs(float4 p: POSITION)
+{
+ VertexOutput OUT;
+ OUT.p = convertPosition(p, 1);
+ OUT.uv = convertUv(p);
+
+ return OUT;
+}
+
+float4 passThrough_ps( VertexOutput IN ) : COLOR0
+{
+ return tex2D(Texture, IN.uv);
+}
+
+VertexOutput_4uv downsample4x4_vs(float4 p: POSITION)
+{
+ float2 uv = convertUv(p);
+
+ VertexOutput_4uv OUT;
+ OUT.p = convertPosition(p, 1);
+ OUT.uv = uv;
+
+ float2 uvOffset = TextureSize.zw * 0.25f;
+
+ OUT.uv12.xy = uv + uvOffset * float2(-1, -1);
+ OUT.uv12.zw = uv + uvOffset * float2(+1, -1);
+ OUT.uv34.xy = uv + uvOffset * float2(-1, +1);
+ OUT.uv34.zw = uv + uvOffset * float2(+1, +1);
+
+ return OUT;
+}
+
+float4 imageProcess_ps( VertexOutput IN ) : COLOR0
+{
+ float3 color = tex2D(Texture, IN.uv).rgb;
+
+ float4 tintColor = float4(Params2.xyz,1);
+ //float4 tintColor = float4(18.0 / 255.0, 58.0 / 255.0, 80.0 / 255.0, 1);
+ float contrast = Params1.y;
+ float brightness = Params1.x;
+ float grayscaleLvl = Params1.z;
+
+ color = contrast*(color - 0.5) + 0.5 + brightness;
+ float grayscale = (color.r + color.g + color.g) / 3.0;
+
+ return lerp(float4(color.rgb,1), float4(grayscale.xxx,1), grayscaleLvl) * tintColor;
+}
+
+float4 gauss(float samples, float2 uv)
+{
+ float2 step = Params1.xy;
+ float sigma = Params1.z;
+
+ float sigmaN1 = 1 / sqrt(2 * 3.1415926 * sigma * sigma);
+ float sigmaN2 = 1 / (2 * sigma * sigma);
+
+ // First sample is in the center and accounts for our pixel
+ float4 result = tex2D(Texture, uv) * sigmaN1;
+ float weight = sigmaN1;
+
+ // Every loop iteration computes impact of 4 pixels
+ // Each sample computes impact of 2 neighbor pixels, starting with the next one to the right
+ // Note that we sample exactly in between pixels to leverage bilinear filtering
+ for (int i = 0; i < samples; ++i)
+ {
+ float ix = 2 * i + 1.5;
+ float iw = 2 * exp(-ix * ix * sigmaN2) * sigmaN1;
+
+ result += (tex2D(Texture, uv + step * ix) + tex2D(Texture, uv - step * ix)) * iw;
+ weight += 2 * iw;
+ }
+
+ // Since the above is an approximation of the integral with step functions, normalization compensates for the error
+ return (result / weight);
+}
+
+
+
+float4 blur3_ps(VertexOutput IN): COLOR0
+{
+ return gauss(3, IN.uv);
+}
+
+float4 blur5_ps(VertexOutput IN): COLOR0
+{
+ return gauss(5, IN.uv);
+}
+
+float4 blur7_ps(VertexOutput IN): COLOR0
+{
+ return gauss(7, IN.uv);
+}
+
+float4 glowApply_ps( VertexOutput IN ) : COLOR0
+{
+ float4 color = tex2D(Texture, IN.uv);
+ return float4(color.rgb * Params1.x, color.a);
+}
+
+// this is specific glow downsample
+float4 downSample4x4Glow_ps( VertexOutput_4uv IN ) : COLOR0
+{
+ float4 avgColor = tex2D( Texture, IN.uv12.xy );
+ avgColor += tex2D( Texture, IN.uv12.zw );
+ avgColor += tex2D( Texture, IN.uv34.xy );
+ avgColor += tex2D( Texture, IN.uv34.zw );
+
+ avgColor *= 0.25;
+ return float4(avgColor.rgb, 1) * (1-avgColor.a);
+}
+
+float4 ShadowBlurPS(VertexOutput IN): COLOR0
+{
+#ifdef GLSLES
+ int N = 1;
+ float sigma = 0.5;
+#else
+ int N = 3;
+ float sigma = 1.5;
+#endif
+
+ float2 step = Params1.xy;
+
+ float sigmaN1 = 1 / sqrt(2 * 3.1415926 * sigma * sigma);
+ float sigmaN2 = 1 / (2 * sigma * sigma);
+
+ float depth = 1;
+ float color = 0;
+ float weight = 0;
+
+ for (int i = -N; i <= N; ++i)
+ {
+ float ix = i;
+ float iw = exp(-ix * ix * sigmaN2) * sigmaN1;
+
+ float4 data = tex2D(Texture, IN.uv + step * ix);
+
+ depth = min(depth, data.x);
+ color += data.y * iw;
+ weight += iw;
+ }
+
+ float mask = tex2D(Mask, IN.uv).r;
+
+ // Since the above is an approximation of the integral with step functions, normalization compensates for the error
+ return float4(depth, color * mask * (1 / weight), 0, 0);
+}
+
diff --git a/Client2016/shaders/source/shadow.hlsl b/Client2016/shaders/source/shadow.hlsl
new file mode 100644
index 0000000..f691f02
--- /dev/null
+++ b/Client2016/shaders/source/shadow.hlsl
@@ -0,0 +1,50 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+
+ ATTR_INT4 Extra : COLOR1;
+};
+
+struct VertexOutput
+{
+ float4 HPosition: POSITION;
+
+ float3 PosLightSpace: TEXCOORD0;
+};
+
+#ifdef PIN_SKINNED
+ WORLD_MATRIX_ARRAY(WorldMatrixArray, MAX_BONE_COUNT * 3);
+#endif
+
+VertexOutput ShadowVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ // Transform position to world space
+#ifdef PIN_SKINNED
+ int boneIndex = IN.Extra.r;
+
+ float4 worldRow0 = WorldMatrixArray[boneIndex * 3 + 0];
+ float4 worldRow1 = WorldMatrixArray[boneIndex * 3 + 1];
+ float4 worldRow2 = WorldMatrixArray[boneIndex * 3 + 2];
+
+ float3 posWorld = float3(dot(worldRow0, IN.Position), dot(worldRow1, IN.Position), dot(worldRow2, IN.Position));
+#else
+ float3 posWorld = IN.Position.xyz;
+#endif
+
+ OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
+
+ OUT.PosLightSpace = shadowPrepareSample(posWorld);
+
+ return OUT;
+}
+
+float4 ShadowPS(VertexOutput IN): COLOR0
+{
+ float depth = shadowDepth(IN.PosLightSpace);
+
+ return float4(depth, 1, 0, 0);
+}
diff --git a/Client2016/shaders/source/sky.hlsl b/Client2016/shaders/source/sky.hlsl
new file mode 100644
index 0000000..05b9708
--- /dev/null
+++ b/Client2016/shaders/source/sky.hlsl
@@ -0,0 +1,53 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float PSize : PSIZE;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+WORLD_MATRIX(WorldMatrix);
+
+uniform float4 Color;
+uniform float4 Color2;
+
+VertexOutput SkyVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float4 wpos = mul(WorldMatrix, IN.Position);
+
+ OUT.HPosition = mul(G(ViewProjection), wpos);
+
+#ifndef GLSLES
+ // snap to far plane to prevent scene-sky intersections
+ // small offset is needed to prevent 0/0 division in case w=0, which causes rasterization issues
+ // some mobile chips (hello, Vivante!) don't like it
+ OUT.HPosition.z = OUT.HPosition.w - 1.f / 16;
+#endif
+
+ OUT.PSize = 2.0; // star size
+
+ OUT.Uv = IN.Uv;
+ OUT.Color = IN.Color * lerp(Color2,Color,wpos.y/1700);
+ //OUT.Color = IN.Color * Color;
+
+ return OUT;
+}
+
+TEX_DECLARE2D(DiffuseMap, 0);
+
+float4 SkyPS(VertexOutput IN): COLOR0
+{
+ return tex2D(DiffuseMap, IN.Uv) * IN.Color;
+}
diff --git a/Client2016/shaders/source/slate.hlsl b/Client2016/shaders/source/slate.hlsl
new file mode 100644
index 0000000..cd135ba
--- /dev/null
+++ b/Client2016/shaders/source/slate.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 0.9
+#define CFG_GLOSS_SCALE 128
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.5
+
+#define CFG_SPECULAR_LOD 0.14
+#define CFG_GLOSS_LOD 20
+
+#define CFG_NORMAL_DETAIL_TILING 5
+#define CFG_NORMAL_DETAIL_SCALE 1
+
+#define CFG_FAR_TILING 0.25
+#define CFG_FAR_DIFFUSE_CUTOFF 0.75
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/smoothcluster.hlsl b/Client2016/shaders/source/smoothcluster.hlsl
new file mode 100644
index 0000000..6929d5d
--- /dev/null
+++ b/Client2016/shaders/source/smoothcluster.hlsl
@@ -0,0 +1,174 @@
+#include "common.h"
+
+struct Appdata
+{
+ ATTR_INT4 Position : POSITION;
+
+ ATTR_INT4 Normal : NORMAL;
+
+ ATTR_INT4 Material0 : TEXCOORD0;
+ ATTR_INT4 Material1 : TEXCOORD1;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float3 Weights: COLOR0;
+
+ float4 Uv0: TEXCOORD0;
+ float4 Uv1: TEXCOORD1;
+ float4 Uv2: TEXCOORD2;
+
+ float4 LightPosition_Fog : TEXCOORD3;
+ float3 PosLightSpace : TEXCOORD4;
+
+#ifdef PIN_HQ
+ float3 Normal: TEXCOORD5;
+ float4 View_Depth: TEXCOORD6;
+
+ float3 Tangents: COLOR1;
+#else
+ float3 Diffuse: COLOR1;
+#endif
+};
+
+WORLD_MATRIX_ARRAY(WorldMatrixArray, 72);
+
+uniform float4 LayerScale;
+
+float4 getUV(float3 position, ATTR_INT material, ATTR_INT projection, float seed)
+{
+ float3 u = WorldMatrixArray[1 + int(projection)].xyz;
+ float3 v = WorldMatrixArray[19 + int(projection)].xyz;
+
+ float4 m = WorldMatrixArray[37 + int(material)];
+
+ float2 uv = float2(dot(position, u), dot(position, v)) * m.x + m.y * float2(seed, floor(seed * 2.6651441f));
+
+ return float4(uv, m.zw);
+}
+
+VertexOutput TerrainVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float3 posWorld = IN.Position.xyz * WorldMatrixArray[0].w + WorldMatrixArray[0].xyz;
+ float3 normalWorld = IN.Normal.xyz * (1.0 / 127.0) - 1.0;
+
+ OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
+
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w);
+
+ OUT.PosLightSpace = shadowPrepareSample(posWorld);
+
+ OUT.Uv0 = getUV(posWorld, IN.Material0.x, IN.Material1.x, IN.Normal.w);
+ OUT.Uv1 = getUV(posWorld, IN.Material0.y, IN.Material1.y, IN.Material0.w);
+ OUT.Uv2 = getUV(posWorld, IN.Material0.z, IN.Material1.z, IN.Material1.w);
+
+#if defined(GLSLES) && !defined(GL3) // iPad2 workaround
+ OUT.Weights = abs(IN.Position.www - float3(0, 1, 2)) < 0.1;
+#else
+ OUT.Weights = IN.Position.www == float3(0, 1, 2);
+#endif
+
+#ifdef PIN_HQ
+ OUT.Normal = normalWorld;
+ OUT.View_Depth = float4(G(CameraPosition) - posWorld, OUT.HPosition.w);
+ OUT.Tangents = float3(IN.Material1.xyz) > 7.5; // side vs top
+#else
+ float ndotl = dot(normalWorld, -G(Lamp0Dir));
+ float3 diffuse = max(ndotl, 0) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
+
+ OUT.Diffuse = diffuse;
+#endif
+
+ return OUT;
+}
+
+TEX_DECLARE2D(AlbedoMap, 0);
+TEX_DECLARE2D(NormalMap, 1);
+TEX_DECLARE2D(SpecularMap, 2);
+TEX_DECLARECUBE(EnvMap, 3);
+LGRID_SAMPLER(LightMap, 4);
+TEX_DECLARE2D(LightMapLookup, 5);
+TEX_DECLARE2D(ShadowMap, 6);
+
+float4 sampleMap(TEXTURE_IN_2D(s), float4 uv)
+{
+#ifdef PIN_HQ
+ float2 uvs = uv.xy * LayerScale.xy;
+
+ return tex2Dgrad(s, frac(uv.xy) * LayerScale.xy + uv.zw, ddx(uvs), ddy(uvs));
+#else
+ return tex2D(s, frac(uv.xy) * LayerScale.xy + uv.zw);
+#endif
+}
+
+float4 sampleBlend(TEXTURE_IN_2D(s), float4 uv0, float4 uv1, float4 uv2, float3 w)
+{
+ return
+ sampleMap(TEXTURE(s), uv0) * w.x +
+ sampleMap(TEXTURE(s), uv1) * w.y +
+ sampleMap(TEXTURE(s), uv2) * w.z;
+}
+
+float3 sampleNormal(TEXTURE_IN_2D(s), float4 uv0, float4 uv1, float4 uv2, float3 w, float3 normal, float3 tsel)
+{
+ return terrainNormal(sampleMap(TEXTURE(s), uv0), sampleMap(TEXTURE(s), uv1), sampleMap(TEXTURE(s), uv2), w, normal, tsel);
+}
+
+void TerrainPS(VertexOutput IN,
+#ifdef PIN_GBUFFER
+ out float4 oColor1: COLOR1,
+#endif
+ out float4 oColor0: COLOR0)
+{
+ float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
+ float shadow = shadowSample(TEXTURE(ShadowMap), IN.PosLightSpace, light.a);
+
+ float3 w = IN.Weights.xyz;
+
+ float4 albedo = sampleBlend(TEXTURE(AlbedoMap), IN.Uv0, IN.Uv1, IN.Uv2, w);
+
+#ifdef PIN_HQ
+ float fade = saturate0(1 - IN.View_Depth.w * G(FadeDistance_GlowFactor).y);
+
+#ifndef PIN_GBUFFER
+ float3 normal = IN.Normal;
+#else
+ float3 normal = sampleNormal(TEXTURE(NormalMap), IN.Uv0, IN.Uv1, IN.Uv2, w, IN.Normal, IN.Tangents);
+#endif
+
+ float4 params = sampleBlend(TEXTURE(SpecularMap), IN.Uv0, IN.Uv1, IN.Uv2, w);
+
+ float ndotl = dot(normal, -G(Lamp0Dir));
+
+ // Compute diffuse term
+ float3 diffuse = (G(AmbientColor) + (saturate(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color)) * shadow + light.rgb + params.b * 2) * albedo.rgb;
+
+ // Compute specular term
+ float specularIntensity = step(0, ndotl) * params.r * fade;
+ float specularPower = params.g * 128 + 0.01;
+
+ float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + normalize(IN.View_Depth.xyz)))), specularPower));
+#else
+ // Compute diffuse term
+ float3 diffuse = (G(AmbientColor) + IN.Diffuse * shadow + light.rgb) * albedo.rgb;
+
+ // Compute specular term
+ float3 specular = 0;
+#endif
+
+ // Combine
+ oColor0.rgb = diffuse + specular;
+ oColor0.a = 1;
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+ oColor0.rgb = lerp(G(FogColor), oColor0.rgb, fogAlpha);
+
+#ifdef PIN_GBUFFER
+ oColor1 = gbufferPack(IN.View_Depth.w, diffuse.rgb, specular.rgb, fogAlpha);
+#endif
+}
diff --git a/Client2016/shaders/source/smoothplastic.hlsl b/Client2016/shaders/source/smoothplastic.hlsl
new file mode 100644
index 0000000..fb0aa90
--- /dev/null
+++ b/Client2016/shaders/source/smoothplastic.hlsl
@@ -0,0 +1,2 @@
+#define PIN_PLASTIC
+#include "default.hlsl"
diff --git a/Client2016/shaders/source/smoothwater.hlsl b/Client2016/shaders/source/smoothwater.hlsl
new file mode 100644
index 0000000..4bee008
--- /dev/null
+++ b/Client2016/shaders/source/smoothwater.hlsl
@@ -0,0 +1,310 @@
+#include "common.h"
+
+// Tunables
+#define CFG_TEXTURE_TILING 0.2
+#define CFG_TEXTURE_DETILING 0.1
+
+#define CFG_SPECULAR 2
+#define CFG_GLOSS 900
+
+#define CFG_NORMAL_STRENGTH 0.25
+
+#define CFG_REFRACTION_STRENGTH 0.05
+
+#define CFG_FRESNEL_OFFSET 0.3
+
+#define CFG_SSR_STEPS 8
+#define CFG_SSR_START_DISTANCE 1
+#define CFG_SSR_STEP_CLAMP 0.2
+#define CFG_SSR_DEPTH_CUTOFF 10
+
+// Shader code
+struct Appdata
+{
+ ATTR_INT4 Position : POSITION;
+
+ ATTR_INT4 Normal : NORMAL;
+
+ ATTR_INT4 Material0 : TEXCOORD0;
+ ATTR_INT4 Material1 : TEXCOORD1;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float4 Weights_Wave: COLOR0;
+ float3 Tangents: COLOR1;
+
+ float2 Uv0: TEXCOORD0;
+ float2 Uv1: TEXCOORD1;
+ float2 Uv2: TEXCOORD2;
+
+ float4 LightPosition_Fog : TEXCOORD3;
+
+ float3 Normal: TEXCOORD4;
+ float4 View_Depth: TEXCOORD5;
+
+#ifdef PIN_HQ
+ float4 PositionScreen: TEXCOORD6;
+#endif
+};
+
+WORLD_MATRIX_ARRAY(WorldMatrixArray, 72);
+
+uniform float4 WaveParams; // .x = frequency .y = phase .z = height .w = lerp
+uniform float4 WaterColor; // deep water color
+uniform float4 WaterParams; // .x = refraction depth scale, .y = refraction depth offset
+
+float3 displacePosition(float3 position, float waveFactor)
+{
+ float x = sin((position.z - position.x) * WaveParams.x - WaveParams.y);
+ float z = sin((position.z + position.x) * WaveParams.x + WaveParams.y);
+ float p = (x + z) * WaveParams.z;
+
+ float3 result = position;
+
+ result.y += p * waveFactor;
+
+ return result;
+}
+
+float4 clipToScreen(float4 pos)
+{
+#ifdef GLSL
+ pos.xy = pos.xy * 0.5 + 0.5 * pos.w;
+#else
+ pos.xy = pos.xy * float2(0.5, -0.5) + 0.5 * pos.w;
+#endif
+ return pos;
+}
+
+float2 getUV(float3 position, ATTR_INT projection, float seed)
+{
+ float3 u = WorldMatrixArray[1 + int(projection)].xyz;
+ float3 v = WorldMatrixArray[19 + int(projection)].xyz;
+
+ float2 uv = float2(dot(position, u), dot(position, v)) * (0.25 * CFG_TEXTURE_TILING) + CFG_TEXTURE_DETILING * float2(seed, floor(seed * 2.6651441f));
+
+ return uv;
+}
+
+VertexOutput WaterVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ float3 posWorld = IN.Position.xyz * WorldMatrixArray[0].w + WorldMatrixArray[0].xyz;
+ float3 normalWorld = IN.Normal.xyz * (1.0 / 127.0) - 1.0;
+
+#if defined(GLSLES) && !defined(GL3) // iPad2 workaround
+ float3 weights = abs(IN.Position.www - float3(0, 1, 2)) < 0.1;
+#else
+ float3 weights = IN.Position.www == float3(0, 1, 2);
+#endif
+
+ float waveFactor = dot(weights, IN.Material0.xyz) * (1.0 / 255.0);
+
+#ifdef PIN_HQ
+ float fade = saturate0(1 - dot(posWorld - G(CameraPosition), -G(ViewDir).xyz) * G(FadeDistance_GlowFactor).y);
+
+ posWorld = displacePosition(posWorld, waveFactor * fade);
+#endif
+
+ OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
+
+ OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w);
+
+ OUT.Uv0 = getUV(posWorld, IN.Material1.x, IN.Normal.w);
+ OUT.Uv1 = getUV(posWorld, IN.Material1.y, IN.Material0.w);
+ OUT.Uv2 = getUV(posWorld, IN.Material1.z, IN.Material1.w);
+
+ OUT.Weights_Wave.xyz = weights;
+ OUT.Weights_Wave.w = waveFactor;
+
+ OUT.Normal = normalWorld;
+ OUT.View_Depth = float4(G(CameraPosition) - posWorld, OUT.HPosition.w);
+ OUT.Tangents = float3(IN.Material1.xyz) > 7.5; // side vs top
+
+#ifdef PIN_HQ
+ OUT.PositionScreen = clipToScreen(OUT.HPosition);
+#endif
+
+ return OUT;
+}
+
+TEX_DECLARE2D(NormalMap1, 0);
+TEX_DECLARE2D(NormalMap2, 1);
+TEX_DECLARECUBE(EnvMap, 2);
+LGRID_SAMPLER(LightMap, 3);
+TEX_DECLARE2D(LightMapLookup, 4);
+TEX_DECLARE2D(GBufferColor, 5);
+TEX_DECLARE2D(GBufferDepth, 6);
+
+float fresnel(float ndotv)
+{
+ return saturate(0.78 - 2.5 * abs(ndotv)) + CFG_FRESNEL_OFFSET;
+}
+
+float4 sampleMix(float2 uv)
+{
+#ifdef PIN_HQ
+ return lerp(tex2D(NormalMap1, uv), tex2D(NormalMap2, uv), WaveParams.w);
+#else
+ return tex2D(NormalMap1, uv);
+#endif
+}
+
+float3 sampleNormal(float2 uv0, float2 uv1, float2 uv2, float3 w, float3 normal, float3 tsel)
+{
+ return terrainNormal(sampleMix(uv0), sampleMix(uv1), sampleMix(uv2), w, normal, tsel);
+}
+
+float3 sampleNormalSimple(float2 uv0, float2 uv1, float2 uv2, float3 w)
+{
+ float4 data = sampleMix(uv0) * w.x + sampleMix(uv1) * w.y + sampleMix(uv2) * w.z;
+
+ return nmapUnpack(data).xzy;
+}
+
+float unpackDepth(float2 uv)
+{
+ float4 geomTex = tex2D(GBufferDepth, uv);
+ float d = geomTex.z * (1.0f/256.0f) + geomTex.w;
+ return d * GBUFFER_MAX_DEPTH;
+}
+
+float3 getRefractedColor(float4 cpos, float3 N, float3 waterColor)
+{
+ float2 refruv0 = cpos.xy / cpos.w;
+ float2 refruv1 = refruv0 + N.xz * CFG_REFRACTION_STRENGTH;
+
+ float4 refr0 = tex2D(GBufferColor, refruv0);
+ refr0.w = unpackDepth(refruv0);
+
+ float4 refr1 = tex2D(GBufferColor, refruv1);
+ refr1.w = unpackDepth(refruv1);
+
+ float4 result = lerp(refr0, refr1, saturate(refr1.w - cpos.w));
+
+ // Estimate water absorption by a scaled depth difference
+ float depthfade = saturate((result.w - cpos.w) * WaterParams.x + WaterParams.y);
+
+ // Since GBuffer depth is clamped we tone the refraction down after half of the range for a smooth fadeout
+ float gbuffade = saturate(cpos.w * (2.f / GBUFFER_MAX_DEPTH) - 1);
+
+ float fade = saturate(depthfade + gbuffade);
+
+ return lerp(result.rgb, waterColor, fade);
+}
+
+float3 getReflectedColor(float4 cpos, float3 wpos, float3 R)
+{
+ float3 result = 0;
+ float inside = 0;
+
+ float distance = CFG_SSR_START_DISTANCE;
+ float diff = 0;
+ float diffclamp = cpos.w * CFG_SSR_STEP_CLAMP;
+
+ float4 Pproj = cpos;
+ float4 Rproj = clipToScreen(mul(G(ViewProjection), float4(R, 0)));
+
+#ifndef GLSL
+ [unroll]
+#endif
+ for (int i = 0; i < CFG_SSR_STEPS; ++i)
+ {
+ distance += clamp(diff, -diffclamp, diffclamp);
+
+ float4 cposi = Pproj + Rproj * distance;
+ float2 uv = cposi.xy / cposi.w;
+ float depth = unpackDepth(uv);
+
+ diff = depth - cposi.w;
+ }
+
+ float4 cposi = Pproj + Rproj * distance;
+ float2 uv = cposi.xy / cposi.w;
+
+ // Ray hit has to be inside the screen bounds
+ float ufade = abs(uv.x - 0.5) < 0.5;
+ float vfade = abs(uv.y - 0.5) < 0.5;
+
+ // Fade reflections out with distance; use max(ray hit, original depth) to discard hits that are too far
+ // 4 - depth * 4 would give us fade out from 0.75 to 1; 3.9 makes sure reflections go to 0 slightly before GBUFFER_MAX_DEPTH
+ float wfade = saturate((4 - 0.1) - max(cpos.w, cposi.w) * (4.f / GBUFFER_MAX_DEPTH));
+
+ // Ray hit has to be reasonably close to where we started
+ float dfade = abs(diff) < CFG_SSR_DEPTH_CUTOFF;
+
+ // Avoid back-projection
+ float Vfade = Rproj.w > 0;
+
+ float fade = ufade * vfade * wfade * dfade * Vfade;
+
+ return lerp(texCUBE(EnvMap, R).rgb, tex2D(GBufferColor, uv).rgb, fade);
+}
+
+float4 WaterPS(VertexOutput IN): COLOR0
+{
+ float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
+ float shadow = light.a;
+
+ float3 w = IN.Weights_Wave.xyz;
+
+ // Use simplified normal reconstruction for LQ mobile (assumes flat water surface)
+#if defined(GLSLES) && !defined(PIN_HQ)
+ float3 normal = sampleNormalSimple(IN.Uv0, IN.Uv1, IN.Uv2, w);
+#else
+ float3 normal = sampleNormal(IN.Uv0, IN.Uv1, IN.Uv2, w, IN.Normal, IN.Tangents);
+#endif
+
+ // Flatten the normal for Fresnel and for reflections to make them less chaotic
+ float3 flatNormal = lerp(IN.Normal, normal, CFG_NORMAL_STRENGTH);
+
+ float3 waterColor = WaterColor.rgb;
+
+#ifdef PIN_HQ
+ float fade = saturate0(1 - IN.View_Depth.w * G(FadeDistance_GlowFactor).y);
+
+ float3 view = normalize(IN.View_Depth.xyz);
+
+ float fre = fresnel(dot(flatNormal, view)) * IN.Weights_Wave.w;
+
+ float3 position = G(CameraPosition) - IN.View_Depth.xyz;
+
+#ifdef PIN_GBUFFER
+ float3 refr = getRefractedColor(IN.PositionScreen, normal, waterColor);
+ float3 refl = getReflectedColor(IN.PositionScreen, position, reflect(-view, flatNormal));
+#else
+ float3 refr = waterColor;
+ float3 refl = texCUBE(EnvMap, reflect(-view, flatNormal)).rgb;
+#endif
+
+ float specularIntensity = CFG_SPECULAR * fade;
+ float specularPower = CFG_GLOSS;
+
+ float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + view))), specularPower));
+#else
+ float3 view = normalize(IN.View_Depth.xyz);
+
+ float fre = fresnel(dot(flatNormal, view));
+
+ float3 refr = waterColor;
+
+ float3 refl = texCUBE(EnvMap, reflect(-IN.View_Depth.xyz, flatNormal)).rgb;
+
+ float3 specular = 0;
+#endif
+
+ // Combine
+ float4 result;
+ result.rgb = lerp(refr, refl, fre) * (G(AmbientColor).rgb + G(Lamp0Color).rgb * shadow + light.rgb) + specular;
+ result.a = 1;
+
+ float fogAlpha = saturate(IN.LightPosition_Fog.w);
+
+ result.rgb = lerp(G(FogColor), result.rgb, fogAlpha);
+
+ return result;
+}
diff --git a/Client2016/shaders/source/ssao.hlsl b/Client2016/shaders/source/ssao.hlsl
new file mode 100644
index 0000000..fcdf566
--- /dev/null
+++ b/Client2016/shaders/source/ssao.hlsl
@@ -0,0 +1,349 @@
+#include "screenspace.hlsl"
+
+// tweakables
+#define SSAO_NUM_PAIRS 8
+#define SSAO_SPHERE_RAD 2.0f // world-space
+#define SSAO_MIN_PIXEL_RANGE 10.0f
+#define SSAO_MAX_PIXEL_RANGE 100.0f
+#define BLUR_DEPTH_DELTA 0.4f
+
+#define COMPOSITE_DEPTH_DELTA 0.02f
+#define COMPOSITE_DEPTH_DELTA2 0.4f
+
+TEX_DECLARE2D(depthBuffer, 0);
+TEX_DECLARE2D(randMap, 1);
+TEX_DECLARE2D(map, 2);
+TEX_DECLARE2D(geomMap, 3);
+TEX_DECLARE2D(colorMap, 4);
+
+VertexOutput_4uv ssaoDepthDown_vs(float4 p: POSITION)
+{
+ float2 uv = convertUv(p);
+
+ VertexOutput_4uv OUT;
+ OUT.p = convertPosition(p, 2);
+ OUT.uv = uv;
+
+ float2 uvOffset = TextureSize.zw * 0.25f;
+
+ OUT.uv12.xy = uv + uvOffset * float2(-1, -1);
+ OUT.uv12.zw = uv + uvOffset * float2(+1, -1);
+ OUT.uv34.xy = uv + uvOffset * float2(-1, +1);
+ OUT.uv34.zw = uv + uvOffset * float2(+1, +1);
+
+ return OUT;
+}
+
+// used for ssao blurring passes
+VertexOutput_8uv ssaoBlur_vs(float4 position, float2 uvOffset)
+{
+ float2 uv = convertUv(position);
+
+ VertexOutput_8uv OUT;
+ OUT.p = convertPosition(position, 2);
+ OUT.uv = uv;
+
+ OUT.uv12.xy = uv + 1 * uvOffset;
+ OUT.uv12.zw = uv + 2 * uvOffset;
+ OUT.uv34.xy = uv + 3 * uvOffset;
+ OUT.uv34.zw = uv + 4 * uvOffset;
+
+ OUT.uv56.xy = uv - 1 * uvOffset;
+ OUT.uv56.zw = uv - 2 * uvOffset;
+ OUT.uv78.xy = uv - 3 * uvOffset;
+ OUT.uv78.zw = uv - 4 * uvOffset;
+
+ return OUT;
+}
+
+VertexOutput_8uv ssaoBlurX_vs(float4 p: POSITION)
+{
+ return ssaoBlur_vs(p, float2(TextureSize.z * 1, 0));
+}
+
+VertexOutput_8uv ssaoBlurY_vs(float4 p: POSITION)
+{
+ return ssaoBlur_vs(p, float2(0, TextureSize.w * 1));
+}
+
+float unpackDepth( TEXTURE_IN_2D(s), float2 uv )
+{
+ float4 geomTex = tex2D(s, uv);
+ float d = geomTex.z * (1.0f/256.0f) + geomTex.w;
+ return d;
+}
+
+float getDepth( TEXTURE_IN_2D(s), float2 uv )
+{
+ return (float)tex2D(s,uv).r;
+}
+
+#define NUM_PAIRS SSAO_NUM_PAIRS
+#define RANGE 60.0/1024.0
+
+#define pi 3.14159265359
+#define RAD(X) ( (X) * (pi/180) )
+
+float2 GetRotatedSample(float i)
+{
+ return (i+1) / (NUM_PAIRS+2) * float2(cos( RAD(45) + i / NUM_PAIRS * 2 * pi ), sin( RAD(45) + i / NUM_PAIRS * 2 * pi ) );
+}
+
+#define NUM_SAMPLES NUM_PAIRS*2+1
+
+float4 ssao_ps(
+ VertexOutput IN): COLOR0
+{
+ float2 mapSize = TextureSize.xy;
+
+ float baseDepth = getDepth( TEXTURE(depthBuffer), IN.uv );
+
+ float4 noiseTex = tex2D(randMap, IN.uv*mapSize/4) * 2 - 1;
+
+ float2x2 rotation =
+ {
+ { noiseTex.y, noiseTex.x },
+ { -noiseTex.x, noiseTex.y }
+ };
+
+ float2 OFFSETS1[NUM_PAIRS] =
+ {
+ GetRotatedSample(0),
+ GetRotatedSample(1),
+ GetRotatedSample(2),
+ GetRotatedSample(3),
+ GetRotatedSample(4),
+ GetRotatedSample(5),
+#if NUM_PAIRS > 6
+ GetRotatedSample(6),
+ GetRotatedSample(7),
+#if NUM_PAIRS > 8
+ GetRotatedSample(8),
+ GetRotatedSample(9),
+ GetRotatedSample(10),
+ GetRotatedSample(11),
+#endif
+#endif
+ };
+
+ float occ = 1;
+
+ float sphereRadiusZB = (float) ( 2.0f / GBUFFER_MAX_DEPTH );
+
+#define MINPIXEL SSAO_MIN_PIXEL_RANGE
+#define MAXPIXEL SSAO_MAX_PIXEL_RANGE
+
+ float radiusTex = (float)clamp( 0.5*sphereRadiusZB / baseDepth, MINPIXEL / mapSize.x, MAXPIXEL / mapSize.y);
+
+ float numSamples = 2;
+
+ for(int i = 0; i < NUM_PAIRS; i++)
+ {
+ float2 offset1 = mul(rotation, OFFSETS1[i]);
+
+ float2 offseted1 = IN.uv + offset1 * radiusTex;
+ float2 offseted2 = IN.uv - offset1 * radiusTex;
+
+ float2 offsetDepth;
+ offsetDepth.x = getDepth( TEXTURE(depthBuffer), offseted1 );
+ offsetDepth.y = getDepth( TEXTURE(depthBuffer), offseted2 );
+
+ float2 diff = offsetDepth - baseDepth.xx;
+
+ float normalizedOffsetLen = (float)(i+1)/(NUM_PAIRS+2);
+
+ float segmentDiff = (float) ( 1.5f*sphereRadiusZB*sqrt(1-normalizedOffsetLen*normalizedOffsetLen) );
+
+ float2 normalizedDiff = (diff / segmentDiff) + 0.5;
+
+ float minDiff = min(normalizedDiff.x, normalizedDiff.y);
+
+ // At 0, full sample
+ // At -1, zero sample, zero weight
+
+ float sampleadd = (float) saturate(1+minDiff);
+
+ float a = (float)(saturate(normalizedDiff.x) + saturate(normalizedDiff.y))*sampleadd;
+ occ += a;
+ numSamples += 2 * sampleadd;
+ }
+
+ occ = occ / numSamples;
+
+ float finalocc = (float)saturate(occ*2);
+
+ if(baseDepth - (1.0f-1/256.0f) > 0)
+ finalocc += 1;
+
+ return float4(finalocc, finalocc, finalocc, 1);
+}
+
+// this function estimates depth discrepancy tolerance for the blur filter
+float depthTolerance( float baseDepth, float sphereRadiusZB )
+{
+ float ramp = 80; // tweak
+ return ( clamp( sphereRadiusZB * (baseDepth * ramp) , 0.1f * sphereRadiusZB, 40*sphereRadiusZB ) );
+}
+
+float ssaoBlur(
+ float2 uv,
+
+ float4 uv12,
+ float4 uv34,
+ float4 uv56,
+ float4 uv78,
+
+ TEXTURE_IN_2D(map),
+ TEXTURE_IN_2D(depthBuffer)
+ )
+{
+ float sphereRadiusZB = BLUR_DEPTH_DELTA / GBUFFER_MAX_DEPTH;
+ float4 i = { 1, 2, 3, 4 };
+ float4 iw = 4-i;
+ float4 denom = 1;
+
+
+ float4 sum = tex2D(map, uv).rrrr * denom;
+
+ float baseDepth = getDepth( TEXTURE(depthBuffer), uv );
+
+ float4 newDepth, delta, ssample, coef;
+
+ newDepth.x = getDepth( TEXTURE(depthBuffer), uv12.xy );
+ newDepth.y = getDepth( TEXTURE(depthBuffer), uv12.zw );
+ newDepth.z = getDepth( TEXTURE(depthBuffer), uv34.xy );
+ newDepth.w = getDepth( TEXTURE(depthBuffer), uv34.zw );
+
+ delta = (newDepth - baseDepth.xxxx);
+ coef = iw * ( abs(delta) < depthTolerance( baseDepth, sphereRadiusZB ).xxxx );
+
+
+ ssample.x = tex2D( map, uv12.xy ).r;
+ ssample.y = tex2D( map, uv12.zw ).r;
+ ssample.z = tex2D( map, uv34.xy ).r;
+ ssample.w = tex2D( map, uv34.zw ).r;
+
+ sum += ssample * coef;
+ denom += coef;
+
+ ////////////////////////////////////////
+
+ newDepth.x = getDepth( TEXTURE(depthBuffer), uv56.xy );
+ newDepth.y = getDepth( TEXTURE(depthBuffer), uv56.zw );
+ newDepth.z = getDepth( TEXTURE(depthBuffer), uv78.xy );
+ newDepth.w = getDepth( TEXTURE(depthBuffer), uv78.zw );
+
+ delta = newDepth - baseDepth.xxxx;
+ coef = iw * ( abs(delta) < depthTolerance( baseDepth, sphereRadiusZB ).xxxx );
+
+ ssample.x = tex2D( map, uv56.xy ).r;
+ ssample.y = tex2D( map, uv56.zw ).r;
+ ssample.z = tex2D( map, uv78.xy ).r;
+ ssample.w = tex2D( map, uv78.zw ).r;
+
+ sum += ssample * coef;
+ denom += coef;
+
+ return dot( sum, float4(1,1,1,1) ) / dot( denom, float4(1,1,1,1) );
+}
+
+
+float4 ssaoBlurX_ps(VertexOutput_8uv IN): COLOR0
+{
+ float ssaoTerm = ssaoBlur( IN.uv, IN.uv12, IN.uv34, IN.uv56, IN.uv78, TEXTURE(map), TEXTURE(depthBuffer));
+
+ return float4(ssaoTerm.xxx, 1);
+}
+
+#define SPECULAR_WEIGHT 3
+
+
+float4 ssaoBlurY_ps(VertexOutput_8uv IN): COLOR0
+{
+ float ssaoTerm = ssaoBlur( IN.uv, IN.uv12, IN.uv34, IN.uv56, IN.uv78, TEXTURE(map), TEXTURE(depthBuffer));
+
+ float4 geom = tex2D(geomMap, IN.uv);
+
+ float specular = geom.x;
+ float diffuse = geom.y + 0.001;
+
+ // Making specular kill SSAO faster, so it doesn't get capped by 1
+ return (SPECULAR_WEIGHT*specular + diffuse * ssaoTerm) / (SPECULAR_WEIGHT*specular + diffuse);
+}
+
+
+
+float4 ssaoDepthDown_ps( VertexOutput_4uv IN ) : COLOR0
+{
+
+ float4 d;
+ d.x = unpackDepth( TEXTURE(depthBuffer), IN.uv12.xy );
+ d.y = unpackDepth( TEXTURE(depthBuffer), IN.uv12.zw );
+ d.z = unpackDepth( TEXTURE(depthBuffer), IN.uv34.xy );
+ d.w = unpackDepth( TEXTURE(depthBuffer), IN.uv34.zw );
+
+ float2 tmp = min( d.xy, d.zw );
+ return min( tmp.x, tmp.y ).x;
+}
+
+VertexOutput_4uv ssaoComposit_vs(float4 p: POSITION)
+{
+ float2 uv = convertUv(p);
+
+ VertexOutput_4uv OUT;
+ OUT.p = convertPosition(p, 1);
+ OUT.uv = uv;
+
+ float2 uvOffset = TextureSize.zw * 2;
+
+ OUT.uv12.xy = uv + float2(uvOffset.x, 0);
+ OUT.uv12.zw = uv - float2(uvOffset.x, 0);
+ OUT.uv34.xy = uv + float2(0, uvOffset.y);
+ OUT.uv34.zw = uv - float2(0, uvOffset.y);
+
+ return OUT;
+}
+
+#define CMP_LESS(X,Y) ( (X) < (Y) )
+
+float4 ssaoComposit_ps(VertexOutput_4uv IN): COLOR0
+{
+ //return float4(1,0,0,0.5);
+ float depth_range = COMPOSITE_DEPTH_DELTA / GBUFFER_MAX_DEPTH;
+ float depth_range2 = COMPOSITE_DEPTH_DELTA2 / GBUFFER_MAX_DEPTH;
+
+ // we're here
+ float baseDepth = unpackDepth( TEXTURE(geomMap), IN.uv );
+ float ssaoTerm = 1.0f;
+
+ float depth = getDepth( TEXTURE(depthBuffer), IN.uv );
+ float diff = abs( depth - baseDepth );
+ ssaoTerm = tex2D( map, IN.uv ).x;
+
+ float chk1 = CMP_LESS( depth_range, diff ); // can we trust the base depth? 0 - yes, 1 - no
+ float4 ssaoTermNew = 0, chk2, depth2, diff2;
+
+ depth2.x = getDepth( TEXTURE(depthBuffer), IN.uv12.xy );
+ depth2.y = getDepth( TEXTURE(depthBuffer), IN.uv12.zw );
+ depth2.z = getDepth( TEXTURE(depthBuffer), IN.uv34.xy );
+ depth2.w = getDepth( TEXTURE(depthBuffer), IN.uv34.zw );
+
+ ssaoTermNew.x = tex2D( map, IN.uv12.xy ).x;
+ ssaoTermNew.y = tex2D( map, IN.uv12.zw ).x;
+ ssaoTermNew.z = tex2D( map, IN.uv34.xy ).x;
+ ssaoTermNew.w = tex2D( map, IN.uv34.zw ).x;
+
+ diff2 = abs( depth2 - baseDepth.xxxx );
+ chk2 = CMP_LESS( diff2, depth_range2.xxxx );
+
+ ssaoTermNew *= chk2;
+ float den = dot( chk2, 1 ); // + 1e-5f; - TODO: add this if we encounter glitches; //
+ ssaoTermNew.x = dot( ssaoTermNew, 1 ) / den;
+
+ // the final decision: pick the base sample or its estimate, if base depth in unauthorative
+ ssaoTerm = saturate(den*chk1) ? ssaoTermNew.x : ssaoTerm;
+
+ //return float4(ssaoTermNew.rgb,1);
+ float4 colorMapSample = tex2D(colorMap, IN.uv);
+ return float4(colorMapSample.rgb * ssaoTerm, colorMapSample.a);
+}
diff --git a/Client2016/shaders/source/texcomp.hlsl b/Client2016/shaders/source/texcomp.hlsl
new file mode 100644
index 0000000..79674ba
--- /dev/null
+++ b/Client2016/shaders/source/texcomp.hlsl
@@ -0,0 +1,39 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+ float2 Uv : TEXCOORD0;
+};
+
+VertexOutput TexCompVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = mul(G(ViewProjection), IN.Position);
+ OUT.Uv = IN.Uv;
+
+ return OUT;
+}
+
+TEX_DECLARE2D(DiffuseMap, 0);
+
+uniform float4 Color;
+
+float4 TexCompPS(VertexOutput IN): COLOR0
+{
+ return tex2Dbias(DiffuseMap, float4(IN.Uv, 0, -10)) * Color;
+}
+
+float4 TexCompPMAPS(VertexOutput IN): COLOR0
+{
+ float4 tex = tex2Dbias(DiffuseMap, float4(IN.Uv, 0, -10));
+
+ return float4(tex.rgb * tex.a * Color.rgb, tex.a * Color.a);
+}
diff --git a/Client2016/shaders/source/ui.hlsl b/Client2016/shaders/source/ui.hlsl
new file mode 100644
index 0000000..6688cc7
--- /dev/null
+++ b/Client2016/shaders/source/ui.hlsl
@@ -0,0 +1,58 @@
+#include "common.h"
+
+struct Appdata
+{
+ float4 Position : POSITION;
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VertexOutput
+{
+ float4 HPosition : POSITION;
+
+ float2 Uv : TEXCOORD0;
+ float4 Color : COLOR0;
+
+#if defined(PIN_FOG)
+ float FogFactor : TEXCOORD1;
+#endif
+};
+
+uniform float4 UIParams; // x = luminance sampling on/off, w = z offset
+TEX_DECLARE2D(DiffuseMap, 0);
+
+VertexOutput UIVS(Appdata IN)
+{
+ VertexOutput OUT = (VertexOutput)0;
+
+ OUT.HPosition = mul(G(ViewProjection), IN.Position);
+ OUT.HPosition.z -= UIParams.w; // against z-fighting
+
+ OUT.Uv = IN.Uv;
+ OUT.Color = IN.Color;
+
+#if defined(PIN_FOG)
+ OUT.FogFactor = (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w;
+#endif
+
+ return OUT;
+}
+
+float4 UIPS(VertexOutput IN): COLOR0
+{
+ float4 base;
+
+ if (UIParams.x > 0.5)
+ base = float4(1, 1, 1,tex2D(DiffuseMap, IN.Uv).r);
+ else
+ base = tex2D(DiffuseMap, IN.Uv);
+
+ float4 result = IN.Color * base;
+
+#if defined(PIN_FOG)
+ result.rgb = lerp(G(FogColor), result.rgb, saturate(IN.FogFactor));
+#endif
+
+ return result;
+}
diff --git a/Client2016/shaders/source/water.hlsl b/Client2016/shaders/source/water.hlsl
new file mode 100644
index 0000000..6c328c3
--- /dev/null
+++ b/Client2016/shaders/source/water.hlsl
@@ -0,0 +1,215 @@
+
+//
+// Water shader.
+// Big, fat and ugly.
+//
+// All (most) things considered, I have converged to this particular way of rendering water:
+//
+// Vertex waves
+// No transparency. Solid color for deep water.
+// Fresnel law, reflects environment.
+// Phong speculars.
+// Ripples via animated normal map. Adjustable intensity, speed and scale. Affect reflection and speculars.
+
+#include "common.h"
+
+WORLD_MATRIX(WorldMatrix);
+
+uniform float4 nmAnimLerp; // ratio between normal map frames
+uniform float4 waveParams; // .x = frequency .y = phase .z = height
+uniform float4 WaterColor; // deep water color
+
+#ifdef PIN_HQ
+# define WATER_LOD 1
+#else
+# define WATER_LOD 2
+#endif
+
+#define LODBIAS (-1)
+
+float fadeFactor( float3 wspos )
+{
+ return saturate( -0.4f + 1.4f*length( G(CameraPosition) - wspos.xyz ) * G(FadeDistance_GlowFactor).y );
+}
+
+float wave( float4 wspos )
+{
+ float x = sin( ( wspos.z - wspos.x - waveParams.y ) * waveParams.x );
+ float z = sin( ( wspos.z + wspos.x + waveParams.y ) * waveParams.x );
+ float p = (x + z) * waveParams.z;
+ return p - p * fadeFactor( wspos.xyz );
+}
+
+
+
+// perturbs the water mesh and vertex normals
+void makeWaves( inout float4 wspos, inout float3 wsnrm )
+{
+#if WATER_LOD == 0
+ float gridSize = 4.0f;
+
+ float4 wspos1 = wspos;
+ float4 wspos2 = wspos;
+
+ wspos1.x += gridSize;
+ wspos2.z += gridSize;
+
+ wspos.y += wave(wspos) ;
+ wspos1.y += wave(wspos1);
+ wspos2.y += wave(wspos2);
+
+ wsnrm = normalize( cross( wspos2.xyz - wspos.xyz, wspos1.xyz - wspos.xyz ) );
+#elif WATER_LOD == 1
+ wspos.y += wave( wspos );
+#else /* do n0thing */
+#endif
+}
+
+struct V2P
+{
+ float4 pos : POSITION;
+ float4 tc0Fog : TEXCOORD0;
+ float4 wspos : TEXCOORD1;
+ float3 wsnrm : TEXCOORD2;
+ float3 light : TEXCOORD3;
+ float3 fade : TEXCOORD4;
+};
+
+V2P water_vs(
+ ATTR_INT4 pos : POSITION,
+ ATTR_INT3 nrm : NORMAL
+)
+{
+ V2P o;
+
+ // Decode vertex data
+ float3 normal = (nrm - 127.0) / 127.0;
+
+ normal = normalize(normal);
+
+ float4 wspos = mul( WorldMatrix, pos );
+ float3 wsnrm = normal;
+
+ wspos.y -= 2*waveParams.z;
+
+ makeWaves( /*INOUT*/ wspos, /*INOUT*/ wsnrm );
+
+ o.wspos = wspos;
+ o.wsnrm = wsnrm;
+
+ if( normal.y < 0.01f ) o.wsnrm = normal;
+
+ // box mapping
+ //float3x2 m = { wspos.xz, wspos.xy, wspos.yz };
+ //float2 tcselect = mul( abs( nrm.yzx ), m );
+
+ float2 tcselect;
+ float3 wspostc = float3( wspos.x, -wspos.y, wspos.z );
+
+ tcselect.x = dot( abs( normal.yxz ), wspostc.xzx );
+ tcselect.y = dot( abs( normal.yxz ), wspostc.zyy );
+
+ o.pos = mul( G(ViewProjection), wspos );
+ o.tc0Fog.xy = tcselect * .05f;
+ o.tc0Fog.z = saturate( (G(FogParams).z - o.pos.w) * G(FogParams).w );
+ o.tc0Fog.w = LODBIAS;
+
+ o.light = lgridPrepareSample(lgridOffset(wspos.xyz, wsnrm.xyz));
+
+ o.fade.x = fadeFactor( wspos.xyz );
+ o.fade.y = (1-o.fade.x) * saturate( dot( wsnrm, -G(Lamp0Dir) ) ) * 100;
+ o.fade.z = 1 - 0.9*saturate1( exp( -0.005 * length( G(CameraPosition) - wspos.xyz ) ) );
+
+ return o;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+TEX_DECLARE2D(NormalMap1, 0);
+TEX_DECLARE2D(NormalMap2, 1);
+TEX_DECLARECUBE(EnvMap, 2);
+LGRID_SAMPLER(LightMap, 3);
+TEX_DECLARE2D(LightMapLookup, 4);
+
+float3 pixelNormal( float4 tc0 )
+{
+ float4 nm1 = tex2Dbias( NormalMap1, tc0 );
+#if WATER_LOD <= 1
+ float4 nm2 = tex2Dbias( NormalMap2, tc0 );
+ float4 nm3 = lerp( nm1, nm2, nmAnimLerp.xxxx );
+#else
+ float4 nm3 = nm1;
+#endif
+ return nmapUnpack( nm3 );
+}
+
+// Fresnel approximation. N1 and N2 are refractive indices.
+// for above water, use n1 = 1, n2 = 1.3, for underwater use n1 = 1.3, n2 = 1
+float fresnel( float3 N, float3 V, float n1, float n2, float p, float fade )
+{
+#if WATER_LOD == 0
+ float r0 = (n1-n2)/(n1+n2);
+ r0 *= r0;
+ return r0 + (1-r0) * pow( 1 - abs( dot( normalize(N), V ) ), p );
+#else
+ return 0.1 + saturate( - 1.9 * abs( dot( N, V ) ) + 0.8); // HAXX!
+ //return 1 - 2 * abs( dot( N, V ) );
+#endif
+}
+
+float4 envColor( float3 N, float3 V, float fade )
+{
+ float3 dir = reflect( V, N );
+ return texCUBE(EnvMap, dir) * 0.91f;
+}
+
+float4 deepWaterColor(float4 light)
+{
+ //float4 tint = 5*float4( 0.1f, 0.1f, 0.13f, 1);
+ float4 tint = 0.8f*float4( 118, 143, 153, 255 ) / 255;
+ return (light + texCUBEbias( EnvMap, float4( 0,1,0, 10.0f) )) * tint;
+}
+
+
+//////////////////////////////////////////
+//////////////////////////////////////////
+
+
+
+float4 water_ps( V2P v ) : COLOR0
+{
+
+ float4 WaterColorTest = 0.5 * float4( 26, 169, 185, 0 ) / 255;
+ float4 FogColorTest = 0.8 * float4( 35, 107, 130, 0 ) / 255;
+
+ float3 N2 = v.wsnrm;
+ float3 N1 = pixelNormal( v.tc0Fog ).xzy;
+ float3 N3 = 0.5*(N2 + N1);
+
+ N3 = lerp( N3, N2, v.fade.z );
+
+ float3 L = /*normalize*/(-G(Lamp0Dir).xyz);
+ float3 E = normalize( G(CameraPosition) - v.wspos.xyz );
+
+ float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), v.light.xyz);
+
+ float fre = fresnel( N3, E, 1.0f, 1.3f, 5, v.fade.x );
+ float3 diffuse = deepWaterColor(light).rgb;
+ float3 env = envColor( N3, -E, v.fade.x ).rgb;
+
+ float3 R = reflect( -L, N1 );
+
+#if WATER_LOD <= 1
+ float specular = pow( saturate0( dot( R, E ) ), 1600 ) * L.y * 100; // baseline
+# ifndef GLSLES
+ specular = 0.65 * saturate1( specular * saturate0( light.a - 0.4f ) );
+# endif
+#else
+ float specular = 0;
+#endif
+
+ float3 result = lerp( diffuse, env, fre ) + specular.xxx;
+ result = lerp( G(FogColor).rgb, result, v.tc0Fog.z );
+
+ return float4( result, 1 );
+}
diff --git a/Client2016/shaders/source/wood.hlsl b/Client2016/shaders/source/wood.hlsl
new file mode 100644
index 0000000..2e7f1e2
--- /dev/null
+++ b/Client2016/shaders/source/wood.hlsl
@@ -0,0 +1,21 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.3
+
+#define CFG_SPECULAR_LOD 0.25
+#define CFG_GLOSS_LOD 32
+
+#define CFG_NORMAL_DETAIL_TILING 7
+#define CFG_NORMAL_DETAIL_SCALE 0.6
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#include "material.hlsl"
diff --git a/Client2016/shaders/source/woodplanks.hlsl b/Client2016/shaders/source/woodplanks.hlsl
new file mode 100644
index 0000000..685f947
--- /dev/null
+++ b/Client2016/shaders/source/woodplanks.hlsl
@@ -0,0 +1,23 @@
+#define CFG_TEXTURE_TILING 1
+
+#define CFG_DIFFUSE_SCALE 1
+#define CFG_SPECULAR_SCALE 2
+#define CFG_GLOSS_SCALE 256
+#define CFG_REFLECTION_SCALE 0
+
+#define CFG_NORMAL_SHADOW_SCALE 0.3
+
+#define CFG_SPECULAR_LOD 0.28
+#define CFG_GLOSS_LOD 53
+
+#define CFG_NORMAL_DETAIL_TILING 0
+#define CFG_NORMAL_DETAIL_SCALE 0
+
+#define CFG_FAR_TILING 0
+#define CFG_FAR_DIFFUSE_CUTOFF 0
+#define CFG_FAR_NORMAL_CUTOFF 0
+#define CFG_FAR_SPECULAR_CUTOFF 0
+
+#define CFG_OPT_BLEND_COLOR
+
+#include "material.hlsl"
diff --git a/Client2016/zlib1.dll b/Client2016/zlib1.dll
new file mode 100644
index 0000000..0c0e87c
Binary files /dev/null and b/Client2016/zlib1.dll differ
diff --git a/Client2018/AppSettings.xml b/Client2018/AppSettings.xml
new file mode 100644
index 0000000..59cc39e
--- /dev/null
+++ b/Client2018/AppSettings.xml
@@ -0,0 +1,5 @@
+
+
+ content
+ http://www.syntax.eco
+
\ No newline at end of file
diff --git a/Client2018/ReflectionMetadata.xml b/Client2018/ReflectionMetadata.xml
new file mode 100644
index 0000000..8600cf6
--- /dev/null
+++ b/Client2018/ReflectionMetadata.xml
@@ -0,0 +1,7215 @@
+
+ -
+
+
-
+
+ BindableFunction
+ Scripting
+ Allow functions defined in one script to be called by another script
+ 40
+ 66
+
+
+
-
+
-
+
+ Invoke
+ Causes the function assigned to OnInvoke to be called. Arguments passed to this function get passed to OnInvoke function.
+
+
+
+ -
+
-
+
+ OnInvoke
+ Should be defined as a function. This function is called when Invoke() is called. Number of arguments is variable.
+
+
+
+
+ -
+
+ BindableEvent
+ Scripting
+ Allow events defined in one script to be subscribed to by another script
+
+ 50
+ 67
+
+
-
+
-
+
+ Fire
+ Used to make the custom event fire (see Event for more info). Arguments can be variable length.
+
+
+
+ -
+
-
+
+ Event
+ This event fires when the Fire() method is used. Receives the variable length arguments from Fire().
+
+
+
+
+ -
+
+ TouchTransmitter
+ Used by networking and replication code to transmit touch events - no other purpose
+
+ false
+ 30
+ 37
+
+
+ -
+
+ ForceField
+ Avatar
+ Prevents joint breakage from explosions, and stops Humanoids from taking damage
+ 30
+ 37
+ Model
+ Model
+
+
+ -
+
+ PluginManager
+
+
+
+ -
+
+ TeleportService
+ Allows players to seamlessly leave a game and join another
+
+
-
+
+ CustomizedTeleportUI
+ true
+ Deprecated
+
+
+
+
+ -
+
+ Plugin
+
+
+
+ -
+
+ PluginMouse
+
+
+
+ -
+
+ Glue
+ BasePart
+ BasePart
+
+
+ -
+
+ CollectionService
+ A service which provides collections of instances based on tags assigned to them.
+
+
-
+
-
+
+ ItemAdded
+ true
+ Deprecated. Use GetInstanceAddedSignal instead.
+
+
+ -
+
+ ItemRemoved
+ true
+ Deprecated. Use GetInstancedRemovedSignal instead.
+
+
+
+ -
+
-
+
+ GetCollection
+ true
+ Deprecated. Use GetTagged instead.
+
+
+ -
+
+ GetTagged
+ Returns an array of all of the instances in the data model which have the given tag.
+
+
+ -
+
+ AddTag
+ Adds a tag to an instance.
+
+
+ -
+
+ RemoveTag
+ Removes a tag to an instance.
+
+
+ -
+
+ GetTags
+ Returns a list of all the collections that an instance belongs to.
+
+
+ -
+
+ HasTag
+ Returns whether the given instance has the given tag.
+
+
+ -
+
+ GetInstanceAddedSignal
+ Returns a signal that fires when the given tag either has a new instance with that tag added to the data model or that tag is assigned to an instance within the data model.
+
+
+ -
+
+ GetInstanceRemovedSignal
+ Returns a signal that fires when the given tag either has an instance with that tag removed from the data model or that tag is removed from an instance within the data model.
+
+
+
+
+ -
+
+ JointsService
+
+
+ -
+
+ RunService
+
+
+ -
+
+ BadgeService
+
+
+ -
+
+ LogService
+
+
+ -
+
+ AssetService
+ A service used to set and get information about assets stored on the Roblox website.
+
+
-
+
-
+
+ RevertAsset
+ Reverts a given place id to the version number provided. Returns true if successful on reverting, false otherwise.
+
+
+ -
+
+ SetPlacePermissions
+ Sets the permissions for a placeID to the place accessType. An optional table (inviteList) can be included that will set the accessType for only the player names provided. The table should be set up as an array of usernames (strings).
+
+
+ -
+
+ GetPlacePermissions
+ Given a placeID, this function will return a table with the permissions of the place. Useful for determining what kind of permissions a particular user may have for a place.
+
+
+ -
+
+ GetAssetVersions
+ Given a placeID, this function will return a table with the version info of the place. An optional arg of page number can be used to page through all revisions (a single page may hold about 50 revisions).
+
+
+ -
+
+ GetCreatorAssetID
+ Given a creationID, this function will return the asset that created the creationID. If no other asset created the given creationID, 0 is returned.
+
+
+
+
+ -
+
+ HttpService
+
+
-
+
-
+
+ HttpEnabled
+ true
+ Enabling http requests from scripts
+
+
+
+ -
+
-
+
+ GetAsync
+ Server
+
+
+ -
+
+ PostAsync
+ Server
+
+
+
+
+ -
+
+ InsertService
+ A service used to insert objects stored on the website into the game.
+
+
-
+
-
+
+ AllowClientInsertModels
+ true
+ Can be set in non-filtering-enabled places to allow LoadAsset to be used in LocalScripts.
+
+
+ -
+
+ AllowInsertFreeModels
+ false
+ true
+ -1
+ Allows free models to be inserted into place.
+
+
+
+ -
+
-
+
+ GetCollection
+ Returns a table for the assets stored in the category. A category is an setId from www.roblox.com that links to a set. <a href="http://wiki.roblox.com/index.php?title=API:Class/InsertService/GetCollection" target="_blank">More info on table format</a>. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ Insert
+ Inserts the Instance into the workspace. It is recommended to use Instance.Parent = game.Workspace instead, as this can cause issues currently.
+
+
+ -
+
+ ApproveAssetId
+ true
+ Deprecated
+
+
+ -
+
+ ApproveAssetVersionId
+ true
+ Deprecated
+
+
+
+
+ -
+
-
+
+ GetBaseSets
+ Returns a table containing a list of the various setIds that are ROBLOX approved. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetUserSets
+ Returns a table containing a list of the various setIds that correspond to argument 'userId'. <a href="http://wiki.roblox.com/index.php/Sets" target="_blank">More info on sets</a>
+
+
+ -
+
+ GetBaseCategories
+ true
+ Deprecated. Use GetBaseSets() instead.
+
+
+ -
+
+ GetUserCategories
+ true
+ Deprecated. Use GetUserSets() instead.
+
+
+ -
+
+ LoadAsset
+ Returns a Model containing the Instance that resides at AssetId on the web. This call will also yield the script until the model is returned. Script execution can still continue, however, if you use a <a href="http://wiki.roblox.com/index.php?title=Coroutine" target="_blank">coroutine</a>.
+
+
+ -
+
+ LoadAssetVersion
+ Similar to LoadAsset, but instead an AssetVersionId is passed in, which refers to a particular version of the asset which is not neccessarily the latest version.
+
+
+
+
+ -
+
+ Hat
+ Avatar
+ 30
+ 45
+ true
+
+
+ -
+
+ Accessory
+ Avatar
+ 30
+ 32
+ Model
+ Model
+
+
+ -
+
+ LocalBackpack
+
+
+ -
+
+ LocalBackpackItem
+
+
+ -
+
+ MotorFeature
+ true
+
+
+ -
+
+ Attachment
+ Constraints
+ 30
+ 81
+ PVInstance
+ PVInstance
+
+
+
-
+
-
+
+ Rotation
+
+
+ -
+
+ WorldRotation
+ true
+ Deprecated. Use WorldOrientation instead
+
+
+ -
+
+ Orientation
+ Euler angles applied in YXZ order
+
+
+ -
+
+ WorldOrientation
+ Euler angles applied in YXZ order
+
+
+
+
+
+ -
+
+ Constraint
+ Physics
+ 30
+ 86
+ BasePart
+ BasePart
+
+
-
+
-
+
+ Enabled
+ Toggles whether or not this constraint is enabled. Disabled constraints will not render in game.
+
+
+ -
+
+ Color
+ The color of the in-game visual.
+
+
+ -
+
+ Visible
+ Toggles the in-game visual associated with this constraint.
+
+
+
+
+
+ -
+
+ BallSocketConstraint
+ Constraints
+ 30
+ 86
+ BasePart
+ BasePart
+
+
-
+
-
+
+ LimitsEnabled
+ Enables the angular limit between the axis of Attachment0 and the axis of Attachment1.
+
+
+ -
+
+ UpperAngle
+ Maximum angle between the two main axes. Value in [0, 180].
+
+
+ -
+
+ Restitution
+ Restitution of the limit, or how elastic it is. Value in [0, 1].
+
+
+ -
+
+ TwistLimitsEnabled
+ Enables the angular limits around the main axis of Attachment1.
+
+
+ -
+
+ TwistUpperAngle
+ Upper angular limit around the axis of Attachment1. Value in [-180, 180].
+
+
+ -
+
+ TwistLowerAngle
+ Lower angular limit around the axis of Attachment1. Value in [-180, 180].
+
+
+ -
+
+ Radius
+ Radius of the in-game visual. Value in [0, inf).
+
+
+
+
+
+ -
+
+ RopeConstraint
+ Constraints
+ 30
+ 89
+ BasePart
+ BasePart
+
+
-
+
-
+
+ Length
+ The length of the rope or the maximum distance between the two attachments. Value in [0, inf).
+
+
+ -
+
+ Restitution
+ Restitution of the rope, or how elastic it is. Value in [0, 1].
+
+
+ -
+
+ CurrentDistance
+ Current distance between the two attachments. Value in [0, inf).
+
+
+ -
+
+ Thickness
+ The thickness of the in-game visual (diameter). Value in [0, inf).
+
+
+
+
+
+ -
+
+ RodConstraint
+ Constraints
+ 30
+ 90
+ BasePart
+ BasePart
+
+
-
+
-
+
+ Length
+ The length of the rod or the distance to be maintained between the two attachments. Value in [0, inf).
+
+
+ -
+
+ CurrentDistance
+ Current distance between the two attachments. Value in [0, inf).
+
+
+ -
+
+ Thickness
+ The thickness of the in-game visual (diameter). Value in [0, inf).
+
+
+
+
+
+ -
+
+ SpringConstraint
+ Constraints
+ 30
+ 91
+ BasePart
+ BasePart
+
+
-
+
-
+
+ LimitsEnabled
+ Enables limits on the length of the spring.
+
+
+ -
+
+ Stiffness
+ The stiffness parameter of the spring. Force is scaled based on distance from the free length. The units of this property are force / distance. Value in [0, inf).
+
+
+ -
+
+ Damping
+ The damping parameter of the spring. The force is scaled with respect to relative velocity. The units of this property are force / velocity. Value in [0, inf).
+
+
+ -
+
+ FreeLength
+ The distance (in studs) between the two attachments at which the spring exerts no stiffness force. Value in [0, inf).
+
+
+ -
+
+ MaxForce
+ The maximum force that the spring can apply. Useful to prevent instabilities. The units are mass * studs / seconds^2. Value in [0, inf).
+
+
+ -
+
+ MaxLength
+ Maximum spring length, or the maxium distance between the two attachments. Value in [0, inf).
+
+
+ -
+
+ MinLength
+ Minimum spring length, or the minimum distance between the two attachments. Value in [0, inf).
+
+
+ -
+
+ Radius
+ The radius of the in-game spring coil visual. Value in [0, inf).
+
+
+ -
+
+ Thickness
+ The thickness of the spring wire (diameter) in the in-game visual. Value in [0, inf).
+
+
+ -
+
+ Coils
+ The number of coils in the in-game visual. Value in [0, 8].
+
+
+ -
+
+ CurrentLength
+ Current distance between the two attachments. Value in [0, inf).
+
+
+
+
+
+ -
+
+ WeldConstraint
+ Constraints
+ 30
+ 94
+ PVInstance
+ PVInstance
+
+
+
+ -
+
+ HingeConstraint
+ Constraints
+ 30
+ 87
+ BasePart
+ BasePart
+
+
-
+
-
+
+ ActuatorType
+ Type of the rotational actuator: None, Motor, or Servo.
+
+
+ -
+
+ LimitsEnabled
+ Enables the angular limits on rotations around the main axis of Attachment0.
+
+
+ -
+
+ UpperAngle
+ Upper limit for the angle from the SecondaryAxis of Attachment0 to the SecondaryAxis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ LowerAngle
+ Lower limit for the angle from the SecondaryAxis of Attachment0 to the SecondaryAxis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ AngularRestitution
+ Restitution of the two limits, or how elastic they are. Value in [0,1].
+
+
+ -
+
+ AngularVelocity
+ The target angular velocity of the motor in radians per second around the rotation axis. Value in [0, inf).
+
+
+ -
+
+ MotorMaxTorque
+ The maximum torque the motor can apply to achieve the target angular velocity. Value in [0, inf).
+
+
+ -
+
+ MotorMaxAcceleration
+ The maximum angular acceleration of the motor in radians per second square. Value in [0, inf).
+
+
+ -
+
+ AngularSpeed
+ Target angular speed. This value is unsigned as the servo will always move toward its target. Value in [0, inf).
+
+
+ -
+
+ ServoMaxTorque
+ Maximum torque the servo motor can apply. Value in [0, inf).
+
+
+ -
+
+ TargetAngle
+ Target angle for the SecondaryAxis of Attachment1 from the SecondaryAxis of Attachment0 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ CurrentAngle
+ Signed angle between the SecondaryAxis of Attchement0 and the SecondaryAxis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ Radius
+ Radius of the in-game visual. Value in [0, inf).
+
+
+
+
+
+ -
+
+ SlidingBallConstraint
+ Constraints
+ 30
+ 88
+ BasePart
+ BasePart
+
+
-
+
-
+
+ ActuatorType
+ Type of linear actuator (along the axis of the slider): None, Motor, or Servo.
+
+
+ -
+
+ LimitsEnabled
+ Enables the limits on the linear motion along the axis of the slider.
+
+
+ -
+
+ LowerLimit
+ Lower limit for the position of Attachment1 with respect to Attachment0 along the slider axis. Value in (-inf, inf).
+
+
+ -
+
+ UpperLimit
+ Upper limit for the position of Attachment1 with respect to Attachment0 along the slider axis. Value in (-inf, inf).
+
+
+ -
+
+ Restitution
+ Restitution of the two limits, or how elastic they are. Value in [0, 1].
+
+
+ -
+
+ Velocity
+ The target linear velocity of the motor in studs per second along the slider axis. Value in (-inf, inf).
+
+
+ -
+
+ MotorMaxForce
+ The maximum force the motor can apply to achieve the target velocity. Units are mass * studs / seconds^2. Value in [0, inf).
+
+
+ -
+
+ MotorMaxAcceleration
+ The maximum acceleration of the motor in studs per second squared. Value in [0, inf).
+
+
+ -
+
+ Speed
+ Target speed in studs per second. This value is unsigned as the servo will always move toward its target. Value in [0, inf).
+
+
+ -
+
+ ServoMaxForce
+ Maximum force the servo motor can apply. Units are mass * studs / seconds^2. Value in [0, inf).
+
+
+ -
+
+ TargetPosition
+ Target position of Attachment1 with respect to Attachment0 along the slider axis. Value in (-inf, inf).
+
+
+ -
+
+ CurrentPosition
+ Current position of Attachment1 with respect to Attachment0 along the slider axis. Value in (-inf, inf).
+
+
+ -
+
+ Size
+ Size of the in-game visual associated with this constraint. Value in [0, inf).
+
+
+
+
+
+ -
+
+ PrismaticConstraint
+ Constraints
+ 30
+ 88
+ BasePart
+ BasePart
+
+
+
+ -
+
+ CylindricalConstraint
+ Constraints
+ 30
+ 95
+ BasePart
+ BasePart
+
+
-
+
-
+
+ InclinationAngle
+ Direction of the rotation axis as an angle from the x-axis in the xy-plane of Attachment0. Value in [-180, 180].
+
+
+ -
+
+ AngularActuatorType
+ Type of angular actuator: None, Motor, or Servo.
+
+
+ -
+
+ AngularLimitsEnabled
+ Enables the angular limits around the rotation axis.
+
+
+ -
+
+ UpperAngle
+ Upper limit for the angle (in degrees) between the reference axis and the SecondaryAxis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ LowerAngle
+ Lower limit for the angle (in degrees) between the reference axis and the SecondaryAxis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ AngularRestitution
+ Restitution of the two limits, or how elastic they are. Value in [0, 1].
+
+
+ -
+
+ AngularVelocity
+ The target angular velocity of the motor in radians per second around the rotation axis. Value in [0, inf).
+
+
+ -
+
+ MotorMaxTorque
+ The maximum torque the motor can apply to achieve the target angular velocity. The units are mass * studs^2 / second^2. Value in [0, inf).
+
+
+ -
+
+ MotorMaxAngularAcceleration
+ The maximum angular acceleration of the motor in radians per second squared. Value in [0, inf).
+
+
+ -
+
+ AngularSpeed
+ Target angular speed. This value is unsigned as the servo will always move toward its target. In radians per second. Value in [0, inf).
+
+
+ -
+
+ ServoMaxTorque
+ Maximum torque the servo motor can apply. The units are mass * studs^2 / second^2. Value in [0, inf).
+
+
+ -
+
+ TargetAngle
+ Target angle (in degrees) between the reference axis and the secondary axis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ CurrentAngle
+ Signed angle (in degrees) between the reference axis and the secondary axis of Attachment1 around the rotation axis. Value in [-180, 180].
+
+
+ -
+
+ WorldRotationAxis
+ The unit vector direction of the rotation axis in world coordinates.
+
+
+ -
+
+ RotationAxisVisible
+ Enable the visibility of the rotation axis.
+
+
+
+
+
+ -
+
+ AlignOrientation
+ Constraints
+ 30
+ 82
+ BasePart
+ BasePart
+
+
+ -
+
+ AlignPosition
+ Constraints
+ 30
+ 82
+ BasePart
+ BasePart
+
+
+ -
+
+ VectorForce
+ Constraints
+ 30
+ 82
+ Model
+ BasePart,Model
+
+
+ -
+
+ LineForce
+ Constraints
+ 30
+ 82
+ BasePart
+ BasePart
+
+
+ -
+
+ Torque
+ Constraints
+ 30
+ 82
+ BasePart
+ BasePart
+
+
+ -
+
+ Mouse
+ Used to receive input from the user. Actually tracks mouse events and keyboard events.
+
+
-
+
-
+
+ Hit
+ The CoordinateFrame of where the Mouse ray is currently hitting a 3D object in the Workspace. If the mouse is not over any 3D objects in the Workspace, this property is nil.
+
+
+ -
+
+ Icon
+ The current Texture of the Mouse Icon. Stored as a string, for more information on how to format the string <a href="http://wiki.roblox.com/index.php/Content" target="_blank">go here</a>
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking.
+
+
+ -
+
+ Origin
+ The CoordinateFrame of where the Mouse is when the mouse is not clicking. This CoordinateFrame will be very close to the Camera.CoordinateFrame.
+
+
+ -
+
+ Target
+ The Part the mouse is currently over. If the mouse is not currently over any object (on the skybox, for example) this property is nil.
+
+
+ -
+
+ TargetFilter
+ A Part or Model that the Mouse will ignore when trying to find the Target, TargetSurface and Hit.
+
+
+ -
+
+ TargetSurface
+ The NormalId (Top, Left, Down, etc.) of the face of the part the Mouse is currently over.
+
+
+ -
+
+ UnitRay
+ The Unit Ray from where the mouse is (Origin) to the current Mouse.Target.
+
+
+ -
+
+ ViewSizeX
+ The viewport's (game window) width in pixels.
+
+
+ -
+
+ ViewSizeY
+ The viewport's (game window) height in pixels.
+
+
+ -
+
+ X
+ The absolute pixel position of the Mouse along the x-axis of the viewport (game window). Values start at 0 on the left hand side of the screen and increase to the right.
+
+
+ -
+
+ Y
+ The absolute pixel position of the Mouse along the y-axis of the viewport (game window). Values start at 0 on the top of the screen and increase to the bottom.
+
+
+
+ -
+
-
+
+ Button1Down
+ Fired when the first button (usually the left, but could be another) on the mouse is depressed.
+
+
+ -
+
+ Button1Up
+ Fired when the first button (usually the left, but could be another) on the mouse is release.
+
+
+ -
+
+ Button2Down
+ This event is currently non-operational.
+
+
+ -
+
+ Button2Up
+ This event is currently non-operational.
+
+
+ -
+
+ Idle
+ Fired constantly when the mouse is not firing any other event (i.e. the mouse isn't moving, nor any buttons being pressed or depressed).
+
+
+ -
+
+ KeyDown
+ Fired when a user presses a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ KeyUp
+ Fired when a user releases a key on the keyboard. Argument is a string representation of the key. If the key has no string representation (such as space), the string passed in is the keycode for that character. Keycodes are currently in ASCII.
+
+
+ -
+
+ Move
+ Fired when the mouse X or Y member changes.
+
+
+ -
+
+ WheelBackward
+ This event is currently non-operational.
+
+
+ -
+
+ WheelForward
+ This event is currently non-operational.
+
+
+
+
+ -
+
+ ProfilingItem
+
+
+ -
+
+ ChangeHistoryService
+
+
+ -
+
+ RotateP
+ BasePart
+ BasePart
+
+
+ -
+
+ RotateV
+ BasePart
+ BasePart
+
+
+ -
+
+ ScriptContext
+
+
+ -
+
+ Selection
+
+
+ -
+
+ VelocityMotor
+ BasePart
+ BasePart
+
+
+ -
+
+ Weld
+ 200
+ 34
+ BasePart
+ BasePart
+
+
+ -
+
+ TaskScheduler
+ false
+
+
-
+
-
+
+ SetThreadShare
+ true
+ Deprecated
+
+
+
+
+ -
+
+ StatsItem
+
+
+ -
+
+ Snap
+ 200
+ 34
+ BasePart
+ BasePart
+
+
+ -
+
+ FileMesh
+ BasePart
+ BasePart
+
+
+ -
+
+ ClickDetector
+ 3D Interfaces
+ Raises mouse events for parent object
+ 30
+ 41
+ BasePart
+ PVInstance
+
+
-
+
-
+
+ MaxActivationDistance
+ The maximum distance a Player's character can be from the ClickDetector's parent Part that will allow the Player's mouse to fire events on this object.
+
+
+
+ -
+
-
+
+ MouseClick
+ Fired when a player clicks on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverEnter
+ Fired when a player's mouse enters on the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+ -
+
+ MouseHoverLeave
+ Fired when a player's mouse leaves the parent Part of ClickDetector. The argument provided is always of type Player.
+
+
+
+
+
+ -
+
+ Clothing
+ 20
+
+
+
+ -
+
+ Smoke
+ Effects
+ Makes the parent part or model object emit smoke
+ 30
+ 59
+ BasePart
+ BasePart
+
+
+
+ -
+
+ Trail
+ Effects
+ Makes two attachments emit trail when moving
+ 30
+ 93
+ Model
+ BasePart,Model
+
+
-
+
-
+
+ LightEmission
+ 0
+ 1
+
+
+
+ -
+
+ LightInfluence
+ 0
+ 1
+
+
+
+ -
+
+ ZOffset
+ -1
+ 1
+
+
+
+ -
+
+ Lifetime
+ 0
+ 20
+
+
+
+ -
+
+ TextureLength
+ 0
+ 5
+ 40
+
+
+
+ -
+
+ MinLength
+ 0
+ 1
+
+
+
+
+
+
+ -
+
+ Beam
+ Effects
+ Makes beam between two attachments
+ 30
+ 96
+ BasePart
+ BasePart,Model
+
+
-
+
-
+
+ LightEmission
+ 0
+ 1
+
+
+
+ -
+
+ LightInfluence
+ 0
+ 1
+
+
+
+ -
+
+ TextureSpeed
+ -1
+ 1
+
+
+
+ -
+
+ TextureLength
+ 0
+ 5
+ 40
+
+
+
+ -
+
+ CurveSize0
+ -10
+ 10
+
+
+
+ -
+
+ CurveSize1
+ -10
+ 10
+
+
+
+ -
+
+ ZOffset
+ -1
+ 1
+
+
+
+
+
+ -
+
+ ParticleEmitter
+ Effects
+ A generic particle system.
+ 30
+ 80
+ BasePart
+ BasePart,Attachment
+
+
-
+
-
+
+ LightEmission
+ 0
+ 1
+
+
+ -
+
+ LightInfluence
+ Specifies the amount of influence lighting has on the particle emmitter. A value of 0 is unlit, 1 is fully lit. Fractional values blend from unlit to lit.
+ 0
+ 1
+
+
+
+ -
+
+ Drag
+ 0
+ 5
+
+
+ -
+
+ VelocityInheritance
+ 0
+ 1
+
+
+ -
+
+ Rate
+ 0
+ 100
+ 100
+
+
+
+ -
+
+ Rotation
+ -180
+ 180
+ 72
+
+
+ -
+
+ RotSpeed
+ -360
+ 360
+ 72
+
+
+ -
+
+ Speed
+ 0
+ 100
+ 100
+
+
+ -
+
+ Lifetime
+ 0
+ 5
+
+
+
+
+
+ -
+
+ Sparkles
+ Effects
+ Makes the parent part or model object fantastic
+ 30
+ 42
+ BasePart
+ BasePart
+
+
+ -
+
+ Explosion
+ Effects
+ 30
+ 36
+ Creates an Explosion! This can be used as a purely graphical effect, or can be made to damage objects.
+ BasePart
+ Basepart,Model
+
+
-
+
-
+
+ BlastPressure
+ How much force this Explosion exerts on objects within it's BlastRadius. Setting this to 0 creates a purely graphical effect. A larger number will cause Parts to fly away at higher velocities.
+
+
+ -
+
+ BlastRadius
+ How big the Explosion is. This is a circle starting from the center of the Explosion's Position, the larger this property the larger the circle of destruction.
+
+
+ -
+
+ Position
+ Where the Explosion occurs in absolute world coordinates.
+
+
+ -
+
+ ExplosionType
+ Defines the behavior of the Explosion. <a href="http://wiki.roblox.com/index.php/ExplosionType" target="_blank">More info</a>
+
+
+
+
+ -
+
+ Fire
+ Effects
+ Makes the parent part or model object emit fire
+ 30
+ 61
+ BasePart
+ BasePart
+
+
-
+
-
+
+ Color
+ The color of the base of the fire. See SecondaryColor for more.
+
+
+ -
+
+ Heat
+ How hot the fire appears to be. The flame moves quicker the higher this value is set.
+
+
+ -
+
+ SecondaryColor
+ The color the fire interpolates to from Color. The longer a particle exists in the fire, the close to this color it becomes.
+
+
+ -
+
+ Size
+ How large the fire appears to be.
+
+
+
+
+ -
+
+ Seat
+ Interaction
+ 30
+ 35
+
+
+ -
+
+ Platform
+
+ Equivalent to a seat, except that the character stands up rather than sits down.
+ 30
+ 35
+
+
+ -
+
+ SkateboardPlatform
+ true
+ 30
+ 35
+
+
+ -
+
+ VehicleSeat
+ Interaction
+ Automatically finds and powers hinge joints in an assembly. Ignores motors.
+ 30
+ 35
+ Model
+ Model
+
+
+ -
+
+ Tool
+ Interaction
+ 30
+ 17
+ StarterPack
+ StarterPack,Backpack
+
+
+ -
+
+ Flag
+ true
+ 30
+ 38
+
+
-
+
-
+
+ CanBeDropped
+ If someone is carrying this flag, this bool determines whether or not they can drop it and run.
+
+
+ -
+
+ TeamColor
+ The Team this flag is for. Corresponds with the TeamColors in the Teams service.
+
+
+
+
+ -
+
+ FlagStand
+ true
+ 30
+ 39
+
+
+ -
+
+ BackpackItem
+ 20
+
+
+ -
+
+ Decal
+ 3D Interfaces
+ 40
+ 7
+ Descibes a texture that is placed on one of the sides of the Part it is parented to.
+ BasePart
+ BasePart
+
+
-
+
-
+
+ Face
+ Describes the face of the Part the decal will be applied to. <a href="http://wiki.roblox.com/index.php/NormalId" target="_blank">More info</a>
+
+
+ -
+
+ Shiny
+ How much light will appear to reflect off of the decal.
+
+
+ -
+
+ Specular
+ How light will react to the surface of the decal.
+
+
+ -
+
+ Transparency
+ How visible the decal is. 1 is completely invisible, while 0 is completely opaque
+ 0
+ 1
+
+
+
+
+ -
+
+ JointInstance
+ 200
+ 34
+
+
+ -
+
+ Message
+ 110
+ 33
+ true
+ StarterGui
+ StarterGui
+
+
+ -
+
+ Hint
+ true
+ 110
+ 33
+
+
+ -
+
+ IntValue
+ Values
+ 30
+ 4
+ Stores a int value in it's Value member. Useful to share int information across multiple scripts.
+
+
+ -
+
+ RayValue
+ Values
+ 30
+ 4
+ Stores a Ray value in it's Value member. Useful to share Ray information across multiple scripts.
+
+
+ -
+
+ IntConstrainedValue
+ true
+ Values
+ 30
+ 4
+ Stores an int value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share int information across multiple scripts.
+
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+ -
+
+ DoubleConstrainedValue
+ true
+ Values
+ 30
+ 4
+ Stores a double value in it's Value member. Value is clamped to be in range of Min and MaxValue. Useful to share double information across multiple scripts.
+
+
-
+
-
+
+ MaxValue
+ The maximum we allow this Value to be set. If Value is set higher than this, it automatically gets adjusted to MaxValue
+
+
+ -
+
+ MinValue
+ The minimum we allow this Value to be set. If Value is set lower than this, it automatically gets adjusted to MinValue
+
+
+
+
+ -
+
+ BoolValue
+ Values
+ 30
+ 4
+ Stores a boolean value in it's Value member. Useful to share boolean information across multiple scripts.
+
+
+ -
+
+ CustomEvent
+ 30
+ true
+ 4
+
+
+ -
+
+ CustomEventReceiver
+ 30
+ true
+ 4
+
+
+ -
+
+ FloorWire
+ true
+ 30
+ 4
+ Renders a thin cylinder than can be adorned with textures that 'flow' from one object to the next. Has basic pathing abilities and attempts to to not intersect anything. <a href="http://wiki.roblox.com/index.php/FloorWire_Guide" target="_blank">More info</a>
+
+
-
+
-
+
+ CycleOffset
+ Controls how the decals are positioned along the wire. <a href="http://wiki.roblox.com/index.php/CycleOffset" target="_blank">More info</a>
+
+
+ -
+
+ From
+ The object the FloorWire 'emits' from
+
+
+ -
+
+ StudsBetweenTextures
+ The space between two textures on the wire. Note: studs are relative depending on how far the camera is from the FloorWire.
+
+
+ -
+
+ Texture
+ The image we use to render the textures that flow from beginning to end of the FloorWire.
+
+
+ -
+
+ TextureSize
+ The size in studs of the Texture we use to flow from one object to the next.
+
+
+ -
+
+ To
+ The object the FloorWire 'emits' to
+
+
+ -
+
+ Velocity
+ The rate of travel that the textures flow along the wire.
+
+
+ -
+
+ WireRadius
+ How thick the wire is.
+
+
+
+
+ -
+
+ NumberValue
+ Values
+ 30
+ 4
+
+
+ -
+
+ StringValue
+ Values
+ 30
+ 4
+
+
+ -
+
+ Vector3Value
+ Values
+ 30
+ 4
+
+
+ -
+
+ CFrameValue
+ Values
+ 30
+ 4
+ Stores a CFrame value in it's Value member. Useful to share CFrame information across multiple scripts.
+
+
+ -
+
+ Color3Value
+ Values
+ 30
+ 4
+ Stores a Color3 value in it's Value member. Useful to share Color3 information across multiple scripts.
+
+
+ -
+
+ BrickColorValue
+ Values
+ 30
+ 4
+ Stores a BrickColor value in it's Value member. Useful to share BrickColor information across multiple scripts.
+
+
+ -
+
+ ValueBase
+ Values
+ 30
+ 4
+ The base class to all Value Objects.
+
+
+ -
+
+ ObjectValue
+ Values
+ 30
+ 4
+
+
+ -
+
+ SpecialMesh
+ Meshes
+ 30
+ 8
+ BasePart
+ BasePart
+
+
+ -
+
+ BlockMesh
+ Meshes
+ 30
+ 8
+ BasePart
+ BasePart
+
+
+ -
+
+ CylinderMesh
+ Meshes
+ 30
+ 8
+ BasePart
+ BasePart
+ true
+
+
+ -
+
+ BevelMesh
+ Meshes
+ false
+ true
+
+
+ -
+
+ DataModelMesh
+ false
+
+
+
+ -
+
+ Texture
+ 3D Interfaces
+ 40
+ 10
+ BasePart
+ BasePart
+
+
+ -
+
+ Sound
+ Sounds
+ 10
+ 11
+ SoundGroup,SoundService
+
+
-
+
-
+
+ play
+ true
+ Deprecated. Use Play() instead
+
+
+
+ -
+
-
+
+ PlayOnRemove
+ The sound will play when it is removed from the Workspace. Looped sounds don't play
+
+
+
+
+
+ -
+
+ EchoSoundEffect
+ An echo audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Delay
+ 0.1
+ 5
+ 100
+
+
+ -
+
+ Feedback
+ 0
+ 1
+ 100
+
+
+ -
+
+ DryLevel
+ -80
+ 10
+ 100
+
+
+ -
+
+ WetLevel
+ -80
+ 100
+ 100
+
+
+
+
+
+ -
+
+ FlangeSoundEffect
+ A Flanging audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Mix
+ 0
+ 1
+ 100
+
+
+ -
+
+ Depth
+ 0.01
+ 1
+ 100
+
+
+ -
+
+ Rate
+ 0
+ 20
+ 100
+
+
+
+
+
+ -
+
+ DistortionSoundEffect
+ A Distortion audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Level
+ 0
+ 1
+ 100
+
+
+
+
+
+ -
+
+ PitchShiftSoundEffect
+ A Pitch Shifting audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Octave
+ 0.5
+ 2
+ 100
+
+
+
+
+
+ -
+
+ ChorusSoundEffect
+ A Chorus audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Mix
+ 0
+ 1
+ 100
+
+
+ -
+
+ Rate
+ 0
+ 20
+ 100
+
+
+ -
+
+ Depth
+ 0
+ 1
+ 100
+
+
+
+
+
+ -
+
+ TremoloSoundEffect
+ A Tremolo audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Frequency
+ 0.1
+ 20
+ 100
+
+
+ -
+
+ Depth
+ 0
+ 1
+ 100
+
+
+ -
+
+ Duty
+ 0
+ 1
+ 100
+
+
+
+
+
+ -
+
+ ReverbSoundEffect
+ A Reverb audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ DecayTime
+ 0.1
+ 20
+ 100
+
+
+ -
+
+ Diffusion
+ 0
+ 1
+ 100
+
+
+ -
+
+ Density
+ 0
+ 1
+ 100
+
+
+ -
+
+ DryLevel
+ -80
+ 20
+ 100
+
+
+ -
+
+ WetLevel
+ -80
+ 20
+ 100
+
+
+
+
+
+ -
+
+ EqualizerSoundEffect
+ An Three-band Equalizer audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ LowGain
+ -80
+ 10
+ 100
+
+
+ -
+
+ MidGain
+ -80
+ 10
+ 100
+
+
+ -
+
+ HighGain
+ -80
+ 10
+ 100
+
+
+
+
+
+ -
+
+ CompressorSoundEffect
+ A Compressor audio effect that can be applied to a Sound or SoundGroup.
+ Sounds
+ 20
+ 84
+ Sound
+ Sound,SoundGroup
+
+
-
+
-
+
+ Threshold
+ -80
+ 0
+ 100
+
+
+ -
+
+ Attack
+ 0.001
+ 1
+ 100
+
+
+ -
+
+ Release
+ 0.001
+ 5
+ 100
+
+
+ -
+
+ Ratio
+ 1
+ 50
+ 100
+
+
+ -
+
+ GainMakeup
+ 0
+ 30
+ 100
+
+
+
+
+
+ -
+
+ SoundGroup
+ Sounds
+ 20
+ 85
+ SoundService
+ SoundService
+
+
-
+
+
+
+
+ -
+
+ StockSound
+ false
+ -1
+
+
+ -
+
+ SoundService
+ 500
+ 31
+
+
-
+
+
-
+
+ AmbientReverb
+
+ The ambient sound environment. May not work when using hardware sound
+
+
+ -
+
+ DopplerScale
+
+ The doppler scale is a general scaling factor for how much the pitch varies due to doppler shifting in 3D sound. Doppler is the pitch bending effect when a sound comes towards the listener or moves away from it, much like the effect you hear when a train goes past you with its horn sounding. With dopplerscale you can exaggerate or diminish the effect.
+
+
+ -
+
+ DistanceFactor
+
+ the relative distance factor, compared to 1.0 meters.
+
+
+ -
+
+ RolloffScale
+
+ Setting this value makes the sound drop off faster or slower. The higher the value, the faster volume will attenuate, and conversely the lower the value, the slower it will attenuate. For example a rolloff factor of 1 will simulate the real world, where as a value of 2 will make sounds attenuate 2 times quicker.
+
+
+
+
+ -
+
+ Backpack
+ 30
+ 20
+ false
+ Player
+
+
+ -
+
+ StarterPack
+ 30
+ 20
+
+
+ -
+
+ StarterPlayer
+ 30
+ 79
+
+
+ -
+
+ StarterGear
+ 30
+ 20
+ false
+
+
+
+ -
+
+ CoreGui
+ 30
+ 46
+
+
+
+
+ -
+
+ PluginGuiService
+ 30
+ 46
+
+
+
+
+ -
+
+ Studio
+
+
-
+
-
+
+ Show Plugin GUI Service in Explorer
+
+
+
+
+
+-
+
+ UIGridStyleLayout
+ GUI
+ false
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ SetCustomSortFunction
+ When SortOrder is set to Custom, this lua function is used to determine the ordering of elements. Function should take two arguments (each will be an Instance child to compare), and return true if a comes before b, otherwise return false. In other words, use this function the same way you would use a table.sort function. The sorting should be deterministic, otherwise sort will fail and fall back to name order.
+ true
+
+
+ -
+
+ ApplyLayout
+ Forces a relayout of all elements. Useful when sort is set to Custom.
+
+
+
+
+ -
+
-
+
+ SortOrder
+ Determines how we decide which element to place next. Can be Name or Custom. If using Custom, make sure SetCustomSortFunction was called with an appropriate sort function.
+
+
+ -
+
+ FillDirection
+ Determines which direction to fill the grid. Can be Horizontal or Vertical.
+
+
+ -
+
+ HorizontalAlignment
+ Determines how grid is placed within it's parent's container in the x direction. Can be Left, Center, or Right.
+
+
+ -
+
+ VerticalAlignment
+ Determines how grid is placed within it's parent's container in the y direction. Can be Top, Center, or Bottom.
+
+
+
+
+
+ -
+
+ UIListLayout
+ 30
+ 26
+ GUI
+ Sets the position of UI elements in a list. You can use a UIListLayout by parenting it to a GuiObject. The UIListLayout will then apply itself to all of its GuiObject siblings.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ Padding
+ Determines the amount of free space between each element. Can be set either using scale (Percentage of parent's size in the current direction) or offset (a static spacing value, similar to pixel size).
+
+
+
+
+
+ -
+
+ UIGridLayout
+ 30
+ 26
+ GUI
+ Sets the position of UI elements in a 2D grid (this can be modified to 1D grid for list layout). This will also set the elements to a particular size, although this can be overridden with particular constraints on elements. You can use a UIGridLayout by parenting it to a GuiObject. The UIGridLayout will then apply itself to all of its GuiObject siblings.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ CellSize
+ Denotes what size each element should be. Can be overridden by elements using constraints on individual elements.
+
+
+ -
+
+ CellPadding
+ How much space between elements there should be.
+
+
+ -
+
+ FillDirectionMaxCells
+ Determines how many cells over in the FillDirection we go before starting a new row or column. Set to 0 for max cell count. Will be clamped if this is set higher than the parent container allows room for.
+
+
+ -
+
+ AbsoluteSize
+ Returns the current size of the grid. If more elements are added, this can increase. If elements are removed this can decrease.
+
+
+ -
+
+ StartCorner
+ Which corner we start laying the elements out from. Can be TopLeft, TopRight, BottomLeft, BottomRight.
+
+
+
+
+
+
+ -
+
+ UIPageLayout
+ 30
+ 26
+ GUI
+ Creates a paged viewing window, like the home screen of a mobile device. You can use a UIPageLayout by parenting it to a GuiObject. The UIPageLayout will then apply itself to all of its GuiObject siblings.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ CurrentPage
+ The page that is either currently being displayed or is the target of the current animation.
+
+
+
+ -
+
+ Circular
+ Whether or not the page layout wraps around at the ends.
+
+
+
+ -
+
+ Padding
+ Determines the amount that pages are separated from each other by. Can be set either using scale (Percentage of parent's size in the current direction) or offset (a static spacing value, similar to pixel size).
+
+
+
+ -
+
+ Animated
+ Whether or not to animate transitions between pages.
+
+
+
+ -
+
+ EasingStyle
+ The easing style to use when performing an animation.
+
+
+
+ -
+
+ EasingDirection
+ The easing direction to use when performing an animation.
+
+
+
+ -
+
+ TweenTime
+ The length of the animation.
+
+
+
+
+ -
+
-
+
+ Next
+ Sets CurrentPage to the page after the current page and animates to it, or does nothing if there isn't a next page.
+
+
+ -
+
+ Previous
+ Sets CurrentPage to the page after the current page and animates to it, or does nothing if there isn't a next page.
+
+
+ -
+
+ JumpTo
+ If the instance is in the layout, then it sets CurrentPage to it and animtes to it. If circular layout is set, it will take the shortest path.
+
+
+ -
+
+ JumpToIndex
+ If the index is >= 0 and less than the size of the layout, acts like JumpTo. If it's out of bounds and circular is set, it will animate the full distance between the in-bounds index of CurrentPage and the new index.
+
+
+
+
+ -
+
-
+
+ PageEnter
+ Fires when a page comes into view, and is going to be rendered.
+
+
+ -
+
+ PageLeave
+ Fires when a page leaves view, and will not be rendered.
+
+
+ -
+
+ Stopped
+ Fires when an animation to CurrentPage is completed without being cancelled, and the view stops scrolling.
+
+
+
+
+
+ -
+
+ UITableLayout
+ 30
+ 26
+ GUI
+ Provides a layout of rows and columns that are sized based on the cells in them.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ Padding
+ The amount of padding to insert in between the cells of the table.
+
+
+
+ -
+
+ FillEmptySpaceRows
+ Whether the table should expand to fill the available space of its container, row-wise.
+
+
+
+ -
+
+ FillEmptySpaceColumns
+ Whether the table should expand to fill the available space of its container, column-wise.
+
+
+
+ -
+
+ MajorAxis
+ Whether the direct siblings are considered the rows or the columns. The children of the direct siblings are the columns or rows, respectively.
+
+
+
+
+
+ -
+
+ UISizeConstraint
+ 30
+ 26
+ GUI
+ Ensures a GuiObject does not become smaller or larger than the min and max size. If an element with a constraint is under the control of a layout, the constraint takes precedence in determining the element’s size, but not position. You can use a Constraint by parenting it to the element you wish to constrain.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ MinSize
+ The smallest size the GuiObject is allowed to be.
+
+
+ -
+
+ MaxSize
+ The biggest size the GuiObject is allowed to be.
+
+
+
+
+
+ -
+
+ UITextSizeConstraint
+ 30
+ 26
+ GUI
+ Ensures a GuiObject with text does not allow the font size to become larger or smaller than min and max text sizes. If an element with a constraint is under the control of a layout, the constraint takes precedence in determining the element’s size, but not position. You can use a Constraint by parenting it to the element you wish to constrain.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ MinTextSize
+ The smallest size the font is allowed to be.
+
+
+ -
+
+ MaxTextSize
+ The biggest size the font is allowed to be.
+
+
+
+
+
+ -
+
+ UIAspectRatioConstraint
+ 30
+ 26
+ GUI
+ Ensures a GuiObject will always have a particular aspect ratio. If an element with a constraint is under the control of a layout, the constraint takes precedence in determining the element’s size, but not position. You can use a Constraint by parenting it to the element you wish to constrain.
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ AspectRatio
+ The aspect ratio to maintain. This is the width/height. Only positive numbers allowed.
+
+
+ -
+
+ AspectType
+ Describes how the aspect ratio will determine its size. Options are FitWithinMaxSize, ScaleWithParentSize. FitWithinMaxSize will make the element the maximum size it can be within the current possible AbsoluteSize of the element while maintaining the AspectRatio. ScaleWithParentSize will make the element the closest to the parent element’s maximum size while maintaining aspect ratio.
+
+
+ -
+
+ DominantAxis
+ Describes which axis to use when determining the new size of the element, while keeping respect to the aspect ratio.
+
+
+
+
+
+ -
+
+ UIScale
+ 30
+ 26
+ GUI
+ Uniformly scales a GUI object and all its children.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ Scale
+ The scale factor to apply.
+
+
+
+
+
+ -
+
+ UIPadding
+ 30
+ 26
+ GUI
+ Insets the children of the GuiObject this is parented to, by the specified padding.
+ GuiBase2d
+ GuiObject,GuiBase2d
+
+
+
-
+
-
+
+ PaddingLeft
+ The padding to apply on the left side relative to the parent's normal size.
+
+
+ -
+
+ PaddingRight
+ The padding to apply on the right side relative to the parent's normal size.
+
+
+ -
+
+ PaddingTop
+ The padding to apply on the top side relative to the parent's normal size.
+
+
+ -
+
+ PaddingBottom
+ The padding to apply on the bottom side relative to the parent's normal size.
+
+
+
+
+
+ -
+
+ TweenBase
+ false
+
+
+
-
+
-
+
+ PlaybackState
+ The current state of how the tween is animating. Possible values are Begin, Playing, Paused, Completed and Cancelled. This property is modified by using functions such as Tween:Play(), Tween:Pause(), and Tween:Cancel(). Read-only.
+
+
+
+
+ -
+
-
+
+ Play
+ Starts or resumes (if Tween.PlaybackState is Paused) the tween animation. If current PlaybackState is Cancelled, this property will reset the tween to the beginning properties and play the animations from the beginning.
+
+
+ -
+
+ Pause
+ Temporarily stops the tween animation. Animation can be resumed by calling Play().
+
+
+ -
+
+ Cancel
+ Stops the tween animation. Animation can be restarted by calling Play(). Animation will start from the beginning values.
+
+
+
+
+ -
+
-
+
+ Completed
+ Fires when the tween either reaches PlaybackState Completed or Cancelled. PlaybackState of one of these types is passed as the first arg to the function listening to this event.
+
+
+
+
+
+
+ -
+
+ Tween
+ An object linked to an instance that animates properties on the instance over a specified period of time. Useful for easily moving UI objects around, rotating objects, etc. without having to write a lot of code. To create a new tween, please use TweenService:Create.
+
+
+
-
+
-
+
+ Instance
+ The object this tween is operating on. Read-only.
+
+
+
+ -
+
+ TweenInfo
+ Specifies how the tween animates. Read-only.
+
+
+
+
+
+
+ -
+
+ TweenService
+ Service responsible for creating tweens on instances.
+
+
+
-
+
-
+
-
+
+ Create
+ Creates a Tween object bound to a particular Instance. The first arg is the Instance to tween. The second arg is a TweenInfo struct, which specifies how a tween should behave. The third arg is a table, which should specify the properties to tween as keys, with the end value specified as values to the keys.
+
+
+
+
+
+
+
+ -
+
+ StarterGui
+ 30
+ 46
+
+
+
-
+
-
+
+ SetCoreGuiEnabled
+ Will stop/begin certain core gui elements being rendered. See CoreGuiType for core guis that can be modified.
+
+
+ -
+
+ GetCoreGuiEnabled
+ Returns a boolean describing whether a CoreGuiType is currently being rendered.
+
+
+
+
+
+ -
+
+ GuiService
+ The GuiService is a special service, which currently allows developers to control what GuiObject is currently being selected by the Gamepad Gui navigator, and allows clients to check if Roblox's main menu is currently open. This service has a lot of hidden members, which are mainly used internally by Roblox's CoreScripts.
+
+
+
-
+
-
+
+ GetGuiInset
+ Returns a Tuple containing two Vector2 values representing the offset of user GUIs in pixels from the top right corner of the screen and the bottom right corner of the screen respectively.
+
+
+
+
+
+ -
+
+ ContextActionService
+ A service used to bind input to various lua functions.
+
+
+
-
+
-
+
+ BindAction
+ Binds 'functionToBind' to fire when any 'inputTypes' happen. InputTypes can be variable in number and type. Types can be Enum.KeyCode, single character strings corresponding to keys, or Enum.UserInputType. 'actionName' is a key used by many other ContextActionService functions to query state. 'createTouchButton' if true will create a button on screen on touch devices. This button will fire 'functionToBind' with three arguments: first argument is the actionName, second argument is the UserInputState of the input, and the third is the InputObject that fired this function. If 'functionToBind' yields or returns nil or Enum.ContextActionResult.Sink, the input will be sunk. If it returns Enum.ContextActionResult.Pass, the next bound action in the stack will be invoked.
+
+
+ -
+
+ SetTitle
+ If 'actionName' key contains a bound action, then 'title' is set as the title of the touch button. Does nothing if a touch button was not created. No guarantees are made whether title will be set when button is manipulated.
+
+
+ -
+
+ SetDescription
+ If 'actionName' key contains a bound action, then 'description' is set as the description of the bound action. This description will appear for users in a listing of current actions availables.
+
+
+ -
+
+ SetImage
+ If 'actionName' key contains a bound action, then 'image' is set as the image of the touch button. Does nothing if a touch button was not created. No guarantees are made whether image will be set when button is manipulated.
+
+
+ -
+
+ SetPosition
+ If 'actionName' key contains a bound action, then 'position' is set as the position of the touch button. Does nothing if a touch button was not created. No guarantees are made whether position will be set when button is manipulated.
+
+
+ -
+
+ UnbindAction
+ If 'actionName' key contains a bound action, removes function from being called by all input that it was bound by (if function was also bound by a different action name as well, those bound input are still active). Will also remove any touch button created (if button was manipulated manually there is no guarantee it will be cleaned up).
+
+
+ -
+
+ UnbindAllActions
+ Removes all functions bound. No actionNames will remain. All touch buttons will be removed. If button was manipulated manually there is no guarantee it will be cleaned up.
+
+
+ -
+
+ GetBoundActionInfo
+ Returns a table with info regarding the function bound with 'actionName'. Table has the keys 'title' (current title that was set with SetTitle) 'image' (image set with SetImage) 'description' (description set with SetDescription) 'inputTypes' (tuple containing all input bound for this 'actionName') 'createTouchButton' (whether or not we created a touch button for this 'actionName').
+
+
+ -
+
+ GetAllBoundActionInfo
+ Returns a table with all bound action info. Each entry is a key with 'actionName' and value being the same table you would get from ContextActionService:GetBoundActionInfo('actionName').
+
+
+
+
+ -
+
-
+
+ GetButton
+ If 'actionName' key contains a bound action, then this will return the touch button (if was created). Returns nil if a touch button was not created. No guarantees are made whether button will be retrievable when button is manipulated.
+
+
+
+
+
+ -
+
+ PointsService
+ A service used to query and award points for Roblox users using the universal point system.
+ true
+
+
+
-
+
-
+
+ PointsAwarded
+ Fired when points are successfully awarded 'userId'. Also returns the updated balance of points for usedId in universe via 'userBalanceInUniverse', total points via 'userTotalBalance', and the amount points that were awarded via 'pointsAwarded'. This event fires on the server and also all clients in the game that awarded the points.
+
+
+
+
+ -
+
-
+
+ AwardPoints
+ Will attempt to award the 'amount' points to 'userId', returns 'userId' awarded to, the number of points awarded, the new point total the user has in the game, and the total number of points the user now has. Will also fire PointsService.PointsAwarded. Works with server scripts ONLY.
+
+
+ -
+
+ GetPointBalance
+ Returns the overall balance of points that player with userId has (the sum of all points across all games). Works with server scripts ONLY.
+
+
+ -
+
+ GetGamePointBalance
+ Returns the balance of points that player with userId has in the current game (all placeID points combined within the game). Works with server scripts ONLY.
+
+
+ -
+
+ GetAwardablePoints
+ Returns the number of points the current universe can award to players. Works with server scripts ONLY.
+
+
+
+
+
+ -
+
+ Chat
+ 510
+ 33
+
+
-
+
-
+
+
+
+
+ -
+
+ ChatService
+ 510
+ 33
+
+
-
+
+
+
+ -
+
+ LocalizationTable
+ 30
+ 97
+ Localization
+ LocalizationService
+ A database of strings used in the game and their translations.
+
+
+
+ -
+
+ LocalizationService
+ 530
+ 92
+
+
-
+
+ PreferredLanguage
+ Gets the system's preferred language (A Language enum).
+
+
+ -
+
+ GetLocaleId
+ Gets the system's LocaleId (Ex: "en-US").
+
+
+
+
+ -
+
+ MarketplaceService
+ 46
+
+
+
-
+
-
+
+ PromptPurchase
+ Will prompt 'player' to purchase the item associated with 'assetId'. 'equipIfPurchased' is an optional argument that will give the item to the player immediately if they buy it (only applies to gear). 'currencyType' is also optional and will attempt to prompt the user with a specified currency if the product can be purchased with this currency, otherwise we use the default currency of the product.
+
+
+
+
+ -
+
-
+
+ GetProductInfo
+ Takes one argument "assetId" which should be a number of an asset on www.roblox.com. Returns a table containing the product information (if this process fails, returns an empty table).
+
+
+ -
+
+ PlayerOwnsAsset
+ Checks to see if 'Player' owns the product associated with 'assetId'. Returns true if the player owns it, false otherwise. This call will produce a warning if called on a guest player.
+
+
+
+ -
+
-
+
+ ProcessReceipt
+ Callback that is executed for pending Developer Product receipts.
+
+ If this function does not return Enum.ProductPurchaseDecision.PurchaseGranted, then you will not be granted the money for the purchase!
+
+ The callback will be invoked with a table, containing the following informational fields:
+ PlayerId - the id of the player making the purchase.
+ PlaceIdWherePurchased - the specific place where the purchase was made.
+ PurchaseId - a unique identifier for the purchase, should be used to prevent granting an item multiple times for one purchase.
+ ProductId - the id of the purchased product.
+ CurrencyType - the type of currency used (Tix, Robux).
+ CurrencySpent - the amount of currency spent on the product for this purchase.
+
+
+
+
+ -
+
-
+
+ PromptPurchaseFinished
+ Fired when a 'player' dismisses a purchase dialog for 'assetId'. If the player purchased the item 'isPurchased' will be true, otherwise it will be false. This call will produce a warning if called on a guest player.
+
+
+
+
+
+ -
+
+ UserInputService
+
+
-
+
-
+
+ TouchEnabled
+ Returns true if the local device accepts touch input, false otherwise.
+
+
+ -
+
+ KeyboardEnabled
+ Returns true if the local device accepts keyboard input, false otherwise.
+
+
+ -
+
+ MouseEnabled
+ Returns true if the local device accepts mouse input, false otherwise.
+
+
+ -
+
+ AccelerometerEnabled
+ Returns true if the local device has an accelerometer, false otherwise.
+
+
+ -
+
+ GyroscopeEnabled
+ Returns true if the local device has an gyroscope, false otherwise.
+
+
+
+
+ -
+
-
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ TouchStarted
+ Fired when a user places their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchMoved
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchEnded
+ Fired when a user moves their finger on a TouchEnabled device. 'touch' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally. This event will always fire regardless of game state.
+
+
+
+ -
+
+ TextBoxFocused
+ Fired when a user clicks/taps on a textbox to begin text entry. Argument is the textbox that was put in focus. This also fires if a textbox forces focus on the user. This event only fires locally.
+
+
+ -
+
+ TextBoxFocusReleased
+ Fired when a user stops text entry into a textbox (usually by pressing return or clicking/tapping somewhere else on the screen). Argument is the textbox that was taken out of focus. This event only fires locally.
+
+
+ -
+
+ DeviceAccelerationChanged
+ Fired when a user moves a device that has an accelerometer. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. This event only fires locally.
+
+
+ -
+
+ DeviceGravityChanged
+ Fired when the force of gravity changes on a device that has an accelerometer. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. This event only fires locally.
+
+
+ -
+
+ DeviceRotationChanged
+ Fired when a user rotates a device that has an gyroscope. This is fired with an InputObject, which has type Enum.InputType.Gyroscope, and position that shows total rotation in each local device axis. The delta property describes the amount of rotation that last happened. A second argument of Vector4 is the device's current quaternion rotation in reference to it's default reference frame. This event only fires locally.
+
+
+
+
+ -
+
-
+
+ GetDeviceAcceleration
+ Returns an InputObject that describes the device's current acceleration. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. The delta property describes the amount of rotation that last happened. This event only fires locally.
+
+
+ -
+
+ GetDeviceGravity
+ Returns an InputObject that describes the device's current gravity vector. This is fired with an InputObject, which has type Enum.InputType.Accelerometer, and position that shows the g force in each local device axis. The delta property describes the amount of rotation that last happened. This event only fires locally.
+
+
+ -
+
+ GetDeviceRotation
+ Returns an InputObject and a Vector4 that describes the device's current rotation vector. This is fired with an InputObject, which has type Enum.InputType.Gyroscope, and position that shows total rotation in each local device axis. The delta property describes the amount of rotation that last happened. The Vector4 is the device's current quaternion rotation in reference to it's default reference frame. This event only fires locally.
+
+
+
+
+
+ -
+
+ Sky
+ 5
+ 28
+ Lighting
+ Lighting
+
+
+ -
+
+ ColorCorrectionEffect
+ Post Processing Effects
+ 20
+ 83
+ Lighting
+
+
-
+
-
+
+ Brightness
+ -1
+ 1
+
+
+ -
+
+ Contrast
+ -1
+ 1
+
+
+ -
+
+ Saturation
+ -1
+ 1
+
+
+
+
+ -
+
+ BloomEffect
+ Post Processing Effects
+ 20
+ 83
+ Lighting
+
+
-
+
-
+
+ Intensity
+ 0
+ 1
+
+
+ -
+
+ Threshold
+ 0.8
+ 4
+ 1000
+
+
+ -
+
+ Size
+ 0
+ 56
+ 56
+
+
+
+
+
+ -
+
+ BlurEffect
+ Post Processing Effects
+ 20
+ 83
+ Lighting
+
+
-
+
-
+
+ Size
+ 0
+ 56
+ 56
+
+
+
+
+
+ -
+
+ SunRaysEffect
+ Post Processing Effects
+ 20
+ 83
+ Lighting
+
+
-
+
-
+
+ Intensity
+ 0
+ 1
+
+
+ -
+
+ Spread
+ 0
+ 1
+
+
+
+
+
+ -
+
+ Motor
+ 20
+ false
+ BasePart
+ BasePart
+
+
+ -
+
+ Humanoid
+ Avatar
+ 30
+ 9
+ Model
+ Model
+
+
-
+
+
-
+
+ MoveTo
+ Attempts to move the Humanoid and it's associated character to 'part'. 'location' is used as an offset from part's origin.
+
+
+ -
+
+ Jump
+
+
+ -
+
+ Sit
+
+
+ -
+
+ TakeDamage
+ Decreases health by the amount. Use this instead of changing health directly to make sure weapons are filtered for things such as ForceField(s).
+
+
+ -
+
+ UnequipTools
+
+ Takes any active gear/tools that the Humanoid is using and puts them into the backpack. This function only works on Humanoids with a corresponding Player.
+
+
+ -
+
+ EquipTool
+
+ Takes a specified tool and equips it to the Humanoid's Character. Tool argument should be of type 'Tool'.
+
+
+ -
+
+ ReplaceBodyPartR15
+ Replaces the desired bodypart on the Humanoid's Character using a specified Enum.BodyPartR15 and BasePart. Returns a success boolean.
+
+
+ -
+
+ GetBodyPartR15
+ Returns a Enum.BodyPartR15 given a body part in the Humanoid's Character.
+
+
+
+ -
+
-
+
+ NameOcclusion
+
+ Sets how to display other humanoid names to this humanoid's player. <a href="http://wiki.roblox.com/index.php/NameOcclusion" target="_blank">More info</a>
+
+
+ Health
+ How many hit points the Humanoid has. When this number reaches 0 or goes below 0, the Humanoid's character falls apart and will respawn.
+
+
+ MaxHealth
+ The maximum number of hit points a Humanoid's health can reach. If the Humanoid's health is set over this amount, the health gets set to this value.
+
+
+ TargetPoint
+ The location that the Humanoid is trying to walk to.
+
+
+ Torso
+ Humanoid.RootPart will be the preferred way of getting a character's humanoid root part.
+ true
+
+
+ LeftLeg
+ In R6 this property get the player's left leg. In R15 this gets nothing.
+ true
+
+
+ RightLeg
+ In R6 this property get the player's right leg. In R15 this gets nothing.
+ true
+
+
+
+
+ -
+
+ BodyColors
+ Avatar
+ 20
+ Model
+ Model
+
+
+ -
+
+ Shirt
+ Avatar
+ 20
+ 43
+ Model
+ Model
+
+
+ -
+
+ Pants
+ Avatar
+ 20
+ 44
+ Model
+ Model
+
+
+ -
+
+ ShirtGraphic
+ Avatar
+ 20
+ 40
+ Model
+ Model
+
+
+ -
+
+ Skin
+ true
+ 20
+
+
+ -
+
+ DebugSettings
+ false
+ 20
+
+
+ -
+
+ FaceInstance
+ false
+
+
+ -
+
+ GameSettings
+ false
+ 20
+
+
+ -
+
+ GlobalSettings
+ false
+ 20
+
+
+ -
+
+ Item
+ false
+ 20
+
+
+ -
+
+ NetworkPeer
+ false
+
+
+ -
+
+ NetworkSettings
+ false
+ 20
+
+
+ -
+
+ PVInstance
+ false
+
+
-
+
-
+
+ CoordinateFrame
+ true
+ Deprecated. Use CFrame instead
+
+
+
+
+ -
+
+ PackageLink
+ 1
+ 98
+ false
+
+
-
+
-
+
+ Status
+ Current status of the Package
+ true
+
+
+
+
+ -
+
+ RenderSettings
+ false
+ 20
+
+
+ -
+
+ RootInstance
+ false
+
+
+ -
+
+ ServiceProvider
+ false
+
+
-
+
-
+
+ service
+ true
+ Use GetService() instead
+
+
+ -
+
+ GetService
+ Instance:isService:0
+
+
+ -
+
+ FindService
+ Instance:isService:0
+
+
+
+
+ -
+
+ ProfilingItem
+ false
+
+
+ -
+
+ NetworkMarker
+ false
+
+
+
+ -
+
+ Hopper
+ true
+ Use StarterPack instead
+ 20
+
+
+
+ -
+
+ Instance
+ false
+
+
+
-
+
-
+
+ Archivable
+ Determines whether or not an Instance can be saved when the game closes/attempts to save the game. Note: this only applies to games that use Data Persistence, or SavePlaceAsync.
+
+
+ -
+
+ ClassName
+ The string name of this Instance's most derived class.
+
+
+ -
+
+ Parent
+ The Instance that is directly above this Instance in the tree.
+
+
+
+
+ -
+
+
-
+
+ GetDebugId
+ false
+ This function is for internal testing. Don't use in production code
+
+
+ -
+
+ Clone
+ Returns a copy of this Object and all its children. The copy's Parent is nil
+
+
+ -
+
+ clone
+ true
+ Use Clone() instead
+
+
+ -
+
+ isA
+ true
+ Use IsA() instead
+
+
+ -
+
+ IsA
+ Returns a boolean if this Instance is of type 'className' or a is a subclass of type 'className'. If 'className' is not a valid class type in ROBLOX, this function will always return false. <a href="http://wiki.roblox.com/index.php/IsA" target="_blank">More info</a>
+ Instance:Any:0
+
+
+ -
+
+ FindFirstChild
+ Returns the first child of this Instance that matches the first argument 'name'. The second argument 'recursive' is an optional boolean (defaults to false) that will force the call to traverse down thru all of this Instance's descendants until it finds an object with a name that matches the 'name' argument. The function will return nil if no Instance is found.
+
+
+ -
+
+ FindFirstChildOfClass
+ Returns the first child of this Instance that with a ClassName equal to 'className'. The function will return nil if no Instance is found.
+ Instance:isScriptCreatable:0
+
+
+ -
+
+ FindFirstChildWhichIsA
+ Returns the first child of this Instance that :IsA(className). The second argument 'recursive' is an optional boolean (defaults to false) that will force the call to traverse down thru all of this Instance's descendants until it finds an object with a name that matches the 'className' argument. The function will return nil if no Instance is found.
+ Instance:Any:0
+
+
+ -
+
+ FindFirstAncestor
+ Returns the first ancestor of this Instance that matches the first argument 'name'. The function will return nil if no Instance is found.
+
+
+ -
+
+ FindFirstAncestorOfClass
+ Returns the first ancestor of this Instance with a ClassName equal to 'className'. The function will return nil if no Instance is found.
+ Instance:isScriptCreatable:0
+
+
+ -
+
+ FindFirstAncestorWhichIsA
+ Returns the first ancestor of this Instance that :IsA(className). The function will return nil if no Instance is found.
+ Instance:Any:0
+
+
+ -
+
+ GetFullName
+ Returns a string that shows the path from the root node (DataModel) to this Instance. This string does not include the root node (DataModel).
+
+
+ -
+
+ children
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ getChildren
+ true
+ Use GetChildren() instead
+
+
+ -
+
+ GetChildren
+ Returns a read-only table of this Object's children
+
+
+ -
+
+ GetDescendants
+ Returns an array containing all of the descendants of the instance. Returns in preorder traversal, or in other words, where the parents come before their children, depth first.
+
+
+ -
+
+ Remove
+ Deprecated. Use ClearAllChildren() to get rid of all child objects, or Destroy() to invalidate this object and its descendants
+ true
+
+
+ -
+
+ remove
+ true
+ Use Remove() instead
+
+
+ -
+
+ ClearAllChildren
+ Removes all children (but not this object) from the workspace.
+
+
+ -
+
+ Destroy
+ Removes object and all of its children from the workspace. Disconnects object and all children from open connections. Object and children may not be usable after calling Destroy.
+
+
+ -
+
+ findFirstChild
+ true
+ Use FindFirstChild() instead
+
+
+
+ -
+
+
-
+
+ AncestryChanged
+ Fired when any of this object's ancestors change. First argument 'child' is the object whose parent changed. Second argument 'parent' is the first argument's new parent.
+
+
+ -
+
+ DescendantAdded
+ Fired after an Instance is parented to this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ DescendantRemoving
+ Fired after an Instance is unparented from this object, or any of this object's descendants. The 'descendant' argument is the Instance that is being added.
+
+
+ -
+
+ Changed
+ Fired after a property changes value. The property argument is the name of the property
+
+
+
+
+
+ -
+
+ BodyGyro
+ Legacy Body Movers
+ Attempts to maintain a fixed orientation of its parent Part
+ 140
+ 14
+ BasePart
+ BasePart
+
+
-
+
+
-
+
+ MaxTorque
+ The maximum torque that will be exerted on the Part
+
+
+ -
+
+ maxTorque
+ true
+ Use MaxTorque instead
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power continually applied to this force
+
+
+ -
+
+ CFrame
+ The cframe that this force is trying to orient its parent Part to. Note: this force only uses the rotation of the cframe, not the position.
+
+
+ -
+
+ cframe
+ true
+ Use CFrame instead
+
+
+
+
+ -
+
+ BodyPosition
+ Legacy Body Movers
+ 140
+ 14
+ BasePart
+ BasePart
+
+
-
+
+
-
+
+ MaxForce
+ The maximum force that will be exerted on the Part
+
+
+ -
+
+ maxForce
+ true
+ Use MaxForce instead
+
+
+ -
+
+ D
+ The dampening factor applied to this force
+
+
+ -
+
+ P
+ The power factor continually applied to this force
+
+
+ -
+
+ Position
+ The Vector3 that this force is trying to position its parent Part to.
+
+
+ -
+
+ position
+ true
+ Use position instead
+
+
+
+
+ -
+
+ RocketPropulsion
+ Legacy Body Movers
+ 140
+ 14
+ A propulsion system that mimics a rocket
+ BasePart
+ BasePart
+
+
+ -
+
+ BodyVelocity
+ Legacy Body Movers
+ 140
+ 14
+ BasePart
+ BasePart
+
+
-
+
-
+
+ MaxForce
+ The maximum force that will be exerted on the Part in each axis
+
+
+ -
+
+ maxForce
+ true
+ Use MaxForce instead
+
+
+ -
+
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+
+ -
+
+ Velocity
+ The velocity this system tries to achieve. How quickly the system reaches this velocity (if ever) is defined by P.
+
+
+ -
+
+ velocity
+ true
+ Use Velocity instead
+
+
+
+
+ -
+
+ BodyAngularVelocity
+ Legacy Body Movers
+ 140
+ 14
+ BasePart
+ BasePart
+
+
-
+
-
+ MaxTorque
+ The maximum torque that will be exerted on the Part in each axis
+
+ -
+ maxTorque
+ true
+ Use MaxTorque instead
+
+ -
+ P
+ The amount of power we add to the system. The higher the power, the quicker the force will achieve its goal.
+
+ -
+ AngularVelocity
+ The rotational velocity this system tries to achieve. How quickly the system reaches this velocity is defined by P.
+
+ -
+ angularVelocity
+ true
+ Use AngularVelocity instead
+
+
+
+ -
+
+ BodyForce
+ Legacy Body Movers
+ 140
+ 14
+ When parented to a physical part, BodyForce will continually exert a force upon its parent object.
+ BasePart
+ BasePart
+
+
-
+
-
+ Force
+ The continual force exerted on an object, defined in each axis.
+
+ -
+ force
+ true
+ Use Force instead
+
+
+
+ -
+
+ BodyThrust
+ Legacy Body Movers
+ 140
+ 14
+ BasePart
+ BasePart
+
+
-
+
+
-
+
+ Force
+ The power continually applied to this force
+
+
+ -
+
+ force
+ true
+ Use Force instead
+
+
+ -
+
+ Location
+ The Vector3 location of where to apply the force to.
+
+
+ -
+
+ location
+ true
+ Use Location instead
+
+
+
+
+ -
+
+ Hole
+ true
+ 20
+
+
+ -
+
+ Feature
+ 20
+
+
+
+ -
+
+ Teams
+ This Service-level object is the container for all Team objects in a level. A map that supports team games must have a Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 140
+ 23
+ Teams
+ Teams
+
+
-
+
-
+
+ GetPlayers
+ Returns a read-only table of players which are on this team.
+
+
+
+
+ -
+
+ Team
+ Interaction
+ The Team class is used to represent a faction in a team game. The only valid location for a Team object is under the Teams service. <a href="http://wiki.roblox.com/index.php/Team" target="_blank">More info</a>
+ 10
+ 24
+ Teams
+ Teams
+
+
+ -
+
+ SpawnLocation
+ Interaction
+ 30
+ 25
+
+
+ -
+
+ NetworkClient
+ false
+ 30
+ 16
+
+
+ -
+
+ NetworkServer
+ false
+ 30
+ 15
+
+
+ -
+
+ LuaSourceContainer
+ false
+ StarterPlayerScripts,StarterCharacterScripts,ServerScriptService
+
+
-
+
-
+
+ CurrentEditor
+ The name of the player who is currently editing the script in Team Create.
+ true
+
+
+
+
+ -
+
+ Script
+ Scripting
+ 30
+ 6
+ ServerStorage,ServerScriptService
+
+
-
+
+
-
+
+ LinkedScript
+
+ This property is under development. Do not use
+
+
+
+
+
+ -
+
+ LocalScript
+ Scripting
+ 40
+ 18
+ ReplicatedFirst,ReplicatedStorage,StarterCharacterScripts,StarterPlayerScripts
+ A script that runs on clients, NOT servers. LocalScripts can only run when parented under one of the following:
+ 1) A player's Backpack.
+ 2) A player's Character model.
+ 3) A player's PlayerGui.
+ 4) A player's PlayerScripts.
+ 5) The ReplicatedFirst service.
+
+
+
+
+ -
+
+ RenderingTest
+ Scripting
+ 40
+ dummy summary
+ 5
+
+
+
+ -
+
+ NetworkReplicator
+ 30
+ 29
+
+
+
+ -
+
+ Model
+ 100
+ 2
+ A construct used to group Parts and other objects together, also allows manipulation of multiple objects.
+ PVInstance
+ PVInstance
+
+
-
+
-
+
+ BreakJoints
+ Breaks all surface joints contained within
+
+
+ -
+
+ GetModelCFrame
+ Returns a CFrame that has position of the centroid of all Parts in the Model. The rotation matrix is either the rotation matrix of the user-defined PrimaryPart, or if not specified then a part in the Model chosen by the engine.
+
+
+ -
+
+ GetModelSize
+ Returns a Vector3 that is union of the extents of all Parts in the model.
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints between all touching Parts contrained within the model. Technically, this function calls MakeJoints() on all Parts inside the model.
+
+
+ -
+
+ MoveTo
+ Moves the centroid of the Model to the specified location, respecting all relative distances between parts in the model.
+
+
+ -
+
+ ResetOrientationToIdentity
+ Rotates all parts in the model to the orientation that was set using SetIdentityOrientation(). If this function has never been called, rotation is reset to GetModelCFrame()'s rotation.
+
+
+ -
+
+ SetIdentityOrientation
+ Takes the current rotation matrix of the model and stores it as the model's identity matrix. The rotation is applied when ResetOrientationToIdentity() is called.
+
+
+ -
+
+ TranslateBy
+ Similar to MoveTo(), except instead of moving to an explicit location, we use the model's current CFrame location and offset it.
+
+
+ -
+
+ GetPrimaryPartCFrame
+ Returns the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error.
+
+
+ -
+
+ SetPrimaryPartCFrame
+ Sets the cframe of the Model.PrimaryPart. If PrimaryPart is nil, then this function will throw an error. This also sets the cframe of all descendant Parts relative to the cframe change to PrimaryPart.
+
+
+ -
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+ -
+
-
+
+ PrimaryPart
+ A Part that serves as a reference for the Model's CFrame. Used in conjunction with GetModelPrimaryPartCFrame and SetModelPrimaryPartCFrame. Use this to rotate/translate all Parts relative to the PrimaryPart.
+
+
+
+
+
+ -
+
+ Status
+ true
+ 100
+ 2
+
+
-
+
-
+
+ move
+ true
+ Use MoveTo() instead
+
+
+
+
+
+ -
+
+ DataModel
+ The root of ROBLOX's parent-child hierarchy (commonly known as game after the global variable used to access it)
+
+
+
-
+
-
+
+ OnClose
+ true
+ Deprecated. Use DataModel.BindToClose
+
+
+
+
+ -
+
+
+
-
+
+ Workspace
+
+
+ -
+
+ workspace
+ true
+ Deprecated. Use Workspace
+
+
+ -
+
+ ShowMouse
+ true
+ Deprecated. Use Workspace.IsMouseCursorVisible
+
+
+ -
+
+ IsLoaded
+ Returns true if the game has finished loading, false otherwise. Check this before listening to the Loaded signal to ensure a script knows when a game finishes loading.
+
+
+
+
+ -
+
-
+
+ Loaded
+ Fires when the game finishes loading. Use this to know when to remove your custom loading gui. It is best to check IsLoaded() before connecting to this event, as the game may load before the event is connected to.
+
+
+
+
+ -
+
-
+
+ SetPlaceID
+ true
+ Use SetPlaceId() instead
+
+
+ -
+
+ SetCreatorID
+ true
+ Use SetCreatorId() instead
+
+
+
+
+
+ -
+
+ DataStoreService
+ Responsible for storing data across multiple user created places
+ -1
+
+
+
-
+
-
+
+ GetDataStore
+ Returns a data store with the given name and scope
+
+
+ -
+
+ GetGlobalDataStore
+ Returns the default data store
+
+
+ -
+
+ GetOrderedDataStore
+ Returns an ordered data store with the given name and scope
+
+
+
+
+
+ -
+
+ GlobalDataStore
+ Exposes functions for saving and loading data for the DataStoreService
+ -1
+
+
+
-
+
-
+
+ OnUpdate
+ Sets callback as a function to be executed any time the value associated with key is changed. It is important to disconnect the connection when the subscription to the key is no longer needed.
+
+
+
+
+ -
+
-
+
+ GetAsync
+ Returns the value of the entry in the DataStore with the given key
+
+
+ -
+
+ IncrementAsync
+ Increments the value of a particular key amd returns the incremented value
+
+
+ -
+
+ SetAsync
+ Sets the value of the key. This overwrites any existing data stored in the key
+
+
+ -
+
+ UpdateAsync
+ Retrieves the value of the key from the website, and updates it with a new value. The callback until the value fetched matches the value on the web. Returning nil means it will not save.
+
+
+
+
+
+ -
+
+ OrderedDataStore
+ A type of DataStore where values must be positive integers. This makes OrderedDataStore suitable for leaderboard related scripting where you are required to order large amounts of data efficiently.
+ -1
+
+
+
-
+
-
+
+ GetSortedAsync
+ Returns a DataStorePages object. The length of each page is determined by pageSize, and the order is determined by isAscending. minValue and maxValue are optional parameters which will filter the result.
+
+
+
+
+
+ -
+
+ HopperBin
+ true
+ 240
+ 22
+
+
+
+ -
+
+ Camera
+ 5
+ 5
+ Model
+ Model
+
+
-
+
-
+
+ CameraSubject
+ Where the Camera's focus is. Any rotation of the camera will be about this subject.
+
+
+ -
+
+ CameraType
+ Defines how the camera will behave. <a href="http://wiki.roblox.com/index.php/CameraType" target="_blank">More info</a>
+
+
+ -
+
+ CoordinateFrame
+ true
+ The current position and rotation of the Camera. For most CameraTypes, the rotation is set such that the CoordinateFrame lookVector is pointing at the Focus.
+
+
+ -
+
+ CFrame
+ The current position and rotation of the Camera. For most CameraTypes, the rotation is set such that the CoordinateFrame lookVector is pointing at the Focus.
+
+
+ -
+
+ FieldOfView
+ The current angle, or width, of what the camera can see. Current acceptable values are from 20 degrees to 80.
+
+
+ -
+
+ Focus
+ The current CoordinateFrame that the camera is looking at. Note: it is not always guaranteed that the camera is always looking here.
+
+
+ -
+
+ ViewportSize
+ Holds the x,y screen resolution of the viewport the camera is presenting (note: this can differ from the AbsoluteSize property of a full screen gui).
+
+
+ -
+
+ NearPlaneZ
+ The negative z-offset of the view frustum's near clipping plane.
+
+
+
+ -
+
-
+
+ GetRoll
+ Returns the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+ -
+
+ WorldToScreenPoint
+ Takes a 3D position in the world and projects it onto x,y coordinates of screen space. Returns two values, first is a Vector3 that has x,y position and z position which is distance from camera (negative if behind camera, positive if in front). Second return value is a boolean indicating if the first argument is an on-screen coordinate.
+
+
+ -
+
+ ScreenPointToRay
+ Takes a 2D screen position and produces a Ray object to be used for 3D raycasting. Input is x,y screen coordinates, and a (optional, defaults to 0) z position which sets how far in the camera look vector to start the ray origin.
+
+
+ -
+
+ ViewportPointToRay
+ Same as ScreenPointToRay, except no GUI offsets are taken into account. Useful for things like casting a ray from the middle of the Camera.ViewportSize
+
+
+ -
+
+ WorldToViewportPoint
+ Same as WorldToScreenPoint, except no GUI offsets are taken into account.
+
+
+ -
+
+ SetRoll
+ Sets the camera's current roll. Roll is defined in radians, and is stored as the delta from the camera's y axis default normal vector.
+
+
+
+
+
+ -
+
+ Players
+ 20
+ 21
+
+
-
+
-
+
+ CharacterAutoLoads
+ true
+ Set to true, when a player joins a game, they get a character automatically, as well as when they die. When set to false, characters do not auto load and will only load in using Player:LoadCharacter().
+
+
+
+ -
+
-
+
+ players
+ true
+ Use GetPlayers() instead
+
+
+
+
+
+ -
+
+ ReplicatedStorage
+ 30
+ 70
+ A container whose contents are replicated to all clients and the server.
+
+
+
+ -
+
+ RobloxReplicatedStorage
+ false
+
+
+
+ -
+
+ ReplicatedFirst
+ 30
+ 70
+ A container whose contents are replicated to all clients (but not back to the server) first before anything else. Useful for creating loading guis, tutorials, etc.
+
+
-
+
-
+
+ RemoveRobloxLoadingScreen
+ Removes the default Roblox loading screen from view. Call this when you are ready to either show your own loading gui, or when the game is ready to play.
+
+
+
+
+
+ -
+
+ ServerStorage
+ 30
+ 69
+ A container whose contents are only on the server.
+
+
+
+ -
+
+ ServerScriptService
+ 30
+ 71
+ A container whose contents should be scripts. Scripts that are added to the container are run on the server.
+
+
+
+ -
+
+ StudioService
+ -1
+ A service for interfacing with the current studio state from Lua.
+
+
+
+ -
+
+ Lighting
+ 30
+ 13
+ Responsible for all lighting aspects of the world (affects how things are rendered).
+
+
-
+
-
+
+ GetMinutesAfterMidnight
+ The number of minutes that the current time is past midnight. If currently at midnight, returns 0. Will return decimal values if not at an exact minute.
+
+
+ -
+
+ GetMoonDirection
+ Returns the lookVector (Vector3) of the moon. If this lookVector was used in a CFrame, the Part would face the moon.
+
+
+ -
+
+ GetMoonPhase
+ Currently always returns 0.75. MoonPhase cannot be edited.
+
+
+ -
+
+ GetSunDirection
+ Returns the lookVector (Vector3) of the sun. If this lookVector was used in a CFrame, the Part would face the sun.
+
+
+ -
+
+ SetMinutesAfterMidnight
+ Sets the time to be a certain number of minutes after midnight. This works with integer and decimal values.
+
+
+
+ -
+
-
+
+ Ambient
+ The hue of the global lighting. Changing this changes the color tint of all objects in the Workspace.
+
+
+ -
+
+ Brightness
+ How much global light each Part in the Workspace receives. Standard range is 0 to 1 (0 being little light), but can be increased all the way to 5 (colors start to be appear very different at this value).
+ 0
+ 2
+
+
+ -
+
+ ExposureCompensation
+ Exposure compensation amount. Applies a bias to the exposure level prior to the tonemap step. +1 indicates twice as much exposure and -1 means half as much exposure.
+ -3
+ 3
+ 600
+
+
+ -
+
+ ColorShift_Bottom
+ The hue of global lighting on the bottom surfaces of an object.
+
+
+ -
+
+ ColorShift_Top
+ The hue of global lighting on the top surfaces of an object.
+
+
+ -
+
+ FogColor
+ A Color3 value that changes the hue of distance fog.
+
+
+ -
+
+ FogEnd
+ The distance at which fog completely blocks your vision. This distance is relative to the camera position. Units are in studs
+
+
+ -
+
+ FogStart
+ The distance at which the fog gradient begins. This distance is relative to the camera position. Units are in studs.
+
+
+ -
+
+ GeographicLatitude
+ The latitude position the level is placed at. This affects sun position. <a href="http://wiki.roblox.com/index.php/GeographicLatitude" target="_blank">More info</a>
+ 0
+ 360
+ 360
+
+
+ -
+
+ GlobalShadows
+ Flag enabling shadows from sun and moon in the place
+
+
+ -
+
+ OutdoorAmbient
+ Effective ambient value for outdoors, effectively shadow color outdoors (requires GlobalShadows enabled)
+
+
+ -
+
+ Outlines
+ Flag enabling or disabling outlines on parts and terrain
+
+
+ -
+
+ ShadowColor
+ Color the shadows appear as. Shadows are drawn mostly for characters, but depending on the lighting will also show for Parts in the Workspace. Rendering settings can also affect if shadows are drawn.
+
+
+ -
+
+ TimeOfDay
+ A string that represent the current time of day. Time is in 24-hour clock format "XX::YY:ZZ", where X is hour, Y is minute, and Z is seconds.
+
+
+ -
+
+ ClockTime
+ 0
+ 24
+ 240
+
+
+
+ -
+
-
+
+ LightingChanged
+ Fired whenever a property of Lighting is changed, or a skybox is added or removed. Skyboxes are of type 'Sky' and should be parented directly to lighting.
+
+
+
+
+
+ -
+
+ TestService
+ 1000
+ 68
+
+
+
+ -
+
+ DebuggerManager
+
+
+
+
+
+ -
+
+ ScriptDebugger
+
+
+
+
+
+ -
+
+ DebuggerBreakpoint
+
+
+
+
+
+ -
+
+ DebuggerWatch
+
+
+
+
+
+ -
+
+ Debris
+ -1
+ 30
+ A service that provides utility in cleaning up objects
+
+
-
+
-
+
+ addItem
+ true
+ Use AddItem() instead
+
+
+ -
+
+ AddItem
+ Adds an Instance into the debris service that will later be destroyed. Second argument 'lifetime' is optional and specifies how long (in seconds) to wait before destroying the item. If no time is specified then the item added will automatically be destroyed in 10 seconds.
+
+
+
+ -
+
-
+
+ MaxItems
+ true
+ Deprecated. No replacement
+
+
+
+
+
+ -
+
+ Accoutrement
+ 20
+ 32
+ false
+
+
+
+ -
+
+ Player
+ false
+ 10
+ 12
+
+
-
+
+
-
+
+ CharacterAppearance
+ false
+ Model
+ Model
+
+
+ -
+
+ CameraMode
+ An enum that describes how a Player's camera is allowed to behave. <a href="http://wiki.roblox.com/index.php/CameraMode" target="_blank">More info</a>.
+
+
+ -
+
+ DataReady
+ true
+ Read-only. If true, this Player's persistent data can be loaded, false otherwise. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+ -
+
+ DataComplexity
+ true
+
+
+
+ -
+
+
-
+
+ LoadCharacter
+ true
+ Loads in a new character for this player. This will replace the player's current character, if they have one. This should be used in conjunction with Players.CharacterAutoLoads to control spawning of characters. This function only works from a server-side script (NOT a LocalScript).
+
+
+ -
+
+ LoadData
+ true
+
+
+ -
+
+ SaveData
+ true
+
+
+ -
+
+ SaveBoolean
+ true
+
+
+ -
+
+ SaveInstance
+ true
+
+
+ -
+
+ SaveString
+ true
+
+
+ -
+
+ LoadBoolean
+ true
+
+
+ -
+
+ LoadNumber
+ true
+
+
+ -
+
+ LoadString
+ true
+
+
+ -
+
+ LoadInstance
+ true
+
+
+ -
+
+ SaveNumber
+ true
+
+
+ -
+
+ playerFromCharacter
+ true
+ Use GetPlayerFromCharacter() instead
+
+
+ -
+
+ SetUnder13
+ true
+
+
+
+
+ -
+
-
+
+ WaitForDataReady
+ true
+ true
+ Yields until the persistent data for this Player is ready to be loaded. <a href="http://wiki.roblox.com/index.php/ROBLOX_Scripting_How_To:_Data_Persistence" target="_blank">Info on Data Persistence</a>.
+
+
+
+
+ -
+
+
-
+
+ Idled
+ Fired periodically after the user has been AFK for a while. Currently this event is only fired for the *local* Player. "time" is the time in seconds that the user has been idle.
+
+
+
+
+
+ -
+
+ Workspace
+ 5
+ 19
+
+
-
+
-
+
+ FindPartsInRegion3
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartsInRegion3WithIgnoreList
+ Returns parts in the area defined by the Region3, up to specified maxCount or 100, whichever is less
+
+
+ -
+
+ FindPartOnRay
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+ -
+
+ FindPartOnRayWithIgnoreList
+ Return type is (BasePart, Vector3) if the ray hits. If it misses it will return (nil, PointAtEndOfRay)
+
+
+
+ -
+
-
+
+ PGSPhysicsSolverEnabled
+ Boolean used to enable the new physics solver
+
+
+ -
+
+ FallenPartsDestroyHeight
+ Sets the height at which falling characters and parts are destroyed. This property is not scriptable and can only be set in Studio
+
+
+
+
+
+ -
+
+ BasePart
+ A structural class, not creatable
+ 3
+ false
+
+
+
-
+
-
+
+ Color
+ Color3 of the part.
+
+
+ -
+
+ CFrame
+ Contains information regarding the Part's position and a matrix that defines the Part's rotation. Can read/write. <a href="http://wiki.roblox.com/index.php/Cframe" target="_blank">More info</a>
+
+
+ -
+
+ CanCollide
+ Determines whether physical interactions with other Parts are respected. If true, will collide and react with physics to other Parts. If false, other parts will pass thru instead of colliding
+
+
+ -
+
+ Anchored
+ Determines whether or not physics acts upon the Part. If true, part stays 'Anchored' in space, not moving regardless of any collision/forces acting upon it. If false, physics works normally on the part.
+
+
+ -
+
+ Elasticity
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will rebound against another. a value of 1 is like a superball, and 0 is like a lead block.
+ 0
+ 1
+
+
+ -
+
+ Friction
+ A float value ranging from 0.0f to 1.0f. Sets how much the Part will be able to slide. a value of 1 is no sliding, and 0 is no friction, so infinite sliding.
+ 0
+ 2
+
+
+ -
+
+ Locked
+ Determines whether building tools (in-game and studio) can manipulate this Part. If true, no editing allowed. If false, editing is allowed.
+
+
+ -
+
+ Material
+ Specifies the look and feel the Part should have. Note: this does not define the color the Part is, see BrickColor for that. <a href="http://wiki.roblox.com/index.php/Material" target="_blank">More info</a>
+
+
+ -
+
+ Reflectance
+ Specifies how shiny the Part is. A value of 1 is completely reflective (chrome), while a value of 0 is no reflectance (concrete wall)
+ 0
+ 1
+
+
+ -
+
+ ResizeIncrement
+ Sets the value for the smallest change in size allowable by the Resize(NormalId, int) function.
+
+
+ -
+
+ ResizeableFaces
+ Sets the value for the faces allowed to be resized by the Resize(NormalId, int) function.
+
+
+ -
+
+ Transparency
+ Sets how visible an object is. A value of 1 makes the object invisible, while a value of 0 makes the object opaque.
+ 0
+ 1
+
+
+ -
+
+ Velocity
+ How fast the Part is traveling in studs/second. This property is NOT recommended to be modified directly, unless there is good reason. Otherwise, try using a BodyForce to move a Part.
+
+
+ -
+
+ PositionLocal
+ Position relative to parent part, or global space if there is no parent.
+
+
+ -
+
+ OrientationLocal
+ Orientation relative to parent part, or global space if there is no parent.
+
+
+ -
+
+ Orientation
+ Rotation around X, Y, and Z axis. Rotations applied in YXZ order.
+
+
+ -
+
+ Rotation
+
+
+ -
+
+ CenterOfMass
+
+
+
+
+ -
+
-
+
+ makeJoints
+ Use MakeJoints() instead
+ true
+
+
+ -
+
+ MakeJoints
+ Creates the appropriate SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model). This uses the SurfaceTypes defined on the surfaces of parts to create the appropriate welds. <a href="http://wiki.roblox.com/index.php/MakeJoints" target="_blank">More info</a>
+
+
+ -
+
+ BreakJoints
+ Destroys SurfaceJoints with all parts that are touching this Instance (including internal joints in the Instance, as in a Model).
+
+
+ -
+
+ GetMass
+ Returns a number that is the mass of this Instance. Mass of a Part is immutable, and is changed only by the size of the Part.
+
+
+ -
+
+ Resize
+ Resizes a Part in the direction of the face defined by 'NormalId', by the amount specified by 'deltaAmount'. If the operation will expand the part to intersect another Instance, the part will not resize at all. Return true if the call is successful, false otherwise.
+
+
+ -
+
+ getMass
+ Use GetMass() instead
+ true
+
+
+
+ -
+
-
+
+ OutfitChanged
+ true
+
+
+ -
+
+ LocalSimulationTouched
+ true
+ Deprecated. Use Touched instead
+
+
+ -
+
+ StoppedTouching
+
+ Deprecated. Use TouchEnded instead
+
+
+ -
+
+ TouchEnded
+ Fired when the part stops touching another part
+
+
+
+
+ -
+
+ Part
+ Parts
+ A plastic building block - the fundamental component of ROBLOX
+ 110
+ 1
+ Workspace
+ Workspace
+
+
+ -
+
+ TrussPart
+ Parts
+ An extendable building truss
+ 120
+ 1
+ Model
+ Model
+
+
+ -
+
+ WedgePart
+ Parts
+ A Wedge Part
+ 120
+ 1
+ Model
+ Model
+
+
+ -
+
+ PrismPart
+ A Prism Part
+ false
+ true
+ 120
+ 1
+
+
+ -
+
+ PyramidPart
+ A Pyramid Part
+ false
+ true
+ 120
+ 1
+
+
+ -
+
+ ParallelRampPart
+ A ParallelRamp Part
+ false
+ true
+ 120
+ 1
+
+
+ -
+
+ RightAngleRampPart
+ A RightAngleRamp Part
+ false
+ true
+ 120
+ 1
+
+
+ -
+
+ CornerWedgePart
+ Parts
+ A CornerWedge Part
+ 120
+ 1
+ Workspace
+ Workspace,Model
+
+
+ -
+
+ PlayerGui
+ A container instance that syncs data between a single player and the server. ScreenGui objects that are placed in this container will be shown to the Player parent only
+ 130
+ 46
+
+
-
+
-
+
+ SelectionImageObject
+ Overrides the default selection adornment (used for gamepads). For best results, this should point to a GuiObject.
+
+
+
+
+ -
+
+ PlayerScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be exectue only when a Player is the parent.
+ 130
+ 78
+
+
+ -
+
+ StarterPlayerScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be copied to new Players on startup.
+ 130
+ 78
+ false
+
+
+ -
+
+ StarterCharacterScripts
+ A container instance that contains LocalScripts. LocalScript objects that are placed in this container will be copied to new characters on startup.
+ 130
+ 78
+ false
+
+
+
+ -
+
+ GuiMain
+ Deprecated, please use ScreenGui
+ true
+ 140
+ 47
+
+
+
+ -
+
+ LayerCollector
+ The base class of ScreenGui, BillboardGui, and SurfaceGui.
+ false
+
+
-
+
-
+ Enabled
+ Whether or not this should be displayed.
+
+ -
+ ZIndexBehavior
+ Controls the behavior of the ZIndex property for descendants of this object. It can be set to Global (Default) or Sibling.
+
+
+
+
+ -
+
+ ScreenGui
+ GUI
+ The core GUI object on which tools are built. Add Frames/Labels/Buttons to this object to have them rendered as a 2D overlay
+ 140
+ 47
+ BasePlayerGui
+ BasePlayerGui
+
+
+ -
+
+ FunctionalTest
+ Deprecated. Use TestService instead
+ true
+ 10
+
+
+ -
+
+ BillboardGui
+ GUI
+ A GUI that adorns an object in the 3D world. Add Frames/Labels/Buttons to this object to have them rendered while attached to a 3D object
+ 140
+ 64
+ GuiBase2d
+ GuiBase2d
+
+
+
-
+
-
+
+ Adornee
+ The Object the billboard gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ AlwaysOnTop
+ If true, billboard gui does not get occluded by 3D objects, but always renders on the screen.
+
+
+ -
+
+ Enabled
+ If true, billboard gui will render, otherwise rendering will be skipped.
+
+
+ -
+
+ ExtentsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the extents of the 3d object it is rendering from.
+
+
+ -
+
+ PlayerToHideFrom
+ Specifies a Player that the BillboardGui will not render to.
+
+
+ -
+
+ StudsOffset
+ A Vector3 (x,y,z) defined in studs that will offset the gui from the centroid of the 3d object it is rendering from
+
+
+ -
+
+ SizeOffset
+ A Vector2 (x,y) defined in studs that will offset the gui size from it's current size.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the BillboardGui. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>. Relative values are defined as one-to-one with studs.
+
+
+ -
+
+ LightInfluence
+ Specifies the amount of influence lighting has on the billboard gui. A value of 0 is unlit, 1 is fully lit. Fractional values blend from unlit to lit.
+ 0
+ 1
+
+
+
+
+
+ -
+
+ SurfaceGui
+ GUI
+ Renders its contained GuiObjects flat against the face of a part.
+ 140
+ 64
+ GuiBase2d
+ GuiBase2d
+
+
+
-
+
-
+
+ Adornee
+ The Object the surface gui uses as its base to render from. Currently, the only way to set this property is thru a script, and must exist in the workspace. This will only render if the object assigned derives from BasePart.
+
+
+ -
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ Enabled
+ If true, surface gui will render, otherwise rendering will be skipped.
+
+
+ -
+
+ LightInfluence
+ Specifies the amount of influence lighting has on the surface gui. A value of 0 is unlit, 1 is fully lit. Fractional values blend from unlit to lit.
+ 0
+ 1
+
+
+
+
+
+
+
+ -
+
+ GuiBase2d
+ false
+ LayerCollector,GuiBase2d
+
+
+
-
+
-
+
+ AbsolutePosition
+ A read-only Vector2 value that is the GuiObject's current position (x,y) in pixel space, from the top left corner of the GuiObject.
+
+
+ -
+
+ AbsoluteSize
+ A read-only Vector2 value that is the GuiObject's current size (width, height) in pixel space.
+
+
+
+
+
+ -
+
+ InputObject
+ An object that describes a particular user input, such as mouse movement, touches, keyboard, and more.
+
+
-
+
-
+
+ UserInputType
+ An enum that describes what kind of input this object is describing (mousebutton, touch, etc.). See Enum.UserInputType for more info.
+
+
+ -
+
+ UserInputState
+ An enum that describes what state of a particular input (touch began, touch moved, touch ended, etc.). See Enum.UserInputState for more info.
+
+
+ -
+
+ Position
+ A Vector3 value that describes a positional value of this input. For mouse and touch input, this is the screen position of the mouse/touch, described in the x and y components. For mouse wheel input, the z component describes whether the wheel was moved forward or backward.
+
+
+ -
+
+ KeyCode
+ An enum that describes what kind of input is being pressed. For types of input like Keyboard, this describes what key was pressed. For input like mousebutton, this provides no additional information.
+
+
+
+
+
+ -
+
+ GuiObject
+ false
+
+
+
-
+
-
+
+ TweenPosition
+ Smoothly moves a GuiObject from its current position to 'endPosition'. The only required argument is 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenPosition" target="_blank">More info</a>
+
+
+ -
+
+ TweenSize
+ Smoothly translates a GuiObject's current size to 'endSize'. The only required argument is 'endSize'. <a href="http://wiki.roblox.com/index.php/TweenSize" target="_blank">More info</a>
+
+
+ -
+
+ TweenSizeAndPosition
+ Smoothly translates a GuiObject's current size to 'endSize', and also smoothly translates the GuiObject's current position to 'endPosition'. The only required arguments are 'endSize' and 'endPosition'. <a href="http://wiki.roblox.com/index.php/TweenSizeAndPosition" target="_blank">More info</a>
+
+
+
+
+ -
+
-
+
+ Active
+ If true, this GuiObject can fire mouse events and will pass them to any GuiObjects layered underneath, while false will do neither.
+
+
+ -
+
+ BackgroundColor3
+ A Color3 value that specifies the background color for the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BackgroundTransparency
+ A number value that specifies how transparent the background of the GuiObject is. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+ 0
+ 1
+
+
+ -
+
+ BorderColor3
+ A Color3 value that specifies the color of the outline of the GuiObject. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ BorderSizePixel
+ A number value that specifies the thickness (in pixels) of the outline of the GuiObject. Currently this value can only be set to either 0 or 1, any other number has no effect. This value is ignored if the Style property (not found on all GuiObjects) is set to something besides custom.
+
+
+ -
+
+ ClipsDescendants
+ If set to true, any descendants of this GuiObject will only render if contained within it's borders. If set to false, all descendants will render regardless of position.
+
+
+ -
+
+ Draggable
+ true
+ If true, allows a GuiObject to be dragged by the user's mouse. The events 'DragBegin' and 'DragStopped' are fired when the appropriate action happens, and only will fire on Draggable=true GuiObjects.
+
+
+ -
+
+ Size
+ A UDim2 value describing the size of the GuiObject on screen in both absolute and relative coordinates. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ Position
+ A UDim2 value describing the position of the top-left corner of the GuiObject on screen. More information on UDim2 is available <a href="http://wiki.roblox.com/index.php/UDim2" target="_blank">here</a>.
+
+
+ -
+
+ SizeConstraint
+ The direction(s) that an object can be resized in. <a href="http://wiki.roblox.com/index.php/SizeConstraint" target="_blank">More info</a>.
+
+
+ -
+
+ ZIndex
+ Describes the ordering in which overlapping GuiObjects will be drawn. A value of 1 is drawn first, while higher values are drawn in ascending order (each value draws over the last).
+
+
+ -
+
+ BackgroundColor
+ true
+ Deprecated. Use BackgroundColor3 instead
+
+
+ -
+
+ BorderColor
+ true
+ Deprecated. Use BorderColor3 instead
+
+
+ -
+
+ SelectionImageObject
+ Overrides the default selection adornment (used for gamepads). For best results, this should point to a GuiObject.
+
+
+
+
+ -
+
-
+
+ DragBegin
+ true
+ Fired when a GuiObject with Draggable set to true starts to be dragged. 'InitialPosition' is a UDim2 value of the position of the GuiObject before any drag operation began.
+
+
+ -
+
+ DragStopped
+ true
+ Always fired after a DragBegin event, DragStopped is fired when the user releases the mouse button causing a drag operation on the GuiObject. Arguments 'x', and 'y' specify the top-left absolute position of the GuiObject when the event is fired.
+
+
+ -
+
+ MouseEnter
+ Fired when the mouse enters a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseLeave
+ Fired when the mouse leaves a GuiObject, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+ -
+
+ MouseMoved
+ Fired when the mouse is inside a GuiObject and moves, as long as the GuiObject is active (see active property for more detail). Arguments 'x', and 'y' specify the absolute pixel position of the mouse.
+
+
+
+ -
+
+ TouchTap
+ Fired when a user taps their finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the tap gesture. This event only fires locally. This event will always fire regardless of game state.
+
+
+ -
+
+ TouchPinch
+ Fired when a user pinches their fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the pinch gesture. 'scale' is a float that indicates the difference from the beginning of the pinch gesture. 'velocity' is a float indicating how quickly the pinch gesture is happening. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchSwipe
+ Fired when a user swipes their fingers on a TouchEnabled device. 'swipeDirection' is an Enum.SwipeDirection, indicating the direction the user swiped. 'numberOfTouches' is an int that indicates how many touches were involved with the gesture. This event only fires locally.
+
+
+ -
+
+ TouchLongPress
+ Fired when a user holds at least one finger for a short amount of time on the same screen position on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchRotate
+ Fired when a user rotates two fingers on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'rotation' is a float indicating how much the rotation has gone from the start of the gesture. 'velocity' is a float that indicates how quickly the gesture is being performed. 'state' indicates the Enum.UserInputState of the gesture. This event only fires locally.
+
+
+ -
+
+ TouchPan
+ Fired when a user drags at least one finger on a TouchEnabled device. 'touchPositions' is a Lua array of Vector2, each indicating the position of all the fingers involved in the gesture. 'totalTranslation' is a Vector2, indicating how far the pan gesture has gone from its starting point. 'velocity' is a Vector2 that indicates how quickly the gesture is being performed in each dimension. 'state' indicates the Enum.UserInputState of the gesture.
+
+
+
+ -
+
+ InputBegan
+ Fired when a user begins interacting via a Human-Computer Interface device (Mouse button down, touch begin, keyboard button down, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputChanged
+ Fired when a user changes interacting via a Human-Computer Interface device (Mouse move, touch move, mouse wheel, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+ -
+
+ InputEnded
+ Fired when a user stops interacting via a Human-Computer Interface device (Mouse button up, touch end, keyboard button up, etc.). 'inputObject' is an InputObject, which contains useful data for querying user input. This event only fires locally.
+
+
+
+
+
+
+ -
+
+ Frame
+ GUI
+ A container object used to layout other GUI objects
+ 150
+ 48
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ Style
+ Determines how a frame will look. Uses Enum.FrameStyle. <a href="http://wiki.roblox.com/index.php?title=API:Enum/FrameStyle" target="_blank">More info</a>
+
+
+
+
+ -
+
+ ScrollingFrame
+ GUI
+ A container object used to layout other GUI objects, and allows for scrolling.
+ 150
+ 48
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ ScrollingEnabled
+ Determines whether or not scrolling is allowed on this frame. If turned off, no scroll bars will be rendered.
+
+
+ -
+
+ CanvasSize
+ Determines the size of the area that is scrollable. The UDim2 is calculated using the parent gui's size, similar to the regular Size property on gui objects.
+
+
+ -
+
+ CanvasPosition
+ The absolute position the scroll frame is in respect to the canvas size. The minimum this can be set to is (0,0), while the max is the absolute canvas size - AbsoluteWindowSize.
+
+
+ -
+
+ AbsoluteWindowSize
+ The size in pixels of the frame, without the scrollbars.
+
+
+ -
+
+ ScrollBarThickness
+ How thick the scroll bar appears. This applies to both the horizontal and vertical scroll bars. Can be set to 0 for no bars render.
+
+
+ -
+
+ TopImage
+ The "Up" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "left" image on the horizontal scroll bar.
+
+
+ -
+
+ MidImage
+ The "Middle" image on the vertical scrollbar. Size of this can vary in the y direction, but is always set at ScrollBarThickness in x direction. This is also used as the "mid" image on the horizontal scroll bar.
+
+
+ -
+
+ BottomImage
+ The "Down" image on the vertical scrollbar. Size of this is always ScrollBarThickness by ScrollBarThickness. This is also used as the "right" image on the horizontal scroll bar.
+
+
+
+
+ -
+
+ ImageLabel
+ GUI
+ A GUI object containing an Image
+ 180
+ 49
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ Image
+ Specifies the id of the texture to display. <a href="http://wiki.roblox.com/index.php?title=API:Class/ImageLabel/Image" target="_blank">More info</a>
+
+
+ -
+
+ ScaleType
+ Specifies how an image should be displayed. See ScaleType for more info.
+
+
+ -
+
+ SliceCenter
+ If ScaleType is set to Slice, this Rect is used to specify the central part of the image. Everything outside of this is considered to be the border.
+
+
+ -
+
+ TileSize
+ If ScaleType is set to Tile, this sets the size of the tile.
+
+
+
+
+ -
+
+ TextLabel
+ GUI
+ A GUI object containing text
+ 190
+ 50
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextButton
+ GUI
+ A GUI button containing text
+ 170
+ 51
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ TextBox
+ GUI
+ A text entry box
+ 170
+ 51
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ TextColor
+ true
+ Deprecated. Use TextColor3 instead
+
+
+
+
+ -
+
+ GuiButton
+ GUI
+ A GUI button containing an Image
+ false
+ 160
+ 52
+
+
-
+
-
+
+ AutoButtonColor
+ Determines whether a button changes color automatically when reacting to mouse events.
+
+
+ -
+
+ Modal
+ Allows the mouse to be free in first person mode. If a button with this property set to true is visible, the mouse is 'free' in first person mode.
+
+
+ -
+
+ Style
+ Determines how a button will look, including mouse event states. Uses Enum.ButtonStyle. <a href="http://wiki.roblox.com/index.php?title=API:Class/GuiButton/Style" target="_blank">More info</a>
+
+
+
+ -
+
-
+
+ MouseButton1Click
+ Fired when the mouse is over the button, and the mouse down and up events fire without the mouse leaving the button.
+
+
+ -
+
+ MouseButton1Down
+ Fired when the mouse button is pushed down on a button.
+
+
+ -
+
+ MouseButton1Up
+ Fired when the mouse button is released on a button.
+
+
+ -
+
+ MouseButton2Click
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Down
+ This function currently does not work :(
+
+
+ -
+
+ MouseButton2Up
+ This function currently does not work :(
+
+
+
+
+ -
+
+ ViewportFrame
+ GUI
+ A GUI that can show 3D objects
+ 30
+ 52
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ CurrentCamera
+ Current Camera of children objects
+
+
+
+
+ -
+
+ ImageButton
+ GUI
+ A GUI button containing an Image
+ 160
+ 52
+ GuiBase2d
+ GuiBase2d
+
+
-
+
-
+
+ Image
+ Specifies the asset id of the texture to display. <a href="http://wiki.roblox.com/index.php?title=API:Class/ImageButton/Image" target="_blank">More info</a>
+
+
+ -
+
+ ScaleType
+ Specifies how an image should be displayed. See ScaleType for more info.
+
+
+ -
+
+ SliceCenter
+ If ScaleType is set to Slice, this Rect is used to specify the central part of the image. Everything outside of this is considered to be the border.
+
+
+ -
+
+ TileSize
+ If ScaleType is set to Tile, this sets the size of the tile.
+
+
+
+
+ -
+
+ Handles
+ Adornments
+ A 3D GUI object to represent draggable handles
+
+ 190
+ 53
+
+
+ -
+
+ ArcHandles
+ Adornments
+ A 3D GUI object to represent draggable arc handles
+
+ 200
+ 56
+
+
+ -
+
+ SelectionBox
+ Adornments
+ A 3D GUI object to represent the visible selection around an object
+ 210
+ 54
+
+
+ -
+
+ SelectionSphere
+ Adornments
+ A 3D GUI object to represent the visible selection around an object
+ 210
+ 54
+
+
+ -
+
+ SurfaceSelection
+ Adornments
+ A 3D GUI object to represent the visible selection around a face of an object
+ 210
+ 55
+
+
+ -
+
+ Configuration
+ An object that can be placed under parts to hold Value objects that represent that part's configuration
+ 220
+ 58
+
+
+ -
+
+ Folder
+ An object that can be created to hold and organize objects
+ 10
+ 77
+ Instance
+
+
+ -
+
+ SelectionPartLasso
+ true
+ A visual line drawn representation between two part objects
+ 220
+ 57
+
+
+ -
+
+ SelectionPointLasso
+ true
+ A visual line drawn representation between two positions
+ 220
+ 57
+
+
+ -
+
+ PartPairLasso
+ A visual line drawn representation between two parts.
+ 220
+ 57
+
+
+ -
+
+ Pose
+ The pose of a joint relative to it's parent part in a keyframe
+ 220
+ 60
+ false
+
+
+ -
+
+ Keyframe
+ One keyframe of an animation
+ 220
+ 60
+ false
+
+
+ -
+
+ Animation
+ Animations
+ Represents a linked animation object, containing keyframes and poses.
+ 220
+ 60
+
+
+ -
+
+ AnimationTrack
+ Returned by a call to LoadAnimation. Controls the playback of an animation on a Humanoid.
+ 220
+ 60
+
+
+ -
+
+ AnimationController
+ Animations
+ Allows animations to be played on joints of the parent object.
+ 220
+ 60
+
+
+ -
+
+ CharacterMesh
+ Meshes
+ Modifies the appearance of a body part.
+ 220
+ 60
+ Model
+ Model
+
+
+ -
+
+ Dialog
+ 3D Interfaces
+ An object used to make dialog trees to converse with players
+ 220
+ 62
+
+
-
+
-
+
+ ConversationDistance
+ The maximum distance that the player's character can be from the dialog's parent in order to use the dialog.
+
+
+ -
+
+ GoodbyeChoiceActive
+ Indicates whether or not an extra choice is available for the player to exit the dialog tree at this node.
+
+
+ -
+
+ GoodbyeDialog
+ The prompt text for an extra choice that allows the player to exit the dialog tree at this node.
+
+
+ -
+
+ InUse
+ Indicates whether or not the dialog is currently being used by one or more players.
+
+
+ -
+
+ InitialPrompt
+ The chat message that is displayed to the player when they first activate the dialog.
+
+
+ -
+
+ Purpose
+ Describes the purpose of the dialog, which is used to display a relevant icon on the dialog's activation button.
+
+
+ -
+
+ Tone
+ Describes the tone of the dialog, which is used to display a relevant color in the dialog interface.
+
+
+ -
+
+ BehaviorType
+ Indicates how the dialog may be used by players. Use Enum.DialogBehaviorType.SinglePlayer if only one player should interact with the dialog at a time, otherwise use Enum.DialogBehaviorType.MultiplePlayers.
+
+
+
+ -
+
-
+
+ GetCurrentPlayers
+ Returns an array of the players currently conversing with this dialog.
+
+
+
+
+ -
+
+ DialogChoice
+ 3D Interfaces
+ An object used to make dialog trees to converse with players
+ 220
+ 63
+
+
+ -
+
+ UnionOperation
+ A UnionOperation is a union of multiple parts
+ true
+ false
+ 20
+ 73
+
+
-
+
-
+
+ UsePartColor
+ Override the colors of the mesh with the part color.
+
+
+
+
+ -
+
+ NegateOperation
+ A NegateOperation can be used to create holes in other parts
+ true
+ false
+ 20
+ 72
+
+
-
+
-
+
+ UsePartColor
+ Override the colors of the mesh with the part color.
+
+
+
+
+ -
+
+ MeshPart
+ Parts
+ A MeshPart is a physically simulatable mesh
+ true
+ true
+ 20
+ 73
+ Model
+ Model
+
+
+ -
+
+ Terrain
+ Object representing a high performance bounded grid of static 4x4 parts
+ true
+ false
+ 5
+ 65
+
+
-
+
-
+
+ WaterTransparency
+ 0
+ 1
+
+
+ -
+
+ WaterWaveSize
+ 0
+ 1
+
+
+ -
+
+ WaterWaveSpeed
+ 0
+ 100
+
+
+ -
+
+ WaterReflectance
+ 0
+ 1
+
+
+
+ -
+
-
+
+ GetCell
+ Returns CellMaterial, CellBlock, CellOrientation
+
+
+ -
+
+ GetWaterCell
+
+ Returns hasAnyWater, WaterForce, WaterDirection
+
+
+ -
+
+ SetWaterCell
+
+
+
+
+
+ -
+
+ Light
+ Lights
+ Parent of all light objects
+ 30
+ 13
+ PVInstance
+ Basepart,Attachment,PVInstance
+
+
-
+
-
+
+ Brightness
+ 0
+ 10
+ 2000
+
+
+
+
+ -
+
+ PointLight
+ Lights
+ Makes the parent part emit light in a spherical shape
+ 30
+ 13
+ PVInstance
+ PVInstance
+
+
-
+
-
+
+ Range
+ 0
+ 60
+
+
+
+
+ -
+
+ SpotLight
+ Lights
+ Makes the parent part emit light in a conical shape
+ 30
+ 13
+ PVInstance
+ PVInstance
+
+
-
+
-
+
+ Range
+ 0
+ 60
+
+
+ -
+
+ Angle
+ 0
+ 180
+
+
+
+
+ -
+
+ SurfaceLight
+ Lights
+ Makes the parent part emit light in a frustum shape from rectangle defined by part
+ 30
+ 13
+ PVInstance
+ PVInstance
+
+
-
+
-
+
+ Range
+ 0
+ 60
+
+
+ -
+
+ Brightness
+ 0
+ 10
+
+
+ -
+
+ Angle
+ 0
+ 180
+
+
+
+
+ -
+
+ RemoteFunction
+ Scripting
+ Allow functions defined in one script to be called by another script across client/server boundary
+ 40
+ 74
+
+
-
+
-
+
+ InvokeClient
+ Server
+
+
+ -
+
+ InvokeServer
+ Client
+
+
+
+ -
+
-
+
+ OnClientInvoke
+ Client
+
+
+ -
+
+ OnServerInvoke
+ Server
+
+
+
+
+ -
+
+ RemoteEvent
+ Scripting
+ Allow events defined in one script to be subscribed to by another script across client/server boundary
+ 50
+ 75
+
+
-
+
-
+
+ FireAllClients
+ Server
+
+
+ -
+
+ FireClient
+ Server
+
+
+ -
+
+ FireServer
+ Client
+
+
+
+ -
+
-
+
+ OnClientEvent
+ Client
+
+
+ -
+
+ OnServerEvent
+ Server
+
+
+
+
+ -
+
+ TerrainRegion
+ Object representing a snapshot of the region of terrain
+ true
+ 20
+ 65
+ false
+
+
+ -
+
+ ModuleScript
+ Scripting
+ A script fragment. Only runs when another script uses require() on it.
+ 50
+ 76
+ Instance
+
+
+
+ -
+
+
-
+
+ ContextActionResult
+
+
-
+
+ Sink
+ If 'functionToBind' from ContextActionService:BindAction() returns Enum.ContextActionResult.Sink, the input event will stop at that function and no other bound actions under it will be invoked. This is the default behavior if 'functionToBind' does not return anything or yields in any way.
+
+
+ -
+
+ Pass
+ If 'functionToBind' from ContextActionService:BindAction() returns Enum.ContextActionResult.Pass, the input event is considered to have not been handled by 'functionToBind' and will continue being passed to actions bound to the same input type.
+
+
+
+ -
+
+ Material
+
+
-
+
+ Air
+ false
+
+
+ -
+
+ Water
+ false
+
+
+ -
+
+ Rock
+ false
+
+
+ -
+
+ Glacier
+ false
+
+
+ -
+
+ Snow
+ false
+
+
+ -
+
+ Sandstone
+ false
+
+
+ -
+
+ Mud
+ false
+
+
+ -
+
+ Basalt
+ false
+
+
+ -
+
+ Ground
+ false
+
+
+ -
+
+ CrackedLava
+ false
+
+
+ -
+
+ Asphalt
+ false
+
+
+ -
+
+ LeafyGrass
+ false
+
+
+ -
+
+ Salt
+ false
+
+
+ -
+
+ Limestone
+ false
+
+
+ -
+
+ Pavement
+ false
+
+
+
+ -
+
+ Status
+ true
+
+
-
+
+ Poison
+ true
+
+
+ -
+
+ Confusion
+ true
+
+
+
+ -
+
+ SaveFilter
+ true
+
+
+ -
+
+ PrivilegeType
+ true
+
+
+ -
+
+ Genre
+ true
+
+
+ -
+
+ GearGenreSetting
+ true
+
+
+ -
+
+ SortOrder
+ The ordering to use for sorting an array of GuiObjects.
+
+
-
+
+ Name
+ Sort by alphabetical ordering of the Name property.
+
+
+ -
+
+ LayoutOrder
+ Sort using the less than operator on the LayoutOrder property of GuiObject.
+
+
+ -
+
+ Custom
+ true
+
+
+
+ -
+
+ ZIndexBehavior
+ Controls the behavior of the ZIndex property.
+
+
-
+
+ Global
+ The ZIndex property will override the default value computed from the depth in the hierarchy.
+
+
+ -
+
+ Sibling
+ The ZIndex property will control the order that the GuiObject will be rendered relative to its siblings.
+
+
+
+ -
+
+ ScaleType
+ Controls how an image is displayed.
+
+
-
+
+ Stretch
+ Force the image to fill the available space.
+
+
+ -
+
+ Slice
+ Use the SliceCenter property to stretch the middle of the image but maintain crisp borders.
+
+
+ -
+
+ Tile
+ Tile the image using the TileSize property.
+
+
+ -
+
+ Fit
+ Size the image to the largest size that will fit in the available space while maintaining aspect ratio.
+
+
+ -
+
+ Crop
+ Fill the available space, maintaining aspect ratio by cropping the edges if necessary.
+
+
+
+
+
diff --git a/Client2018/SyntaxPlayerBeta.exe b/Client2018/SyntaxPlayerBeta.exe
new file mode 100644
index 0000000..9fe5c37
Binary files /dev/null and b/Client2018/SyntaxPlayerBeta.exe differ
diff --git a/Client2018/content/LuaPackages/.luacheckrc b/Client2018/content/LuaPackages/.luacheckrc
new file mode 100644
index 0000000..5f5cf25
--- /dev/null
+++ b/Client2018/content/LuaPackages/.luacheckrc
@@ -0,0 +1,41 @@
+stds.roblox = {
+ globals = {
+ "game"
+ },
+ read_globals = {
+ -- Roblox globals
+ "script",
+
+ -- Extra functions
+ "tick", "warn", "spawn",
+ "wait", "settings", "typeof", "delay",
+
+ -- Types
+ "Vector2", "Vector3",
+ "Color3",
+ "UDim", "UDim2",
+ "Rect",
+ "CFrame",
+ "Enum",
+ "Instance",
+ }
+}
+
+stds.testez = {
+ read_globals = {
+ "describe",
+ "it", "itFOCUS", "itSKIP",
+ "FOCUS", "SKIP", "HACK_NO_XPCALL",
+ "expect",
+ }
+}
+
+ignore = {
+ "212", -- unused arguments
+}
+
+std = "lua51+roblox"
+
+files["**/*.spec.lua"] = {
+ std = "+testez",
+}
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Action.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Action.lua
new file mode 100644
index 0000000..d3d1ff4
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Action.lua
@@ -0,0 +1,68 @@
+--[[
+ A helper function to define a Rodux action creator with an associated name.
+
+ Normally when creating a Rodux action, you can just create a function:
+
+ return function(value)
+ return {
+ type = "MyAction",
+ value = value,
+ }
+ end
+
+ And then when you check for it in your reducer, you either use a constant,
+ or type out the string name:
+
+ if action.type == "MyAction" then
+ -- change some state
+ end
+
+ Typos here are a remarkably common bug. We also have the issue that there's
+ no link between reducers and the actions that they respond to!
+
+ `Action` (this helper) provides a utility that makes this a bit cleaner.
+
+ Instead, define your Rodux action like this:
+
+ return Action("MyAction", function(value)
+ return {
+ value = value,
+ }
+ end)
+
+ We no longer need to add the `type` field manually.
+
+ Additionally, the returned action creator now has a 'name' property that can
+ be checked by your reducer:
+
+ local MyAction = require(Reducers.MyAction)
+
+ ...
+
+ if action.type == MyAction.name then
+ -- change some state!
+ end
+
+ Now we have a clear link between our reducers and the actions they use, and
+ if we ever typo a name, we'll get a warning in LuaCheck as well as an error
+ at runtime!
+]]
+
+return function(name, fn)
+ assert(type(name) == "string", "A name must be provided to create an Action")
+ assert(type(fn) == "function", "A function must be provided to create an Action")
+
+ return setmetatable({
+ name = name,
+ }, {
+ __call = function(self, ...)
+ local result = fn(...)
+
+ assert(type(result) == "table", "An action must return a table")
+
+ result.type = name
+
+ return result
+ end
+ })
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Action.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Action.spec.lua
new file mode 100644
index 0000000..799c2b3
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Action.spec.lua
@@ -0,0 +1,85 @@
+return function()
+ local Action = require(script.Parent.Action)
+
+ it("should return a table", function()
+ local action = Action("foo", function()
+ return {}
+ end)
+
+ expect(action).to.be.a("table")
+ end)
+
+ it("should set the name of the action", function()
+ local action = Action("foo", function()
+ return {}
+ end)
+
+ expect(action.name).to.equal("foo")
+ end)
+
+ it("should be able to be called as a function", function()
+ local action = Action("foo", function()
+ return {}
+ end)
+
+ expect(action).never.to.throw()
+ end)
+
+ it("should return a table when called as a function", function()
+ local action = Action("foo", function()
+ return {}
+ end)
+
+ expect(action()).to.be.a("table")
+ end)
+
+ it("should set the type of the action", function()
+ local action = Action("foo", function()
+ return {}
+ end)
+
+ expect(action().type).to.equal("foo")
+ end)
+
+ it("should set values", function()
+ local action = Action("foo", function(value)
+ return {
+ value = value
+ }
+ end)
+
+ expect(action(100).value).to.equal(100)
+ end)
+
+ it("should throw when passed a function", function()
+ local action = Action("foo", function()
+ return function() end
+ end)
+
+ expect(action).to.throw()
+ end)
+
+ it("should throw with a invalid name", function()
+ expect(function()
+ Action(nil, function()
+ return {}
+ end)
+ end).to.throw()
+
+ expect(function()
+ Action(100, function()
+ return {}
+ end)
+ end).to.throw()
+ end)
+
+ it("should throw when passed a invalid function", function()
+ expect(function()
+ Action("foo", nil)
+ end).to.throw()
+
+ expect(function()
+ Action("foo", {})
+ end).to.throw()
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.lua
new file mode 100644
index 0000000..a40c8ad
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.lua
@@ -0,0 +1,131 @@
+--[[
+ Provides an implementation of functional programming primitives.
+]]
+
+local Functional = {}
+
+--[[
+ Create a copy of a list with only values for which `callback` returns true
+]]
+function Functional.Filter(list, callback)
+ local new = {}
+
+ for key = 1, #list do
+ local value = list[key]
+ if callback(value, key) then
+ table.insert(new, value)
+ end
+ end
+
+ return new
+end
+
+--[[
+ Create a copy of a list where each value is transformed by `callback`
+]]
+function Functional.Map(list, callback)
+ local new = {}
+
+ for key = 1, #list do
+ new[key] = callback(list[key], key)
+ end
+
+ return new
+end
+
+--[[
+ Identical to Map, except that the result will be reversed.
+]]
+function Functional.MapReverse(list, callback)
+ local new = {}
+
+ for key = #list, 1, -1 do
+ new[key] = callback(list[key], key)
+ end
+
+ return new
+end
+
+--[[
+ Create a copy of a list doing a combination filter and map.
+
+ If callback returns nil for any item, it is considered filtered from the
+ list. Any other value is considered the result of the 'map' operation.
+]]
+function Functional.FilterMap(list, callback)
+ local new = {}
+
+ for key = 1, #list do
+ local value = list[key]
+ local result = callback(value, key)
+
+ if result ~= nil then
+ table.insert(new, result)
+ end
+ end
+
+ return new
+end
+
+--[[
+ Performs a left-fold of the list with the given initial value and callback.
+]]
+function Functional.Fold(list, initial, callback)
+ local accum = initial
+
+ for key = 1, #list do
+ accum = callback(accum, list[key], key)
+ end
+
+ return accum
+end
+
+--[[
+ Performs a fold over the entries in the given dictionary.
+]]
+function Functional.FoldDictionary(dictionary, initial, callback)
+ local accum = initial
+
+ for key, value in pairs(dictionary) do
+ accum = callback(accum, key, value)
+ end
+
+ return accum
+end
+
+--[[
+ Returns a list that contains at most `count` values from the given list.
+]]
+function Functional.Take(list, count, startingIndex)
+ startingIndex = startingIndex or 1
+
+ local maxIndex = count + (startingIndex - 1)
+ if maxIndex > #list then
+ maxIndex = #list
+ end
+
+ local new = {}
+
+ for i = startingIndex, maxIndex do
+ local value = list[i]
+ local newIndex = i - (startingIndex - 1)
+ new[newIndex] = value
+ end
+
+ return new
+end
+
+--[[
+ If the list contains the sought-after element, return its index, or nil otherwise.
+]]
+function Functional.Find(list, value)
+ for index, element in ipairs(list) do
+ if element == value then
+ return index
+ end
+ end
+
+ return nil
+end
+
+return Functional
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.spec.lua
new file mode 100644
index 0000000..4ea87a4
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Functional.spec.lua
@@ -0,0 +1,218 @@
+return function()
+ local Functional = require(script.Parent.Functional)
+
+ local function identity(...)
+ return ...
+ end
+
+ local function add(a, b)
+ return a + b
+ end
+
+ describe("Filter", function()
+ it("should copy lists correctly", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.Filter(listA, function()
+ return true
+ end)
+
+ expect(listB).never.to.equal(listA)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i])
+ end
+ end)
+
+ it("should correctly use the filter predicate", function()
+ local listA = {1, 2, 3, 4, 5}
+ local listB = Functional.Filter(listA, function(value, key)
+ expect(value).to.equal(key)
+
+ return value % 2 == 0
+ end)
+
+ expect(listB[1]).to.equal(2)
+ expect(listB[2]).to.equal(4)
+ end)
+ end)
+
+ describe("Map", function()
+ it("should copy lists correctly using the identity function", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.Map(listA, identity)
+
+ expect(listB).never.to.equal(listA)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i])
+ end
+ end)
+
+ it("should correctly use the map predicate", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.Map(listA, function(value, key)
+ expect(value).to.equal(key)
+
+ return value * 2
+ end)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i] * 2)
+ end
+ end)
+ end)
+
+ describe("MapReverse", function()
+ it("should copy lists correctly using the identity function", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.MapReverse(listA, identity)
+
+ expect(listB).never.to.equal(listA)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i])
+ end
+ end)
+
+ it("should correctly use the map predicate", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.MapReverse(listA, function(value, key)
+ expect(value).to.equal(key)
+
+ return value * 2
+ end)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i] * 2)
+ end
+ end)
+
+ it("should iterate backwards", function()
+ local list = {1, 2, 3}
+ local nextKey = 3
+
+ Functional.MapReverse(list, function(value, key)
+ expect(value).to.equal(nextKey)
+ expect(key).to.equal(nextKey)
+
+ nextKey = nextKey - 1
+ end)
+
+ expect(nextKey).to.equal(0)
+ end)
+ end)
+
+ describe("FilterMap", function()
+ it("should copy truthy lists using the identity function", function()
+ local listA = {1, 2, 3}
+ local listB = Functional.FilterMap(listA, identity)
+
+ expect(listB).never.to.equal(listA)
+
+ for i = 1, #listB do
+ expect(listB[i]).to.equal(listA[i])
+ end
+ end)
+
+ it("should correctly use the filter-map predicate", function()
+ local listA = {1, 2, 3, 4, 5}
+
+ -- Create a list containing only the odd numbers, and double those numbers
+ local listB = Functional.FilterMap(listA, function(value, key)
+ expect(value).to.equal(key)
+
+ if value % 2 == 0 then
+ return nil
+ end
+
+ return value * 2
+ end)
+
+ expect(listB[1]).to.equal(2)
+ expect(listB[2]).to.equal(6)
+ expect(listB[3]).to.equal(10)
+ end)
+ end)
+
+ describe("Fold", function()
+ it("should left-fold lists", function()
+ local list = {1, 2, 3, 4, 5}
+
+ local sum = Functional.Fold(list, 0, add)
+
+ expect(sum).to.equal(15)
+ end)
+ end)
+
+ describe("Take", function()
+ it("should take values from a list", function()
+ local a = {1, 2, 3}
+ local b = Functional.Take(a, 2)
+
+ expect(#b).to.equal(2)
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(2)
+ end)
+
+ it("should not take past the end of a list", function()
+ local a = {1, 2, 3}
+ local b = Functional.Take(a, 4)
+
+ expect(#b).to.equal(3)
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(2)
+ expect(b[3]).to.equal(3)
+ end)
+
+ it("should copy all values when taking past the end of a list", function()
+ local a = {1, 2, 3}
+ local b = Functional.Take(a, 4)
+
+ expect(#b).to.equal(#a)
+ expect(a[1]).to.equal(b[1])
+ expect(a[2]).to.equal(b[2])
+ expect(a[3]).to.equal(b[3])
+ end)
+
+ it("should take values from a starting index when provided", function()
+ local a = {1, 2, 3, 4}
+ local b = Functional.Take(a, 2, 2)
+
+ expect(#b).to.equal(2)
+ expect(b[1]).to.equal(2)
+ expect(b[2]).to.equal(3)
+ end)
+
+ it("should not take past the end of a list when the starting index is provided", function()
+ local a = {1, 2, 3, 4}
+ local b = Functional.Take(a, 3, 3)
+
+ expect(#b).to.equal(2)
+ expect(b[1]).to.equal(3)
+ expect(b[2]).to.equal(4)
+ end)
+ end)
+
+ describe("Find", function()
+ it("should return index of matched item", function()
+ local a = {"foo", "bar", "garply"}
+ local b = Functional.Find(a, "bar")
+
+ expect(b).to.equal(2)
+ end)
+
+ it("should find the first example in the case of duplicates", function()
+ local a = {"foo", "bar", "garply", "bar"}
+ local b = Functional.Find(a, "bar")
+
+ expect(b).to.equal(2)
+ end)
+
+ it("should return nil if item is not found", function()
+ local a = {"foo", "bar", "garply"}
+ local b = Functional.Find(a, "fleebledegoop")
+
+ expect(b).to.equal(nil)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.lua
new file mode 100644
index 0000000..a73d203
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.lua
@@ -0,0 +1,141 @@
+--[[
+ Provides functions for manipulating immutable data structures.
+]]
+
+local Immutable = {}
+
+--[[
+ Merges dictionary-like tables together.
+]]
+function Immutable.JoinDictionaries(...)
+ local result = {}
+
+ for i = 1, select("#", ...) do
+ local dictionary = select(i, ...)
+ for key, value in pairs(dictionary) do
+ result[key] = value
+ end
+ end
+
+ return result
+end
+
+--[[
+ Joins any number of lists together into a new list
+]]
+function Immutable.JoinLists(...)
+ local new = {}
+
+ for listKey = 1, select("#", ...) do
+ local list = select(listKey, ...)
+ local len = #new
+
+ for itemKey = 1, #list do
+ new[len + itemKey] = list[itemKey]
+ end
+ end
+
+ return new
+end
+
+--[[
+ Creates a new copy of the dictionary and sets a value inside it.
+]]
+function Immutable.Set(dictionary, key, value)
+ local new = {}
+
+ for key, value in pairs(dictionary) do
+ new[key] = value
+ end
+
+ new[key] = value
+
+ return new
+end
+
+--[[
+ Creates a new copy of the list with the given elements appended to it.
+]]
+function Immutable.Append(list, ...)
+ local new = {}
+ local len = #list
+
+ for key = 1, len do
+ new[key] = list[key]
+ end
+
+ for i = 1, select("#", ...) do
+ new[len + i] = select(i, ...)
+ end
+
+ return new
+end
+
+--[[
+ Remove elements from a dictionary
+]]
+function Immutable.RemoveFromDictionary(dictionary, ...)
+ local result = {}
+
+ for key, value in pairs(dictionary) do
+ local found = false
+ for listKey = 1, select("#", ...) do
+ if key == select(listKey, ...) then
+ found = true
+ break
+ end
+ end
+ if not found then
+ result[key] = value
+ end
+ end
+
+ return result
+end
+
+--[[
+ Remove the given key from the list.
+]]
+function Immutable.RemoveFromList(list, removeIndex)
+ local new = {}
+
+ for i = 1, #list do
+ if i ~= removeIndex then
+ table.insert(new, list[i])
+ end
+ end
+
+ return new
+end
+
+--[[
+ Remove the range from the list starting from the index.
+]]
+function Immutable.RemoveRangeFromList(list, index, count)
+ local new = {}
+
+ for i = 1, #list do
+ if i < index or i >= index + count then
+ table.insert(new, list[i])
+ end
+ end
+
+ return new
+end
+
+--[[
+ Creates a new list that has no occurrences of the given value.
+]]
+function Immutable.RemoveValueFromList(list, removeValue)
+ local new = {}
+
+ for i = 1, #list do
+ if list[i] ~= removeValue then
+ table.insert(new, list[i])
+ end
+ end
+
+ return new
+end
+
+return Immutable
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.spec.lua
new file mode 100644
index 0000000..c9adc5f
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Immutable.spec.lua
@@ -0,0 +1,284 @@
+return function()
+ local Immutable = require(script.Parent.Immutable)
+
+ describe("JoinDictionaries", function()
+ it("should preserve immutability", function()
+ local a = {}
+ local b = {}
+
+ local c = Immutable.JoinDictionaries(a, b)
+
+ expect(c).never.to.equal(a)
+ expect(c).never.to.equal(b)
+ end)
+
+ it("should treat list-like values like dictionary values", function()
+ local a = {
+ [1] = 1,
+ [2] = 2,
+ [3] = 3
+ }
+
+ local b = {
+ [1] = 11,
+ [2] = 22
+ }
+
+ local c = Immutable.JoinDictionaries(a, b)
+
+ expect(c[1]).to.equal(b[1])
+ expect(c[2]).to.equal(b[2])
+ expect(c[3]).to.equal(a[3])
+ end)
+
+ it("should merge dictionary values correctly", function()
+ local a = {
+ hello = "world",
+ foo = "bar"
+ }
+
+ local b = {
+ foo = "baz",
+ tux = "penguin"
+ }
+
+ local c = Immutable.JoinDictionaries(a, b)
+
+ expect(c.hello).to.equal(a.hello)
+ expect(c.foo).to.equal(b.foo)
+ expect(c.tux).to.equal(b.tux)
+ end)
+
+ it("should merge multiple dictionaries", function()
+ local a = {
+ foo = "yes"
+ }
+
+ local b = {
+ bar = "yup"
+ }
+
+ local c = {
+ baz = "sure"
+ }
+
+ local d = Immutable.JoinDictionaries(a, b, c)
+
+ expect(d.foo).to.equal(a.foo)
+ expect(d.bar).to.equal(b.bar)
+ expect(d.baz).to.equal(c.baz)
+ end)
+ end)
+
+ describe("JoinLists", function()
+ it("should preserve immutability", function()
+ local a = {}
+ local b = {}
+
+ local c = Immutable.JoinLists(a, b)
+
+ expect(c).never.to.equal(a)
+ expect(c).never.to.equal(b)
+ end)
+
+ it("should treat list-like values correctly", function()
+ local a = {1, 2, 3}
+ local b = {4, 5, 6}
+
+ local c = Immutable.JoinLists(a, b)
+
+ expect(#c).to.equal(6)
+
+ for i = 1, #c do
+ expect(c[i]).to.equal(i)
+ end
+ end)
+
+ it("should merge multiple lists", function()
+ local a = {1, 2}
+ local b = {3, 4}
+ local c = {5, 6}
+
+ local d = Immutable.JoinLists(a, b, c)
+
+ expect(#d).to.equal(6)
+
+ for i = 1, #d do
+ expect(d[i]).to.equal(i)
+ end
+ end)
+ end)
+
+ describe("Set", function()
+ it("should preserve immutability", function()
+ local a = {}
+
+ local b = Immutable.Set(a, "foo", "bar")
+
+ expect(b).never.to.equal(a)
+ end)
+
+ it("should treat numeric keys normally", function()
+ local a = {1, 2, 3}
+
+ local b = Immutable.Set(a, 2, 4)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(4)
+ expect(b[3]).to.equal(3)
+ end)
+
+ it("should overwrite dictionary-like keys", function()
+ local a = {
+ foo = "bar",
+ baz = "qux"
+ }
+
+ local b = Immutable.Set(a, "foo", "hello there")
+
+ expect(b.foo).to.equal("hello there")
+ expect(b.baz).to.equal(a.baz)
+ end)
+ end)
+
+ describe("Append", function()
+ it("should preserve immutability", function()
+ local a = {}
+
+ local b = Immutable.Append(a, "another happy landing")
+
+ expect(b).never.to.equal(a)
+ end)
+
+ it("should append values", function()
+ local a = {1, 2, 3}
+ local b = Immutable.Append(a, 4, 5)
+
+ expect(#b).to.equal(5)
+
+ for i = 1, #b do
+ expect(b[i]).to.equal(i)
+ end
+ end)
+ end)
+
+ describe("RemoveFromDictionary", function()
+ it("should preserve immutability", function()
+ local a = { foo = "bar" }
+
+ local b = Immutable.RemoveFromDictionary(a, "foo")
+
+ expect(b).to.never.equal(a)
+ end)
+
+ it("should remove fields from the dictionary", function()
+ local a = {
+ foo = "bar",
+ baz = "qux",
+ boof = "garply",
+ }
+
+ local b = Immutable.RemoveFromDictionary(a, "foo", "boof")
+
+ expect(b.foo).to.never.be.ok()
+ expect(b.baz).to.equal("qux")
+ expect(b.boof).to.never.be.ok()
+ end)
+ end)
+
+ describe("RemoveFromList", function()
+ it("should preserve immutability", function()
+ local a = {1, 2, 3}
+ local b = Immutable.RemoveFromList(a, 2)
+
+ expect(b).never.to.equal(a)
+ end)
+
+ it("should remove elements from the list", function()
+ local a = {1, 2, 3}
+ local b = Immutable.RemoveFromList(a, 2)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(3)
+ expect(b[3]).never.to.be.ok()
+ end)
+ end)
+
+ describe("RemoveRangeFromList", function()
+ it("should preserve immutability", function()
+ local a = {1, 2, 3}
+ local b = Immutable.RemoveRangeFromList(a, 2, 1)
+
+ expect(b).never.to.equal(a)
+ end)
+
+ it("should remove elements properly from the list", function()
+ local a = {1, 2, 3}
+ local b = Immutable.RemoveRangeFromList(a, 2, 1)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(3)
+ expect(b[3]).never.to.be.ok()
+ end)
+
+ it("should remove elements properly from the list", function()
+ local a = {1, 2, 3, 4, 5, 6}
+ local b = Immutable.RemoveRangeFromList(a, 1, 4)
+
+ expect(b[1]).to.equal(5)
+ expect(b[2]).to.equal(6)
+ expect(b[3]).never.to.be.ok()
+ end)
+
+ it("should remove elements properly from the list", function()
+ local a = {1, 2, 3, 4, 5, 6}
+ local b = Immutable.RemoveRangeFromList(a, 2, 4)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(6)
+ expect(b[3]).never.to.be.ok()
+ end)
+
+ it("should remove elements properly from the list", function()
+ local a = {1, 2, 3, 4, 5, 6, 7}
+ local b = Immutable.RemoveRangeFromList(a, 4, 4)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(2)
+ expect(b[3]).to.equal(3)
+ expect(b[4]).never.to.be.ok()
+ end)
+
+ it("should not remove any elements when count is 0 or less", function()
+ local a = {1, 2, 3}
+ local b = Immutable.RemoveRangeFromList(a, 2, 0)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(2)
+ expect(b[3]).to.equal(3)
+
+ local c = Immutable.RemoveRangeFromList(a, 2, -1)
+ expect(c[1]).to.equal(1)
+ expect(c[2]).to.equal(2)
+ expect(c[3]).to.equal(3)
+ end)
+ end)
+
+ describe("RemoveValueFromList", function()
+ it("should preserve immutability", function()
+ local a = {1, 1, 1}
+ local b = Immutable.RemoveValueFromList(a, 1)
+
+ expect(b).never.to.equal(a)
+ end)
+
+ it("should remove all elements from the list", function()
+ local a = {1, 2, 2, 3}
+ local b = Immutable.RemoveValueFromList(a, 2)
+
+ expect(b[1]).to.equal(1)
+ expect(b[2]).to.equal(3)
+ expect(b[3]).never.to.be.ok()
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Text.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Text.lua
new file mode 100644
index 0000000..acd3a4b
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Text.lua
@@ -0,0 +1,123 @@
+local LuaUseUtf8TextTruncation = settings():GetFFlag("LuaUseUtf8TextTruncation")
+local TextMeasureTemporaryPatch = settings():GetFFlag("TextMeasureTemporaryPatch")
+
+local TextService = game:GetService("TextService")
+
+local Text = {}
+
+-- FYI: Any number greater than 2^30 will make TextService:GetTextSize give invalid results
+local MAX_BOUND = 10000
+
+-- TODO(CLIPLAYEREX-1633): We can remove this padding patch after fixing TextService:GetTextSize sizing bug
+Text._TEMP_PATCHED_PADDING = Vector2.new(0, 0)
+
+if TextMeasureTemporaryPatch then
+ Text._TEMP_PATCHED_PADDING = Vector2.new(2, 2)
+end
+
+-- Wrapper function for GetTextSize
+function Text.GetTextBounds(text, font, fontSize, bounds)
+ return TextService:GetTextSize(text, fontSize, font, bounds) + Text._TEMP_PATCHED_PADDING
+end
+
+function Text.GetTextWidth(text, font, fontSize)
+ return Text.GetTextBounds(text, font, fontSize, Vector2.new(MAX_BOUND, MAX_BOUND)).X
+end
+
+function Text.GetTextHeight(text, font, fontSize, widthCap)
+ return Text.GetTextBounds(text, font, fontSize, Vector2.new(widthCap, MAX_BOUND)).Y
+end
+
+-- TODO(CLIPLAYEREX-391): Kill these truncate functions once we have official support for text truncation
+function Text.Truncate(text, font, fontSize, widthInPixels, overflowMarker)
+ overflowMarker = overflowMarker or ""
+
+ if Text.GetTextWidth(text, font, fontSize) > widthInPixels then
+ if LuaUseUtf8TextTruncation then
+ -- A binary search may be more efficient
+ local lastText = ""
+ for _, stopIndex in utf8.graphemes(text) do
+ local newText = string.sub(text, 1, stopIndex) .. overflowMarker
+ if Text.GetTextWidth(newText, font, fontSize) > widthInPixels then
+ return lastText
+ end
+ lastText = newText
+ end
+ else
+ for len = #text, 1, -1 do
+ local newText = string.sub(text, 1, len) .. overflowMarker
+ if Text.GetTextWidth(newText, font, fontSize) <= widthInPixels then
+ return newText
+ end
+ end
+ end
+ else -- No truncation needed
+ return text
+ end
+
+ return ""
+end
+
+function Text.TruncateTextLabel(textLabel, overflowMarker)
+ textLabel.Text = Text.Truncate(textLabel.Text, textLabel.Font,
+ textLabel.TextSize, textLabel.AbsoluteSize.X, overflowMarker)
+end
+
+-- Remove whitespace from the beginning and end of the string
+function Text.Trim(str)
+ if type(str) ~= "string" then
+ error(string.format("Text.Trim called on non-string type %s.", type(str)), 2)
+ end
+ return (str:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+-- Remove whitespace from the end of the string
+function Text.RightTrim(str)
+ if type(str) ~= "string" then
+ error(string.format("Text.RightTrim called on non-string type %s.", type(str)), 2)
+ end
+ return (str:gsub("%s+$", ""))
+end
+
+-- Remove whitespace from the beginning of the string
+function Text.LeftTrim(str)
+ if type(str) ~= "string" then
+ error(string.format("Text.LeftTrim called on non-string type %s.", type(str)), 2)
+ end
+ return (str:gsub("^%s+", ""))
+end
+
+-- Replace multiple whitespace with one; remove leading and trailing whitespace
+function Text.SpaceNormalize(str)
+ if type(str) ~= "string" then
+ error(string.format("Text.SpaceNormalize called on non-string type %s.", type(str)), 2)
+ end
+ return (str:gsub("%s+", " "):gsub("^%s+" , ""):gsub("%s+$" , ""))
+end
+
+-- Splits a string by the provided pattern into a table. The pattern is interpreted as plain text.
+function Text.Split(str, pattern)
+ if type(str) ~= "string" then
+ error(string.format("Text.Split called on non-string type %s.", type(str)), 2)
+ elseif type(pattern) ~= "string" then
+ error(string.format("Text.Split called with a pattern that is non-string type %s.", type(pattern)), 2)
+ elseif pattern == "" then
+ error("Text.Split called with an empty pattern.", 2)
+ end
+
+ local result = {}
+ local currentPosition = 1
+
+ while true do
+ local patternStart, patternEnd = string.find(str, pattern, currentPosition, true)
+ if not patternStart or not patternEnd then break end
+ table.insert(result, string.sub(str, currentPosition, patternStart - 1))
+ currentPosition = patternEnd + 1
+ end
+
+ table.insert(result, string.sub(str, currentPosition, string.len(str)))
+
+ return result
+end
+
+return Text
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/Text.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/Text.spec.lua
new file mode 100644
index 0000000..4fbd73a
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/Text.spec.lua
@@ -0,0 +1,410 @@
+return function()
+ local Text = require(script.Parent.Text)
+
+ describe("GetTextBounds", function()
+ it("should return a bounds of padding width and font-size height when the string is empty", function()
+ local bounds = Text.GetTextBounds("", Enum.Font.SourceSans, 18, Vector2.new(1000, 1000))
+ expect(bounds.X).to.equal(Text._TEMP_PATCHED_PADDING.x)
+ expect(bounds.Y).to.equal(18 + Text._TEMP_PATCHED_PADDING.y)
+ end)
+ it("should return the height and width of a string as one line with large bounds", function()
+ local bounds = Text.GetTextBounds("One Two Three", Enum.Font.SourceSans, 18, Vector2.new(1000, 1000))
+ expect(bounds.Y).to.equal(18 + Text._TEMP_PATCHED_PADDING.y)
+ end)
+
+ it("should return the height of the string as multiple lines with short bounds", function()
+ local bounds = Text.GetTextBounds("One Two Three Four", Enum.Font.SourceSans, 18, Vector2.new(32, 1000))
+ expect(bounds.Y > 18).to.equal(true)
+ end)
+ end)
+
+ describe("GetTextHeight", function()
+ it("should return height equal to font size when string is empty", function()
+ local height = Text.GetTextHeight("", Enum.Font.SourceSans, 18, 0)
+ expect(height).to.equal(18 + Text._TEMP_PATCHED_PADDING.y)
+ end)
+ end)
+
+ describe("GetTextWidth", function()
+ it("should return width equal to 1 when string is empty", function()
+ local width = Text.GetTextWidth("", Enum.Font.SourceSans, 18, 18)
+ expect(width).to.equal(Text._TEMP_PATCHED_PADDING.x)
+ end)
+ end)
+
+ describe("Truncate", function()
+ it("should return empty string", function()
+ local emptyQuery = Text.Truncate("", Enum.Font.SourceSans, 18, 0, "...")
+ expect(emptyQuery).to.be.a("string")
+ expect(emptyQuery).to.equal("")
+ end)
+
+ it("should return empty string for not empty box", function()
+ local emptyQuery = Text.Truncate("", Enum.Font.SourceSans, 18, 50, "...")
+ expect(emptyQuery).to.be.a("string")
+ expect(emptyQuery).to.equal("")
+ end)
+
+ it("should truncate with ...", function()
+ local reallyLongQuery = Text.Truncate(
+ "One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve", Enum.Font.SourceSans, 18, 100, "...")
+ expect(reallyLongQuery).to.equal("One Two Thre...")
+ end)
+
+ it("should truncate without a ...", function()
+ local reallyLongQueryNoOverflowMarker = Text.Truncate(
+ "One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve", Enum.Font.SourceSans, 18, 100)
+ expect(reallyLongQueryNoOverflowMarker).to.equal("One Two Three ")
+ end)
+
+ it("should not truncate", function()
+ local shouldFitQuery = Text.Truncate("One Two", Enum.Font.SourceSans, 18, 100)
+ expect(shouldFitQuery).to.equal("One Two")
+ end)
+
+ it("should not truncate, off by one check", function()
+ local oneCharQuery = Text.Truncate("O", Enum.Font.SourceSans, 18, 100)
+ expect(oneCharQuery).to.equal("O")
+ end)
+
+ it("should truncate, off by one check", function()
+ local oneCharNoRoomQuery = Text.Truncate("O", Enum.Font.SourceSans, 18, 0)
+ expect(oneCharNoRoomQuery).to.equal("")
+ end)
+
+ it("should perform a negative width check", function()
+ local shouldFitQuery = Text.Truncate("One Two", Enum.Font.SourceSans, 18, -100, "...")
+ expect(shouldFitQuery).to.equal("")
+ end)
+
+ it("should truncate long graphemes properly", function()
+ -- 11-byte rainbow flag grapheme
+ -- Flag, zero-space-joiner, rainbow
+ local rainbowFlag = utf8.char(127987) .. utf8.char(8205) .. utf8.char(127752)
+ local oneFlagWithinLimit = Text.Truncate(
+ rainbowFlag, Enum.Font.SourceSans, 18, 100, "...")
+ expect(oneFlagWithinLimit).to.equal(rainbowFlag)
+
+ local twoRainbowFlags = rainbowFlag .. rainbowFlag
+ local twoFlagsAreFine = Text.Truncate(
+ twoRainbowFlags, Enum.Font.SourceSans, 18, 100, "...")
+ expect(twoFlagsAreFine).to.equal(twoRainbowFlags)
+
+ local fourRainbowFlags = twoRainbowFlags .. twoRainbowFlags
+ local fourFlagsIsTooLong = Text.Truncate(
+ fourRainbowFlags, Enum.Font.SourceSans, 18, 100, "...")
+ expect(fourFlagsIsTooLong).to.equal(twoRainbowFlags .. "...")
+ end)
+ end)
+
+ describe("TruncateTextLabel", function()
+ it("should use text label attributes to truncate text", function()
+ local screenGui = Instance.new("ScreenGui")
+ local textLabel = Instance.new("TextLabel")
+ textLabel.Size = UDim2.new(0, 100, 0, 32)
+ textLabel.Text = "One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve"
+ textLabel.Font = Enum.Font.SourceSans
+ textLabel.TextSize = 18
+ textLabel.Parent = screenGui
+ Text.TruncateTextLabel(textLabel)
+
+ expect(textLabel.Text).to.equal("One Two Three ")
+ end)
+ end)
+
+
+ describe("TrimString", function()
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim("")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim(" ")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim("ab")
+ local expected = "ab"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim(" ab ")
+ local expected = "ab"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim(" a b ")
+ local expected = "a b"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim("\r\n\t\f a\r\n\t\f ")
+ local expected = "a"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string with unicode characters properly", function()
+ local trimmedInput = Text.Trim("😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓")
+ local expected = "😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim(" 😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓 ")
+ local expected = "😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should trim the string properly", function()
+ local trimmedInput = Text.Trim("\n 😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓 \n")
+ local expected = "😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ end)
+
+
+ describe("RightTrimString", function()
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim("")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim(" ")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim("ab")
+ local expected = "ab"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim(" ab ")
+ local expected = " ab"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim(" a b ")
+ local expected = " a b"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim("\r\n\t\f a\r\n\t\f ")
+ local expected = "\r\n\t\f a"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string with unicode characters properly", function()
+ local trimmedInput = Text.RightTrim("😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓")
+ local expected = "😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim(" 😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓 ")
+ local expected = " 😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should right trim the string properly", function()
+ local trimmedInput = Text.RightTrim("\n 😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓 \n")
+ local expected = "\n 😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ end)
+
+
+ describe("LeftTrimString", function()
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim("")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim(" ")
+ local expected = ""
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim("ab")
+ local expected = "ab"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim(" ab ")
+ local expected = "ab "
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim(" a b ")
+ local expected = " a b "
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim("\r\n\t\f a\r\n\t\f ")
+ local expected = "a\r\n\t\f "
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string with unicode characters properly", function()
+ local trimmedInput = Text.LeftTrim("😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓")
+ local expected = "😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim(" 😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓 ")
+ local expected = "😤👩🏼🏫😭ぼ😀で😹🤕あ👩🏻🎓 "
+ expect(trimmedInput).to.equal(expected)
+ end)
+ it("Should left trim the string properly", function()
+ local trimmedInput = Text.LeftTrim("\n 😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓 \n")
+ local expected = "😤👩🏼🏫😭ぼ😀 \nで😹🤕あ👩🏻🎓 \n"
+ expect(trimmedInput).to.equal(expected)
+ end)
+ end)
+
+
+ describe("SpaceNormalize", function()
+ it("should remove multiple spaces between words", function()
+ local a = "This is not a normal sentence."
+
+ expect(Text.SpaceNormalize(a)).to.equal("This is not a normal sentence.")
+ end)
+
+ it("should remove leading and trailing whitespace", function()
+ local a = " SpaceTabSpaceTab "
+
+ expect(Text.SpaceNormalize(a)).to.equal("SpaceTabSpaceTab")
+ end)
+
+ it("should not change a string with no whitespace", function()
+ local a = "There'sNo%Whit.e\\space--InThis."
+
+ expect(Text.SpaceNormalize(a)).to.equal(a)
+ end)
+
+ it("should remove all whitespace in a string that is nothing but whitespace", function()
+ local a = " "
+
+ expect(Text.SpaceNormalize(a)).to.equal("")
+ end)
+
+ it("should handle the case where the string is empty", function()
+ local a = ""
+
+ expect(Text.SpaceNormalize(a)).to.equal(a)
+ end)
+
+ it("should throw an error if called an a non-string type", function()
+ local a = { first = 1, second = 2 }
+
+ expect(function()
+ Text.SpaceNormalize(a)
+ end).to.throw()
+ end)
+ end)
+
+
+ describe("Split", function()
+ local function tableEquals(tb1, tb2)
+ local tables = { tb1, tb2 }
+
+ for _,tb in ipairs(tables) do
+ for key in pairs(tb) do
+ if tb1[key] ~= tb2[key] then
+ return false
+ end
+ end
+ end
+
+ return true
+ end
+
+ it("should return the correct table for your standard use case", function()
+ local a = "this,is,comma,separated"
+ local pattern = ","
+ local expectedResult = {
+ [1] = "this",
+ [2] = "is",
+ [3] = "comma",
+ [4] = "separated",
+ }
+
+ expect(tableEquals(Text.Split(a, pattern), expectedResult)).to.equal(true)
+ end)
+
+ it("should not remove whitespace", function()
+ local a = " SpaceTab , , Space"
+ local pattern = ","
+ local expectedResult = {
+ [1] = " SpaceTab ",
+ [2] = " ",
+ [3] = " Space",
+ }
+
+ expect(tableEquals(Text.Split(a, pattern), expectedResult)).to.equal(true)
+ end)
+
+ it("should treat regular expressions as plain text", function()
+ local a = "Notyour^%s+normalstring.Thisisasecondsentence."
+ local b = "."
+ local c = "^%s+"
+ local d = "%A"
+
+ local expectedB = {
+ [1] = "Notyour^%s+normalstring",
+ [2] = "Thisisasecondsentence",
+ [3] = "",
+ }
+ local expectedC = {
+ [1] = "Notyour",
+ [2] = "normalstring.Thisisasecondsentence."
+ }
+ local expectedD = {
+ [1] = "Notyour^%s+normalstring.Thisisasecondsentence."
+ }
+
+ expect(tableEquals(Text.Split(a, b), expectedB)).to.equal(true)
+ expect(tableEquals(Text.Split(a, c), expectedC)).to.equal(true)
+ expect(tableEquals(Text.Split(a, d), expectedD)).to.equal(true)
+ end)
+
+ it("should work when pattern is not in string", function()
+ local a = "The pattern you are looking for does not exist."
+ local pattern = ","
+ local expectedResult = {
+ [1] = "The pattern you are looking for does not exist.",
+ }
+
+ expect(tableEquals(Text.Split(a, pattern), expectedResult)).to.equal(true)
+ end)
+
+ it("should work when called on an empty string", function()
+ local a = ""
+ local pattern = ","
+ local expectedResult = {
+ [1] = "",
+ }
+
+ expect(tableEquals(Text.Split(a, pattern), expectedResult)).to.equal(true)
+ end)
+
+ it("should throw an error if called on an empty pattern", function()
+ local a = "The pattern definitely doesn't exist here."
+ local pattern = ""
+
+ expect(function()
+ Text.Split(a, pattern)
+ end).to.throw()
+ end)
+
+ it("should throw an error if called an a non-string type", function()
+ local a = { first = 1, second = 2 }
+ local b = "an actual string"
+
+ expect(function()
+ Text.Split(a, b)
+ end).to.throw()
+
+ expect(function()
+ Text.Split(b, a)
+ end).to.throw()
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.lua
new file mode 100644
index 0000000..261dcd0
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.lua
@@ -0,0 +1,68 @@
+--[[
+ memoize creates a function as a wrapper that caches the last outputs of a function.
+ This is useful if you know that the function should return the same output every
+ time it is run with the same inputs. The function should only return an output, and
+ not have any side effects. These side effects are not cached.
+
+ Without memoize's caching, even though the function ouputs the same values, the
+ memory locations of the values are different; tables made in the function, even if
+ they have the same values, won't be the same tables.
+
+ memoize only caches the last set of inputs and ouputs. This means that it is only
+ helpful when the function is likely to be called with the same inputs multiple
+ times in a row. This is the case with most Roact use cases.
+
+ Note that memoize only does a ** shallow check on table inputs ** . This means
+ that if the same table is input but the elements of the table are different then
+ it will be assumed that the table has not changed.
+
+ In addition to all the previous warnings, memoize strips trailing nils. This means
+ that if foo is a memoized function and we call foo(), then foo(nil) will return a
+ cached value. This is opposed to how print handles input. print() only outputs a
+ new line, but print(nil) outputs "nil". This is because varargs can detect the
+ number of arguments passed in. So, be careful when using memoize with varargs.
+ Trailing nils will be stripped.
+
+ The wrapper can take any number of inputs and give any number of outputs.
+ Leading and interspersed nils are handled gracefully. Trailing nils on the input
+ are stripped.
+]]
+local function captureSize(...)
+ return {...}, select("#", ...)
+end
+
+local function memoize(func)
+ assert(type(func) == "function", "memoize requires a function to memoize")
+
+ local lastArgs
+ local lastNumArgs
+ local lastOutput
+ local lastNumOutput
+
+ return function(...)
+ local numArgs = select("#", ...)
+
+ while numArgs > 0 and select(numArgs, ...) == nil do
+ numArgs = numArgs - 1
+ end
+
+ if numArgs ~= lastNumArgs then
+ lastArgs = {...}
+ lastNumArgs = numArgs
+ lastOutput, lastNumOutput = captureSize(func(...))
+ return unpack(lastOutput, 1, lastNumOutput)
+ end
+
+ for i = 1, lastNumArgs do
+ if select(i, ...) ~= lastArgs[i] then
+ lastArgs = {...}
+ lastOutput, lastNumOutput = captureSize(func(...))
+ break
+ end
+ end
+
+ return unpack(lastOutput, 1, lastNumOutput)
+ end
+end
+
+return memoize
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.spec.lua
new file mode 100644
index 0000000..5ae2b6e
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Common/memoize.spec.lua
@@ -0,0 +1,213 @@
+return function()
+ local memoize = require(script.Parent.memoize)
+
+ describe("memoize", function()
+ it("should handle arity 0", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ expect(identity()).to.equal(nil)
+ expect(identity(nil)).to.equal(nil)
+ expect(identity(nil, nil)).to.equal(nil)
+ expect(callCount).to.equal(1)
+ end)
+
+ it("should handle arity 1", function()
+ local callCount = 0
+ local identity = memoize(function(a)
+ callCount = callCount + 1
+ return a
+ end)
+
+ expect(identity(5)).to.equal(5)
+ expect(identity(5)).to.equal(5)
+ expect(callCount).to.equal(1)
+
+ expect(identity(6)).to.equal(6)
+ expect(callCount).to.equal(2)
+
+ expect(identity(5)).to.equal(5)
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle arity 2", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(6, 5)
+ expect(a).to.equal(6)
+ expect(b).to.equal(5)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle mixed arity", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity()
+ expect(a).to.equal(nil)
+ expect(b).to.equal(nil)
+
+ a, b = identity()
+ expect(a).to.equal(nil)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle trailing nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, nil)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle leading nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle interspersed nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b, c, d)
+ callCount = callCount + 1
+ return a, b, c, d
+ end)
+
+ local a, b, c, d
+
+ a, b, c, d = identity(7, nil, 7, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ -- Trailing nils can affect how interspersed nils are handled
+ a, b, c, d = identity(7, nil, 7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(1)
+
+ a, b, c, d = identity(7, nil, nil, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(nil)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b, c, d = identity(7, nil, 7, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUser.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUser.lua
new file mode 100644
index 0000000..7ac8be2
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUser.lua
@@ -0,0 +1,8 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(user)
+ return {
+ user = user
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUsers.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUsers.lua
new file mode 100644
index 0000000..fad0bcb
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/AddUsers.lua
@@ -0,0 +1,8 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(users)
+ return {
+ users = users
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/RemoveUser.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/RemoveUser.lua
new file mode 100644
index 0000000..b407b15
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/RemoveUser.lua
@@ -0,0 +1,8 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(userId)
+ return {
+ userId = userId,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetDeviceOrientation.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetDeviceOrientation.lua
new file mode 100644
index 0000000..6cfa228
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetDeviceOrientation.lua
@@ -0,0 +1,8 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(deviceOrientation)
+ return {
+ deviceOrientation = deviceOrientation,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetFriendCount.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetFriendCount.lua
new file mode 100644
index 0000000..39aa112
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetFriendCount.lua
@@ -0,0 +1,10 @@
+local CorePackages = game:GetService("CorePackages")
+local Common = CorePackages.AppTempCommon.Common
+
+local Action = require(Common.Action)
+
+return Action(script.Name, function(count)
+ return {
+ count = count,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserIsFriend.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserIsFriend.lua
new file mode 100644
index 0000000..690a05e
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserIsFriend.lua
@@ -0,0 +1,9 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(userId, isFriend)
+ return {
+ userId = userId,
+ isFriend = isFriend,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserMembershipType.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserMembershipType.lua
new file mode 100644
index 0000000..1c08dbe
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserMembershipType.lua
@@ -0,0 +1,11 @@
+local CorePackages = game:GetService("CorePackages")
+local Common = CorePackages.AppTempCommon.Common
+
+local Action = require(Common.Action)
+
+return Action(script.Name, function(userId, membershipType)
+ return {
+ userId = userId,
+ membershipType = membershipType,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserPresence.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserPresence.lua
new file mode 100644
index 0000000..b25a118
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserPresence.lua
@@ -0,0 +1,10 @@
+local CorePackages = game:GetService("CorePackages")
+local Action = require(CorePackages.AppTempCommon.Common.Action)
+
+return Action(script.Name, function(userId, presence, lastLocation)
+ return {
+ userId = tostring(userId),
+ presence = presence,
+ lastLocation = lastLocation,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserThumbnail.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserThumbnail.lua
new file mode 100644
index 0000000..508cf70
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Actions/SetUserThumbnail.lua
@@ -0,0 +1,13 @@
+local CorePackages = game:GetService("CorePackages")
+local Common = CorePackages.AppTempCommon.Common
+
+local Action = require(Common.Action)
+
+return Action(script.Name, function(userId, image, thumbnailType, thumbnailSize)
+ return {
+ userId = userId,
+ image = image,
+ thumbnailType = thumbnailType,
+ thumbnailSize = thumbnailSize,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatSendMessage.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatSendMessage.lua
new file mode 100644
index 0000000..1642bb5
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatSendMessage.lua
@@ -0,0 +1,15 @@
+local CorePackages = game:GetService("CorePackages")
+local HttpService = game:GetService("HttpService")
+
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+return function(requestImpl, conversationId, messageText)
+ local payload = HttpService:JSONEncode({
+ conversationId = conversationId,
+ message = messageText,
+ })
+
+ local url = string.format("%s/send-message", Url.CHAT_URL)
+
+ return requestImpl(url, "POST", { postBody = payload })
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatStartOneToOneConversation.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatStartOneToOneConversation.lua
new file mode 100644
index 0000000..4f7a75f
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/ChatStartOneToOneConversation.lua
@@ -0,0 +1,14 @@
+local CorePackages = game:GetService("CorePackages")
+local HttpService = game:GetService("HttpService")
+
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+return function(requestImpl, userId, clientId)
+ local payload = HttpService:JSONEncode({
+ participantuserId = userId
+ })
+
+ local url = string.format("%s/start-one-to-one-conversation", Url.CHAT_URL)
+
+ return requestImpl(url, "POST", { postBody = payload })
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/GetPlaceInfos.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/GetPlaceInfos.lua
new file mode 100644
index 0000000..883bc34
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/GetPlaceInfos.lua
@@ -0,0 +1,17 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+return function(requestImpl, placeIds)
+ local argTable = {
+ placeIds = placeIds,
+ }
+
+ -- construct the url
+ local args = Url:makeQueryString(argTable)
+ local url = string.format("%s/v1/games/multiget-place-details?%s",
+ Url.GAME_URL, args
+ )
+
+ return requestImpl(url, "GET")
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriendCount.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriendCount.lua
new file mode 100644
index 0000000..b4fa8c3
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriendCount.lua
@@ -0,0 +1,30 @@
+local CorePackages = game:GetService("CorePackages")
+local Players = game:GetService("Players")
+
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+--[[
+ This endpoint returns a promise that resolves to:
+
+ [
+ {
+ "success:" true,
+ "count": "0"
+ },
+ ]
+]]--
+
+-- requestImpl - (function>(url, requestMethod, options))
+return function(requestImpl)
+
+ local argTable = {
+ userId = Players.LocalPlayer.UserId,
+ }
+
+ local args = Url:makeQueryString(argTable)
+ local url = string.format("%s/user/get-friendship-count?%s",
+ Url.API_URL, tostring(Players.LocalPlayer.UserId), args
+ )
+
+ return requestImpl(url, "GET")
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriends.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriends.lua
new file mode 100644
index 0000000..79b8653
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetFriends.lua
@@ -0,0 +1,10 @@
+local CorePackages = game:GetService("CorePackages")
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+return function(requestImpl, userId)
+ local url = string.format("%s/users/%s/friends",
+ Url.FRIEND_URL, userId
+ )
+
+ return requestImpl(url, "GET")
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetPresence.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetPresence.lua
new file mode 100644
index 0000000..b054e6e
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetPresence.lua
@@ -0,0 +1,25 @@
+local CorePackages = game:GetService("CorePackages")
+local HttpService = game:GetService("HttpService")
+
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+-- Endpoint documented here:
+-- https://presence.roblox.com/docs
+
+return function(requestImpl, userIds)
+ local userIdsToNumber = {}
+ for _, id in pairs(userIds) do
+ local idToNumber = tonumber(id)
+ if idToNumber then
+ table.insert(userIdsToNumber, idToNumber)
+ end
+ end
+
+ local payload = HttpService:JSONEncode({
+ userIds = userIdsToNumber,
+ })
+
+ local url = string.format("%s/presence/users", Url.PRESENCE_URL)
+
+ return requestImpl(url, "POST", { postBody = payload })
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetThumbnail.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetThumbnail.lua
new file mode 100644
index 0000000..ac79bd6
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Requests/UsersGetThumbnail.lua
@@ -0,0 +1,46 @@
+local CorePackages = game:GetService("CorePackages")
+local Players = game:GetService("Players")
+
+local Promise = require(CorePackages.AppTempCommon.LuaApp.Promise)
+
+local THUMBNAIL_TYPE_BY_NAME = {
+ AvatarThumbnail = Enum.ThumbnailType.AvatarThumbnail,
+ HeadShot = Enum.ThumbnailType.HeadShot,
+}
+
+local THUMBNAIL_SIZE_BY_NAME = {
+ Size48x48 = Enum.ThumbnailSize.Size48x48,
+ Size100x100 = Enum.ThumbnailSize.Size100x100,
+ Size150x150 = Enum.ThumbnailSize.Size150x150,
+}
+
+return function(userId, thumbnailType, thumbnailSize)
+ return Promise.new(function(resolve, reject)
+ --Async methods will yield the thread
+ spawn(function()
+ local result = {success = false}
+ local success, message = pcall(function()
+ local image, isFinal = Players:GetUserThumbnailAsync(
+ userId, THUMBNAIL_TYPE_BY_NAME[thumbnailType], THUMBNAIL_SIZE_BY_NAME[thumbnailSize]
+ )
+
+ result = {
+ success = true,
+ id = userId,
+ thumbnailType = thumbnailType,
+ thumbnailSize = thumbnailSize,
+
+ image = isFinal and image or nil,
+ isFinal = isFinal,
+ }
+ end)
+
+ if success then
+ resolve(result)
+ else
+ result.message = message
+ reject(result)
+ end
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.lua
new file mode 100644
index 0000000..4201c06
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.lua
@@ -0,0 +1,110 @@
+--[[
+ Url Constructor
+
+ Provides a single location for base urls.
+
+]]--
+local ContentProvider = game:GetService("ContentProvider")
+
+-- helper functions
+local function parseBaseUrlInformation()
+ -- get the current base url from the current configuration
+ local baseUrl = ContentProvider.BaseUrl
+
+ -- keep a copy of the base url (https://www.roblox.com/)
+ -- append a trailing slash if there isn't one
+ if baseUrl:sub(#baseUrl) ~= "/" then
+ baseUrl = baseUrl .. "/"
+ end
+
+ -- parse out scheme (http, https)
+ local _, schemeEnd = baseUrl:find("://")
+
+ -- parse out the prefix (www, kyle, ying, etc.)
+ local prefixIndex, prefixEnd = baseUrl:find("%.", schemeEnd + 1)
+ local basePrefix = baseUrl:sub(schemeEnd + 1, prefixIndex - 1)
+
+ -- parse out the domain (roblox.com/, sitetest1.robloxlabs.com/, etc.)
+ local baseDomain = baseUrl:sub(prefixEnd + 1)
+
+ return baseUrl, basePrefix, baseDomain
+end
+local function preventTableModification(aTable, key, value)
+ error("Attempt to modify read-only table")
+end
+local function createReadOnlyTable(aTable)
+ return setmetatable({}, {
+ __index = aTable,
+ __newindex = preventTableModification,
+ __metatable = false
+ });
+end
+
+
+-- url construction building blocks
+local _baseUrl, _basePrefix, _baseDomain = parseBaseUrlInformation()
+
+-- construct urls once
+local _baseApiUrl = string.format("https://api.%s", _baseDomain)
+local _baseAuthUrl = string.format("https://auth.%s", _baseDomain)
+local _baseChatUrl = string.format("https://chat.%sv2", _baseDomain)
+local _baseFriendUrl = string.format("https://friends.%sv1", _baseDomain)
+local _baseGameAssetUrl = string.format("https://assetgame.%s", _baseDomain)
+local _baseGamesUrl = string.format("https://games.%s", _baseDomain)
+local _baseNotificationUrl = string.format("https://notifications.%s", _baseDomain)
+local _basePresenceUrl = string.format("https://presence.%sv1", _baseDomain)
+local _baseRealtimeUrl = string.format("https://realtime.%s", _baseDomain)
+local _baseWebUrl = string.format("https://web.%s", _baseDomain)
+
+-- public api
+local Url = {
+ DOMAIN = _baseDomain,
+ PREFIX = _basePrefix,
+ BASE_URL = _baseUrl,
+ API_URL = _baseApiUrl,
+ AUTH_URL = _baseAuthUrl,
+ GAME_URL = _baseGamesUrl,
+ GAME_ASSET_URL = _baseGameAssetUrl,
+ CHAT_URL = _baseChatUrl,
+ FRIEND_URL = _baseFriendUrl,
+ PRESENCE_URL = _basePresenceUrl,
+ NOTIFICATION_URL = _baseNotificationUrl,
+ REALTIME_URL = _baseRealtimeUrl,
+ WEB_URL = _baseWebUrl
+}
+
+function Url:getUserProfileUrl(userId)
+ return string.format("%susers/%s/profile", self.BASE_URL, userId)
+end
+
+function Url:isVanitySite()
+ return self.PREFIX ~= "www"
+end
+
+-- data - (table) a table of key/value pairs to format
+function Url:makeQueryString(data)
+ --NOTE - This function can be used to create a query string of parameters
+ -- at the end of url query, or create a application/form-url-encoded post body string
+ local params = {}
+
+ -- NOTE - Arrays are handled, but generally data is expected to be flat.
+ for key, value in pairs(data) do
+ if value ~= nil then --for optional params
+ if type(value) == "table" then
+ for i = 1, #value do
+ table.insert(params, key .. "=" .. value[i])
+ end
+ else
+ table.insert(params, key .. "=" .. tostring(value))
+ end
+ end
+ end
+
+ return table.concat(params, "&")
+end
+
+
+-- prevent anyone from modifying this table:
+Url = createReadOnlyTable(Url)
+
+return Url
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.spec.lua
new file mode 100644
index 0000000..62b8fab
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Http/Url.spec.lua
@@ -0,0 +1,12 @@
+return function()
+
+ local ContentProvider = game:GetService("ContentProvider")
+ local Url = require(script.Parent.Url)
+
+ it("The base url has not been changed for debugging", function()
+ local baseUrl = ContentProvider.BaseUrl
+
+ expect(baseUrl).to.equal(Url.BASE_URL)
+ end)
+
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/MockId.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/MockId.lua
new file mode 100644
index 0000000..456cea0
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/MockId.lua
@@ -0,0 +1,10 @@
+--[[
+ A function to return a fake ID, used for testing
+]]
+
+local lastId = 0
+
+return function()
+ lastId = lastId + 1
+ return ("MOCK-%d"):format(lastId)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/ThumbnailRequest.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/ThumbnailRequest.lua
new file mode 100644
index 0000000..6df561f
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/ThumbnailRequest.lua
@@ -0,0 +1,18 @@
+local ThumbnailRequest = {}
+
+function ThumbnailRequest.new()
+ local self = {}
+
+ return self
+end
+
+function ThumbnailRequest.fromData(thumbnailType, thumbnailSize)
+ local self = ThumbnailRequest.new()
+
+ self.thumbnailType = thumbnailType
+ self.thumbnailSize = thumbnailSize
+
+ return self
+end
+
+return ThumbnailRequest
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/User.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/User.lua
new file mode 100644
index 0000000..98bdc6b
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Models/User.lua
@@ -0,0 +1,84 @@
+local CorePackages = game:GetService("CorePackages")
+local Players = game:GetService("Players")
+
+local MockId = require(CorePackages.AppTempCommon.LuaApp.MockId)
+
+local FFlagFixUsersReducerDataLoss = settings():GetFFlag("FixUsersReducerDataLoss")
+
+local User = {}
+
+User.PresenceType = {
+ OFFLINE = "OFFLINE",
+ ONLINE = "ONLINE",
+ IN_GAME = "IN_GAME",
+ IN_STUDIO = "IN_STUDIO",
+}
+
+function User.new()
+ local self = {}
+
+ return self
+end
+
+function User.mock()
+ local self = User.new()
+
+ self.id = MockId()
+
+ self.isFetching = false
+ self.isFriend = false
+ self.lastLocation = nil
+ self.name = "USER NAME"
+ self.placeId = nil
+ self.presence = User.PresenceType.OFFLINE
+ self.membership = nil
+ if not FFlagFixUsersReducerDataLoss then
+ self.thumbnails = {}
+ end
+
+ return self
+end
+
+function User.fromData(id, name, isFriend)
+ local self = User.new()
+
+ self.id = tostring(id)
+
+ self.isFetching = false
+ self.isFriend = isFriend
+ self.lastLocation = nil
+ self.name = name
+ self.placeId = nil
+ if FFlagFixUsersReducerDataLoss then
+ self.presence = (self.id == tostring(Players.LocalPlayer.UserId)) and User.PresenceType.ONLINE or nil
+ else
+ self.presence = (self.id == tostring(Players.LocalPlayer.UserId)) and User.PresenceType.ONLINE or
+ User.PresenceType.OFFLINE
+ self.thumbnails = {}
+ end
+
+ return self
+end
+
+function User.userPresenceToText(localization, user)
+ local presence = user.presence
+ local lastLocation = user.lastLocation
+
+ if not presence then
+ return ''
+ end
+
+ if presence == User.PresenceType.OFFLINE then
+ return localization:Format("Common.Presence.Label.Offline")
+ elseif presence == User.PresenceType.ONLINE then
+ return localization:Format("Common.Presence.Label.Online")
+ elseif (presence == User.PresenceType.IN_GAME) or (presence == User.PresenceType.IN_STUDIO) then
+ if lastLocation ~= nil then
+ return lastLocation
+ else
+ return localization:Format("Common.Presence.Label.Online")
+ end
+ end
+end
+
+return User
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.lua
new file mode 100644
index 0000000..465e93c
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.lua
@@ -0,0 +1,337 @@
+--[[
+ An implementation of Promises similar to Promise/A+.
+]]
+local TU = require(script.Parent.TableUtilities)
+
+local PROMISE_DEBUG = true
+
+-- If promise debugging is on, use a version of pcall that warns on failure.
+-- This is useful for finding errors that happen within Promise itself.
+local wpcall
+if PROMISE_DEBUG then
+ wpcall = function(f, ...)
+ local result = { pcall(f, ...) }
+
+ if not result[1] then
+ warn(result[2])
+ end
+
+ return unpack(result)
+ end
+else
+ wpcall = pcall
+end
+
+--[[
+ Creates a function that invokes a callback with correct error handling and
+ resolution mechanisms.
+]]
+local function createAdvancer(callback, resolve, reject)
+ return function(...)
+ local result = { wpcall(callback, ...) }
+ local ok = table.remove(result, 1)
+
+ if ok then
+ resolve(unpack(result))
+ else
+ reject(unpack(result))
+ end
+ end
+end
+
+local function isEmpty(t)
+ return next(t) == nil
+end
+
+local Promise = {}
+Promise.__index = Promise
+
+Promise.Status = {
+ Started = "Started",
+ Resolved = "Resolved",
+ Rejected = "Rejected",
+}
+
+--[[
+ Constructs a new Promise with the given initializing callback.
+
+ This is generally only called when directly wrapping a non-promise API into
+ a promise-based version.
+
+ The callback will receive 'resolve' and 'reject' methods, used to start
+ invoking the promise chain.
+
+ For example:
+
+ local function get(url)
+ return Promise.new(function(resolve, reject)
+ spawn(function()
+ resolve(HttpService:GetAsync(url))
+ end)
+ end)
+ end
+
+ get("https://google.com")
+ :andThen(function(stuff)
+ print("Got some stuff!", stuff)
+ end)
+]]
+function Promise.new(callback)
+ local promise = {
+ -- Used to locate where a promise was created
+ _source = debug.traceback(),
+
+ -- A tag to identify us as a promise
+ _type = "Promise",
+
+ _status = Promise.Status.Started,
+
+ -- A table containing a list of all results, whether success or failure.
+ -- Only valid if _status is set to something besides Started
+ _value = nil,
+
+ -- Queues representing functions we should invoke when we update!
+ _queuedResolve = {},
+ _queuedReject = {},
+ }
+
+ setmetatable(promise, Promise)
+
+ local function resolve(...)
+ promise:_resolve(...)
+ end
+
+ local function reject(...)
+ promise:_reject(...)
+ end
+
+ local ok, err = wpcall(callback, resolve, reject)
+
+ if not ok and promise._status == Promise.Status.Started then
+ reject(err)
+ end
+
+ return promise
+end
+
+--[[
+ Create a promise that represents the immediately resolved value.
+]]
+function Promise.resolve(value)
+ return Promise.new(function(resolve)
+ resolve(value)
+ end)
+end
+
+--[[
+ Create a promise that represents the immediately rejected value.
+]]
+function Promise.reject(value)
+ return Promise.new(function(_, reject)
+ reject(value)
+ end)
+end
+
+--[[
+ Returns a new promise that:
+ * is resolved when all input promises resolve
+ * is rejected if ANY input promises reject
+]]
+function Promise.all(...)
+ local promises = {...}
+
+ -- check if we've been given a list of promises, not just a variable number of promises
+ if type(promises[1]) == "table" and promises[1]._type ~= "Promise" then
+ -- we've been given a table of promises already
+ promises = promises[1]
+ end
+
+ return Promise.new(function(resolve, reject)
+ local isResolved = false
+ local results = {}
+ local totalCompleted = 0
+ local function promiseCompleted(index, result)
+ if isResolved then
+ return
+ end
+
+ results[index] = result
+ totalCompleted = totalCompleted + 1
+
+ if totalCompleted == #promises then
+ resolve(results)
+ isResolved = true
+ end
+ end
+
+ for index, promise in ipairs(promises) do
+ -- if a promise isn't resolved yet, add listeners for when it does
+ if promise._status == Promise.Status.Started then
+ promise:andThen(function(result)
+ promiseCompleted(index, result)
+ end):catch(function(reason)
+ isResolved = true
+ reject(reason)
+ end)
+
+ -- if a promise is already resolved, move on
+ elseif promise._status == Promise.Status.Resolved then
+ promiseCompleted(index, promise._value)
+
+ -- if a promise is rejected, reject the whole chain
+ else --if promise._status == Promise.Status.Rejected then
+ isResolved = true
+ reject(promise._value)
+ end
+ end
+ end)
+end
+
+--[[
+ Is the given object a Promise instance?
+]]
+function Promise.is(object)
+ if type(object) ~= "table" then
+ return false
+ end
+
+ return object._type == "Promise"
+end
+
+--[[
+ Creates a new promise that receives the result of this promise.
+
+ The given callbacks are invoked depending on that result.
+]]
+function Promise:andThen(successHandler, failureHandler)
+ -- Create a new promise to follow this part of the chain
+ return Promise.new(function(resolve, reject)
+ -- Our default callbacks just pass values onto the next promise.
+ -- This lets success and failure cascade correctly!
+
+ local successCallback = resolve
+ if successHandler then
+ successCallback = createAdvancer(successHandler, resolve, reject)
+ end
+
+ local failureCallback = reject
+ if failureHandler then
+ failureCallback = createAdvancer(failureHandler, resolve, reject)
+ end
+
+ if self._status == Promise.Status.Started then
+ -- If we haven't resolved yet, put ourselves into the queue
+ table.insert(self._queuedResolve, successCallback)
+ table.insert(self._queuedReject, failureCallback)
+ elseif self._status == Promise.Status.Resolved then
+ -- This promise has already resolved! Trigger success immediately.
+ successCallback(unpack(self._value))
+ elseif self._status == Promise.Status.Rejected then
+ -- This promise died a terrible death! Trigger failure immediately.
+ failureCallback(unpack(self._value))
+ end
+ end)
+end
+
+--[[
+ Used to catch any errors that may have occurred in the promise.
+]]
+function Promise:catch(failureCallback)
+ return self:andThen(nil, failureCallback)
+end
+
+--[[
+ Yield until the promise is completed.
+
+ This matches the execution model of normal Roblox functions.
+]]
+function Promise:await()
+ if self._status == Promise.Status.Started then
+ local result
+ local bindable = Instance.new("BindableEvent")
+
+ self:andThen(function(...)
+ result = {...}
+ bindable:Fire(true)
+ end, function(...)
+ result = {...}
+ bindable:Fire(false)
+ end)
+
+ local ok = bindable.Event:Wait()
+ bindable:Destroy()
+
+ if not ok then
+ error(tostring(result[1]), 2)
+ end
+
+ return unpack(result)
+ elseif self._status == Promise.Status.Resolved then
+ return unpack(self._value)
+ elseif self._status == Promise.Status.Rejected then
+ error(tostring(self._value[1]), 2)
+ end
+end
+
+function Promise:_resolve(...)
+ if self._status ~= Promise.Status.Started then
+ return
+ end
+
+ -- If the resolved value was a Promise, we chain onto it!
+ if Promise.is((...)) then
+ -- Without this warning, arguments sometimes mysteriously disappear
+ if select("#", ...) > 1 then
+ local message = ("When returning a Promise from andThen, extra arguments are discarded! See:\n\n%s"):format(
+ self._source
+ )
+ warn(message)
+ end
+
+ (...):andThen(function(...)
+ self:_resolve(...)
+ end, function(...)
+ self:_reject(...)
+ end)
+
+ return
+ end
+
+ self._status = Promise.Status.Resolved
+ self._value = {...}
+
+ -- We assume that these callbacks will not throw errors.
+ for _, callback in ipairs(self._queuedResolve) do
+ callback(...)
+ end
+end
+
+function Promise:_reject(...)
+ if self._status ~= Promise.Status.Started then
+ return
+ end
+
+ self._status = Promise.Status.Rejected
+ self._value = {...}
+
+ -- If there are any rejection handlers, call those!
+ if not isEmpty(self._queuedReject) then
+ -- We assume that these callbacks will not throw errors.
+ for _, callback in ipairs(self._queuedReject) do
+ callback(...)
+ end
+ else
+ -- At this point, no one was able to observe the error.
+ -- An error handler might still be attached if the error occurred
+ -- synchronously. We'll wait one tick, and if there are still no
+ -- observers, then we should put a message in the console.
+
+ local message = ("Unhandled promise rejection:\n\n%s\n\n%s"):format(
+ TU.RecursiveToString((...)),
+ self._source
+ )
+ warn(message)
+ end
+end
+
+return Promise
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.spec.lua
new file mode 100644
index 0000000..2193fcb
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Promise.spec.lua
@@ -0,0 +1,262 @@
+return function()
+ local Promise = require(script.Parent.Promise)
+
+ describe("Promise.new", function()
+ it("should instantiate with a callback", function()
+ local promise = Promise.new(function() end)
+
+ expect(promise).to.be.ok()
+ end)
+
+ it("should invoke the given callback with resolve and reject", function()
+ local callCount = 0
+ local resolveArg
+ local rejectArg
+
+ local promise = Promise.new(function(resolve, reject)
+ callCount = callCount + 1
+ resolveArg = resolve
+ rejectArg = reject
+ end)
+
+ expect(promise).to.be.ok()
+
+ expect(callCount).to.equal(1)
+ expect(resolveArg).to.be.a("function")
+ expect(rejectArg).to.be.a("function")
+ expect(promise._status).to.equal(Promise.Status.Started)
+ end)
+
+ it("should resolve promises on resolve()", function()
+ local callCount = 0
+
+ local promise = Promise.new(function(resolve)
+ callCount = callCount + 1
+ resolve()
+ end)
+
+ expect(promise).to.be.ok()
+ expect(callCount).to.equal(1)
+ expect(promise._status).to.equal(Promise.Status.Resolved)
+ end)
+
+ it("should reject promises on reject()", function()
+ local callCount = 0
+
+ local promise = Promise.new(function(resolve, reject)
+ callCount = callCount + 1
+ reject()
+ end)
+
+ expect(promise).to.be.ok()
+ expect(callCount).to.equal(1)
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ end)
+
+ it("should reject on error in callback", function()
+ local callCount = 0
+
+ local promise = Promise.new(function()
+ callCount = callCount + 1
+ error("hahah")
+ end)
+
+ expect(promise).to.be.ok()
+ expect(callCount).to.equal(1)
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]:find("hahah")).to.be.ok()
+ end)
+ end)
+
+ describe("Promise.resolve", function()
+ it("should immediately resolve with a value", function()
+ local promise = Promise.resolve(5)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Resolved)
+ expect(promise._value[1]).to.equal(5)
+ end)
+
+ it("should chain onto passed promises", function()
+ local promise = Promise.resolve(Promise.new(function(_, reject)
+ reject(7)
+ end))
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]).to.equal(7)
+ end)
+ end)
+
+ describe("Promise.reject", function()
+ it("should immediately reject with a value", function()
+ local promise = Promise.reject(6)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]).to.equal(6)
+ end)
+
+ it("should pass a promise as-is as an error", function()
+ local innerPromise = Promise.new(function(resolve)
+ resolve(6)
+ end)
+
+ local promise = Promise.reject(innerPromise)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]).to.equal(innerPromise)
+ end)
+ end)
+
+ describe("Promise:andThen", function()
+ it("should chain onto resolved promises", function()
+ local args
+ local argsLength
+ local callCount = 0
+ local badCallCount = 0
+
+ local promise = Promise.resolve(5)
+
+ local chained = promise
+ :andThen(function(...)
+ args = {...}
+ argsLength = select("#", ...)
+ callCount = callCount + 1
+ end, function()
+ badCallCount = badCallCount + 1
+ end)
+
+ expect(badCallCount).to.equal(0)
+
+ expect(callCount).to.equal(1)
+ expect(argsLength).to.equal(1)
+ expect(args[1]).to.equal(5)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Resolved)
+ expect(promise._value[1]).to.equal(5)
+
+ expect(chained).to.be.ok()
+ expect(chained).never.to.equal(promise)
+ expect(chained._status).to.equal(Promise.Status.Resolved)
+ expect(#chained._value).to.equal(0)
+ end)
+
+ it("should chain onto rejected promises", function()
+ local args
+ local argsLength
+ local callCount = 0
+ local badCallCount = 0
+
+ local promise = Promise.reject(5)
+
+ local chained = promise
+ :andThen(function(...)
+ badCallCount = badCallCount + 1
+ end, function(...)
+ args = {...}
+ argsLength = select("#", ...)
+ callCount = callCount + 1
+ end)
+
+ expect(badCallCount).to.equal(0)
+
+ expect(callCount).to.equal(1)
+ expect(argsLength).to.equal(1)
+ expect(args[1]).to.equal(5)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]).to.equal(5)
+
+ expect(chained).to.be.ok()
+ expect(chained).never.to.equal(promise)
+ expect(chained._status).to.equal(Promise.Status.Resolved)
+ expect(#chained._value).to.equal(0)
+ end)
+
+ it("should chain onto asynchronously resolved promises", function()
+ local args
+ local argsLength
+ local callCount = 0
+ local badCallCount = 0
+
+ local startResolution
+ local promise = Promise.new(function(resolve)
+ startResolution = resolve
+ end)
+
+ local chained = promise
+ :andThen(function(...)
+ args = {...}
+ argsLength = select("#", ...)
+ callCount = callCount + 1
+ end, function()
+ badCallCount = badCallCount + 1
+ end)
+
+ expect(callCount).to.equal(0)
+ expect(badCallCount).to.equal(0)
+
+ startResolution(6)
+
+ expect(badCallCount).to.equal(0)
+
+ expect(callCount).to.equal(1)
+ expect(argsLength).to.equal(1)
+ expect(args[1]).to.equal(6)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Resolved)
+ expect(promise._value[1]).to.equal(6)
+
+ expect(chained).to.be.ok()
+ expect(chained).never.to.equal(promise)
+ expect(chained._status).to.equal(Promise.Status.Resolved)
+ expect(#chained._value).to.equal(0)
+ end)
+
+ it("should chain onto asynchronously rejected promises", function()
+ local args
+ local argsLength
+ local callCount = 0
+ local badCallCount = 0
+
+ local startResolution
+ local promise = Promise.new(function(_, reject)
+ startResolution = reject
+ end)
+
+ local chained = promise
+ :andThen(function()
+ badCallCount = badCallCount + 1
+ end, function(...)
+ args = {...}
+ argsLength = select("#", ...)
+ callCount = callCount + 1
+ end)
+
+ expect(callCount).to.equal(0)
+ expect(badCallCount).to.equal(0)
+
+ startResolution(6)
+
+ expect(badCallCount).to.equal(0)
+
+ expect(callCount).to.equal(1)
+ expect(argsLength).to.equal(1)
+ expect(args[1]).to.equal(6)
+
+ expect(promise).to.be.ok()
+ expect(promise._status).to.equal(Promise.Status.Rejected)
+ expect(promise._value[1]).to.equal(6)
+
+ expect(chained).to.be.ok()
+ expect(chained).never.to.equal(promise)
+ expect(chained._status).to.equal(Promise.Status.Resolved)
+ expect(#chained._value).to.equal(0)
+ end)
+ end)
+end
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.lua
new file mode 100644
index 0000000..9374895
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.lua
@@ -0,0 +1,113 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Immutable = require(CorePackages.AppTempCommon.Common.Immutable)
+
+local AddUser = require(CorePackages.AppTempCommon.LuaApp.Actions.AddUser)
+local AddUsers = require(CorePackages.AppTempCommon.LuaApp.Actions.AddUsers)
+local ReceivedUserPresence = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedUserPresence)
+local RemoveUser = require(CorePackages.AppTempCommon.LuaApp.Actions.RemoveUser)
+local SetUserIsFriend = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserIsFriend)
+local SetUserMembershipType = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserMembershipType)
+local SetUserPresence = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserPresence)
+local SetUserThumbnail = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserThumbnail)
+
+local FFlagFixUsersReducerDataLoss = settings():GetFFlag("FixUsersReducerDataLoss")
+
+return function(state, action)
+ state = state or {}
+
+ if action.type == AddUser.name then
+ local user = action.user
+ state = Immutable.Set(state, user.id, user)
+ elseif action.type == AddUsers.name then
+ if FFlagFixUsersReducerDataLoss then
+ local addedUsers = action.users
+ local usersUpdate = {}
+ for userId, addedUser in pairs(addedUsers) do
+ local existingUser = state[userId]
+ if existingUser then
+ usersUpdate[userId] = Immutable.JoinDictionaries(existingUser, addedUser)
+ else
+ usersUpdate[userId] = addedUser
+ end
+ end
+
+ state = Immutable.JoinDictionaries(state, usersUpdate)
+ else
+ local users = action.users
+ state = Immutable.JoinDictionaries(state, users)
+ end
+
+ elseif action.type == SetUserIsFriend.name then
+ local user = state[action.userId]
+ if user then
+ local newUser = Immutable.Set(user, "isFriend", action.isFriend)
+ state = Immutable.Set(state, user.id, newUser)
+ else
+ warn("Setting isFriend on user", action.userId, "who doesn't exist yet")
+ end
+ elseif action.type == SetUserPresence.name then
+ local user = state[action.userId]
+ if user then
+ local newUser = Immutable.JoinDictionaries(user, {
+ presence = action.presence,
+ lastLocation = action.lastLocation,
+ })
+ state = Immutable.Set(state, user.id, newUser)
+ else
+ warn("Setting presence on user", action.userId, "who doesn't exist yet")
+ end
+ elseif action.type == ReceivedUserPresence.name then
+ local user = state[action.userId]
+ if user then
+ state = Immutable.JoinDictionaries(state, {
+ [action.userId] = Immutable.JoinDictionaries(user, {
+ presence = action.presence,
+ lastLocation = action.lastLocation,
+ placeId = action.placeId,
+ }),
+ })
+ end
+ elseif action.type == SetUserThumbnail.name then
+ local user = state[action.userId]
+ if user then
+ if FFlagFixUsersReducerDataLoss then
+ local thumbnails = user.thumbnails or {}
+ state = Immutable.JoinDictionaries(state, {
+ [action.userId] = Immutable.JoinDictionaries(user, {
+ thumbnails = Immutable.JoinDictionaries(thumbnails, {
+ [action.thumbnailType] = Immutable.JoinDictionaries(thumbnails[action.thumbnailType] or {}, {
+ [action.thumbnailSize] = action.image,
+ }),
+ }),
+ }),
+ })
+ else
+ state = Immutable.JoinDictionaries(state, {
+ [action.userId] = Immutable.JoinDictionaries(user, {
+ thumbnails = Immutable.JoinDictionaries(user.thumbnails, {
+ [action.thumbnailType] = Immutable.JoinDictionaries(user.thumbnails[action.thumbnailType] or {}, {
+ [action.thumbnailSize] = action.image,
+ }),
+ }),
+ }),
+ })
+ end
+ end
+ elseif action.type == SetUserMembershipType.name then
+ local user = state[action.userId]
+ if user then
+ state = Immutable.JoinDictionaries(state, {
+ [action.userId] = Immutable.JoinDictionaries(user, {
+ membership = action.membershipType,
+ }),
+ })
+ end
+ elseif action.type == RemoveUser.name then
+ if state[action.userId] then
+ state = Immutable.RemoveFromDictionary(state, action.userId)
+ end
+ end
+
+ return state
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.spec.lua
new file mode 100644
index 0000000..f3969bc
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Reducers/Users.spec.lua
@@ -0,0 +1,107 @@
+return function()
+ local CorePackages = game:GetService("CorePackages")
+
+ local Constants = require(CorePackages.AppTempCommon.LuaChat.Constants)
+ local MockId = require(CorePackages.AppTempCommon.LuaApp.MockId)
+ local User = require(CorePackages.AppTempCommon.LuaApp.Models.User)
+ local Users = require(CorePackages.AppTempCommon.LuaApp.Reducers.Users)
+
+ local AddUser = require(CorePackages.AppTempCommon.LuaApp.Actions.AddUser)
+ local ReceivedUserPresence = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedUserPresence)
+ local SetUserIsFriend = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserIsFriend)
+ local SetUserMembershipType = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserMembershipType)
+ local SetUserPresence = require(CorePackages.AppTempCommon.LuaApp.Actions.SetUserPresence)
+
+ describe("initial state", function()
+ it("should return an initial table when passed nil", function()
+ local state = Users(nil, {})
+ expect(state).to.be.a("table")
+ end)
+ end)
+
+ describe("AddUser", function()
+ it("should add a user to the store", function()
+ local user = User.mock()
+ local state = {}
+
+ state = Users(state, AddUser(user))
+
+ expect(state[user.id]).to.equal(user)
+ end)
+ end)
+
+ describe("SetUserIsFriend", function()
+ it("should set isFriend on an existing user", function()
+ local user = User.mock()
+ local state = {
+ [user.id] = user
+ }
+
+ expect(state[user.id].isFriend).to.equal(false)
+
+ state = Users(state, SetUserIsFriend(user.id, true))
+ expect(state[user.id].isFriend).to.equal(true)
+
+ state = Users(state, SetUserIsFriend(user.id, false))
+ expect(state[user.id].isFriend).to.equal(false)
+ end)
+ end)
+
+ describe("SetUserPresence", function()
+ it("should set presence on an existing user", function()
+ local user = User.mock()
+ local state = {
+ [user.id] = user
+ }
+
+ expect(state[user.id].presence).to.equal(User.PresenceType.OFFLINE)
+
+ state = Users(state, SetUserPresence(user.id, User.PresenceType.ONLINE))
+ expect(state[user.id].presence).to.equal(User.PresenceType.ONLINE)
+
+ state = Users(state, SetUserPresence(user.id, User.PresenceType.IN_GAME))
+ expect(state[user.id].presence).to.equal(User.PresenceType.IN_GAME)
+
+ state = Users(state, SetUserPresence(user.id, User.PresenceType.IN_STUDIO))
+ expect(state[user.id].presence).to.equal(User.PresenceType.IN_STUDIO)
+ end)
+ end)
+
+ describe("ReceivedUserPresence", function()
+ it("should set presence on an existing user", function()
+ local user = User.mock()
+ local state = {
+ [user.id] = user
+ }
+
+ local existingPresence = user.presence
+ local newPresence = Constants.PresenceType.ONLINE
+ local lastLocation = MockId()
+ local newPlaceId = MockId()
+
+ state = Users(state, ReceivedUserPresence(user.id, newPresence, lastLocation, newPlaceId))
+
+ expect(user.presence).to.equal(existingPresence)
+ expect(state[user.id].presence).to.equal(newPresence)
+ expect(state[user.id].lastLocation).to.equal(lastLocation)
+ expect(state[user.id].placeId).to.equal(newPlaceId)
+ end)
+ end)
+
+ describe("SetUserMembershipType", function()
+ it("should set membership on an existing user", function()
+ local user = User.mock()
+ local state = {
+ [user.id] = user
+ }
+
+ local existingMembership = user.membership
+ local newMembership = Enum.MembershipType.BuildersClub
+
+ state = Users(state, SetUserMembershipType(user.id, newMembership))
+
+ expect(user.membership).to.equal(existingMembership)
+ expect(state[user.id].membership).to.equal(newMembership)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.lua
new file mode 100644
index 0000000..635536b
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.lua
@@ -0,0 +1,173 @@
+--[[
+ Provides functions for comparing and printing lua tables.
+]]
+
+local TableUtilities = {}
+local defaultIgnore = {}
+
+--[[
+ Takes two tables A and B, returns if they have the same key-value pairs
+ Except ignored keys
+]]
+function TableUtilities.ShallowEqual(A, B, ignore)
+ if not A or not B then
+ return false
+ elseif A == B then
+ return true
+ end
+
+ if not ignore then
+ ignore = defaultIgnore
+ end
+
+ for key, value in pairs(A) do
+ if B[key] ~= value and not ignore[key] then
+ return false
+ end
+ end
+ for key, value in pairs(B) do
+ if A[key] ~= value and not ignore[key] then
+ return false
+ end
+ end
+
+ return true
+end
+
+--[[
+ Takes two tables A, B and a key, returns if two tables have the same value at key
+]]
+function TableUtilities.EqualKey(A, B, key)
+ if A and B and key and key ~= "" and A[key] and B[key] and A[key] == B[key] then
+ return true
+ end
+ return false
+end
+
+--[[
+ Takes two tables A and B, returns a new table with elements of A
+ which are either not keys in B or have a different value in B
+]]
+function TableUtilities.TableDifference(A, B)
+ local new = {}
+
+ for key, value in pairs(A) do
+ if B[key] ~= A[key] then
+ new[key] = value
+ end
+ end
+
+ return new
+end
+
+
+--[[
+ Takes a list and returns a table whose
+ keys are elements of the list and whose
+ values are all true
+]]
+local function membershipTable(list)
+ local result = {}
+ for i = 1, #list do
+ result[list[i]] = true
+ end
+ return result
+end
+
+
+--[[
+ Takes a table and returns a list of keys in that table
+]]
+local function listOfKeys(t)
+ local result = {}
+ for key,_ in pairs(t) do
+ table.insert(result, key)
+ end
+ return result
+end
+
+
+--[[
+ Takes two lists A and B, returns a new list of elements of A
+ which are not in B
+]]
+function TableUtilities.ListDifference(A, B)
+ return listOfKeys(TableUtilities.TableDifference(membershipTable(A), membershipTable(B)))
+end
+
+
+--[[
+ For debugging. Returns false if the given table has any of the following:
+ - a key that is neither a number or a string
+ - a mix of number and string keys
+ - number keys which are not exactly 1..#t
+]]
+function TableUtilities.CheckListConsistency(t)
+ local containsNumberKey = false
+ local containsStringKey = false
+ local numberConsistency = true
+
+ local index = 1
+ for x, _ in pairs(t) do
+ if type(x) == 'string' then
+ containsStringKey = true
+ elseif type(x) == 'number' then
+ if index ~= x then
+ numberConsistency = false
+ end
+ containsNumberKey = true
+ else
+ return false
+ end
+
+ if containsStringKey and containsNumberKey then
+ return false
+ end
+
+ index = index + 1
+ end
+
+ if containsNumberKey then
+ return numberConsistency
+ end
+
+ return true
+end
+
+
+--[[
+ For debugging, serializes the given table to a reasonable string that might even interpret as lua.
+]]
+function TableUtilities.RecursiveToString(t, indent)
+ indent = indent or ''
+
+ if type(t) == 'table' then
+ local result = ""
+ if not TableUtilities.CheckListConsistency(t) then
+ result = result .. "-- WARNING: this table fails the list consistency test\n"
+ end
+ result = result .. "{\n"
+ for k,v in pairs(t) do
+ if type(k) == 'string' then
+ result = result
+ .. " "
+ .. indent
+ .. tostring(k)
+ .. " = "
+ .. TableUtilities.RecursiveToString(v, " "..indent)
+ ..";\n"
+ end
+ if type(k) == 'number' then
+ result = result .. " " .. indent .. TableUtilities.RecursiveToString(v, " "..indent)..",\n"
+ end
+ end
+ result = result .. indent .. "}"
+ return result
+ else
+ return tostring(t)
+ end
+end
+
+
+return TableUtilities
+
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.spec.lua
new file mode 100644
index 0000000..692757c
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TableUtilities.spec.lua
@@ -0,0 +1,140 @@
+return function()
+ local TableUtilities = require(script.Parent.TableUtilities)
+
+ it("should return whether tables are equal to each other", function()
+ local tableA = nil
+ local tableB = nil
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = nil
+ tableB = {}
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = {}
+ tableB = nil
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = {}
+ tableB = {}
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(true)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value1",
+ }
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(true)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value2",
+ }
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key2 = "value1",
+ }
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key2 = "value2",
+ }
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value1",
+ key2 = "value2",
+ }
+ expect(TableUtilities.ShallowEqual(tableA, tableB)).to.equal(false)
+ end)
+
+ it("should return whether tables are equal to each other at key", function()
+ local tableA = nil
+ local tableB = nil
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = nil
+ tableB = {}
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {}
+ tableB = nil
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {}
+ tableB = {}
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value1",
+ }
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(true)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value2",
+ }
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key2 = "value1",
+ }
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key2 = "value2",
+ }
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(false)
+
+ tableA = {
+ key1 = "value1",
+ }
+ tableB = {
+ key1 = "value1",
+ key2 = "value2",
+ }
+ expect(TableUtilities.EqualKey(tableA, tableB)).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "")).to.equal(false)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key1")).to.equal(true)
+ expect(TableUtilities.EqualKey(tableA, tableB, "key2")).to.equal(false)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.lua
new file mode 100644
index 0000000..db07e59
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.lua
@@ -0,0 +1,36 @@
+--[[
+ A hub for faking networking responses for tests
+]]
+
+local CorePackages = game:GetService("CorePackages")
+local AppTempCommon = CorePackages.AppTempCommon
+
+local Promise = require(AppTempCommon.LuaApp.Promise)
+local HttpError = require(AppTempCommon.LuaApp.Http.HttpError)
+local HttpResponse = require(AppTempCommon.LuaApp.Http.HttpResponse)
+local StatusCodes = require(AppTempCommon.LuaApp.Http.StatusCodes)
+
+
+local MockRequest = {}
+
+-- responseBody : (string)
+function MockRequest.simpleSuccessRequest(responseBody)
+ assert(responseBody ~= nil, "Expected responseBody not to be nil")
+
+ -- create a simple network handler that only needs a response body specified
+ return function(url, requestMethod, options)
+ return Promise.resolve(HttpResponse.new(url, responseBody, 0, StatusCodes.OK))
+ end
+end
+
+-- errMsg : (HttpError.Kind)
+function MockRequest.simpleFailRequest(errKind)
+ assert(errKind ~= nil, "Expected errKind not to be nil")
+
+ -- create a simple network handler that only needs an error kind specified
+ return function(url, requestMethod, options)
+ return Promise.reject(HttpError.new(url, errKind, "Fake request failed"))
+ end
+end
+
+return MockRequest
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.spec.lua
new file mode 100644
index 0000000..66711b7
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/TestHelpers/MockRequest.spec.lua
@@ -0,0 +1,50 @@
+return function()
+ local MockRequest = require(script.Parent.MockRequest)
+
+ local Modules = game:GetService("CoreGui").RobloxGui.Modules
+ local HttpError = require(Modules.LuaApp.Http.HttpError)
+
+ describe("simpleSuccessRequest", function()
+ it("should return a function", function()
+ local request = MockRequest.simpleSuccessRequest("this is a test")
+
+ expect(type(request)).to.equal("function")
+ end)
+
+ it("should return the provided response as the resolution to a promise", function()
+ local testBodyMatches = false
+
+ local testBody = "this is a test"
+ local request = MockRequest.simpleSuccessRequest(testBody)
+
+ local httpPromise = request("testUrl", "GET")
+ httpPromise:andThen(function(httpResponse)
+ testBodyMatches = httpResponse.responseBody == testBody
+ end)
+ expect(testBodyMatches).to.equal(true)
+ end)
+ end)
+
+
+ describe("simpleFailRequest", function()
+ it("should return a function", function()
+ local request = MockRequest.simpleFailRequest(HttpError.Kind.Unknown)
+
+ expect(type(request)).to.equal("function")
+ end)
+
+ it("should return the provided error code as the rejection to a promise", function()
+ local testErrMatches = false
+
+ local testErrKind = HttpError.Kind.Unknown
+ local request = MockRequest.simpleFailRequest(testErrKind)
+
+ local httpPromise = request("testUrl", "GET")
+ httpPromise:catch(function(httpError)
+ testErrMatches = httpError.kind == testErrKind
+ end)
+
+ expect(testErrMatches).to.equal(true)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchPlaceInfos.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchPlaceInfos.lua
new file mode 100644
index 0000000..d80ae99
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchPlaceInfos.lua
@@ -0,0 +1,24 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Functional = require(CorePackages.AppTempCommon.Common.Functional)
+local GetPlaceInfos = require(CorePackages.AppTempCommon.LuaApp.Http.Requests.GetPlaceInfos)
+
+-- LuaChat
+local PlaceInfoModel = require(CorePackages.AppTempCommon.LuaChat.Models.PlaceInfoModel)
+local ReceivedMultiplePlaceInfos = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedMultiplePlaceInfos)
+
+return function(networkImpl, placeIds)
+ return function(store)
+ return GetPlaceInfos(networkImpl, placeIds):andThen(function(result)
+ local data = result.responseBody
+
+ local placeInfos = Functional.Map(data, function(placeInfoData)
+ return PlaceInfoModel.fromWeb(placeInfoData)
+ end)
+
+ store:dispatch(ReceivedMultiplePlaceInfos(placeInfos))
+
+ return placeInfos
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersData.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersData.lua
new file mode 100644
index 0000000..36b9d05
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersData.lua
@@ -0,0 +1,17 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Promise = require(CorePackages.AppTempCommon.LuaApp.Promise)
+local ApiFetchUsersPresences = require(CorePackages.AppTempCommon.LuaApp.Thunks.ApiFetchUsersPresences)
+local ApiFetchUsersThumbnail = require(CorePackages.AppTempCommon.LuaApp.Thunks.ApiFetchUsersThumbnail)
+
+--this thunk will fill out users list with thumbnail and presence info
+return function(networkImpl, userIds, thumbnailRequest)
+ return function(store)
+ local fetchedPromises = {}
+
+ table.insert(fetchedPromises, store:dispatch(ApiFetchUsersPresences(networkImpl, userIds)))
+ table.insert(fetchedPromises, store:dispatch(ApiFetchUsersThumbnail(networkImpl, userIds, thumbnailRequest)))
+
+ return Promise.all(fetchedPromises)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriendCount.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriendCount.lua
new file mode 100644
index 0000000..2301055
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriendCount.lua
@@ -0,0 +1,21 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Actions = CorePackages.AppTempCommon.LuaApp.Actions
+local Requests = CorePackages.AppTempCommon.LuaApp.Http.Requests
+
+local UsersGetFriendCount = require(Requests.UsersGetFriendCount)
+local SetFriendCount = require(Actions.SetFriendCount)
+
+return function(networkImpl)
+ return function(store)
+ return UsersGetFriendCount(networkImpl):andThen(function(result)
+ local data = result.responseBody
+
+ if data.success and data.count then
+ store:dispatch(SetFriendCount(data.count))
+ end
+
+ return data.count
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriends.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriends.lua
new file mode 100644
index 0000000..1420205
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersFriends.lua
@@ -0,0 +1,34 @@
+local CorePackages = game:GetService("CorePackages")
+local Requests = CorePackages.AppTempCommon.LuaApp.Http.Requests
+
+local ApiFetchUsersData = require(CorePackages.AppTempCommon.LuaApp.Thunks.ApiFetchUsersData)
+local ApiFetchUsersFriendCount = require(CorePackages.AppTempCommon.LuaApp.Thunks.ApiFetchUsersFriendCount)
+local UsersGetFriends = require(Requests.UsersGetFriends)
+
+local AddUsers = require(CorePackages.AppTempCommon.LuaApp.Actions.AddUsers)
+local UserModel = require(CorePackages.AppTempCommon.LuaApp.Models.User)
+
+return function(requestImpl, userId, thumbnailRequests)
+ return function(store)
+ return store:dispatch(ApiFetchUsersFriendCount(requestImpl)):andThen(function()
+ return UsersGetFriends(requestImpl, userId):andThen(function(response)
+ local responseBody = response.responseBody
+
+ local userIds = {}
+ local newUsers = {}
+ for _, userData in pairs(responseBody.data) do
+ local id = tostring(userData.id)
+ local newUser = UserModel.fromData(id, userData.name, true)
+
+ table.insert(userIds, id)
+ newUsers[newUser.id] = newUser
+ end
+ store:dispatch(AddUsers(newUsers))
+
+ return userIds
+ end):andThen(function(userIds)
+ store:dispatch(ApiFetchUsersData(requestImpl, userIds, thumbnailRequests))
+ end)
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersPresences.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersPresences.lua
new file mode 100644
index 0000000..3e50932
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersPresences.lua
@@ -0,0 +1,29 @@
+local CorePackages = game:GetService("CorePackages")
+
+local ReceivedUserPresence = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedUserPresence)
+local User = require(CorePackages.AppTempCommon.LuaApp.Models.User)
+local UsersGetPresence = require(CorePackages.AppTempCommon.LuaApp.Http.Requests.UsersGetPresence)
+
+local webPresenceMap = {
+ [0] = User.PresenceType.OFFLINE,
+ [1] = User.PresenceType.ONLINE,
+ [2] = User.PresenceType.IN_GAME,
+ [3] = User.PresenceType.IN_STUDIO
+}
+
+return function(networkImpl, userIds)
+ return function(store)
+ return UsersGetPresence(networkImpl, userIds):andThen(function(result)
+ local responseBody = result.responseBody
+
+ for _, presenceModel in pairs(responseBody.userPresences) do
+ store:dispatch(ReceivedUserPresence(
+ tostring(presenceModel.userId),
+ webPresenceMap[presenceModel.userPresenceType],
+ presenceModel.lastLocation,
+ presenceModel.placeId
+ ))
+ end
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersThumbnail.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersThumbnail.lua
new file mode 100644
index 0000000..0743c60
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiFetchUsersThumbnail.lua
@@ -0,0 +1,42 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Actions = CorePackages.AppTempCommon.LuaApp.Actions
+local Requests = CorePackages.AppTempCommon.LuaApp.Http.Requests
+
+local UsersGetThumbnail = require(Requests.UsersGetThumbnail)
+local SetUserThumbnail = require(Actions.SetUserThumbnail)
+local Promise = require(CorePackages.AppTempCommon.LuaApp.Promise)
+
+local function fetchThumbnailsBatch(networkImpl, userIds, thumbnailRequest)
+ local fetchedPromises = {}
+
+ for _, userId in pairs(userIds) do
+ table.insert(fetchedPromises,
+ UsersGetThumbnail(userId, thumbnailRequest.thumbnailType, thumbnailRequest.thumbnailSize)
+ )
+ end
+
+ return Promise.all(fetchedPromises)
+end
+
+return function(networkImpl, userIds, thumbnailRequests)
+ return function(store)
+ return Promise.new(function()
+ -- We currently cannot batch request user avatar thumbnails,
+ -- so each thumbnailRequest has to be processed individually.
+
+ local fetchedPromises = {}
+ for _, thumbnailRequest in pairs(thumbnailRequests) do
+ table.insert(fetchedPromises,
+ fetchThumbnailsBatch(networkImpl, userIds, thumbnailRequest):andThen(function(result)
+ for _, data in pairs(result) do
+ store:dispatch(SetUserThumbnail(data.id, data.image, data.thumbnailType, data.thumbnailSize))
+ end
+ end)
+ )
+ end
+
+ return Promise.all(fetchedPromises)
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiSendGameInvite.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiSendGameInvite.lua
new file mode 100644
index 0000000..4f0fe01
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/Thunks/ApiSendGameInvite.lua
@@ -0,0 +1,42 @@
+local CorePackages = game:GetService("CorePackages")
+local Players = game:GetService("Players")
+
+local AppTempCommon = CorePackages.AppTempCommon
+local Requests = CorePackages.AppTempCommon.LuaApp.Http.Requests
+
+local ChatSendMessage = require(Requests.ChatSendMessage)
+local ChatStartOneToOneConversation = require(Requests.ChatStartOneToOneConversation)
+local Url = require(CorePackages.AppTempCommon.LuaApp.Http.Url)
+
+local trimCharacterFromEndString = require(AppTempCommon.Temp.trimCharacterFromEndString)
+
+local INVITE_MESSAGE = "Come join me in %s %s/games/%s"
+
+return function(networkImpl, userId, placeInfo)
+ local clientId = Players.LocalPlayer.UserId
+
+ local trimmedUrl = trimCharacterFromEndString(Url.BASE_URL, "/")
+ -- Construct the invite message based on place info
+ local messageText = string.format(INVITE_MESSAGE,
+ placeInfo.name, trimmedUrl, placeInfo.universeRootPlaceId
+ )
+
+ return function(store)
+ return ChatStartOneToOneConversation(networkImpl, userId, clientId):andThen(function(result)
+ local conversation = result.responseBody.conversation
+
+ return ChatSendMessage(networkImpl, conversation.id, messageText):andThen(function(result)
+ local data = result.responseBody
+ local wasModerated = data.resultType ~= "Success"
+ if wasModerated then
+ warn("Game invite was moderated")
+ end
+ return {
+ conversationId = conversation.id,
+ placeId = placeInfo.universeRootPlaceId,
+ wasModerated = wasModerated
+ }
+ end)
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.lua
new file mode 100644
index 0000000..261dcd0
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.lua
@@ -0,0 +1,68 @@
+--[[
+ memoize creates a function as a wrapper that caches the last outputs of a function.
+ This is useful if you know that the function should return the same output every
+ time it is run with the same inputs. The function should only return an output, and
+ not have any side effects. These side effects are not cached.
+
+ Without memoize's caching, even though the function ouputs the same values, the
+ memory locations of the values are different; tables made in the function, even if
+ they have the same values, won't be the same tables.
+
+ memoize only caches the last set of inputs and ouputs. This means that it is only
+ helpful when the function is likely to be called with the same inputs multiple
+ times in a row. This is the case with most Roact use cases.
+
+ Note that memoize only does a ** shallow check on table inputs ** . This means
+ that if the same table is input but the elements of the table are different then
+ it will be assumed that the table has not changed.
+
+ In addition to all the previous warnings, memoize strips trailing nils. This means
+ that if foo is a memoized function and we call foo(), then foo(nil) will return a
+ cached value. This is opposed to how print handles input. print() only outputs a
+ new line, but print(nil) outputs "nil". This is because varargs can detect the
+ number of arguments passed in. So, be careful when using memoize with varargs.
+ Trailing nils will be stripped.
+
+ The wrapper can take any number of inputs and give any number of outputs.
+ Leading and interspersed nils are handled gracefully. Trailing nils on the input
+ are stripped.
+]]
+local function captureSize(...)
+ return {...}, select("#", ...)
+end
+
+local function memoize(func)
+ assert(type(func) == "function", "memoize requires a function to memoize")
+
+ local lastArgs
+ local lastNumArgs
+ local lastOutput
+ local lastNumOutput
+
+ return function(...)
+ local numArgs = select("#", ...)
+
+ while numArgs > 0 and select(numArgs, ...) == nil do
+ numArgs = numArgs - 1
+ end
+
+ if numArgs ~= lastNumArgs then
+ lastArgs = {...}
+ lastNumArgs = numArgs
+ lastOutput, lastNumOutput = captureSize(func(...))
+ return unpack(lastOutput, 1, lastNumOutput)
+ end
+
+ for i = 1, lastNumArgs do
+ if select(i, ...) ~= lastArgs[i] then
+ lastArgs = {...}
+ lastOutput, lastNumOutput = captureSize(func(...))
+ break
+ end
+ end
+
+ return unpack(lastOutput, 1, lastNumOutput)
+ end
+end
+
+return memoize
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.spec.lua
new file mode 100644
index 0000000..5ae2b6e
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaApp/memoize.spec.lua
@@ -0,0 +1,213 @@
+return function()
+ local memoize = require(script.Parent.memoize)
+
+ describe("memoize", function()
+ it("should handle arity 0", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ expect(identity()).to.equal(nil)
+ expect(identity(nil)).to.equal(nil)
+ expect(identity(nil, nil)).to.equal(nil)
+ expect(callCount).to.equal(1)
+ end)
+
+ it("should handle arity 1", function()
+ local callCount = 0
+ local identity = memoize(function(a)
+ callCount = callCount + 1
+ return a
+ end)
+
+ expect(identity(5)).to.equal(5)
+ expect(identity(5)).to.equal(5)
+ expect(callCount).to.equal(1)
+
+ expect(identity(6)).to.equal(6)
+ expect(callCount).to.equal(2)
+
+ expect(identity(5)).to.equal(5)
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle arity 2", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(6, 5)
+ expect(a).to.equal(6)
+ expect(b).to.equal(5)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle mixed arity", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ a, b = identity(5, 6)
+ expect(a).to.equal(5)
+ expect(b).to.equal(6)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity()
+ expect(a).to.equal(nil)
+ expect(b).to.equal(nil)
+
+ a, b = identity()
+ expect(a).to.equal(nil)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle trailing nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(5, nil)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(5)
+ expect(a).to.equal(5)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle leading nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b)
+ callCount = callCount + 1
+ return a, b
+ end)
+
+ local a, b
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ expect(callCount).to.equal(1)
+
+ a, b = identity(7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b = identity(nil, 7)
+ expect(a).to.equal(nil)
+ expect(b).to.equal(7)
+
+ expect(callCount).to.equal(3)
+ end)
+
+ it("should handle interspersed nils", function()
+ local callCount = 0
+ local identity = memoize(function(a, b, c, d)
+ callCount = callCount + 1
+ return a, b, c, d
+ end)
+
+ local a, b, c, d
+
+ a, b, c, d = identity(7, nil, 7, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ -- Trailing nils can affect how interspersed nils are handled
+ a, b, c, d = identity(7, nil, 7)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(1)
+
+ a, b, c, d = identity(7, nil, nil, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(nil)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(2)
+
+ a, b, c, d = identity(7, nil, 7, nil)
+ expect(a).to.equal(7)
+ expect(b).to.equal(nil)
+ expect(c).to.equal(7)
+ expect(d).to.equal(nil)
+
+ expect(callCount).to.equal(3)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedConversation.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedConversation.lua
new file mode 100644
index 0000000..4d63e47
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedConversation.lua
@@ -0,0 +1,9 @@
+local Modules = game:GetService("CorePackages").AppTempCommon
+local Common = Modules.Common
+local Action = require(Common.Action)
+
+return Action(script.Name, function(convo)
+ return {
+ conversation = convo,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedMultiplePlaceInfos.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedMultiplePlaceInfos.lua
new file mode 100644
index 0000000..2bb1bb1
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedMultiplePlaceInfos.lua
@@ -0,0 +1,10 @@
+local Modules = game:GetService("CorePackages").AppTempCommon
+
+local Common = Modules.Common
+local Action = require(Common.Action)
+
+return Action(script.Name, function(placeInfos)
+ return {
+ placeInfos = placeInfos,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedUserPresence.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedUserPresence.lua
new file mode 100644
index 0000000..42da515
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Actions/ReceivedUserPresence.lua
@@ -0,0 +1,12 @@
+local Modules = game:GetService("CorePackages").AppTempCommon
+
+local Action = require(Modules.Common.Action)
+
+return Action(script.Name, function(userId, presence, lastLocation, placeId)
+ return {
+ userId = userId,
+ presence = presence,
+ lastLocation = lastLocation,
+ placeId = placeId,
+ }
+end)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Models/PlaceInfoModel.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Models/PlaceInfoModel.lua
new file mode 100644
index 0000000..103305a
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Models/PlaceInfoModel.lua
@@ -0,0 +1,39 @@
+local CorePackages = game:GetService("CorePackages")
+
+local MockId = require(CorePackages.AppTempCommon.LuaApp.MockId)
+
+local PlaceInfoModel = {}
+
+function PlaceInfoModel.new()
+ local self = {}
+
+ return self
+end
+
+function PlaceInfoModel.mock()
+ local self = PlaceInfoModel.new()
+
+ self.builder = "builder"
+ self.builderId = MockId()
+ self.description = "description"
+ self.imageToken = MockId()
+ self.isPlayable = true
+ self.name = "name"
+ self.placeId = MockId()
+ self.price = 0
+ self.reasonProhibited = nil
+ self.universeId = MockId()
+ self.universeRootPlaceId = MockId()
+ self.url = "url"
+
+ return self
+end
+
+function PlaceInfoModel.fromWeb(data)
+ local self = data or {}
+ self.placeId = tostring(self.placeId)
+
+ return self
+end
+
+return PlaceInfoModel
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.lua
new file mode 100644
index 0000000..4a9ab03
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.lua
@@ -0,0 +1,22 @@
+local CorePackages = game:GetService("CorePackages")
+
+local Common = CorePackages.AppTempCommon.Common
+local LuaChat = CorePackages.AppTempCommon.LuaChat
+
+local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
+
+local Immutable = require(Common.Immutable)
+
+return function(state, action)
+ state = state or {}
+ if action.type == ReceivedMultiplePlaceInfos.name then
+
+ local newInfos = {}
+ for _, placeInfo in ipairs(action.placeInfos) do
+ newInfos[placeInfo.placeId] = placeInfo
+ end
+
+ state = Immutable.JoinDictionaries(state, newInfos)
+ end
+ return state
+end
diff --git a/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.spec.lua
new file mode 100644
index 0000000..075534e
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/LuaChat/Reducers/PlaceInfos.spec.lua
@@ -0,0 +1,36 @@
+return function()
+ local CoreGui = game:GetService("CoreGui")
+ local Modules = CoreGui.RobloxGui.Modules
+ local LuaApp = Modules.LuaApp
+ local LuaChat = Modules.LuaChat
+
+ local MockId = require(LuaApp.MockId)
+ local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
+
+ local PlaceInfosReducer = require(script.Parent.PlaceInfos)
+
+ describe("initial state", function()
+ it("should return an initial table when passed nil", function()
+ local state = PlaceInfosReducer(nil, {})
+ expect(state).to.be.a("table")
+ end)
+ end)
+
+ describe("ReceivedMultiplePlaceInfos", function()
+ it("should add place info to the store", function()
+ local state = PlaceInfosReducer(nil, {})
+
+ local placeId = MockId()
+ local returnedPlaceInfo = ReceivedMultiplePlaceInfos({
+ {
+ placeId = placeId,
+ imageToken = "image-token",
+ },
+ })
+
+ state = PlaceInfosReducer(state, returnedPlaceInfo)
+
+ expect(state[placeId]).to.equal(returnedPlaceInfo.placeInfos[1])
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Temp/EventStream.lua b/Client2018/content/LuaPackages/AppTempCommon/Temp/EventStream.lua
new file mode 100644
index 0000000..05cb39b
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Temp/EventStream.lua
@@ -0,0 +1,79 @@
+local AnalyticsService = game:GetService("AnalyticsService")
+local RunService = game:GetService("RunService")
+local UserInputService = game:GetService("UserInputService")
+
+local SETTINGS_HUB_INVITE_RELEASE_STREAM_TIME = tonumber(settings():GetFVariable("SettingsHubInviteReleaseStreamTime"))
+ or math.huge
+
+local function getPlatformTarget()
+ local platformTarget = "unknownLua"
+ local platformEnum = Enum.Platform.None
+
+ -- the call to GetPlatform is wrapped in a pcall() because the Testing Service
+ -- executes the scripts in the wrong authorization level
+ pcall(function()
+ platformEnum = UserInputService:GetPlatform()
+ end)
+
+ -- bucket the platform based on consumer platform
+ local isDesktopClient = (platformEnum == Enum.Platform.Windows) or (platformEnum == Enum.Platform.OSX)
+
+ local isMobileClient = (platformEnum == Enum.Platform.IOS) or (platformEnum == Enum.Platform.Android)
+ isMobileClient = isMobileClient or (platformEnum == Enum.Platform.UWP)
+
+ local isConsole = (platformEnum == Enum.Platform.XBox360) or (platformEnum == Enum.Platform.XBoxOne)
+ isConsole = isConsole or (platformEnum == Enum.Platform.PS3) or (platformEnum == Enum.Platform.PS4)
+ isConsole = isConsole or (platformEnum == Enum.Platform.WiiU)
+
+ -- assign a target based on the form factor
+ if isDesktopClient then
+ platformTarget = "client"
+ elseif isMobileClient then
+ platformTarget = "mobile"
+ elseif isConsole then
+ platformTarget = "console"
+ else
+ -- if we don't have a name for the form factor, report it here so that we can eventually track it down
+ platformTarget = platformTarget .. tostring(platformEnum)
+ end
+
+ return platformTarget
+end
+
+local EventStream = {}
+EventStream.__index = EventStream
+
+function EventStream.new(overridePlatformTarget, overrideAnalyticsImpl)
+ local self = {}
+ setmetatable(self, EventStream)
+
+ self._analyticsImpl = overrideAnalyticsImpl or AnalyticsService
+ self._platformTarget = overridePlatformTarget or getPlatformTarget()
+
+ return self
+end
+
+function EventStream:setRBXEventStream(eventContext, eventName, additionalArgs)
+ additionalArgs = additionalArgs or {}
+ -- this function sends reports to the server in batches, not real-time
+ self._analyticsImpl:SetRBXEventStream(self._platformTarget, eventContext, eventName, additionalArgs)
+
+ if not self.timerSteppedConnection then
+ local lastGameTime = time()
+ self.timerSteppedConnection = RunService.Stepped:Connect(function(gameTime)
+ if gameTime - lastGameTime > SETTINGS_HUB_INVITE_RELEASE_STREAM_TIME then
+ self:releaseRBXEventStream()
+ end
+ end)
+ end
+end
+
+function EventStream:releaseRBXEventStream()
+ self._analyticsImpl:ReleaseRBXEventStream(self._platformTarget)
+ if self.timerSteppedConnection then
+ self.timerSteppedConnection:Disconnect()
+ self.timerSteppedConnection = nil
+ end
+end
+
+return EventStream
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.lua b/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.lua
new file mode 100644
index 0000000..42b855d
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.lua
@@ -0,0 +1,90 @@
+local CorePackages = game:GetService("CorePackages")
+local HttpService = game:GetService("HttpService")
+
+local LuaApp = CorePackages.AppTempCommon.LuaApp
+
+local Promise = require(LuaApp.Promise)
+
+local DEFAULT_THROTTLING_PRIORITY = Enum.ThrottlingPriority.Extreme
+local DEFAULT_POST_ASYNC_CONTENT_TYPE = Enum.HttpContentType.ApplicationJson
+
+-- httpRequest : (table, optional) an object that implements the same http functions as the data model
+return function(httpImpl)
+
+ local function doHttpPost(url, options)
+ assert(options.postBody, "Expected a postBody to be specified with this request")
+ assert(type(options.postBody) == "string", "Expected postBody to be a string")
+
+ if not options.contentType then
+ options.contentType = DEFAULT_POST_ASYNC_CONTENT_TYPE
+ end
+
+ if not options.throttlingPriority then
+ options.throttlingPriority = DEFAULT_THROTTLING_PRIORITY
+ end
+
+ return function()
+ return httpImpl:PostAsyncFullUrl(
+ url,
+ options.postBody,
+ options.throttlingPriority,
+ options.contentType
+ )
+ end
+ end
+
+ local function doHttpGet(url)
+ return function()
+ return httpImpl:GetAsyncFullUrl(url, DEFAULT_THROTTLING_PRIORITY)
+ end
+ end
+
+ -- return the request function
+ -- url : (string)
+ -- requestMethod : (string) "GET", "POST"
+ -- args : (table, optional)
+ -- options.throttlingPriority : (Enum.ThrottlingPriority, optional)
+ -- options.contentType : (Enum.HttpContentType, optional)
+ -- options.postBody : (string, optional ("POST" only))
+ -- RETURNS : (promise)
+ return function(url, requestMethod, options)
+ assert(type(url) == "string", "Expected url to be a string")
+ assert(type(requestMethod) == "string", "Expected requestMethod to be a string")
+ assert(not options or type(options) == "table", "Expected options to be a table")
+ requestMethod = string.upper(requestMethod)
+
+ local httpFunction
+ if requestMethod == "POST" then
+ httpFunction = doHttpPost(url, options)
+ elseif requestMethod == "GET" then
+ httpFunction = doHttpGet(url)
+ else
+ error(string.format("Unsupported requestMethod : %s", requestMethod or "nil"))
+ end
+
+ return Promise.new(function(resolve, reject)
+ if httpFunction then
+ spawn(function()
+ local success, response = pcall(httpFunction)
+
+ if success then
+ local jsonSuccess, decodedJson = pcall(function()
+ return HttpService:JSONDecode(response)
+ end)
+ if jsonSuccess then
+ resolve({
+ responseBody = decodedJson,
+ })
+ else
+ reject(decodedJson)
+ end
+ else
+ reject(response)
+ end
+ end)
+ else
+ reject()
+ end
+ end)
+ end
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.spec.lua
new file mode 100644
index 0000000..fed3d32
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Temp/httpRequest.spec.lua
@@ -0,0 +1,61 @@
+return function()
+ local httpRequest = require(script.Parent.httpRequest)
+
+ local function createTestRequestFunc(testResponse)
+ local requestService = {}
+ function requestService:GetAsyncFullUrl()
+ return testResponse
+ end
+ function requestService:PostAsyncFullUrl()
+ return testResponse
+ end
+
+ return httpRequest(requestService)
+ end
+
+ it("should return a function", function()
+ expect(httpRequest()).to.be.ok()
+ expect(type(httpRequest())).to.equal("function")
+ end)
+
+ it("should validate its inputs", function()
+ local testRequest = createTestRequestFunc()
+ local function testParams(url, requestMethod, args)
+ return function()
+ testRequest(url, requestMethod, args)
+ end
+ end
+
+ local validUrl = "friends.roblox.com"
+ local validMethod = "GET"
+ local validArgs = {}
+
+ -- url checks
+ expect(testParams(nil, validMethod, validArgs)).to.throw()
+ expect(testParams(123, validMethod, validArgs)).to.throw()
+ expect(testParams({}, validMethod, validArgs)).to.throw()
+ expect(testParams(true, validMethod, validArgs)).to.throw()
+ expect(testParams(function() end, validMethod, validArgs)).to.throw()
+
+ -- request method checks
+ expect(testParams(validUrl, nil, validArgs)).to.throw()
+ expect(testParams(validUrl, 123, validArgs)).to.throw()
+ expect(testParams(validUrl, {}, validArgs)).to.throw()
+ expect(testParams(validUrl, true, validArgs)).to.throw()
+ expect(testParams(validUrl, function() end, validArgs)).to.throw()
+
+ -- args checks
+ expect(testParams(validUrl, validMethod, 123)).to.throw()
+ expect(testParams(validUrl, validMethod, "Test")).to.throw()
+ expect(testParams(validUrl, validMethod, true)).to.throw()
+ expect(testParams(validUrl, validMethod, function() end)).to.throw()
+ end)
+
+ it("should throw an error if the requestMethod isn't supported", function()
+ local testRequest = createTestRequestFunc("foo")
+
+ expect(function()
+ testRequest("testUrl", "GIVEANDTAKE")
+ end).to.throw()
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.lua b/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.lua
new file mode 100644
index 0000000..3a0d69f
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.lua
@@ -0,0 +1,16 @@
+return function(targetString, blacklistedCharacter)
+ local charactersArray = {}
+ local indexArray = {}
+ for index, byte in utf8.codes(targetString) do
+ local graphemeCharacter = utf8.char(byte)
+ table.insert(charactersArray, 1, graphemeCharacter)
+ table.insert(indexArray, 1, index)
+ end
+ for index, graphemeCharacter in ipairs(charactersArray) do
+ if graphemeCharacter ~= blacklistedCharacter then
+ return targetString:sub(1, indexArray[index])
+ end
+ end
+
+ return ""
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.spec.lua b/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.spec.lua
new file mode 100644
index 0000000..a08d217
--- /dev/null
+++ b/Client2018/content/LuaPackages/AppTempCommon/Temp/trimCharacterFromEndString.spec.lua
@@ -0,0 +1,71 @@
+return function()
+ local trimCharacterFromEndString = require(script.Parent.trimCharacterFromEndString)
+
+ describe("single byte characters", function()
+ it("should not trim a string if it does not end with passed character", function()
+ local passedString = "testing"
+ local passedCharacter = "/"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(passedString)
+ end)
+
+ it("should trim a string if it ends with a single instance of the passed character", function()
+ local passedString = "testing/"
+ local passedCharacter = "/"
+ local expectedString = "testing"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+
+ it("should trim a string if it ends with multiple instances of the passed character", function()
+ local passedString = "testing///"
+ local passedCharacter = "/"
+ local expectedString = "testing"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+
+ it("should do nothing if the passed character is empty", function()
+ local passedString = "hunter2"
+ local passedCharacter = ""
+ local expectedString = "hunter2"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+ end)
+
+ describe("multiple byte characters", function()
+ it("should not trim a string if it does not end with passed character", function()
+ local passedString = "testing"
+ local passedCharacter = "🐶"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(passedString)
+ end)
+
+ it("should trim a string if it ends with a single instance of the passed character", function()
+ local passedString = "testing🐶"
+ local passedCharacter = "🐶"
+ local expectedString = "testing"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+
+ it("should trim a string if it ends with multiple instances of the passed character", function()
+ local passedString = "testing🐶🐶🐶"
+ local passedCharacter = "🐶"
+ local expectedString = "testing"
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+ end)
+
+ describe("a string with all blacklisted characters", function()
+ it("should return a empty string", function()
+ local passedString = "pppppppppppp"
+ local passedCharacter = "p"
+ local expectedString = ""
+
+ expect(trimCharacterFromEndString(passedString, passedCharacter)).to.equal(expectedString)
+ end)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/Roact.lua b/Client2018/content/LuaPackages/Roact.lua
new file mode 100644
index 0000000..5b48405
--- /dev/null
+++ b/Client2018/content/LuaPackages/Roact.lua
@@ -0,0 +1,7 @@
+local CorePackages = game:GetService("CorePackages")
+
+local initify = require(CorePackages.initify)
+
+initify(CorePackages.RoactImpl)
+
+return require(CorePackages.RoactImpl)
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Change.lua b/Client2018/content/LuaPackages/RoactImpl/Change.lua
new file mode 100644
index 0000000..b7d259c
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Change.lua
@@ -0,0 +1,36 @@
+--[[
+ Change is used to generate special prop keys that can be used to connect to
+ GetPropertyChangedSignal.
+
+ Generally, Change is indexed by a Roblox property name:
+
+ Roact.createElement("TextBox", {
+ [Roact.Change.Text] = function(rbx)
+ print("The TextBox", rbx, "changed text to", rbx.Text)
+ end,
+ })
+]]
+
+local Change = {}
+
+local changeMetatable = {
+ __tostring = function(self)
+ return ("ChangeListener(%s)"):format(self.name)
+ end
+}
+
+setmetatable(Change, {
+ __index = function(self, propertyName)
+ local changeListener = {
+ type = Change,
+ name = propertyName
+ }
+
+ setmetatable(changeListener, changeMetatable)
+ Change[propertyName] = changeListener
+
+ return changeListener
+ end,
+})
+
+return Change
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Change.spec.lua b/Client2018/content/LuaPackages/RoactImpl/Change.spec.lua
new file mode 100644
index 0000000..154539a
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Change.spec.lua
@@ -0,0 +1,15 @@
+return function()
+ local Change = require(script.Parent.Change)
+
+ it("should yield change listener objects when indexed", function()
+ expect(Change.Text).to.be.ok()
+ expect(Change.Selected).to.be.ok()
+ end)
+
+ it("should yield the same object when indexed again", function()
+ local a = Change.Text
+ local b = Change.Text
+
+ expect(a).to.equal(b)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Component.lua b/Client2018/content/LuaPackages/RoactImpl/Component.lua
new file mode 100644
index 0000000..ca28cd8
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Component.lua
@@ -0,0 +1,435 @@
+--[[
+ The base implementation of a stateful component in Roact.
+
+ Stateful components handle most of their own mounting and reconciliation
+ process. Many of the private methods here are invoked by the reconciler.
+
+ Stateful components expose a handful of lifecycle events:
+ - didMount
+ - willUnmount
+ - willUpdate
+ - didUpdate
+ - (static) getDerivedStateFromProps
+
+ These lifecycle events line up with their semantics in React, and more
+ information (and a diagram) is available in the Roact documentation.
+]]
+
+local Reconciler = require(script.Parent.Reconciler)
+local Core = require(script.Parent.Core)
+local GlobalConfig = require(script.Parent.GlobalConfig)
+local Instrumentation = require(script.Parent.Instrumentation)
+
+local invalidSetStateMessages = require(script.Parent.invalidSetStateMessages)
+
+local Component = {}
+
+-- Locally cache tick so we can minimize impact of calling it for instrumentation
+local tick = tick
+
+Component.__index = Component
+
+--[[
+ Merge any number of dictionaries into a new dictionary, overwriting keys.
+
+ If a value of `Core.None` is encountered, the key will be removed instead.
+ This is necessary because Lua doesn't differentiate between a key being
+ missing and a key being set to nil.
+]]
+local function merge(...)
+ local result = {}
+
+ for i = 1, select("#", ...) do
+ local entry = select(i, ...)
+
+ for key, value in pairs(entry) do
+ if value == Core.None then
+ result[key] = nil
+ else
+ result[key] = value
+ end
+ end
+ end
+
+ return result
+end
+
+--[[
+ Create a new stateful component.
+
+ Not intended to be a general OO implementation, this function only intends
+ to let users extend Component and PureComponent.
+
+ Instead of using inheritance, use composition and props to extend
+ components.
+]]
+function Component:extend(name)
+ assert(type(name) == "string", "A name must be provided to create a Roact Component")
+
+ local class = {}
+
+ for key, value in pairs(self) do
+ -- We don't want users using 'extend' to create component inheritance
+ -- see https://reactjs.org/docs/composition-vs-inheritance.html
+ if key ~= "extend" then
+ class[key] = value
+ end
+ end
+
+ class.__index = class
+
+ setmetatable(class, {
+ __tostring = function(self)
+ return name
+ end
+ })
+
+ function class._new(props, context)
+ local self = {}
+
+ -- When set to a value, setState will fail, using the given reason to
+ -- create a detailed error message.
+ -- You can see a list of reasons in invalidSetStateMessages.
+ self._setStateBlockedReason = nil
+
+ if class.defaultProps == nil then
+ self.props = props
+ else
+ self.props = merge(class.defaultProps, props)
+ end
+
+ self._context = {}
+
+ -- Shallow copy all context values from our parent element.
+ if context then
+ for key, value in pairs(context) do
+ self._context[key] = value
+ end
+ end
+
+ setmetatable(self, class)
+
+ -- Call the user-provided initializer, where state and _props are set.
+ if class.init then
+ self._setStateBlockedReason = "init"
+ class.init(self, props)
+ self._setStateBlockedReason = nil
+ end
+
+ -- The user constructer might not set state, so we can.
+ if not self.state then
+ self.state = {}
+ end
+
+ if class.getDerivedStateFromProps then
+ local partialState = class.getDerivedStateFromProps(props, self.state)
+
+ if partialState then
+ self.state = merge(self.state, partialState)
+ end
+ end
+
+ return self
+ end
+
+ return class
+end
+
+--[[
+ render is intended to describe what a UI should look like at the current
+ point in time.
+
+ The default implementation throws an error, since forgetting to define
+ render is usually a mistake.
+
+ The simplest implementation for render is:
+
+ function MyComponent:render()
+ return nil
+ end
+
+ You should explicitly return nil from functions in Lua to avoid edge cases
+ related to none versus nil.
+]]
+function Component:render()
+ local message = (
+ "The component %q is missing the 'render' method.\n" ..
+ "render must be defined when creating a Roact component!"
+ ):format(
+ tostring(getmetatable(self))
+ )
+
+ error(message, 0)
+end
+
+--[[
+ Used to tell Roact whether this component *might* need to be re-rendered
+ given a new set of props and state.
+
+ This method is an escape hatch for when the Roact element creation and
+ reconciliation algorithms are not fast enough for specific cases. Poorly
+ written shouldUpdate methods *will* cause hard-to-trace bugs.
+
+ If you're thinking of writing a shouldUpdate function, consider using
+ PureComponent instead, which provides a good implementation given that your
+ data is immutable.
+
+ This function must be faster than the render method in order to be a
+ performance improvement.
+]]
+function Component:shouldUpdate(newProps, newState)
+ return true
+end
+
+--[[
+ Applies new state to the component.
+
+ partialState may be one of two things:
+ - A table, which will be merged onto the current state.
+ - A function, returning a table to merge onto the current state.
+
+ The table variant generally looks like:
+
+ self:setState({
+ foo = "bar",
+ })
+
+ The function variant generally looks like:
+
+ self:setState(function(prevState, props)
+ return {
+ foo = prevState.count + 1,
+ })
+ end)
+
+ The function variant may also return nil in the callback, which allows Roact
+ to cancel updating state and abort the render.
+
+ Future versions of Roact will potentially batch or delay state merging, so
+ any state updates that depend on the current state should use the function
+ variant.
+]]
+function Component:setState(partialState)
+ -- If setState was disabled, we should check for a detailed message and
+ -- display it.
+ if self._setStateBlockedReason ~= nil then
+ local messageSource = invalidSetStateMessages[self._setStateBlockedReason]
+
+ if messageSource == nil then
+ messageSource = invalidSetStateMessages["default"]
+ end
+
+ -- We assume that each message has a formatting placeholder for a component name.
+ local formattedMessage = string.format(messageSource, tostring(getmetatable(self)))
+
+ error(formattedMessage, 2)
+ end
+
+ -- If the partial state is a function, invoke it to get the actual partial state.
+ if type(partialState) == "function" then
+ partialState = partialState(self.state, self.props)
+
+ -- If partialState is nil, abort the render.
+ if partialState == nil then
+ return
+ end
+ end
+
+ local newState = merge(self.state, partialState)
+ self:_update(nil, newState)
+end
+
+--[[
+ Returns the current stack trace for this component, or nil if the
+ elementTracing configuration flag is set to false.
+]]
+function Component:getElementTraceback()
+ return self._handle._element.source
+end
+
+--[[
+ Notifies the component that new props and state are available. This function
+ is invoked by the reconciler.
+
+ If shouldUpdate returns true, this method will trigger a re-render and
+ reconciliation step.
+]]
+function Component:_update(newProps, newState)
+ self._setStateBlockedReason = "shouldUpdate"
+
+ local doUpdate
+ if GlobalConfig.getValue("componentInstrumentation") then
+ local startTime = tick()
+
+ doUpdate = self:shouldUpdate(newProps or self.props, newState or self.state)
+
+ local elapsed = tick() - startTime
+ Instrumentation.logShouldUpdate(self._handle, doUpdate, elapsed)
+ else
+ doUpdate = self:shouldUpdate(newProps or self.props, newState or self.state)
+ end
+
+ self._setStateBlockedReason = nil
+
+ if doUpdate then
+ self:_forceUpdate(newProps, newState)
+ end
+end
+
+--[[
+ Forces the component to re-render itself and its children.
+
+ This is essentially the inner portion of _update.
+
+ newProps and newState are optional.
+]]
+function Component:_forceUpdate(newProps, newState)
+ -- Compute new derived state.
+ -- Get the class - getDerivedStateFromProps is static.
+ local class = getmetatable(self)
+
+ -- If newProps are passed, compute derived state and default props
+ if newProps then
+ if class.getDerivedStateFromProps then
+ local derivedState = class.getDerivedStateFromProps(newProps, newState or self.state)
+
+ -- getDerivedStateFromProps can return nil if no changes are necessary.
+ if derivedState ~= nil then
+ newState = merge(newState or self.state, derivedState)
+ end
+ end
+
+ if class.defaultProps then
+ -- We only allocate another prop table if there are props that are
+ -- falling back to their default.
+ local replacementProps
+
+ for key in pairs(class.defaultProps) do
+ if newProps[key] == nil then
+ replacementProps = merge(class.defaultProps, newProps)
+ break
+ end
+ end
+
+ if replacementProps then
+ newProps = replacementProps
+ end
+ end
+ end
+
+ if self.willUpdate then
+ self._setStateBlockedReason = "willUpdate"
+ self:willUpdate(newProps or self.props, newState or self.state)
+ self._setStateBlockedReason = nil
+ end
+
+ local oldProps = self.props
+ local oldState = self.state
+
+ if newProps then
+ self.props = newProps
+ end
+
+ if newState then
+ self.state = newState
+ end
+
+ self._setStateBlockedReason = "render"
+
+ local newChildElement
+ if GlobalConfig.getValue("componentInstrumentation") then
+ local startTime = tick()
+
+ newChildElement = self:render()
+
+ local elapsed = tick() - startTime
+ Instrumentation.logRenderTime(self._handle, elapsed)
+ else
+ newChildElement = self:render()
+ end
+
+ self._setStateBlockedReason = nil
+
+ self._setStateBlockedReason = "reconcile"
+ if self._handle._child ~= nil then
+ -- We returned an element during our last render, update it.
+ self._handle._child = Reconciler._reconcileInternal(
+ self._handle._child,
+ newChildElement
+ )
+ elseif newChildElement then
+ -- We returned nil during our last render, construct a new child.
+ self._handle._child = Reconciler._mountInternal(
+ newChildElement,
+ self._handle._parent,
+ self._handle._key,
+ self._context
+ )
+ end
+ self._setStateBlockedReason = nil
+
+ if self.didUpdate then
+ self:didUpdate(oldProps, oldState)
+ end
+end
+
+--[[
+ Initializes the component instance and attaches it to the given
+ instance handle, created by Reconciler._mount.
+]]
+function Component:_mount(handle)
+ self._handle = handle
+
+ self._setStateBlockedReason = "render"
+
+ local virtualTree
+ if GlobalConfig.getValue("componentInstrumentation") then
+ local startTime = tick()
+
+ virtualTree = self:render()
+
+ local elapsed = tick() - startTime
+ Instrumentation.logRenderTime(self._handle, elapsed)
+ else
+ virtualTree = self:render()
+ end
+
+ self._setStateBlockedReason = nil
+
+ if virtualTree then
+ self._setStateBlockedReason = "reconcile"
+ handle._child = Reconciler._mountInternal(
+ virtualTree,
+ handle._parent,
+ handle._key,
+ self._context
+ )
+ self._setStateBlockedReason = nil
+ end
+
+ if self.didMount then
+ self:didMount()
+ end
+end
+
+--[[
+ Destructs the component and invokes all necessary lifecycle methods.
+]]
+function Component:_unmount()
+ local handle = self._handle
+
+ if self.willUnmount then
+ self._setStateBlockedReason = "willUnmount"
+ self:willUnmount()
+ self._setStateBlockedReason = nil
+ end
+
+ -- Stateful components can return nil from render()
+ if handle._child then
+ Reconciler.unmount(handle._child)
+ end
+
+ self._handle = nil
+end
+
+return Component
diff --git a/Client2018/content/LuaPackages/RoactImpl/Component.spec.lua b/Client2018/content/LuaPackages/RoactImpl/Component.spec.lua
new file mode 100644
index 0000000..d7f7bb1
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Component.spec.lua
@@ -0,0 +1,615 @@
+return function()
+ local Core = require(script.Parent.Core)
+ local createElement = require(script.Parent.createElement)
+ local Reconciler = require(script.Parent.Reconciler)
+ local GlobalConfig = require(script.Parent.GlobalConfig)
+
+ local Component = require(script.Parent.Component)
+
+ it("should be extendable", function()
+ local MyComponent = Component:extend("The Senate")
+
+ expect(MyComponent).to.be.ok()
+ expect(MyComponent._new).to.be.ok()
+ end)
+
+ it("should prevent extending a user component", function()
+ local MyComponent = Component:extend("Sheev")
+
+ expect(function()
+ MyComponent:extend("Frank")
+ end).to.throw()
+ end)
+
+ it("should use a given name", function()
+ local MyComponent = Component:extend("FooBar")
+
+ local name = tostring(MyComponent)
+
+ expect(name).to.be.a("string")
+ expect(name:find("FooBar")).to.be.ok()
+ end)
+
+ it("should throw on render with a useful message by default", function()
+ local MyComponent = Component:extend("Foo")
+
+ local instance = MyComponent._new({})
+
+ expect(instance).to.be.ok()
+
+ local ok, err = pcall(function()
+ instance:render()
+ end)
+
+ expect(ok).to.equal(false)
+ expect(err:find("Foo")).to.be.ok()
+ end)
+
+ it("should pass props to the initializer", function()
+ local MyComponent = Component:extend("Wazo")
+
+ local callCount = 0
+ local testProps = {}
+
+ function MyComponent:init(props)
+ expect(props).to.equal(testProps)
+ callCount = callCount + 1
+ end
+
+ MyComponent._new(testProps)
+
+ expect(callCount).to.equal(1)
+ end)
+
+ it("should fire didMount and willUnmount when reified", function()
+ local MyComponent = Component:extend("MyComponent")
+ local mounts = 0
+ local unmounts = 0
+
+ function MyComponent:render()
+ return nil
+ end
+
+ function MyComponent:didMount()
+ mounts = mounts + 1
+ end
+
+ function MyComponent:willUnmount()
+ unmounts = unmounts + 1
+ end
+
+ expect(mounts).to.equal(0)
+ expect(unmounts).to.equal(0)
+
+ local instance = Reconciler.mount(createElement(MyComponent))
+
+ expect(mounts).to.equal(1)
+ expect(unmounts).to.equal(0)
+
+ Reconciler.unmount(instance)
+
+ expect(mounts).to.equal(1)
+ expect(unmounts).to.equal(1)
+ end)
+
+ it("should provide the proper arguments to willUpdate and didUpdate", function()
+ local willUpdateCount = 0
+ local didUpdateCount = 0
+ local prevProps
+ local prevState
+ local nextProps
+ local nextState
+ local setValue
+
+ local Child = Component:extend("PureChild")
+
+ function Child:willUpdate(newProps, newState)
+ nextProps = assert(newProps)
+ nextState = assert(newState)
+ prevProps = assert(self.props)
+ prevState = assert(self.state)
+ willUpdateCount = willUpdateCount + 1
+ end
+
+ function Child:didUpdate(oldProps, oldState)
+ assert(oldProps)
+ assert(oldState)
+ expect(prevProps.value).to.equal(oldProps.value)
+ expect(prevState.value).to.equal(oldState.value)
+ expect(nextProps.value).to.equal(self.props.value)
+ expect(nextState.value).to.equal(self.state.value)
+ didUpdateCount = didUpdateCount + 1
+ end
+
+ function Child:render()
+ return nil
+ end
+
+ local Container = Component:extend("Container")
+
+ function Container:init()
+ self.state = {
+ value = 0,
+ }
+ end
+
+ function Container:didMount()
+ setValue = function(value)
+ self:setState({
+ value = value,
+ })
+ end
+ end
+
+ function Container:willUnmount()
+ setValue = nil
+ end
+
+ function Container:render()
+ return createElement(Child, {
+ value = self.state.value,
+ })
+ end
+
+ local element = createElement(Container)
+ local instance = Reconciler.mount(element)
+
+ expect(willUpdateCount).to.equal(0)
+ expect(didUpdateCount).to.equal(0)
+
+ setValue(1)
+
+ expect(willUpdateCount).to.equal(1)
+ expect(didUpdateCount).to.equal(1)
+
+ setValue(1)
+
+ expect(willUpdateCount).to.equal(2)
+ expect(didUpdateCount).to.equal(2)
+
+ setValue(2)
+
+ expect(willUpdateCount).to.equal(3)
+ expect(didUpdateCount).to.equal(3)
+
+ setValue(1)
+
+ expect(willUpdateCount).to.equal(4)
+ expect(didUpdateCount).to.equal(4)
+
+ Reconciler.unmount(instance)
+ end)
+
+ it("should call getDerivedStateFromProps appropriately", function()
+ local TestComponent = Component:extend("TestComponent")
+ local getStateCallback
+
+ function TestComponent.getDerivedStateFromProps(newProps, oldState)
+ return {
+ visible = newProps.visible
+ }
+ end
+
+ function TestComponent:init(props)
+ self.state = {
+ visible = false
+ }
+
+ getStateCallback = function()
+ return self.state
+ end
+ end
+
+ function TestComponent:render() end
+
+ local handle = Reconciler.mount(createElement(TestComponent, {
+ visible = true
+ }))
+
+ local state = getStateCallback()
+ expect(state.visible).to.equal(true)
+
+ handle = Reconciler.reconcile(handle, createElement(TestComponent, {
+ visible = 123
+ }))
+
+ state = getStateCallback()
+ expect(state.visible).to.equal(123)
+
+ Reconciler.unmount(handle)
+ end)
+
+ it("should pull values from defaultProps where appropriate", function()
+ local lastProps
+ local TestComponent = Component:extend("TestComponent")
+
+ TestComponent.defaultProps = {
+ foo = "hello",
+ bar = "world",
+ }
+
+ function TestComponent:render()
+ lastProps = self.props
+ return nil
+ end
+
+ local handle = Reconciler.mount(createElement(TestComponent))
+
+ expect(lastProps).to.be.a("table")
+ expect(lastProps.foo).to.equal("hello")
+ expect(lastProps.bar).to.equal("world")
+
+ Reconciler.unmount(handle)
+
+ lastProps = nil
+ handle = Reconciler.mount(createElement(TestComponent, {
+ foo = 5,
+ }))
+
+ expect(lastProps).to.be.a("table")
+ expect(lastProps.foo).to.equal(5)
+ expect(lastProps.bar).to.equal("world")
+
+ Reconciler.unmount(handle)
+
+ lastProps = nil
+ handle = Reconciler.mount(createElement(TestComponent, {
+ bar = false,
+ }))
+
+ expect(lastProps).to.be.a("table")
+ expect(lastProps.foo).to.equal("hello")
+ expect(lastProps.bar).to.equal(false)
+
+ Reconciler.unmount(handle)
+ end)
+
+ it("should fall back to defaultProps correctly after an update", function()
+ local lastProps
+ local TestComponent = Component:extend("TestComponent")
+
+ TestComponent.defaultProps = {
+ foo = "hello",
+ bar = "world",
+ }
+
+ function TestComponent:render()
+ lastProps = self.props
+ return nil
+ end
+
+ local handle = Reconciler.mount(createElement(TestComponent, {
+ foo = "hey"
+ }))
+
+ expect(lastProps).to.be.a("table")
+ expect(lastProps.foo).to.equal("hey")
+ expect(lastProps.bar).to.equal("world")
+
+ handle = Reconciler.reconcile(handle, createElement(TestComponent))
+
+ expect(lastProps).to.be.a("table")
+ expect(lastProps.foo).to.equal("hello")
+ expect(lastProps.bar).to.equal("world")
+
+ Reconciler.unmount(handle)
+ end)
+
+ describe("setState", function()
+ it("should throw when called in init", function()
+ local InitComponent = Component:extend("InitComponent")
+
+ function InitComponent:init()
+ self:setState({
+ a = 1
+ })
+ end
+
+ function InitComponent:render()
+ return nil
+ end
+
+ local initElement = createElement(InitComponent)
+
+ expect(function()
+ Reconciler.mount(initElement)
+ end).to.throw()
+ end)
+
+ it("should throw when called in render", function()
+ local RenderComponent = Component:extend("RenderComponent")
+
+ function RenderComponent:render()
+ self:setState({
+ a = 1
+ })
+ end
+
+ local renderElement = createElement(RenderComponent)
+
+ expect(function()
+ Reconciler.mount(renderElement)
+ end).to.throw()
+ end)
+
+ it("should throw when called in shouldUpdate", function()
+ local TestComponent = Component:extend("TestComponent")
+
+ local triggerTest
+
+ function TestComponent:init()
+ triggerTest = function()
+ self:setState({
+ a = 1
+ })
+ end
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ function TestComponent:shouldUpdate()
+ self:setState({
+ a = 1
+ })
+ end
+
+ local testElement = createElement(TestComponent)
+
+ expect(function()
+ Reconciler.mount(testElement)
+ triggerTest()
+ end).to.throw()
+ end)
+
+ it("should throw when called in willUpdate", function()
+ local TestComponent = Component:extend("TestComponent")
+ local forceUpdate
+
+ function TestComponent:init()
+ forceUpdate = function()
+ self:_forceUpdate()
+ end
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ function TestComponent:willUpdate()
+ self:setState({
+ a = 1
+ })
+ end
+
+ local testElement = createElement(TestComponent)
+
+ expect(function()
+ Reconciler.mount(testElement)
+ forceUpdate()
+ end).to.throw()
+ end)
+
+ it("should throw when called in willUnmount", function()
+ local TestComponent = Component:extend("TestComponent")
+
+ function TestComponent:render()
+ return nil
+ end
+
+ function TestComponent:willUnmount()
+ self:setState({
+ a = 1
+ })
+ end
+
+ local element = createElement(TestComponent)
+ local instance = Reconciler.mount(element)
+
+ expect(function()
+ Reconciler.unmount(instance)
+ end).to.throw()
+ end)
+
+ it("should remove values from state when the value is Core.None", function()
+ local TestComponent = Component:extend("TestComponent")
+ local setStateCallback, getStateCallback
+
+ function TestComponent:init()
+ setStateCallback = function(newState)
+ self:setState(newState)
+ end
+
+ getStateCallback = function()
+ return self.state
+ end
+
+ self.state = {
+ value = 0
+ }
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ local element = createElement(TestComponent)
+ local instance = Reconciler.mount(element)
+
+ expect(getStateCallback().value).to.equal(0)
+
+ setStateCallback({
+ value = Core.None
+ })
+
+ expect(getStateCallback().value).to.equal(nil)
+
+ Reconciler.unmount(instance)
+ end)
+
+ it("should invoke functions to compute a partial state", function()
+ local TestComponent = Component:extend("TestComponent")
+ local setStateCallback, getStateCallback, getPropsCallback
+
+ function TestComponent:init()
+ setStateCallback = function(newState)
+ self:setState(newState)
+ end
+
+ getStateCallback = function()
+ return self.state
+ end
+
+ getPropsCallback = function()
+ return self.props
+ end
+
+ self.state = {
+ value = 0
+ }
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ local element = createElement(TestComponent)
+ local instance = Reconciler.mount(element)
+
+ expect(getStateCallback().value).to.equal(0)
+
+ setStateCallback(function(state, props)
+ expect(state).to.equal(getStateCallback())
+ expect(props).to.equal(getPropsCallback())
+
+ return {
+ value = state.value + 1
+ }
+ end)
+
+ expect(getStateCallback().value).to.equal(1)
+
+ Reconciler.unmount(instance)
+ end)
+
+ it("should cancel rendering if the function returns nil", function()
+ local TestComponent = Component:extend("TestComponent")
+ local setStateCallback
+ local renderCount = 0
+
+ function TestComponent:init()
+ setStateCallback = function(newState)
+ self:setState(newState)
+ end
+
+ self.state = {
+ value = 0
+ }
+ end
+
+ function TestComponent:render()
+ renderCount = renderCount + 1
+ return nil
+ end
+
+ local element = createElement(TestComponent)
+ local instance = Reconciler.mount(element)
+ expect(renderCount).to.equal(1)
+
+ setStateCallback(function(state, props)
+ return nil
+ end)
+
+ expect(renderCount).to.equal(1)
+
+ Reconciler.unmount(instance)
+ end)
+
+ it("should not call getDerivedStateFromProps on setState", function()
+ local TestComponent = Component:extend("TestComponent")
+ local setStateCallback
+ local getDerivedStateFromPropsCount = 0
+
+ function TestComponent:init()
+ setStateCallback = function(newState)
+ self:setState(newState)
+ end
+
+ self.state = {
+ value = 0
+ }
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ function TestComponent.getDerivedStateFromProps(nextProps, lastState)
+ getDerivedStateFromPropsCount = getDerivedStateFromPropsCount + 1
+ end
+
+ local element = createElement(TestComponent, {
+ someProp = 1,
+ })
+
+ local instance = Reconciler.mount(element)
+ expect(getDerivedStateFromPropsCount).to.equal(1)
+
+ setStateCallback({
+ value = 1,
+ })
+ expect(getDerivedStateFromPropsCount).to.equal(1)
+
+
+ Reconciler.unmount(instance)
+ end)
+ end)
+
+ describe("getElementTraceback", function()
+ it("should return stack traces", function()
+ local stackTraceCallback = nil
+
+ GlobalConfig.set({
+ elementTracing = true
+ })
+
+ local TestComponent = Component:extend("TestComponent")
+
+ function TestComponent:init()
+ stackTraceCallback = function()
+ return self:getElementTraceback()
+ end
+ end
+
+ function TestComponent:render()
+ return createElement("StringValue")
+ end
+
+ local handle = Reconciler.mount(createElement(TestComponent))
+ expect(stackTraceCallback()).to.be.ok()
+ Reconciler.unmount(handle)
+ GlobalConfig.reset()
+ end)
+
+ it("should return nil when elementTracing is off", function()
+ local stackTraceCallback = nil
+
+ local TestComponent = Component:extend("TestComponent")
+
+ function TestComponent:init()
+ stackTraceCallback = function()
+ return self:getElementTraceback()
+ end
+ end
+
+ function TestComponent:render()
+ return createElement("StringValue")
+ end
+
+ local handle = Reconciler.mount(createElement(TestComponent))
+ expect(stackTraceCallback()).to.never.be.ok()
+ Reconciler.unmount(handle)
+ end)
+ end)
+end
diff --git a/Client2018/content/LuaPackages/RoactImpl/Config.lua b/Client2018/content/LuaPackages/RoactImpl/Config.lua
new file mode 100644
index 0000000..ced1fc6
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Config.lua
@@ -0,0 +1,146 @@
+--[[
+ Exposes an interface to set global configuration values for Roact.
+
+ Configuration can only occur once, and should only be done by an application
+ using Roact, not a library.
+
+ Any keys that aren't recognized will cause errors. Configuration is only
+ intended for configuring Roact itself, not extensions or libraries.
+
+ Configuration is expected to be set immediately after loading Roact. Setting
+ configuration values after an application starts may produce unpredictable
+ behavior.
+]]
+
+-- Every valid configuration value should be non-nil in this table.
+local defaultConfig = {
+ -- Enables storage of `debug.traceback()` values on elements for debugging.
+ ["elementTracing"] = false,
+ -- Enables instrumentation of shouldUpdate and render methods for Roact components
+ ["componentInstrumentation"] = false,
+}
+
+-- Build a list of valid configuration values up for debug messages.
+local defaultConfigKeys = {}
+for key in pairs(defaultConfig) do
+ table.insert(defaultConfigKeys, key)
+end
+
+--[[
+ Merges two tables together into a new table.
+]]
+local function join(a, b)
+ local new = {}
+
+ for key, value in pairs(a) do
+ new[key] = value
+ end
+
+ for key, value in pairs(b) do
+ new[key] = value
+ end
+
+ return new
+end
+
+local Config = {}
+
+function Config.new()
+ local self = {}
+
+ -- Once configuration has been set, we record a traceback.
+ -- That way, if the user mistakenly calls `set` twice, we can point to the
+ -- first place it was called.
+ self._lastConfigTraceback = nil
+
+ self._currentConfig = defaultConfig
+
+ -- We manually bind these methods here so that the Config's methods can be
+ -- used without passing in self, since they eventually get exposed on the
+ -- root Roact object.
+ self.set = function(...)
+ return Config.set(self, ...)
+ end
+
+ self.getValue = function(...)
+ return Config.getValue(self, ...)
+ end
+
+ self.reset = function(...)
+ return Config.reset(self, ...)
+ end
+
+ return self
+end
+
+function Config.set(self, configValues)
+ if self._lastConfigTraceback then
+ local message = (
+ "Global configuration can only be set once. Configuration was already set at:%s"
+ ):format(
+ self._lastConfigTraceback
+ )
+
+ error(message, 3)
+ end
+
+ -- We use 3 as our traceback and error level because all of the methods are
+ -- manually bound to 'self', which creates an additional stack frame we want
+ -- to skip through.
+ self._lastConfigTraceback = debug.traceback("", 3)
+
+ -- Validate values without changing any configuration.
+ -- We only want to apply this configuration if it's valid!
+ for key, value in pairs(configValues) do
+ if defaultConfig[key] == nil then
+ local message = (
+ "Invalid global configuration key %q (type %s). Valid configuration keys are: %s"
+ ):format(
+ tostring(key),
+ typeof(key),
+ table.concat(defaultConfigKeys, ", ")
+ )
+
+ error(message, 3)
+ end
+
+ -- Right now, all configuration values must be boolean.
+ if typeof(value) ~= "boolean" then
+ local message = (
+ "Invalid value %q (type %s) for global configuration key %q. Valid values are: true, false"
+ ):format(
+ tostring(value),
+ typeof(value),
+ tostring(key)
+ )
+
+ error(message, 3)
+ end
+ end
+
+ -- Assign all of the (validated) configuration values in one go.
+ self._currentConfig = join(self._currentConfig, configValues)
+end
+
+function Config.getValue(self, key)
+ if defaultConfig[key] == nil then
+ local message = (
+ "Invalid global configuration key %q (type %s). Valid configuration keys are: %s"
+ ):format(
+ tostring(key),
+ typeof(key),
+ table.concat(defaultConfigKeys, ", ")
+ )
+
+ error(message, 3)
+ end
+
+ return self._currentConfig[key]
+end
+
+function Config.reset(self)
+ self._lastConfigTraceback = nil
+ self._currentConfig = defaultConfig
+end
+
+return Config
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Config.spec.lua b/Client2018/content/LuaPackages/RoactImpl/Config.spec.lua
new file mode 100644
index 0000000..cec7076
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Config.spec.lua
@@ -0,0 +1,86 @@
+return function()
+ local Config = require(script.Parent.Config)
+
+ it("should accept valid configuration", function()
+ local config = Config.new()
+
+ expect(config.getValue("elementTracing")).to.equal(false)
+
+ config.set({
+ elementTracing = true,
+ })
+
+ expect(config.getValue("elementTracing")).to.equal(true)
+ end)
+
+ it("should reject invalid configuration keys", function()
+ local config = Config.new()
+
+ local badKey = "garblegoop"
+
+ local ok, err = pcall(function()
+ config.set({
+ [badKey] = true,
+ })
+ end)
+
+ expect(ok).to.equal(false)
+
+ -- The error should mention our bad key somewhere.
+ expect(err:find(badKey)).to.be.ok()
+ end)
+
+ it("should reject invalid configuration values", function()
+ local config = Config.new()
+
+ local goodKey = "elementTracing"
+ local badValue = "Hello there!"
+
+ local ok, err = pcall(function()
+ config.set({
+ [goodKey] = badValue,
+ })
+ end)
+
+ expect(ok).to.equal(false)
+
+ -- The error should mention both our key and value
+ expect(err:find(goodKey)).to.be.ok()
+ expect(err:find(badValue)).to.be.ok()
+ end)
+
+ it("should prevent setting configuration more than once", function()
+ local config = Config.new()
+
+ -- We're going to use the name of this function to see if the traceback
+ -- was correct.
+ local function setEmptyConfig()
+ config.set({})
+ end
+
+ setEmptyConfig()
+
+ local ok, err = pcall(setEmptyConfig)
+
+ expect(ok).to.equal(false)
+
+ -- The error should mention the stack trace with the original set call.
+ expect(err:find("setEmptyConfig")).to.be.ok()
+ end)
+
+ it("should reset to default values after invoking reset()", function()
+ local config = Config.new()
+
+ expect(config.getValue("elementTracing")).to.equal(false)
+
+ config.set({
+ elementTracing = true,
+ })
+
+ expect(config.getValue("elementTracing")).to.equal(true)
+
+ config.reset()
+
+ expect(config.getValue("elementTracing")).to.equal(false)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Core.lua b/Client2018/content/LuaPackages/RoactImpl/Core.lua
new file mode 100644
index 0000000..76d9658
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Core.lua
@@ -0,0 +1,24 @@
+--[[
+ Provides a set of markers used for annotating data in Roact.
+]]
+
+local Symbol = require(script.Parent.Symbol)
+
+local Core = {}
+
+-- Marker used to specify children of a node.
+Core.Children = Symbol.named("Children")
+
+-- Marker used to specify a callback to receive the underlying Roblox object.
+Core.Ref = Symbol.named("Ref")
+
+-- Marker used to specify that a component is a Roact Portal.
+Core.Portal = Symbol.named("Portal")
+
+-- Marker used to specify that the value is nothing, because nil cannot be stored in tables.
+Core.None = Symbol.named("None")
+
+-- Marker used to specify that the table it is present within is a component.
+Core.Element = Symbol.named("Element")
+
+return Core
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Event.lua b/Client2018/content/LuaPackages/RoactImpl/Event.lua
new file mode 100644
index 0000000..499e56f
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Event.lua
@@ -0,0 +1,39 @@
+--[[
+ Index into 'Event' to get a prop key for attaching to an event on a
+ Roblox Instance.
+
+ Example:
+
+ Roact.createElement("TextButton", {
+ Text = "Hello, world!",
+
+ [Roact.Event.MouseButton1Click] = function(rbx)
+ print("Clicked", rbx)
+ end
+ })
+]]
+
+local Event = {}
+
+local eventMetatable = {
+ __tostring = function(self)
+ return ("Event(%s)"):format(self.name)
+ end
+}
+
+setmetatable(Event, {
+ __index = function(self, eventName)
+ local event = {
+ type = Event,
+ name = eventName
+ }
+
+ setmetatable(event, eventMetatable)
+
+ Event[eventName] = event
+
+ return event
+ end
+})
+
+return Event
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Event.spec.lua b/Client2018/content/LuaPackages/RoactImpl/Event.spec.lua
new file mode 100644
index 0000000..6c1283b
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Event.spec.lua
@@ -0,0 +1,15 @@
+return function()
+ local Event = require(script.Parent.Event)
+
+ it("should yield event objects when indexed", function()
+ expect(Event.MouseButton1Click).to.be.ok()
+ expect(Event.Touched).to.be.ok()
+ end)
+
+ it("should yield the same object when indexed again", function()
+ local a = Event.MouseButton1Click
+ local b = Event.MouseButton1Click
+
+ expect(a).to.equal(b)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.lua b/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.lua
new file mode 100644
index 0000000..3219835
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.lua
@@ -0,0 +1,7 @@
+--[[
+ Exposes a single instance of a configuration as Roact's GlobalConfig.
+]]
+
+local Config = require(script.Parent.Config)
+
+return Config.new()
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.spec.lua b/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.spec.lua
new file mode 100644
index 0000000..5974c79
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/GlobalConfig.spec.lua
@@ -0,0 +1,10 @@
+return function()
+ local GlobalConfig = require(script.Parent.GlobalConfig)
+
+ it("should have the correct methods", function()
+ expect(GlobalConfig).to.be.ok()
+ expect(GlobalConfig.set).to.be.ok()
+ expect(GlobalConfig.getValue).to.be.ok()
+ expect(GlobalConfig.reset).to.be.ok()
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Instrumentation.lua b/Client2018/content/LuaPackages/RoactImpl/Instrumentation.lua
new file mode 100644
index 0000000..771860d
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Instrumentation.lua
@@ -0,0 +1,104 @@
+--[[
+ An optional instrumentation layer that the reconciler calls into to record
+ various events.
+
+ Tracks a number of stats, including:
+ Recorded stats:
+ - Render count by component
+ - Update request count by component
+ - Actual update count by component
+ - shouldUpdate returned true count by component
+ - Time taken to run shouldUpdate
+ - Time taken to render by component
+ Derivable stats (for profiling manually or with a future tool):
+ - Average render time by component
+ - Percent of total render time by component
+ - Percent of time shouldUpdate returns true
+ - Average shouldUpdate time by component
+ - Percent of total shouldUpdate time by component
+]]
+
+local Instrumentation = {}
+
+local componentStats = {}
+
+--[[
+ Determines name of component from the given instance handle and returns a
+ stat object from the componentStats table, generating a new one if needed
+]]
+local function getStatEntry(handle)
+ local name
+ if handle and handle._element and handle._element.component then
+ name = tostring(handle._element.component)
+ else
+ warn("Component name not valid for " .. tostring(handle._key))
+ return nil
+ end
+ local entry = componentStats[name]
+ if not entry then
+ entry = {
+ -- update requests
+ updateReqCount = 0,
+ -- actual updates
+ didUpdateCount = 0,
+ -- time spent in shouldUpdate
+ shouldUpdateTime = 0,
+ -- number of renders
+ renderCount = 0,
+ -- total render time spent
+ renderTime = 0,
+ }
+ componentStats[name] = entry
+ end
+
+ return entry
+end
+
+--[[
+ Logs the time taken and resulting value of a Component's shouldUpdate function
+]]
+function Instrumentation.logShouldUpdate(handle, updateNeeded, shouldUpdateTime)
+ -- Grab or create associated entry in stats table
+ local statEntry = getStatEntry(handle)
+ if statEntry then
+ -- Increment the total number of times update was invoked
+ statEntry.updateReqCount = statEntry.updateReqCount + 1
+
+ -- Increment (when applicable) total number of times shouldUpdate returned true
+ statEntry.didUpdateCount = statEntry.didUpdateCount + (updateNeeded and 1 or 0)
+
+ -- Add time spent checking if an update is needed (in millis) to total time
+ statEntry.shouldUpdateTime = statEntry.shouldUpdateTime + shouldUpdateTime * 1000
+ end
+end
+
+--[[
+ Logs the time taken value of a Component's render function
+]]
+function Instrumentation.logRenderTime(handle, renderTime)
+ -- Grab or create associated entry in stats table
+ local statEntry = getStatEntry(handle)
+ if statEntry then
+ -- Increment total render count
+ statEntry.renderCount = statEntry.renderCount + 1
+
+ -- Add render time (in millis) to total rendering time
+ statEntry.renderTime = statEntry.renderTime + renderTime * 1000
+ end
+end
+
+--[[
+ Clears all the stats collected thus far. Useful for testing and for profiling in the future
+]]
+function Instrumentation.clearCollectedStats()
+ componentStats = {}
+end
+
+--[[
+ Returns all the stats collected thus far. Useful for testing and for profiling in the future
+]]
+function Instrumentation.getCollectedStats()
+ return componentStats
+end
+
+return Instrumentation
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Instrumentation.spec.lua b/Client2018/content/LuaPackages/RoactImpl/Instrumentation.spec.lua
new file mode 100644
index 0000000..a3af4f7
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Instrumentation.spec.lua
@@ -0,0 +1,98 @@
+return function()
+ local Component = require(script.Parent.PureComponent)
+ local GlobalConfig = require(script.Parent.GlobalConfig)
+ local Reconciler = require(script.Parent.Reconciler)
+ local createElement = require(script.Parent.createElement)
+
+ local Instrumentation = require(script.Parent.Instrumentation)
+
+ it("should count and time renders when enabled", function()
+ GlobalConfig.set({
+ ["componentInstrumentation"] = true,
+ })
+ local triggerUpdate
+
+ local TestComponent = Component:extend("TestComponent")
+ function TestComponent:init()
+ self.state = {
+ value = 0
+ }
+ end
+
+ function TestComponent:render()
+ return nil
+ end
+
+ function TestComponent:didMount()
+ triggerUpdate = function()
+ self:setState({
+ value = self.state.value + 1
+ })
+ end
+ end
+
+ local instance = Reconciler.mount(createElement(TestComponent))
+
+ local stats = Instrumentation.getCollectedStats()
+ expect(stats.TestComponent).to.be.ok()
+ expect(stats.TestComponent.renderCount).to.equal(1)
+
+ triggerUpdate()
+ expect(stats.TestComponent.renderCount).to.equal(2)
+
+ Reconciler.unmount(instance)
+ Instrumentation.clearCollectedStats()
+ GlobalConfig.reset()
+ end)
+
+ it("should count and time shouldUpdate calls when enabled", function()
+ GlobalConfig.set({
+ ["componentInstrumentation"] = true,
+ })
+ local triggerUpdate
+ local willDoUpdate = false
+
+ local TestComponent = Component:extend("TestComponent")
+
+ function TestComponent:init()
+ self.state = {
+ value = 0,
+ }
+ end
+
+ function TestComponent:shouldUpdate()
+ return willDoUpdate
+ end
+
+ function TestComponent:didMount()
+ triggerUpdate = function()
+ self:setState({
+ value = self.state.value + 1,
+ })
+ end
+ end
+
+ function TestComponent:render() end
+
+ local instance = Reconciler.mount(createElement(TestComponent))
+
+ local stats = Instrumentation.getCollectedStats()
+
+ willDoUpdate = true
+ triggerUpdate()
+
+ expect(stats.TestComponent).to.be.ok()
+ expect(stats.TestComponent.updateReqCount).to.equal(1)
+ expect(stats.TestComponent.didUpdateCount).to.equal(1)
+
+ willDoUpdate = false
+ triggerUpdate()
+
+ expect(stats.TestComponent.updateReqCount).to.equal(2)
+ expect(stats.TestComponent.didUpdateCount).to.equal(1)
+
+ Reconciler.unmount(instance)
+ Instrumentation.clearCollectedStats()
+ GlobalConfig.reset()
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/PureComponent.lua b/Client2018/content/LuaPackages/RoactImpl/PureComponent.lua
new file mode 100644
index 0000000..0283298
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/PureComponent.lua
@@ -0,0 +1,41 @@
+--[[
+ A version of Component with a `shouldUpdate` method that forces the
+ resulting component to be pure.
+]]
+
+local Component = require(script.Parent.Component)
+
+local PureComponent = Component:extend("PureComponent")
+
+-- When extend()ing a component, you don't get an extend method.
+-- This is to promote composition over inheritance.
+-- PureComponent is an exception to this rule.
+PureComponent.extend = Component.extend
+
+function PureComponent:shouldUpdate(newProps, newState)
+ -- In a vast majority of cases, if state updated, something has updated.
+ -- We don't bother checking in this case.
+ if newState ~= self.state then
+ return true
+ end
+
+ if newProps == self.props then
+ return false
+ end
+
+ for key, value in pairs(newProps) do
+ if self.props[key] ~= value then
+ return true
+ end
+ end
+
+ for key, value in pairs(self.props) do
+ if newProps[key] ~= value then
+ return true
+ end
+ end
+
+ return false
+end
+
+return PureComponent
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/PureComponent.spec.lua b/Client2018/content/LuaPackages/RoactImpl/PureComponent.spec.lua
new file mode 100644
index 0000000..b0732c7
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/PureComponent.spec.lua
@@ -0,0 +1,71 @@
+return function()
+ local createElement = require(script.Parent.createElement)
+ local Reconciler = require(script.Parent.Reconciler)
+
+ local PureComponent = require(script.Parent.PureComponent)
+
+ it("should be extendable", function()
+ local MyComponent = PureComponent:extend("MyComponent")
+
+ expect(MyComponent).to.be.ok()
+ end)
+
+ it("should skip updates for shallow-equal props", function()
+ local updateCount = 0
+ local setValue
+
+ local PureChild = PureComponent:extend("PureChild")
+
+ function PureChild:willUpdate(newProps, newState)
+ updateCount = updateCount + 1
+ end
+
+ function PureChild:render()
+ end
+
+ local PureContainer = PureComponent:extend("PureContainer")
+
+ function PureContainer:init()
+ self.state = {
+ value = 0,
+ }
+ end
+
+ function PureContainer:didMount()
+ setValue = function(value)
+ self:setState({
+ value = value,
+ })
+ end
+ end
+
+ function PureContainer:render()
+ return createElement(PureChild, {
+ value = self.state.value,
+ })
+ end
+
+ local element = createElement(PureContainer)
+ local instance = Reconciler.mount(element)
+
+ expect(updateCount).to.equal(0)
+
+ setValue(1)
+
+ expect(updateCount).to.equal(1)
+
+ setValue(1)
+
+ expect(updateCount).to.equal(1)
+
+ setValue(2)
+
+ expect(updateCount).to.equal(2)
+
+ setValue(1)
+
+ expect(updateCount).to.equal(3)
+
+ Reconciler.unmount(instance)
+ end)
+end
\ No newline at end of file
diff --git a/Client2018/content/LuaPackages/RoactImpl/Reconciler.lua b/Client2018/content/LuaPackages/RoactImpl/Reconciler.lua
new file mode 100644
index 0000000..66e50ad
--- /dev/null
+++ b/Client2018/content/LuaPackages/RoactImpl/Reconciler.lua
@@ -0,0 +1,543 @@
+--[[
+ The reconciler uses the virtual DOM generated by components to create a real
+ tree of Roblox instances.
+
+ The reonciler has three basic operations:
+ * mount (previously reify)
+ * reconcile
+ * unmount (previously teardown)
+
+ Mounting is the process of creating new components. This is first
+ triggered when the user calls `Roact.mount` on an element. This is where the
+ structure of the component tree is built, later used and modified by the
+ reconciliation and unmounting steps.
+
+ Reconciliation accepts an existing concrete instance tree (created by mount)
+ along with a new element that describes the desired tree. The reconciler
+ will do the minimum amount of work required to update tree's components to
+ match the new element, sometimes invoking mount to create new branches.
+
+ Unmounting destructs for the tree. It will crawl through the tree,
+ destroying nodes from the bottom up.
+
+ Much of the reconciler's work is done by Component, which is the base for
+ all stateful components in Roact. Components can trigger reconciliation (and
+ implicitly, unmounting) via state updates that come with their own caveats.
+]]
+
+local Core = require(script.Parent.Core)
+local Event = require(script.Parent.Event)
+local Change = require(script.Parent.Change)
+local getDefaultPropertyValue = require(script.Parent.getDefaultPropertyValue)
+local SingleEventManager = require(script.Parent.SingleEventManager)
+local Symbol = require(script.Parent.Symbol)
+
+local isInstanceHandle = Symbol.named("isInstanceHandle")
+
+local DEFAULT_SOURCE = "\n\t