diff --git a/Assets/Models/GameObjects/Projectiles/Missiles/missile.blend b/Assets/Models/GameObjects/Projectiles/Missiles/missile.blend
new file mode 100644
index 0000000..55e0a49
Binary files /dev/null and b/Assets/Models/GameObjects/Projectiles/Missiles/missile.blend differ
diff --git a/Assets/Models/GameObjects/Projectiles/Missiles/missile.xml b/Assets/Models/GameObjects/Projectiles/Missiles/missile.xml
new file mode 100644
index 0000000..154a076
--- /dev/null
+++ b/Assets/Models/GameObjects/Projectiles/Missiles/missile.xml
@@ -0,0 +1,1506 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assets/Models/GameObjects/Units/Structures/Forts/fort.xml b/Assets/Models/GameObjects/Units/Structures/Forts/fort.xml
deleted file mode 100644
index 803942c..0000000
--- a/Assets/Models/GameObjects/Units/Structures/Forts/fort.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.blend b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.blend
new file mode 100644
index 0000000..9399603
Binary files /dev/null and b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.blend differ
diff --git a/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.jpg b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.jpg
new file mode 100644
index 0000000..2df3706
Binary files /dev/null and b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.jpg differ
diff --git a/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.xml b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.xml
new file mode 100644
index 0000000..7169156
--- /dev/null
+++ b/Assets/Models/GameObjects/Units/Structures/IceSheets/iceSheet.xml
@@ -0,0 +1,550 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assets/Models/GameObjects/Units/Structures/PointDefenses/pointDefense.xml b/Assets/Models/GameObjects/Units/Structures/PointDefenses/pointDefense.xml
deleted file mode 100644
index b8828a1..0000000
--- a/Assets/Models/GameObjects/Units/Structures/PointDefenses/pointDefense.xml
+++ /dev/null
@@ -1,1564 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.blend b/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.blend
index a110d4d..26ce15a 100644
Binary files a/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.blend and b/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.blend differ
diff --git a/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.xml b/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.xml
index fd10b86..eeb64d6 100644
--- a/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.xml
+++ b/Assets/Models/GameObjects/Units/Vehicles/Artillery/artillery.xml
@@ -151,897 +151,897 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -1052,1091 +1052,1083 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.blend b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.blend
new file mode 100644
index 0000000..5d1e474
Binary files /dev/null and b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.blend differ
diff --git a/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.jpg b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.jpg
new file mode 100644
index 0000000..d431a59
Binary files /dev/null and b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.jpg differ
diff --git a/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.xml b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.xml
new file mode 100644
index 0000000..90602dd
--- /dev/null
+++ b/Assets/Models/GameObjects/Units/Vehicles/Icebreakers/icebreaker.xml
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assets/Models/Maps/water/water.lua b/Assets/Models/Maps/water/water.lua
index bd8e541..1933b3a 100644
--- a/Assets/Models/Maps/water/water.lua
+++ b/Assets/Models/Maps/water/water.lua
@@ -1,6 +1,7 @@
map = {
lights = {
-{type = 3, color = {x = 0.900000, y = 0.900000, z = 0.900000}},},
+{type = 3, color = {x = 0.900000, y = 0.900000, z = 0.900000}},
+},
numWaterBodies = 1,
size = {x = 1000.000000, y = 169.766891, z = 1000.000000},
impassibleNodeValue = 65535,
@@ -12,24 +13,27 @@ spawnPoints = {
},
players = {
{
-resourceDeposits = {
-{id = 0, pos = {x = 100.000000, y = 0.000000, z = 100.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}, initAmmount = 1000},
-{id = 0, pos = {x = -200.000000, y = 0.000000, z = 50.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}, initAmmount = 1000},
-},
+resourceDeposits = {},
units = {
-{id = 1, pos = {x = 300.000000, y = 0.000000, z = 0.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
-{id = 18, pos = {x = 300.000000, y = 0.000000, z = 100.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
+{id = 0, pos = {x = 290.000000, y = 0.000000, z = 0.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
+{id = UnitId.POINT_DEFENSE, pos = {x = 280.000000, y = 0.000000, z = 50.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}, buildStatus = 100},
}
,},
{
resourceDeposits = {},
spawnPoint = 0,
units = {
-{id = 0, pos = {x = 300.000000, y = 0.000000, z = 450.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
-{id = 1, pos = {x = -300.000000, y = 0.000000, z = -450.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
-{id = 13, pos = {x = 0.000000, y = 0.000000, z = 0.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
+{id = UnitId.ENGINEER, pos = {x = 300.000000, y = 0.000000, z = 450.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
+{id = UnitId.ENGINEER, pos = {x = -300.000000, y = 0.000000, z = -450.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}},
+}
+,},
+{
+ resourceDeposits = {
+ {id = 0, pos = {x = 100.000000, y = 0.000000, z = 100.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}, initAmmount = 1000},
+ {id = 0, pos = {x = -200.000000, y = 0.000000, z = 50.000000}, rot = {w = 1.000000, x = 0.000000, y = 0.000000, z = 0.000000}, initAmmount = 1000},
+ },
+ units = {}
}
-,}
},
numCells = 37306,
cells = {
diff --git a/Assets/Scripts/GameObjects/Projectiles/projectileData.lua b/Assets/Scripts/GameObjects/Projectiles/projectileData.lua
index 8e4f2f0..05db300 100644
--- a/Assets/Scripts/GameObjects/Projectiles/projectileData.lua
+++ b/Assets/Scripts/GameObjects/Projectiles/projectileData.lua
@@ -1,13 +1,60 @@
-ProjectileId = {CRUISE_MISSILE = 0, TORPEDO = 1}
-ProjectileClass = {CRUISE_MISSILE = 0, TORPEDO = 1}
+ProjectileId = {HE_SHELL = 0, EMP_SHELL = 1, CRUISE_MISSILE = 2, MISSILE = 3, TORPEDO = 4}
+ProjectileClass = {SHELL = 0, CRUISE_MISSILE = 1, MISSILE = 2, TORPEDO = 3}
+G = 9.8
+
+explosionVfx = {
+ vfx = true,
+ duration = 50,
+ offset = 0,
+ mesh = {
+ numParticles = 1,
+ texture = PATH .. 'Textures/Explosion/explosion07.png',
+ lowLife = 3,
+ highLife = 3,
+ size = {x = 10, y = 10},
+ }
+}
+explosionSfx = {
+ vfx = false,
+ offset = 100,
+ path = PATH .. 'Sounds/SFX/Explosions/explosion02.ogg',
+ duration = 2500
+}
+Detonation = {EXPLOSION = 0, EMP = 1, CRYO = 2}
projectiles = {
+ {
+ projectileClass = ProjectileClass.SHELL,
+ size = {x = 1, y = 1, z = 1},
+ speed = 5,
+ rotAngle = .1,
+ explosion = {detonation = Detonation.EXPLOSION, damage = 100, radius = 20, fx = {explosionVfx, explosionSfx}},
+ directHitDamage = 200,
+ rayLength = 1,
+ name = "Shell",
+ basePath = PATH .. "Models/GameObjects/Projectiles/Shells/",
+ meshPath = "shell.xml",
+ albedoPath = 'shell.jpg'
+ },
+ {
+ projectileClass = ProjectileClass.SHELL,
+ size = {x = 1, y = 1, z = 1},
+ speed = 5,
+ rotAngle = .1,
+ explosion = {detonation = Detonation.EMP, damage = 0, radius = 20, fx = {explosionVfx, explosionSfx}},
+ directHitDamage = 0,
+ rayLength = 1,
+ name = "Shell",
+ basePath = PATH .. "Models/GameObjects/Projectiles/Shells/",
+ meshPath = "shell.xml",
+ albedoPath = 'shell.jpg'
+ },
{
projectileClass = ProjectileClass.CRUISE_MISSILE,
size = {x = 6, y = 13.5, z = 2.54},
speed = .5,
rotAngle = .1,
- explosion = {damage = 100, radius = 20, sfx = PATH .. 'Sounds/SFX/Explosions/explosion02.ogg'},
+ explosion = {detonation = Detonation.EXPLOSION, damage = 100, radius = 20, fx = {explosionVfx, explosionSfx}},
directHitDamage = 450,
rayLength = 6,
name = "Cruise missile",
@@ -15,11 +62,24 @@ projectiles = {
meshPath = "cruiseMissile.xml",
albedoPath = 'cruiseMissile.jpg'
},
+ {
+ projectileClass = ProjectileClass.MISSILE,
+ size = {x = 3, y = 7., z = 1.27},
+ speed = .5,
+ rotAngle = .1,
+ explosion = {detonation = Detonation.EXPLOSION, damage = 70, radius = 12, fx = {explosionVfx, explosionSfx}},
+ directHitDamage = 250,
+ rayLength = 3,
+ name = "Missile",
+ basePath = PATH .. "Models/GameObjects/Projectiles/Missiles/",
+ meshPath = "missile.xml",
+ albedoPath = 'cruiseMissile.jpg'
+ },
{
projectileClass = ProjectileClass.TORPEDO,
size = {x = 1, y = 6, z = 1},
speed = .06,
- explosion = {damage = 20, radius = 3, sfx = PATH .. 'Sounds/Units/Submarines/torpedo.ogg'},
+ explosion = {detonation = Detonation.EXPLOSION, damage = 20, radius = 3, fx = {explosionVfx, explosionSfx}},
directHitDamage = 450,
rayLength = 3.5,
name = "Torpedo",
diff --git a/Assets/Scripts/GameObjects/Units/unitData.lua b/Assets/Scripts/GameObjects/Units/unitData.lua
index fe09445..cece203 100644
--- a/Assets/Scripts/GameObjects/Units/unitData.lua
+++ b/Assets/Scripts/GameObjects/Units/unitData.lua
@@ -10,7 +10,8 @@ OrderType = {
SUPPLY = 7,
LOAD = 8,
UNLOAD = 9,
- HACK = 10
+ HACK = 10,
+ FREEZE = 11
}
UnitId = {
WAR_MECH = 0,
@@ -28,16 +29,20 @@ UnitId = {
CHAMPION_CARRIER = 12,
MISSILE_SUBMARINE = 13,
STEALTH_SUBMARINE = 14,
- LAND_FACTORY = 15,
- NAVAL_FACTORY = 16,
- TRADE_CENTER = 17,
- LAB = 18,
- POINT_DEFENSE = 19,
- EXTRACTOR = 20,
- REFINERY = 21,
- FORT = 22
+ ICEBREAKER = 15,
+ FREEZER = 16,
+ EMP_BOAT = 17,
+ LAND_FACTORY = 18,
+ NAVAL_FACTORY = 19,
+ TRADE_CENTER = 20,
+ LAB = 21,
+ POINT_DEFENSE = 22,
+ EXTRACTOR = 23,
+ REFINERY = 24,
+ FORT = 25,
+ ICE_SHEET = 26
}
-WeaponClass = {HITSCAN = 0, SHELL = 1, TORPEDO = 2, CRUISE_MISSILE = 3, HACK = 4}
+WeaponClass = {FREEZE = 1}
UnitClass = {
WAR_MECH = 0,
TANK = 1,
@@ -48,14 +53,18 @@ UnitClass = {
CRUISER = 6,
CARRIER = 7,
SUBMARINE = 8,
- LAND_FACTORY = 9,
- NAVAL_FACTORY = 10,
- TRADE_CENTER = 11,
- LAB = 12,
- POINT_DEFENSE = 13,
- EXTRACTOR = 14,
- REFINERY = 15,
- FORT = 16
+ ICEBREAKER = 9,
+ FREEZER = 10,
+ EMP_BOAT = 11,
+ LAND_FACTORY = 12,
+ NAVAL_FACTORY = 13,
+ TRADE_CENTER = 14,
+ LAB = 15,
+ POINT_DEFENSE = 16,
+ EXTRACTOR = 17,
+ REFINERY = 18,
+ FORT = 19,
+ ICE_SHEET = 20
}
UnitType = {UNDERWATER = 0, SEA_LEVEL = 1, HOVER = 2, LAND = 3, AIR = 4}
@@ -84,14 +93,13 @@ explosionSfx = {
duration = 2500
}
-
units = {
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 100,
- maxRange = 10,
+ maxRange = 14,
damage = 50,
fireFx = {
{
@@ -143,28 +151,35 @@ units = {
cost = 500,
size = {x = 6, y = 9.22, z = 2.42},
hitboxOffset = {x = 0, y = 4.5, z = 0},
- lineOfSight = 250,
+ lineOfSight = 25,
name = 'War mech',
basePath = PATH .. vehiclePrefix .. 'WarMechs/',
meshPath = 'warMech.xml',
albedoPath = 'mech.jpg',
colorNodes = {'WarRobotTemplate.001'},
selectionSfx = PATH .. 'Sounds/Units/WarMechs/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .3,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 1
+ garrisonCategory = 1,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 1000,
damage = 200,
maxRange = 25,
+ horizontalNode = {name = 'Turret', rotationSpeed = .05, maxFireAngle = .1},
+ projectile = {id = ProjectileId.HE_SHELL, parent = 'Turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = 1, x = 0, y = 0, z = 0}},
fireFx = {
+ {
+ vfx = false,
+ duration = 300,
+ path = PATH .. 'Sounds/Units/Tanks/attack.ogg',
+ },
{
vfx = true,
duration = 50,
@@ -172,19 +187,14 @@ units = {
path = PATH .. vfxPrefix .. 'muzzleFlash.xml',
color = {x = 1, y = 1, z = 0, a = 1},
},
- parent = 'Turret',
+ parent = 'CannonBarrel',
pos = {x = 0.06, y = 5.82, z = 11.4},
rot = {w = 1, x = 0, y = 0, z = 0},
--scale = .5
- },
- {
- vfx = false,
- duration = 300,
- path = PATH .. 'Sounds/Units/Tanks/attack.ogg',
}
},
- landHitFx = {explosionVfx, explosionSfx},
- unitHitFx = {explosionVfx, explosionSfx}
+ --landHitFx = {explosionVfx, explosionSfx},
+ --unitHitFx = {explosionVfx, explosionSfx}
}
},
unitClass = UnitClass.TANK,
@@ -203,40 +213,42 @@ units = {
albedoPath = 'tank.jpg',
colorNodes = {'Antenna_S', 'Antenna_L', 'Hatch'},
selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 2
+ garrisonCategory = 2,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 2000,
damage = 5000,
- maxRange = 30,
+ maxRange = 70,
+ horizontalNode = {name = 'turret', rotationSpeed = .05, maxFireAngle = .1},
+ verticalNode = {name = 'tubes', rotationSpeed = .05, maxFireAngle = .1},
+ projectile = {id = ProjectileId.MISSILE, parent = 'tubes', pos = {x = 0.95, y = 2.16, z = 4.11}, rot = {w = 1, x = 0, y = 0, z = 0}},
fireFx = {
{
vfx = true,
duration = 50,
+ parent = 'tubes',
+ pos = {x = 0.95, y = 2.16, z = 4.11},
+ rot = {w = 1, x = 0, y = 0, z = 0},
mesh = {
path = PATH .. vfxPrefix .. 'muzzleFlash.xml',
color = {x = 1, y = 1, z = 0, a = 1},
},
- pos = {x = 1, y = 5.8, z = 3.9},
- rot = {w = 1, x = 0, y = 0, z = 0},
--scale = .5
},
{
vfx = false,
- duration = 300,
- path = PATH .. 'Sounds/Units/Tanks/attack.ogg',
+ duration = 2500,
+ path = PATH .. 'Sounds/Units/Submarines/missile.ogg',
}
},
- landHitFx = {explosionVfx, explosionSfx},
- unitHitFx = {explosionVfx, explosionSfx}
}
},
unitClass = UnitClass.ARTILLERY,
@@ -255,17 +267,14 @@ units = {
albedoPath = 'artillery.jpg',
colorNodes = {'turret'},
selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 2
+ garrisonCategory = 2,
+ deathFx = {explosionVfx, explosionSfx},
},
{
- weapons = {
- {type = WeaponClass.HITSCAN, rateOfFire = 2000, fireSfx = PATH .. 'Sounds/Units/WarMechs/fire.ogg', damage = 20, maxRange = 8},
- },
buildableUnits = {
{id = UnitId.LAND_FACTORY, buildable = true, trigger = 76},
{id = UnitId.NAVAL_FACTORY, buildable = true, trigger = 78},
@@ -295,15 +304,15 @@ units = {
colorNodes = {'Cube.008'},
meshPath = 'engineer2.xml',
selectionSfx = PATH .. 'Sounds/Units/Engineers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
- weapons = {{type = WeaponClass.HITSCAN, rateOfFire = 2000, fireSfx = PATH .. 'Sounds/Units/WarMechs/fire.ogg', damage = 50, maxRange = 20}},
+ weapons = {{orderType = OrderType.ATTACK, rateOfFire = 2000, fireSfx = PATH .. 'Sounds/Units/WarMechs/fire.ogg', damage = 50, maxRange = 20}},
unitClass = UnitClass.TRANSPORT,
unitType = UnitType.HOVER,
isVehicle = true,
@@ -320,15 +329,15 @@ units = {
basePath = PATH .. vehiclePrefix .. 'Transports/',
meshPath = 'scoutTransport.xml',
selectionSfx = PATH .. 'Sounds/Units/Transports/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
- weapons = {{type = WeaponClass.HITSCAN, rateOfFire = 2000, fireSfx = PATH .. 'Sounds/Units/Tanks/attack.ogg', damage = 100, maxRange = 25}},
+ weapons = {{orderType = OrderType.ATTACK, rateOfFire = 2000, fireSfx = PATH .. 'Sounds/Units/Tanks/attack.ogg', damage = 100, maxRange = 25}},
unitClass = UnitClass.TRANSPORT,
unitType = UnitType.HOVER,
armor = {ArmorType.MECHANIC},
@@ -346,12 +355,12 @@ units = {
meshPath = 'hoverTransport.xml',
albedoPath = 'transport.jpg',
selectionSfx = PATH .. 'Sounds/Units/Transports/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {},
@@ -379,20 +388,20 @@ units = {
meshPath = 'cargoship.xml',
albedoPath = 'cargoship.jpg',
selectionSfx = PATH .. 'Sounds/Units/Cargoships/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 200,
- damage = 300,
- maxRange = 15,
+ damage = 10,
+ maxRange = 50,
fireFx = {
{
vfx = true,
@@ -430,17 +439,17 @@ units = {
meshPath = 'tacticalCruiser.xml',
albedoPath = 'cruiser.jpg',
selectionSfx = PATH .. 'Sounds/Units/Cruisers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 200,
fireFx = {
{
@@ -481,17 +490,17 @@ units = {
meshPath = 'defensiveCruiser.xml',
albedoPath = 'cruiser.jpg',
selectionSfx = PATH .. 'Sounds/Units/Cruisers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 200,
damage = 300,
maxRange = 15,
@@ -531,17 +540,17 @@ units = {
meshPath = 'cheapCruiser.xml',
albedoPath = 'cruiser.jpg',
selectionSfx = PATH .. 'Sounds/Units/Cruisers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 200,
fireSfx = PATH .. 'Sounds/Units/Cruisers/fire.ogg',
damage = 300,
@@ -582,17 +591,17 @@ units = {
meshPath = 'transportCruiser.xml',
albedoPath = 'cruiser.jpg',
selectionSfx = PATH .. 'Sounds/Units/Cruisers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 100,
damage = 80,
maxRange = 100,
@@ -631,17 +640,17 @@ units = {
meshPath = 'heavyCarrier.xml',
albedoPath = 'carrier.jpg',
selectionSfx = PATH .. 'Sounds/Units/Carriers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 450,
damage = 500,
maxRange = 100,
@@ -667,7 +676,7 @@ units = {
waterHitFx = {explosionVfx, explosionSfx}
},
{
- type = WeaponClass.CRUISE_MISSILE,
+ orderType = OrderType.LAUNCH,
projectile = {id = ProjectileId.CRUISE_MISSILE, pos = {x = 0, y = 15, z = 0}, rot = {w = .707, x = -.707, y = 0, z = 0}},
rateOfFire = 500,
maxRange = 30,
@@ -695,17 +704,17 @@ units = {
meshPath = 'championCarrier.xml',
albedoPath = 'carrier.jpg',
selectionSfx = PATH .. 'Sounds/Units/Carriers/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.TORPEDO,
+ orderType = OrderType.ATTACK,
rateOfFire = 1000,
fireFx = {
{
@@ -719,7 +728,7 @@ units = {
projectile = {id = ProjectileId.TORPEDO, pos = {x = 0, y = -.27, z = 4.6}, rot = {w = 1, x = 0, y = 0, z = 0}}
},
{
- type = WeaponClass.CRUISE_MISSILE,
+ orderType = OrderType.LAUNCH,
rateOfFire = 500,
maxRange = 30,
fireFx = {
@@ -747,17 +756,17 @@ units = {
albedoPath = 'submarine.jpg',
colorNodes = {'missileSubmarine.001'},
selectionSfx = PATH .. 'Sounds/Units/Submarines/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.TORPEDO,
+ orderType = OrderType.ATTACK,
projectile = {id = ProjectileId.TORPEDO, pos = {x = 0, y = -.27, z = 4.6}, rot = {w = 1, x = 0, y = 0, z = 0}},
damage = 200,
maxRange = 20,
@@ -786,12 +795,118 @@ units = {
meshPath = 'stealthSubmarine.xml',
albedoPath = 'submarine.jpg',
selectionSfx = PATH .. 'Sounds/Units/Submarines/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
speed = .1,
destinationOffset = .1,
anglePrecision = .1,
maxTurnAngle = .1,
- garrisonCategory = 3
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
+ },
+ {
+ unitClass = UnitClass.ICEBREAKER,
+ unitType = UnitType.SEA_LEVEL,
+ isVehicle = true,
+ health = 500,
+ buildTime = 1000,
+ cost = 500,
+ size = {x = 12.6, y = 8.5, z = 32.8},
+ hitboxOffset = {x = 0, y = 2.07, z = .8},
+ lineOfSight = 25,
+ name = 'Icebreaker',
+ --colorNodes = {'stealthSubmarine.001'},
+ basePath = PATH .. vehiclePrefix .. 'Icebreakers/',
+ meshPath = 'icebreaker.xml',
+ albedoPath = 'icebreaker.jpg',
+ selectionSfx = PATH .. 'Sounds/Units/Submarines/selection.ogg',
+ speed = .1,
+ destinationOffset = .1,
+ anglePrecision = .1,
+ maxTurnAngle = .1,
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
+ },
+ {
+ weapons = {
+ {
+ type = WeaponClass.FREEZE,
+ orderType = OrderType.ATTACK,
+ rateOfFire = 100,
+ maxRange = 10,
+ damage = 0,
+ fireFx = {
+ {
+ vfx = false,
+ duration = 500,
+ path = PATH .. 'Sounds/SFX/Freezing/freeze.ogg'
+ },
+ },
+ unitHitFx = {},
+ landHitFx = {},
+ waterHitFx = {},
+ }
+ },
+ buildableUnits = {{id = UnitId.ICE_SHEET, buildable = true, trigger = 83}},
+ unitClass = UnitClass.FREEZER,
+ unitType = UnitType.SEA_LEVEL,
+ isVehicle = true,
+ health = 500,
+ buildTime = 1000,
+ cost = 500,
+ size = {x = 8.5, y = 6.3, z = 17.6},
+ hitboxOffset = {x = 0, y = 1.6, z = 0},
+ lineOfSight = 25,
+ name = 'Freezer',
+ --colorNodes = {'stealthSubmarine.001'},
+ basePath = PATH .. vehiclePrefix .. 'Freezers/',
+ meshPath = 'freezer.xml',
+ albedoPath = 'freezer.jpg',
+ selectionSfx = PATH .. 'Sounds/Units/Submarines/selection.ogg',
+ speed = .1,
+ destinationOffset = .1,
+ anglePrecision = .1,
+ maxTurnAngle = .1,
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
+ },
+ {
+ weapons = {
+ {
+ orderType = OrderType.ATTACK,
+ rateOfFire = 1000,
+ damage = 0,
+ maxRange = 25,
+ horizontalNode = {name = 'turret', rotationSpeed = .05, maxFireAngle = .1},
+ projectile = {id = ProjectileId.EMP_SHELL, parent = 'turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = .998, x = -.066, y = 0, z = 0}},
+ fireFx = {
+ {
+ vfx = false,
+ duration = 300,
+ path = PATH .. 'Sounds/Units/Tanks/attack.ogg',
+ },
+ },
+ }
+ },
+ unitClass = UnitClass.EMP_BOAT,
+ unitType = UnitType.SEA_LEVEL,
+ isVehicle = true,
+ health = 500,
+ buildTime = 1000,
+ cost = 500,
+ size = {x = 4.75, y = 5.15, z = 19.55},
+ hitboxOffset = {x = 0, y = .18, z = .25},
+ lineOfSight = 25,
+ name = 'EMP boat',
+ --colorNodes = {'stealthSubmarine.001'},
+ basePath = PATH .. vehiclePrefix .. 'EMPShips/',
+ meshPath = 'empShip.xml',
+ albedoPath = 'empShip.jpg',
+ selectionSfx = PATH .. 'Sounds/Units/Submarines/selection.ogg',
+ speed = .1,
+ destinationOffset = .1,
+ anglePrecision = .1,
+ maxTurnAngle = .1,
+ garrisonCategory = 3,
+ deathFx = {explosionVfx, explosionSfx},
},
{
buildableUnits = {
@@ -815,7 +930,7 @@ units = {
basePath = PATH .. structurePrefix .. 'LandFactories/',
meshPath = 'landFactory.xml',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
unitClass = UnitClass.NAVAL_FACTORY,
@@ -832,7 +947,7 @@ units = {
meshPath = 'navalFactory.xml',
albedoPath = 'factory.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
unitClass = UnitClass.TRADE_CENTER,
@@ -856,7 +971,7 @@ units = {
meshPath = 'tradeCenter.xml',
albedoPath = 'tradeCenter.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
unitClass = UnitClass.LAB,
@@ -878,15 +993,17 @@ units = {
meshPath = 'lab2.xml',
albedoPath = 'lab.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
weapons = {
{
- type = WeaponClass.HITSCAN,
+ orderType = OrderType.ATTACK,
rateOfFire = 100,
damage = 50,
maxRange = 50,
+ horizontalNode = {name = 'TurretBody', rotationSpeed = .05, maxFireAngle = .1},
+ --verticalNode = {name = 'TurretArms', rotationSpeed = .05, maxFireAngle = .1},
fireFx = {
{
vfx = true,
@@ -937,7 +1054,7 @@ units = {
meshPath = 'pointDefense2.xml',
albedoPath = 'pointDefense.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
unitClass = UnitClass.EXTRACTOR,
@@ -957,7 +1074,7 @@ units = {
meshPath = 'extractor.xml',
albedoPath = 'extractor.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
unitClass = UnitClass.REFINERY,
@@ -975,7 +1092,7 @@ units = {
meshPath = 'refinery.xml',
albedoPath = 'refinery.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
{
buildableUnits = {{id = UnitId.ENGINEER, buildable = true, trigger = 69}},
@@ -994,6 +1111,21 @@ units = {
colorNodes = {'Cube.004'},
albedoPath = 'fort.jpg',
selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
- deathSfx = PATH .. 'Sounds/SFX/Explosions/explosion01.ogg',
+ deathFx = {explosionVfx, explosionSfx},
+ },
+ {
+ unitClass = UnitClass.ICE_SHEET,
+ unitType = UnitType.SEA_LEVEL,
+ isVehicle = false,
+ health = 1000,
+ size = {x = 7, y = 1.5, z = 7},
+ hitboxOffset = {x = 0, y = 0, z = 0},
+ lineOfSight = 5,
+ name = 'Ice sheet',
+ basePath = PATH .. structurePrefix .. 'IceSheets/',
+ meshPath = 'iceSheet.xml',
+ albedoPath = 'iceSheet.jpg',
+ selectionSfx = PATH .. 'Sounds/Units/Sample/selection.ogg',
+ deathFx = {explosionVfx, explosionSfx},
},
}
diff --git a/Assets/Scripts/Gui/unitGui.lua b/Assets/Scripts/Gui/unitGui.lua
index deb6fbf..c230648 100644
--- a/Assets/Scripts/Gui/unitGui.lua
+++ b/Assets/Scripts/Gui/unitGui.lua
@@ -82,12 +82,17 @@ function generateGui(unitId)
mainUnit.unitClass == UnitClass.FORT
)
+ isEng = (
+ mainUnit.unitClass == UnitClass.ENGINEER or
+ mainUnit.unitClass == UnitClass.FREEZER
+ )
+
buttonData = {
trigger = buildUnit.trigger,
name = units[buildUnit.id + 1].name,
buttonType = (mainUnit.isVehicle and ButtonType.BUILD or ButtonType.TRAIN),
factoryId = (isFactory and unitId or nil),
- engineerId = (mainUnit.unitClass == UnitClass.ENGINEER and unitId or nil),
+ engineerId = (isEng and unitId or nil),
slotId = (ButtonType.BUILD and i - 1 or nil)
}
gui[#gui + 1] = generateButton(#gui, buttonData)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f8c479b..49156cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.9)
+cmake_minimum_required(VERSION 3.5)
set(GAME_NAME battleship)
project(${GAME_NAME})
@@ -10,31 +10,35 @@ else()
endif()
set(CMAKE_CXX_STANDART 17)
+set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
set(CMAKE_BUILD_TYPE Debug)
set(BUILD_TESTS ON)
set(BUILD_SHARED_LIBS OFF CACHE BOOL FORCED)
cmake_policy(SET CMP0015 NEW)
+set(STATES activeGameState.cpp inGameAppState.cpp guiAppState.cpp mapEditorAppState.cpp loadingAppState.cpp)
+
set(UNIT_BUTTONS unitButton.cpp tradeButton.cpp buildButton.cpp trainButton.cpp researchButton.cpp orderButton.cpp stateToggleButton.cpp)
set(OPTIONS_BUTTONS optionsButton.cpp tabButton.cpp okButton.cpp defaultsButton.cpp)
set(TRADING_BUTTONS activeStateBackButton.cpp playerTradeButton.cpp tradingScreenButton.cpp offerButton.cpp resourceAmmountButton.cpp)
set(MENU_BUTTONS mainMenuButton.cpp singlePlayerButton.cpp exitButton.cpp backButton.cpp playButton.cpp)
set(MAP_EDITOR_BUTTONS mapEditorButton.cpp newMapButton.cpp loadMapButton.cpp exportButton.cpp)
set(BUTTONS statsButton.cpp activeStateButton.cpp minimapButton.cpp ${TRADING_BUTTONS} ${OPTIONS_BUTTONS} ${MENU_BUTTONS} ${MAP_EDITOR_BUTTONS} ${UNIT_BUTTONS})
-
set(LISTBOXES skyboxTextureListbox.cpp landTextureListbox.cpp gameObjectListbox.cpp mapListbox.cpp)
set(GUI tooltip.cpp concreteGuiManager.cpp ${BUTTONS} ${LISTBOXES})
-set(STATES activeGameState.cpp inGameAppState.cpp guiAppState.cpp mapEditorAppState.cpp loadingAppState.cpp)
-set(UTIL util.cpp binds.h)
set(CONTROLLERS gameObjectFrameController.cpp cameraController.cpp)
set(CONSOLE console.cpp abstractCommand.cpp addUnitCommand.cpp addResourceCommand.cpp addTechnologyCommand.cpp toggleDebugCommand.cpp)
-set(CORE gameManager.cpp game.cpp fxManager.cpp defConfigs.cpp ${CONSOLE} ${CONTROLLERS})
-set(PROJECTILES projectile.cpp cruiseMissile.cpp)
-set(VEHICLES vehicle.cpp engineer.cpp resourceRover.cpp)
-set(STRUCTURES structure.cpp factory.cpp pointDefense.cpp extractor.cpp researchStruct.cpp)
-set(UNITS gameObjectFactory.cpp unit.cpp ${STRUCTURES} ${VEHICLES})
+set(CORE gameManager.cpp game.cpp environment.cpp fxManager.cpp defConfigs.cpp ${CONSOLE} ${CONTROLLERS})
+
+set(PROJECTILES projectile.cpp missile.cpp cruiseMissile.cpp shell.cpp)
+set(VEHICLES vehicle.cpp submarine.cpp engineer.cpp resourceRover.cpp freezer.cpp)
+set(STRUCTURES structure.cpp factory.cpp pointDefense.cpp extractor.cpp researchStruct.cpp iceSheet.cpp)
+set(UNITS gameObjectFactory.cpp unit.cpp weapon.cpp ${STRUCTURES} ${VEHICLES})
set(CONTENT player.cpp trader.cpp pathfinder.cpp map.cpp gameObject.cpp gameObjectFrame.h resourceDeposit.cpp ${UNITS} ${PROJECTILES})
+
+set(UTIL util.cpp binds.h)
+
set(GAME_SRC ${STATES} ${GUI} ${CORE} ${CONTENT} ${UTIL})
set(SFML_DIR external/SFML)
diff --git a/activeGameState.cpp b/activeGameState.cpp
index 397a4e0..b6553c7 100755
--- a/activeGameState.cpp
+++ b/activeGameState.cpp
@@ -238,7 +238,7 @@ namespace battleship{
}
else if(cursorState == CursorState::HACK)
orderPossible = (!ownGameObj && gameObjUnit && mainPlayer->getSelectedUnit(0)->getUnitClass() == UnitClass::ENGINEER);
- else if(gameObjUnit)
+ else if(controlPressed)
cursorState = CursorState::ATTACK;
else
cursorState = CursorState::NORMAL;
@@ -337,7 +337,7 @@ namespace battleship{
void ActiveGameState::updateGameObjHoveredOn(){
vector gameObjs;
- vector players = Game::getSingleton()->getPlayers();
+ vector players = Game::getSingleton()->getPlayers(true);
for(Player *pl : players){
vector resDeps = pl->getResourceDeposits();
@@ -482,7 +482,7 @@ namespace battleship{
vector units;
- for (Player *p : Game::getSingleton()->getPlayers())
+ for (Player *p : Game::getSingleton()->getPlayers(true))
for (Unit *u : p->getUnits())
units.push_back(u);
@@ -703,7 +703,7 @@ namespace battleship{
else if(cursorState == CursorState::HACK){
if(orderPossible) issueOrder(Order::TYPE::HACK, vector{Order::Target((Unit*)gameObjHoveredOn)}, shiftPressed);
}
- else if(selectedUnits[0]->getUnitClass() == UnitClass::ENGINEER && ufCtr->isPlacingOnSurface()){
+ else if((selectedUnits[0]->getUnitClass() == UnitClass::ENGINEER || selectedUnits[0]->getUnitClass() == UnitClass::FREEZER) && ufCtr->isPlacingOnSurface()){
castRayToTerrain();
GameObjectFrame gmObjFr = ufCtr->getGameObjectFrame(0);
@@ -717,7 +717,7 @@ namespace battleship{
buildableStructSelected = false;
}
- else if(!canSelectHoveredOnGameObj()){
+ else{
if(targets.empty()) castRayToTerrain();
issueOrder(Order::TYPE::MOVE, targets, shiftPressed);
@@ -788,6 +788,7 @@ namespace battleship{
forceCursorState = isPressed;
controlPressed = isPressed;
+ orderPossible = isPressed;
break;
case Bind::LEFT_SHIFT:
{
diff --git a/cruiseMissile.cpp b/cruiseMissile.cpp
index e4014b0..5034db8 100644
--- a/cruiseMissile.cpp
+++ b/cruiseMissile.cpp
@@ -12,7 +12,7 @@ namespace battleship{
using namespace std;
using namespace vb01;
- CruiseMissile::CruiseMissile(Unit *unit, Vector3 tp, Vector3 pos, Quaternion rot) : Projectile(unit, 0, pos, rot), targetPoint(tp), flightStage(FlightStage::ASCENT){
+ CruiseMissile::CruiseMissile(Unit *unit, int id, Vector3 tp, Vector3 pos, Quaternion rot) : Projectile(unit, id, pos, rot), targetPoint(tp), flightStage(FlightStage::ASCENT){
Vector3 unitDir = unit->getDirVec();
Vector3 leftDir = unit->getLeftVec();
Vector3 targDir = (Vector3(targetPoint.x, pos.y, targetPoint.z) - pos).norm();
@@ -29,7 +29,7 @@ namespace battleship{
if(flightStage == FlightStage::ASCENT && pos.y - initPos.y > minHeight){
orientAt(Quaternion(angle, leftVec) * rot);
- if(dirVec.y <= 0) flightStage = FlightStage::CRUISE;
+ if(dirVec.y <= .001) flightStage = FlightStage::CRUISE;
}
else if(flightStage == FlightStage::DESCENT){
Vector3 targDir = (Vector3(targetPoint.x, initPos.y, targetPoint.z) - initPos).norm();
@@ -47,19 +47,8 @@ namespace battleship{
flightStage = FlightStage::DESCENT;
}
- void CruiseMissile::checkSurfaceCollision(){
- Map *map = Map::getSingleton();
- int cellId = map->getCellId(pos, false);
-
- if((pos + dirVec * rayLength).y <= map->getCells()[cellId].pos.y){
- Game::getSingleton()->explode(pos, explosionDamage, explosionRadius, explosionSfx);
- remove = true;
- }
- }
-
void CruiseMissile::update(){
- GameObject::update();
- placeAt(pos + dirVec * speed);
+ Projectile::update();
switch(flightStage){
case FlightStage::ASCENT:
@@ -73,10 +62,11 @@ namespace battleship{
break;
}
- if(!remove && flightStage == FlightStage::DESCENT){
- checkSurfaceCollision();
- if(remove) return;
- checkUnitCollision();
- }
+ checkCollision();
+ }
+
+ void CruiseMissile::checkCollision(){
+ if(flightStage == FlightStage::DESCENT)
+ Projectile::checkCollision();
}
}
diff --git a/cruiseMissile.h b/cruiseMissile.h
index b7b84d9..19101ab 100644
--- a/cruiseMissile.h
+++ b/cruiseMissile.h
@@ -6,7 +6,7 @@
namespace battleship{
class CruiseMissile : public Projectile{
public:
- CruiseMissile(Unit*, vb01::Vector3, vb01::Vector3, vb01::Quaternion);
+ CruiseMissile(Unit*, int, vb01::Vector3, vb01::Vector3, vb01::Quaternion);
void update();
private:
enum class FlightStage{ASCENT, CRUISE, DESCENT};
@@ -15,7 +15,7 @@ namespace battleship{
void pitch(float, vb01::Vector3);
void cruise();
- void checkSurfaceCollision();
+ void checkCollision();
};
}
diff --git a/engineer.cpp b/engineer.cpp
index 8d54681..f509ba9 100644
--- a/engineer.cpp
+++ b/engineer.cpp
@@ -50,40 +50,12 @@ namespace battleship{
hackStatus = 0;
}
- void Engineer::build(Order order){
- if(pathPoints.empty()){
- if(!order.targets[0].unit)
- player->addUnit(order.targets[0].unit);
- else {
- Structure *structure = (Structure*)order.targets[0].unit;
- sol::table targTable = generateView()["units"][order.targets[0].unit->getId()];
- int costRate = (int)targTable["cost"] / 100, buildRate = (int)targTable["buildTime"] / 100;
-
- if(structure->getBuildStatus() < 100 && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastIncrementTime > buildRate){
- structure->incrementBuildStatus();
- player->updateResource(ResourceType::REFINEDS, -costRate, true);
- lastIncrementTime = getTime();
- }
- else if(structure->getBuildStatus() >= 100){
- removeOrder(0);
- player->incStructuresBuilt();
- }
- }
- }
- else{
- navigate(0.5 * Map::getSingleton()->getCellSize().x);
-
- if(type == UnitType::LAND)
- alignToSurface();
- }
- }
-
//TODO change unit colors after faction change
void Engineer::hack(Order order){
Unit *targUnit = order.targets[0].unit;
bool withinRange = (targUnit->getPos().getDistanceFrom(pos) < hackRange);
int hackRate = int(generateView()["units"][id + 1]["hackTime"]) / 100;
- bool canHack = (getTime() - lastIncrementTime > hackRate);
+ bool canHack = (getTime() - lastHackTime > hackRate);
if(withinRange && canHack){
hackStatus++;
diff --git a/engineer.h b/engineer.h
index f038591..efa71b5 100644
--- a/engineer.h
+++ b/engineer.h
@@ -20,10 +20,9 @@ namespace battleship{
private:
int hackStatus = 0;
float hackRange;
- vb01::s64 lastIncrementTime = 0;
+ vb01::s64 lastHackTime = 0;
vb01::Node *hackStatusBackground = nullptr, *hackStatusForeground = nullptr;
- void build(Order);
void hack(Order);
};
}
diff --git a/environment.cpp b/environment.cpp
new file mode 100644
index 0000000..57971f2
--- /dev/null
+++ b/environment.cpp
@@ -0,0 +1,49 @@
+#include "environment.h"
+#include "fxManager.h"
+#include "player.h"
+#include "unit.h"
+#include "game.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace battleship{
+ using namespace std;
+ using namespace vb01;
+
+ static Environment *environment = nullptr;
+
+ Environment* Environment::getSingleton(){
+ if(!environment)
+ environment = new Environment();
+
+ return environment;
+ }
+
+ //TODO use the pos argument from the fx
+ void Environment::explode(FxManager::Fx *fx, Detonation det, Vector3 pos, int damage, float radius){
+ FxManager::getSingleton()->addFx(fx);
+
+ if(radius == 0) return;
+
+ for(Player *pl : Game::getSingleton()->getPlayers()){
+ for(Unit *un : pl->getUnits()){
+ float distance = un->getPos().getDistanceFrom(pos);
+
+ if(distance < radius){
+ switch(det){
+ case Detonation::EXPLOSION:
+ un->takeDamage(int(damage * (1.f - distance / radius)));
+ break;
+ case Detonation::EMP:
+ un->setCondition(Unit::Condition::EM_JAMMED);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/environment.h b/environment.h
new file mode 100644
index 0000000..8e3bcaf
--- /dev/null
+++ b/environment.h
@@ -0,0 +1,20 @@
+#ifndef ENVIRONMENT_H
+#define ENVIRONMENT_H
+
+#include
+
+#include "fxManager.h"
+
+namespace battleship{
+ class Environment{
+ public:
+ enum class Detonation{EXPLOSION, EMP, CRYO};
+
+ static Environment* getSingleton();
+ static void explode(FxManager::Fx*, Detonation, vb01::Vector3, int = 0, float = 0);
+ private:
+ Environment(){}
+ };
+}
+
+#endif
diff --git a/extractor.cpp b/extractor.cpp
index 412d4f8..2e5d0cc 100644
--- a/extractor.cpp
+++ b/extractor.cpp
@@ -12,21 +12,13 @@ namespace battleship{
using namespace gameBase;
Extractor::Extractor(Player *player, int id, Vector3 pos, Quaternion rot, int buildStatus, ResourceDeposit *rd, Unit::State state) : Structure(player, id, pos, rot, buildStatus, state){
- if(!rd){
- vector deposits;
-
- for(Player *pl : Game::getSingleton()->getPlayers()){
- vector dep = pl->getResourceDeposits();
- deposits.insert(deposits.end(), dep.begin(), dep.end());
- }
-
- for(ResourceDeposit *dep : deposits)
+ if(!rd)
+ for(ResourceDeposit *dep : Game::getSingleton()->getCivilianPlayer()->getResourceDeposits())
if(dep->getPos().getDistanceFrom(pos) < .001){
deposit = dep;
deposit->setExtractor(this);
break;
}
- }
Vector2 size = Vector2(lenHpBar, 10);
ammountBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1));
diff --git a/freezer.cpp b/freezer.cpp
new file mode 100644
index 0000000..f0f81d0
--- /dev/null
+++ b/freezer.cpp
@@ -0,0 +1,17 @@
+#include "freezer.h"
+
+namespace battleship{
+ using namespace vb01;
+
+ //TODO rename the class to a more generic name
+ Freezer::Freezer(Player *player, int id, Vector3 pos, Quaternion rot, Unit::State state) : Vehicle(player, id, pos, rot, state){}
+
+ void Freezer::attack(Order order){
+ Vehicle::attack(order);
+
+ Unit *target = order.targets[0].unit;
+
+ if(target && target->getFreezeStatus() == 100)
+ removeOrder(0);
+ }
+}
diff --git a/freezer.h b/freezer.h
new file mode 100644
index 0000000..49a3ffb
--- /dev/null
+++ b/freezer.h
@@ -0,0 +1,15 @@
+#ifndef FREEZER_H
+#define FREEZER_H
+
+#include "vehicle.h"
+
+namespace battleship{
+ class Freezer : public Vehicle{
+ public:
+ Freezer(Player*, int, vb01::Vector3, vb01::Quaternion, Unit::State);
+ private:
+ void attack(Order);
+ };
+}
+
+#endif
diff --git a/fxManager.cpp b/fxManager.cpp
index b44577d..3273cab 100644
--- a/fxManager.cpp
+++ b/fxManager.cpp
@@ -1,14 +1,18 @@
#include "fxManager.h"
+#include "gameObject.h"
#include
-#include
+#include
+#include
+#include
+#include
+#include
#include
namespace battleship{
using namespace std;
using namespace vb01;
- using namespace sf;
FxManager::Fx::Component::Component(void *c, bool v, s64 dur, vb01::Vector3 p, s64 ot) : comp(c), vfx(v), duration(dur), pos(p), offsetTime(ot) {
if(v) ((vb01::Node*)c)->setVisible(false);
@@ -18,6 +22,118 @@ namespace battleship{
toggleComponents(!re);
}
+ FxManager::Fx* FxManager::initFx(sol::table fxTbl, Node *baseNode, bool attached, Vector3 cp){
+ int numComponents = fxTbl.size();
+
+ if(numComponents == 0) return nullptr;
+
+ vector fxComponents;
+
+ for(int i = 0; i < numComponents; i++){
+ sol::table compTbl = fxTbl[i + 1];
+
+ bool vfx = compTbl["vfx"];
+ s64 duration = compTbl["duration"], offset = compTbl["offset"].get_or(0);
+
+ if(vfx){
+ sol::table meshTbl = compTbl["mesh"];
+
+ string meshPath = "";
+ Material *mat = nullptr;
+ Node *flashNode = nullptr;
+
+ sol::optional posOpt = compTbl["pos"], rotOpt = compTbl["rot"];
+ Vector3 compPos = cp;
+ Quaternion compRot = Quaternion::QUAT_W;
+ float sc = compTbl["scale"].get_or(1);
+
+ if(posOpt != sol::nullopt){
+ sol::table posTable = compTbl["pos"];
+ compPos = Vector3(posTable["x"], posTable["y"], posTable["z"]);
+ }
+
+ if(rotOpt != sol::nullopt){
+ sol::table rotTable = compTbl["rot"];
+ compRot = Quaternion(rotTable["w"], rotTable["x"], rotTable["y"], rotTable["z"]);
+ }
+
+ sol::optional pathOpt = meshTbl["path"];
+ sol::optional numPartOpt = meshTbl["numParticles"];
+
+ if(pathOpt != sol::nullopt){
+ mat = new Material(Root::getSingleton()->getLibPath() + "texture");
+
+ meshPath = meshTbl["path"];
+ flashNode = new Model(meshPath);
+ ((Model*)flashNode)->setMaterial(mat);
+ flashNode->setPosition(compPos);
+ flashNode->setOrientation(compRot);
+ flashNode->setScale(Vector3(sc, sc, sc));
+ }
+ else if(numPartOpt != sol::nullopt){
+ mat = new Material(Root::getSingleton()->getLibPath() + "particle");
+
+ int numParticles = meshTbl["numParticles"];
+ ParticleEmitter *pe = new ParticleEmitter(numParticles);
+ pe->setMaterial(mat);
+ pe->setLowLife(meshTbl["lowLife"]);
+ pe->setHighLife(meshTbl["highLife"]);
+ pe->setSpeed(0);
+
+ sol::table sizeTbl = meshTbl["size"];
+ pe->setSize(Vector2(sizeTbl["x"], sizeTbl["y"]));
+
+ flashNode = new Node(compPos + Vector3(0, 2, 0), compRot, Vector3(sc, sc, sc));
+ flashNode->attachParticleEmitter(pe);
+ flashNode->lookAt(Vector3::VEC_J, Vector3::VEC_K);
+ }
+ else{
+ mat = new Material(Root::getSingleton()->getLibPath() + "texture");
+
+ sol::table sizeTbl = meshTbl["size"];
+ Box *box = new Box(Vector3(sizeTbl["x"], sizeTbl["y"], 0));
+ box->setMaterial(mat);
+
+ flashNode = new Node(compPos, compRot, Vector3(sc, sc, sc), "laser");
+ flashNode->attachMesh(box);
+ }
+
+ sol::optional texOpt = meshTbl["texture"];
+
+ if(texOpt != sol::nullopt){
+ string p[]{meshTbl["texture"]};
+ Texture *tex = new Texture(p, 1, false);
+ mat->addBoolUniform("texturingEnabled", true);
+ mat->addTexUniform("diffuseMap[0]", tex, false);
+ }
+ else{
+ sol::table colorTable = meshTbl["color"];
+ mat->addVec4Uniform("diffuseColor", Vector4(colorTable["x"], colorTable["y"], colorTable["z"], colorTable["a"]));
+ mat->addBoolUniform("texturingEnabled", false);
+ }
+
+ flashNode->setVisible(false);
+ Node *parNode = (attached ? baseNode : Root::getSingleton()->getRootNode());
+ sol::optional parNameOpt = compTbl["parent"];
+
+ if(parNameOpt != sol::nullopt){
+ string parName = compTbl["parent"];
+ parNode = baseNode->findDescendant(parName, true);
+ }
+
+ parNode->attachChild(flashNode);
+ fxComponents.push_back(FxManager::Fx::Component((void*)flashNode, vfx, duration, compPos, offset));
+ }
+ else{
+ sf::SoundBuffer *sfxBuffer = new sf::SoundBuffer();
+ sf::Sound *sfx = GameObject::prepareSfx(sfxBuffer, compTbl["path"]);
+ fxComponents.push_back(FxManager::Fx::Component((void*)sfx, vfx, duration, Vector3::VEC_ZERO, offset));
+ }
+ }
+
+ return new FxManager::Fx(fxComponents, attached);
+ }
+
void FxManager::Fx::toggleComponents(bool active){
for(Component &component : components){
component.active = active;
diff --git a/fxManager.h b/fxManager.h
index 027e8ac..64090b6 100644
--- a/fxManager.h
+++ b/fxManager.h
@@ -3,6 +3,12 @@
#include
+#include
+
+namespace vb01{
+ class Node;
+}
+
namespace battleship{
class FxManager{
public:
@@ -24,6 +30,7 @@ namespace battleship{
};
static FxManager* getSingleton();
+ FxManager::Fx* initFx(sol::table, vb01::Node*, bool, vb01::Vector3 = vb01::Vector3::VEC_ZERO);
void update();
void removeFx(Fx*);
inline void addFx(Fx *fx){fxs.push_back(fx);}
diff --git a/game.cpp b/game.cpp
index 127d761..68e4ac2 100644
--- a/game.cpp
+++ b/game.cpp
@@ -122,11 +122,11 @@ namespace battleship{
for(Projectile *proj : pl->getProjectiles())
gameObjs.push_back((GameObject*)proj);
-
- for(ResourceDeposit *dep : pl->getResourceDeposits())
- gameObjs.push_back((GameObject*)dep);
}
+ for(ResourceDeposit *dep : civilianPlayer->getResourceDeposits())
+ gameObjs.push_back((GameObject*)dep);
+
for(GameObject *obj : gameObjs)
obj->reinit();
}
@@ -137,47 +137,6 @@ namespace battleship{
paused = !paused;
}
- void Game::explode(Vector3 pos, int damage, float radius, sf::Sound *explosionSfx){
- if(!(damage == 0 || radius == 0))
- for(Player *pl : players){
- for(Unit *un : pl->getUnits()){
- float distance = un->getPos().getDistanceFrom(pos);
-
- if(distance < radius)
- un->takeDamage(int(damage * (1.f - distance / radius)));
- }
- }
-
- Root *root = Root::getSingleton();
-
- const int numFrames = 1;
- string p[numFrames];
-
- for(int i = 0; i < numFrames; i++)
- p[i] = GameManager::getSingleton()->getPath() + "Textures/Explosion/explosion07.png";
-
- Texture *tex = new Texture(p, numFrames, false);
-
- Material *mat = new Material(root->getLibPath() + "particle");
- mat->addTexUniform("tex", tex, true);
-
- ParticleEmitter *pe = new ParticleEmitter(1);
- pe->setMaterial(mat);
- pe->setLowLife(3);
- pe->setHighLife(3);
- pe->setSize(10 * Vector2::VEC_IJ);
- pe->setSpeed(0);
-
- Node *node = new Node(pos + Vector3(0, 2, 0));
- node->attachParticleEmitter(pe);
- node->lookAt(Vector3::VEC_J, Vector3::VEC_K);
- root->getRootNode()->attachChild(node);
-
- typedef FxManager::Fx Fx;
- typedef FxManager::Fx::Component Component;
- FxManager::getSingleton()->addFx(new Fx(vector{Component((void*)node, true, 50), Component((void*)explosionSfx, false, 2500)}));
- }
-
void Game::changeUnitPlayer(Unit *unit, Player *newPlayer){
Player *oldPlayer = unit->getPlayer();
vector &oldPlayerUnits = oldPlayer->getUnits();
@@ -276,4 +235,12 @@ namespace battleship{
return false;
}
+
+ vector Game::getPlayers(bool civPl){
+ vector playersVec = players;
+
+ if(civPl) playersVec.push_back(civilianPlayer);
+
+ return playersVec;
+ }
}
diff --git a/game.h b/game.h
index 38d077b..1d862af 100644
--- a/game.h
+++ b/game.h
@@ -22,16 +22,17 @@ namespace battleship{
void update();
void togglePause();
void removeAllElements();
- void explode(vb01::Vector3, int, float, sf::Sound*);
void changeUnitPlayer(Unit*, Player*);
void initTechnologies();
float calcAbilFromTech(Ability::Type, std::vector, int, int);
bool isUnitUnlocked(std::vector, int);
+ std::vector getPlayers(bool = false);
inline void setDebug(bool d){this->debug = d;}
inline void addPlayer(Player *pl){players.push_back(pl);}
inline bool isDebug(){return debug;}
- inline std::vector& getPlayers(){return players;}
inline Player* getPlayer(int id){return players[id];}
+ inline void setCivilianPlayer(Player *pl){this->civilianPlayer = pl;}
+ inline Player* getCivilianPlayer(){return civilianPlayer;}
inline int getNumPlayers(){return players.size();}
inline Technology getTechnology(int id){return technologies[id];}
inline Ability getAbility(int id){return abilities[id];}
@@ -44,6 +45,7 @@ namespace battleship{
std::vector technologies;
std::vector abilities;
std::vector players;
+ Player *civilianPlayer = nullptr;
};
}
diff --git a/gameObject.cpp b/gameObject.cpp
index ebd5b64..2ee2c76 100644
--- a/gameObject.cpp
+++ b/gameObject.cpp
@@ -45,8 +45,11 @@ namespace battleship{
}
void GameObject::orientAt(Quaternion rotQuat){
- model->setOrientation(rotQuat);
rot = rotQuat;
+ model->setOrientation(rotQuat);
+ leftVec = model->getGlobalAxis(0);
+ upVec = model->getGlobalAxis(1);
+ dirVec = model->getGlobalAxis(2);
}
//TODO remove neccessity to create a material for an invisible mesh
@@ -153,10 +156,25 @@ namespace battleship{
return sfx;
}
- void GameObject::initSound(){
- deathSfxBuffer = new sf::SoundBuffer();
- string sfxPath = generateView()[getGameObjTableName()][id + 1]["deathSfx"];
- deathSfx = prepareSfx(deathSfxBuffer, sfxPath);
+ bool GameObject::pointWithinObj(Vector3 point, float deltaLength, float deltaWidth, bool useHeight, float deltaHeight){
+ Vector3 pointDir = point - pos;
+ bool within = true;
+
+ float forwAngle = std::min(dirVec.getAngleBetween(pointDir.norm()), (-dirVec).getAngleBetween(pointDir.norm()));
+ float forwDist = pointDir.getLength() * cos(forwAngle);
+ within &= (forwDist < .5 * (length + deltaLength));
+
+ float leftAngle = std::min(leftVec.getAngleBetween(pointDir.norm()), (-leftVec).getAngleBetween(pointDir.norm()));
+ float leftDist = pointDir.getLength() * cos(leftAngle);
+ within &= (leftDist < .5 * (width + deltaWidth));
+
+ if(useHeight){
+ float upAngle = std::min(upVec.getAngleBetween(pointDir.norm()), (-upVec).getAngleBetween(pointDir.norm()));
+ float upDist = pointDir.getLength() * cos(upAngle);
+ within &= (upDist < .5 * (height + deltaHeight));
+ }
+
+ return within;
}
string GameObject::getGameObjTableName(){
diff --git a/gameObject.h b/gameObject.h
index 2bb7ba1..8be2d56 100644
--- a/gameObject.h
+++ b/gameObject.h
@@ -23,11 +23,12 @@ namespace battleship{
virtual void reinit();
virtual void update();
virtual void select(){}
- void placeAt(vb01::Vector3);
+ virtual void placeAt(vb01::Vector3);
void orientAt(vb01::Quaternion);
std::string getGameObjTableName();
void updateGameStats(Unit*);
static sf::Sound* prepareSfx(sf::SoundBuffer*, std::string);
+ bool pointWithinObj(vb01::Vector3, float = 0, float = 0, bool = false, float = 0);
inline vb01::Vector2 getScreenPos(){return screenPos;}
inline vb01::Vector3 getCorner(int i){return corners[i];}
inline bool isSelectable(){return selectable;}
@@ -55,13 +56,11 @@ namespace battleship{
virtual void initHitbox();
virtual void destroyHitbox();
virtual void destroySound();
- virtual void initSound();
+ virtual void initSound(){}
Type type;
int id;
Player *player;
- sf::SoundBuffer *deathSfxBuffer;
- sf::Sound *deathSfx;
vb01::Model *model = nullptr;
vb01::Node *hitbox = nullptr;
vb01::Vector3 pos = vb01::Vector3(0, 0, 0), upVec = vb01::Vector3(0, 1, 0), dirVec = vb01::Vector3(0, 0, 1), leftVec = vb01::Vector3(1, 0, 0), corners[8];
diff --git a/gameObjectFactory.cpp b/gameObjectFactory.cpp
index 1e91069..f4550ee 100644
--- a/gameObjectFactory.cpp
+++ b/gameObjectFactory.cpp
@@ -2,13 +2,18 @@
#include "player.h"
#include "factory.h"
#include "engineer.h"
+#include "submarine.h"
#include "resourceRover.h"
#include "projectile.h"
#include "resourceDeposit.h"
#include "pointDefense.h"
#include "extractor.h"
-#include "cruiseMissile.h"
+#include "freezer.h"
#include "researchStruct.h"
+#include "missile.h"
+#include "cruiseMissile.h"
+#include "iceSheet.h"
+#include "shell.h"
#include "defConfigs.h"
#include
@@ -23,41 +28,54 @@ namespace battleship{
Unit* GameObjectFactory::createUnit(Player *player, int id, Vector3 pos, Quaternion rot, int buildStatus){
sol::state_view SOL_LUA_VIEW = generateView();
int unitClass = SOL_LUA_VIEW["units"][id + 1]["unitClass"];
+ bool vehicle = SOL_LUA_VIEW["units"][id + 1]["isVehicle"];
- switch((UnitClass)unitClass){
- case UnitClass::FORT:
- case UnitClass::LAND_FACTORY:
- case UnitClass::NAVAL_FACTORY:
- return new Factory(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
- case UnitClass::POINT_DEFENSE:
- return new PointDefense(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
- case UnitClass::EXTRACTOR:
- return new Extractor(player, id, pos, rot, buildStatus);
- case UnitClass::LAB:
- return new ResearchStruct(player, id, pos, rot, buildStatus);
- case UnitClass::TRADE_CENTER:
- case UnitClass::REFINERY:
- return new Structure(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
- case UnitClass::ENGINEER:
- return new Engineer(player, id, pos, rot, Unit::State::STAND_GROUND);
- case UnitClass::RESOURCE_ROVER:
- return new ResourceRover(player, id, pos, rot, Unit::State::STAND_GROUND);
- default:
- return new Vehicle(player, id, pos, rot, Unit::State::STAND_GROUND);
- }
+ if(vehicle)
+ switch((UnitClass)unitClass){
+ case UnitClass::ENGINEER:
+ return new Engineer(player, id, pos, rot, Unit::State::STAND_GROUND);
+ case UnitClass::RESOURCE_ROVER:
+ return new ResourceRover(player, id, pos, rot, Unit::State::STAND_GROUND);
+ case UnitClass::SUBMARINE:
+ return new Submarine(player, id, pos, rot, Unit::State::STAND_GROUND);
+ case UnitClass::FREEZER:
+ return new Freezer(player, id, pos, rot, Unit::State::STAND_GROUND);
+ default:
+ return new Vehicle(player, id, pos, rot, Unit::State::STAND_GROUND);
+ }
+ else
+ switch((UnitClass)unitClass){
+ case UnitClass::FORT:
+ case UnitClass::LAND_FACTORY:
+ case UnitClass::NAVAL_FACTORY:
+ return new Factory(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
+ case UnitClass::POINT_DEFENSE:
+ return new PointDefense(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
+ case UnitClass::EXTRACTOR:
+ return new Extractor(player, id, pos, rot, buildStatus);
+ case UnitClass::LAB:
+ return new ResearchStruct(player, id, pos, rot, buildStatus);
+ case UnitClass::ICE_SHEET:
+ return new IceSheet(player, id, pos, rot, buildStatus);
+ default:
+ return new Structure(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND);
+ }
}
Projectile* GameObjectFactory::createProjectile(Unit *unit, int id, Vector3 pos, Quaternion rot){
sol::state_view SOL_LUA_VIEW = generateView();
int projectileClass = SOL_LUA_VIEW["projectiles"][id + 1]["projectileClass"];
+ Order::Target target = unit->getOrder(0).targets[0];
+ Vector3 targetPos = (target.unit ? target.unit->getPos() : target.pos);
+
switch((ProjectileClass)projectileClass){
+ case ProjectileClass::SHELL:
+ return new Shell(unit, id, pos, rot);
case ProjectileClass::CRUISE_MISSILE:
- {
- Order::Target target = unit->getOrder(0).targets[0];
- Vector3 targetPos = (target.unit ? target.unit->getPos() : target.pos);
- return new CruiseMissile(unit, targetPos, pos, rot);
- }
+ return new CruiseMissile(unit, id, targetPos, pos, rot);
+ case ProjectileClass::MISSILE:
+ return new Missile(unit, id, targetPos, pos, rot);
default:
return new Projectile(unit, id, pos, rot);
}
diff --git a/gameObjectFrameController.cpp b/gameObjectFrameController.cpp
index d3f2b16..a58de16 100644
--- a/gameObjectFrameController.cpp
+++ b/gameObjectFrameController.cpp
@@ -59,17 +59,9 @@ namespace battleship{
void GameObjectFrameController::snapToObj(GameObjectFrame &s, GameObject::Type type, int unitId, float maxDist){
if(s.getType() == GameObject::Type::UNIT && s.getId() == unitId){
s.status = GameObjectFrame::NOT_PLACEABLE;
- vector players = Game::getSingleton()->getPlayers();
- vector deposits;
-
- for(Player *pl : players){
- vector deps = pl->getResourceDeposits();
-
- for(ResourceDeposit *dep : deps)
- deposits.push_back(dep);
- }
+ Player *civPl = Game::getSingleton()->getCivilianPlayer();
- for(ResourceDeposit *dep : deposits){
+ for(ResourceDeposit *dep : civPl->getResourceDeposits()){
Vector3 depPos = dep->getPos();
if(!dep->getExtractor() && s.getPos().getDistanceFrom(depPos) < maxDist){
diff --git a/iceSheet.cpp b/iceSheet.cpp
new file mode 100644
index 0000000..fea125f
--- /dev/null
+++ b/iceSheet.cpp
@@ -0,0 +1,27 @@
+#include "iceSheet.h"
+#include "player.h"
+#include "game.h"
+
+namespace battleship{
+ using namespace vb01;
+ using namespace std;
+
+ IceSheet::IceSheet(Player *player, int id, Vector3 pos, Quaternion rot, int bldSt) : Structure(player, id, pos, rot, bldSt, Unit::State::STAND_GROUND){}
+
+ void IceSheet::update(){
+ Structure::update();
+
+ if(buildStatus < 100)
+ model->getChild(0)->setScale(.01 * buildStatus * Vector3::VEC_IJK);
+
+ for(Player *pl : Game::getSingleton()->getPlayers(true)){
+ vector icebreakers = pl->getUnitsByClass(UnitClass::ICEBREAKER);
+
+ for(Unit *icebreaker : icebreakers)
+ if(icebreaker->pointWithinObj(pos)){
+ player->removeUnit(this);
+ return;
+ }
+ }
+ }
+}
diff --git a/iceSheet.h b/iceSheet.h
new file mode 100644
index 0000000..83ecf1f
--- /dev/null
+++ b/iceSheet.h
@@ -0,0 +1,15 @@
+#ifndef ICE_SHEET_H
+#define ICE_SHEET_H
+
+#include "structure.h"
+
+namespace battleship{
+ class IceSheet : public Structure{
+ public:
+ IceSheet(Player*, int, vb01::Vector3, vb01::Quaternion, int);
+ void update();
+ private:
+ };
+}
+
+#endif
diff --git a/map.cpp b/map.cpp
index 8353a64..1b35696 100755
--- a/map.cpp
+++ b/map.cpp
@@ -48,9 +48,8 @@ namespace battleship{
string refIconFile = SOL_STATE_VIEW["refIcon"];
string basePath = GameManager::getSingleton()->getPath() + "Textures/Icons/Minimap/";
- for(Player *pl : Game::getSingleton()->getPlayers())
- for(ResourceDeposit *rd : pl->getResourceDeposits())
- depositIcons.push_back(initIcon(rd->getPos(), basePath + refIconFile));
+ for(ResourceDeposit *rd : Game::getSingleton()->getCivilianPlayer()->getResourceDeposits())
+ depositIcons.push_back(initIcon(rd->getPos(), basePath + refIconFile));
string camIconFile = SOL_STATE_VIEW["eyeIcon"];
camIcon = initIcon(Root::getSingleton()->getCamera()->getPosition(), basePath + camIconFile);
@@ -107,7 +106,7 @@ namespace battleship{
Vector3 mapSize = Map::getSingleton()->getMapSize();
vector> unitMinimapPos;
- for(Player *pl : Game::getSingleton()->getPlayers())
+ for(Player *pl : Game::getSingleton()->getPlayers(true))
for(Unit *un : pl->getUnits()){
Vector2 coords = Vector2(
int(un->getPos().x / mapSize.x * width),
@@ -383,6 +382,41 @@ namespace battleship{
return spawnPointsTbl.size();
}
+ //TODO improve for underwater cells
+ vector Map::getSurroundingCells(Vector3 p, int numRings){
+ int numHorCells = int(mapSize.x / CELL_SIZE.x);
+ int numVertCells = int(mapSize.z / CELL_SIZE.z);
+ int horId = int((.5 * mapSize.x + p.x) / CELL_SIZE.x);
+ int vertId = int((.5 * mapSize.z + p.z) / CELL_SIZE.z);
+
+ vector cellIds;
+
+ for(int i = vertId - numRings; i <= vertId + numRings; i++)
+ for(int j = horId - numRings; j <= horId + numRings; j++)
+ cellIds.push_back(numHorCells * i + j);
+
+ return cellIds;
+ }
+
+ void Map::blockCells(Unit *unit){
+ vector surroundingCellIds = getSurroundingCells(unit->getPos(), 0);
+
+ for(int scid : surroundingCellIds){
+ if(cells[scid].blockedBy && cells[scid].blockedBy != unit) continue;
+
+ bool within = unit->pointWithinObj(cells[scid].pos);
+ cells[scid].blockedBy = (within ? unit : nullptr);
+ }
+ }
+
+ void Map::unblockCells(Unit *unit){
+ vector surroundingCellIds = getSurroundingCells(unit->getPos(), 0);
+
+ for(int scid : surroundingCellIds)
+ if(cells[scid].blockedBy == unit)
+ cells[scid].blockedBy = nullptr;
+ }
+
void Map::loadSpawnPoints(){
sol::state_view SOL_LUA_VIEW = generateView();
int numSpawnPoints = getNumMapSpawnPoints();
@@ -395,15 +429,15 @@ namespace battleship{
//TODO move minimap loading elsewhere
void Map::loadPlayerGameObjects(){
- int numPlayers = Game::getSingleton()->getNumPlayers();
+ vector players = Game::getSingleton()->getPlayers(true);
sol::state_view SOL_LUA_VIEW = generateView();
string playerInd = "players";
- for(int i = 0; i < numPlayers; i++){
+ for(int i = 0; i < players.size(); i++){
string resDepInd = "resourceDeposits";
SOL_LUA_VIEW.script("numResourceDeposits = #" + mapTable + "." + playerInd + "[" + to_string(i + 1) + "]." + resDepInd);
int numNpcObjs = SOL_LUA_VIEW["numResourceDeposits"];
- Player *player = Game::getSingleton()->getPlayer(i);
+ Player *player = players[i];
for(int j = 0; j < numNpcObjs; j++){
sol::table npcObjTable = SOL_LUA_VIEW[mapTable][playerInd][i + 1][resDepInd][j + 1];
@@ -587,7 +621,7 @@ namespace battleship{
}
void Map::unloadPlayerObjects(){
- for(Player *pl : Game::getSingleton()->getPlayers()){
+ for(Player *pl : Game::getSingleton()->getPlayers(true)){
while(pl->getNumUnits() > 0){
pl->removeUnit(0);
}
@@ -668,6 +702,7 @@ namespace battleship{
}
//TODO replace search with binary search
+ //TODO optimize horizontal and vertical id calculcation
int Map::getCellId(Vector3 pos, bool checkUnderwaterCells){
int numHorCells = int(mapSize.x / CELL_SIZE.x), horId = -1;
diff --git a/map.h b/map.h
index 3dfb454..3002e2c 100755
--- a/map.h
+++ b/map.h
@@ -39,6 +39,7 @@ namespace battleship{
Type type;
vb01::Vector3 pos;
std::vector edges;
+ Unit *blockedBy = nullptr;
std::vector underWaterCellIds;
Cell(){}
@@ -77,6 +78,9 @@ namespace battleship{
bool isPointWithinTerrainObject(vb01::Vector3, int);
void loadPlayerGameObjects();
int getNumMapSpawnPoints(std::string = "");
+ std::vector getSurroundingCells(vb01::Vector3, int);
+ void blockCells(Unit*);
+ void unblockCells(Unit*);
inline std::string getMapName(){return mapName;}
inline vb01::Node* getNodeParent(){return terrainNode;}
inline vb01::Vector3 getCellSize(){return CELL_SIZE;}
diff --git a/missile.cpp b/missile.cpp
new file mode 100644
index 0000000..64754b5
--- /dev/null
+++ b/missile.cpp
@@ -0,0 +1,19 @@
+#include "missile.h"
+
+namespace battleship{
+ using namespace vb01;
+
+ Missile::Missile(Unit *un, int id, Vector3 tp, Vector3 pos, Quaternion rot) :
+ Projectile(un, id, pos, rot),
+ targetPos(tp){}
+
+ void Missile::update(){
+ Vector3 targDir = (targetPos - pos).norm();
+ float angle = targDir.getAngleBetween(dirVec);
+ float ra = (rotAngle < angle ? rotAngle : angle);
+ orientAt(Quaternion(ra, dirVec.cross(targDir)) * rot);
+
+ Projectile::update();
+ checkCollision();
+ }
+}
diff --git a/missile.h b/missile.h
new file mode 100644
index 0000000..44024f9
--- /dev/null
+++ b/missile.h
@@ -0,0 +1,17 @@
+#ifndef MISSILE_H
+#define MISSILE_H
+
+#include "projectile.h"
+
+namespace battleship{
+ class Missile : public Projectile{
+ public:
+ Missile(Unit*, int, vb01::Vector3, vb01::Vector3, vb01::Quaternion);
+ ~Missile(){}
+ void update();
+ private:
+ vb01::Vector3 targetPos;
+ };
+}
+
+#endif
diff --git a/pathfinder.cpp b/pathfinder.cpp
index df64892..e397719 100644
--- a/pathfinder.cpp
+++ b/pathfinder.cpp
@@ -1,7 +1,7 @@
#include
#include "pathfinder.h"
-#include "unit.h"
+#include "vehicle.h"
namespace battleship{
using namespace std;
@@ -16,7 +16,7 @@ namespace battleship{
return pathfinder;
}
- vector Pathfinder::findPath(vector &cells, vector &heuristics, int source, int dest, int unitType){
+ vector Pathfinder::findPath(vector &cells, vector &heuristics, int source, int dest, Vehicle *vehicle){
const int size = cells.size();
u32 *distances = new u32[size];
vector *paths = new vector[size];
@@ -67,10 +67,31 @@ namespace battleship{
}
bool canMoveToStrichCell = true;
- bool ship = ((UnitType)unitType == UnitType::UNDERWATER || (UnitType)unitType == UnitType::SEA_LEVEL);
- if((ship && cells[vertStrich].type != Map::Cell::WATER) || ((UnitType)unitType == UnitType::LAND && cells[vertStrich].type != Map::Cell::LAND))
- continue;
+ if(vehicle){
+ UnitType unitType = vehicle->getType();
+ bool ship = (unitType == UnitType::UNDERWATER || unitType == UnitType::SEA_LEVEL);
+ Unit *blockingUnit = cells[vertStrich].blockedBy;
+ bool diffBlockingUnit = (blockingUnit && blockingUnit != vehicle);
+
+ if(
+ (unitType == UnitType::LAND && (diffBlockingUnit || cells[vertStrich].type != Map::Cell::LAND)) ||
+ (
+ ship &&
+ (
+ cells[vertStrich].type != Map::Cell::WATER ||
+ (
+ diffBlockingUnit &&
+ blockingUnit->getUnitClass() == UnitClass::ICE_SHEET &&
+ vehicle->getUnitClass() != UnitClass::ICEBREAKER
+ )
+ )
+ )
+ )
+ {
+ continue;
+ }
+ }
if(distances[vertStrich] + cells[vertStrich].edges[i].weight < distances[edgeNode]){
distances[edgeNode] = distances[vertStrich] + cells[vertStrich].edges[i].weight;
diff --git a/pathfinder.h b/pathfinder.h
index b071db5..13f38af 100644
--- a/pathfinder.h
+++ b/pathfinder.h
@@ -8,10 +8,12 @@
#include
namespace battleship{
+ class Vehicle;
+
class Pathfinder{
public:
static Pathfinder* getSingleton();
- std::vector findPath(std::vector&, std::vector&, int, int, int = -1);
+ std::vector findPath(std::vector&, std::vector&, int, int, Vehicle* = nullptr);
inline vb01::u32 getImpassibleNodeVal(){return impassibleNodeVal;}
inline void setImpassibleNodeVal(vb01::u32 val){this->impassibleNodeVal = val;}
private:
diff --git a/pathfinderTest.cpp b/pathfinderTest.cpp
index cd116a3..5bb56ed 100644
--- a/pathfinderTest.cpp
+++ b/pathfinderTest.cpp
@@ -66,7 +66,7 @@ namespace battleship{
int src = 0, dest = cells.size() - 1;
vector heur;
- vector path = pathfinder->findPath(cells, heur, src, dest, 3);
+ vector path = pathfinder->findPath(cells, heur, src, dest);
CPPUNIT_ASSERT(path == vector({0, 1, 2, 4, 3, 6}));
int sumPathWeights = calcPathLength(path);
@@ -82,7 +82,7 @@ namespace battleship{
for(int i = 0; i < numIterations; i++){
s64 t0 = getTime();
- pathfinder->findPath(cells, heur, src, dest, 3);
+ pathfinder->findPath(cells, heur, src, dest);
s64 t1 = getTime();
sumTime += t1 - t0;
}
diff --git a/playButton.cpp b/playButton.cpp
index 785f5ef..16feb73 100644
--- a/playButton.cpp
+++ b/playButton.cpp
@@ -66,6 +66,8 @@ namespace battleship{
string name = (cpuPlayer ? "CPU player #" + to_string(i) : "Player");
game->addPlayer(new Player(difficulty, faction, team, color, cpuPlayer, i, name));
}
+
+ game->setCivilianPlayer(new Player(0, 0, 0, .5 * Vector3::VEC_IJK));
handleLoadingGui(new LoadingAppState(new InGameAppState(mapName), "inGame.lua"));
}
diff --git a/pointDefense.cpp b/pointDefense.cpp
index 1a5336d..47faeab 100644
--- a/pointDefense.cpp
+++ b/pointDefense.cpp
@@ -7,36 +7,11 @@ namespace battleship{
using namespace std;
using namespace gameBase;
- PointDefense::PointDefense(Player *player, int id, Vector3 pos, Quaternion rot, int buildStatus, Unit::State state) : Structure(player, id, pos, rot, buildStatus, state){
- turretDir = dirVec;
- }
+ PointDefense::PointDefense(Player *player, int id, Vector3 pos, Quaternion rot, int buildStatus, Unit::State state) : Structure(player, id, pos, rot, buildStatus, state){}
void PointDefense::attack(Order order){
if(!isComplete()) return;
- Unit *targUnit = order.targets[0].unit;
- Vector3 targDir = (targUnit ? targUnit->getPos() : order.targets[0].pos) - pos;
-
- if(targDir.getLength() > weapons[0]->getMaxRange()){
- removeOrder(0);
- return;
- }
-
- float angleToTarg = targDir.norm().getAngleBetween(turretDir);
-
- if(angleToTarg > .05)
- rotateTurret(calculateRotation(targDir.norm(), angleToTarg, .1));
- else
- weapons[0]->fire(order);
-
Unit::attack(order);
}
-
- void PointDefense::rotateTurret(float angle){
- string nodeName = generateView()[GameObject::getGameObjTableName()][id + 1]["turretNode"];
- Node *turretNode = model->findDescendant(nodeName, true);
- Quaternion rotQuat = Quaternion(angle, Vector3::VEC_J);
- turretNode->setOrientation(rotQuat * turretNode->getOrientation());
- turretDir = rotQuat * turretDir;
- }
}
diff --git a/pointDefense.h b/pointDefense.h
index 3004f58..b5f6746 100644
--- a/pointDefense.h
+++ b/pointDefense.h
@@ -8,10 +8,7 @@ namespace battleship{
public:
PointDefense(Player*, int, vb01::Vector3, vb01::Quaternion, int, Unit::State);
private:
- vb01::Vector3 turretDir;
-
void attack(Order);
- void rotateTurret(float);
};
}
diff --git a/projectile.cpp b/projectile.cpp
index 87b8bcd..03873a3 100755
--- a/projectile.cpp
+++ b/projectile.cpp
@@ -10,6 +10,7 @@
#include "unit.h"
#include "util.h"
#include "player.h"
+#include "environment.h"
#include "projectile.h"
#include "defConfigs.h"
#include "resourceDeposit.h"
@@ -43,7 +44,6 @@ namespace battleship{
initProperties();
initModel();
- initSound();
GameObject::reinit();
}
@@ -64,25 +64,23 @@ namespace battleship{
rotAngle = projTable["rotAngle"].get_or(0.0);
}
- void Projectile::initSound(){
- explosionSfxBuffer = new sf::SoundBuffer();
- string sfxPath = generateView()[GameObject::getGameObjTableName()][id + 1]["explosion"]["sfx"];
- explosionSfx = GameObject::prepareSfx(explosionSfxBuffer, sfxPath);
- }
-
void Projectile::update() {
GameObject::update();
placeAt(pos + speed * dirVec);
-
- if(!remove){
- checkSurfaceCollision();
- if(remove) return;
- checkUnitCollision();
- }
}
+ void Projectile::detonate(Unit *target){
+ if(target) target->takeDamage(directHitDamage);
+
+ sol::table tbl = generateView()[getGameObjTableName()][id + 1]["explosion"];
+ FxManager::Fx *fx = FxManager::getSingleton()->initFx(tbl["fx"], model, false, pos);
+ Environment::explode(fx, (Environment::Detonation)tbl["detonation"], pos, tbl["damage"], tbl["radius"]);
+
+ remove = true;
+ }
+
void Projectile::checkUnitCollision(){
- vector players = Game::getSingleton()->getPlayers();
+ vector players = Game::getSingleton()->getPlayers(true);
vector targetUnits;
vector targetNodes;
@@ -98,22 +96,26 @@ namespace battleship{
vector results = RayCaster::cast(pos, dirVec, targetNodes, rayLength);
- if(!results.empty()){
+ if(!results.empty())
for(int i = 0; i < targetNodes.size(); i++)
- if(targetNodes[i]->getMesh(0) == results[0].mesh){
- targetUnits[i]->takeDamage(directHitDamage);
- Game::getSingleton()->explode(pos, explosionDamage, explosionRadius, explosionSfx);
- remove = true;
- }
- }
+ if(targetNodes[i]->getMesh(0) == results[0].mesh)
+ detonate(targetUnits[i]);
}
void Projectile::checkSurfaceCollision(){
Map *map = Map::getSingleton();
int cellId = map->getCellId(pos, false);
- if(map->getCells()[cellId].type == Map::Cell::LAND)
- remove = true;
+ if((pos + dirVec * rayLength).y <= map->getCells()[cellId].pos.y)
+ detonate();
+ }
+
+ void Projectile::checkCollision(){
+ if(!remove){
+ checkSurfaceCollision();
+ if(remove) return;
+ checkUnitCollision();
+ }
}
void Projectile::debug(){
diff --git a/projectile.h b/projectile.h
index 0062ddf..24329d9 100755
--- a/projectile.h
+++ b/projectile.h
@@ -1,20 +1,20 @@
#ifndef PROJECTILE_H
#define PROJECTILE_H
-#include
-
#include "gameObject.h"
+#include "fxManager.h"
-#include
+#include
namespace vb01{
class Node;
}
namespace battleship {
- enum class ProjectileClass{CRUISE_MISSILE, TORPEDO};
class Unit;
+ enum class ProjectileClass{SHELL, CRUISE_MISSILE, MISSILE, TORPEDO};
+
class Projectile : public GameObject{
public:
Projectile(Unit*, int, vb01::Vector3, vb01::Quaternion);
@@ -23,17 +23,18 @@ namespace battleship {
virtual void debug();
private:
void initProperties();
- void initSound();
- void checkCollision();
+ void detonate(Unit *u = nullptr);
protected:
virtual void reinit();
virtual void checkUnitCollision();
virtual void checkSurfaceCollision();
+ void checkCollision();
- float speed, rayLength, explosionRadius, rotAngle;
- int directHitDamage, explosionDamage;
vb01::Vector3 initPos;
Unit *unit = nullptr;
+ FxManager::Fx *explosionFx = nullptr;
+ float speed, rayLength, explosionRadius, rotAngle;
+ int directHitDamage, explosionDamage;
sf::SoundBuffer *shotSfxBuffer, *explosionSfxBuffer;
sf::Sound *shotSfx = nullptr, *explosionSfx = nullptr;
};
diff --git a/shell.cpp b/shell.cpp
new file mode 100644
index 0000000..a7febf7
--- /dev/null
+++ b/shell.cpp
@@ -0,0 +1,37 @@
+#include "shell.h"
+
+#include
+
+#include
+
+namespace battleship{
+ using namespace std;
+ using namespace vb01;
+ using namespace gameBase;
+
+ Shell::Shell(Unit *un, int id, Vector3 pos, Quaternion rot) :
+ Projectile(un, id, pos, rot),
+ initTime(getTime()),
+ initDir(dirVec) {}
+
+ void Shell::update(){
+ float currTime = float(getTime() - initTime) / 1000;
+
+ if(currTime == 0) return;
+
+ const float G = generateView()["G"];
+ float angle = initDir.getAngleBetween(Vector3(initDir.x, 0, initDir.z).norm());
+
+ dirVec = (
+ pos +
+ speed * currTime * cos(angle) * Vector3(initDir.x, 0, initDir.z).norm() +
+ (currTime * speed * sin(angle) - G * currTime * currTime) * Vector3::VEC_J -
+ pos
+ ).norm();
+ upVec = Quaternion(-PI / 2, leftVec) * dirVec;
+ model->lookAt(dirVec, upVec);
+
+ Projectile::update();
+ checkCollision();
+ }
+}
diff --git a/shell.h b/shell.h
new file mode 100644
index 0000000..3b73877
--- /dev/null
+++ b/shell.h
@@ -0,0 +1,19 @@
+#ifndef SHELL_H
+#define SHELL_H
+
+#include "projectile.h"
+
+#include
+
+namespace battleship{
+ class Shell : public Projectile{
+ public:
+ Shell(Unit*, int, vb01::Vector3, vb01::Quaternion);
+ void update();
+ private:
+ vb01::s64 initTime;
+ vb01::Vector3 initDir;
+ };
+}
+
+#endif
diff --git a/structure.h b/structure.h
index da01ffa..37d4fa3 100644
--- a/structure.h
+++ b/structure.h
@@ -17,9 +17,9 @@ namespace battleship{
inline int getBuildStatus(){return buildStatus;}
inline void incrementBuildStatus(){buildStatus++;}
private:
- int buildStatus = 0;
protected:
vb01::Node *buildStatusBackground = nullptr, *buildStatusForeground = nullptr;
+ int buildStatus = 0;
};
}
diff --git a/submarine.cpp b/submarine.cpp
new file mode 100644
index 0000000..2fc1110
--- /dev/null
+++ b/submarine.cpp
@@ -0,0 +1,27 @@
+#include "submarine.h"
+#include "map.h"
+
+#include
+
+namespace battleship{
+ using namespace vb01;
+ using namespace std;
+
+ Submarine::Submarine(Player *player, int id, Vector3 pos, Quaternion rot, Unit::State state) : Vehicle(player, id, pos, rot, state){}
+
+ bool Submarine::validateLaunchOrder(){
+ if(!Unit::validateLaunchOrder()) return false;
+
+ vector terrainNodes = Map::getSingleton()->getNodeParent()->getChildren();
+
+ for(int i = 1; i < terrainNodes.size(); i++){
+ Vector3 wbPos = terrainNodes[i]->getPosition();
+ Vector3 size = ((Quad*)terrainNodes[i]->getMesh(0))->getSize();
+
+ if(fabs(wbPos.x - pos.x) < .5 * size.x && fabs(wbPos.z - pos.z) < .5 * size.y && pos.y - wbPos.y > -.1)
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/submarine.h b/submarine.h
new file mode 100644
index 0000000..4e1d914
--- /dev/null
+++ b/submarine.h
@@ -0,0 +1,15 @@
+#ifndef SUBMARINE_H
+#define SUBMARINE_H
+
+#include "vehicle.h"
+
+namespace battleship{
+ class Submarine : public Vehicle{
+ public:
+ Submarine(Player*, int, vb01::Vector3, vb01::Quaternion, Unit::State);
+ private:
+ bool validateLaunchOrder();
+ };
+}
+
+#endif
diff --git a/unit.cpp b/unit.cpp
index 587c0cd..36730eb 100755
--- a/unit.cpp
+++ b/unit.cpp
@@ -13,9 +13,12 @@
#include
#include "unit.h"
+#include "weapon.h"
#include "util.h"
#include "game.h"
+#include "map.h"
#include "vehicle.h"
+#include "environment.h"
#include "gameObjectFactory.h"
#include "activeGameState.h"
#include "gameManager.h"
@@ -30,264 +33,9 @@ using namespace gameBase;
using namespace std;
namespace battleship{
- string Unit::Weapon::LASER_FLAG = "laser";
-
- Unit::Weapon::Weapon(Unit *u, sol::table unitTable, int wid) :
- unit(u),
- id(wid),
- type((Weapon::Type)unitTable["weapons"][wid + 1]["type"]),
- rateOfFire(unitTable["weapons"][wid + 1]["rateOfFire"]),
- damage(unitTable["weapons"][wid + 1]["damage"].get_or(0))
- {
- sol::table weaponTable = unitTable["weapons"][wid + 1];
- maxRange = weaponTable["maxRange"];
- initProjectileData(weaponTable);
-
- fireFx = initFx(weaponTable, "fireFx", true);
- if(fireFx) FxManager::getSingleton()->addFx(fireFx);
- }
-
- void Unit::Weapon::initProjectileData(sol::table weaponTable){
- string projTableKey = "projectile";
- sol::optional proj = weaponTable[projTableKey];
-
- if(proj != sol::nullopt){
- projId = weaponTable[projTableKey]["id"];
- sol::table projTable = generateView()["projectiles"];
- ProjectileClass pc = (ProjectileClass)projTable[projId + 1]["projectileClass"];
-
- if(pc == ProjectileClass::CRUISE_MISSILE){
- minRange = 0;
- float rotAngle = projTable[projId + 1]["rotAngle"];
- float speed = projTable[projId + 1]["speed"];
- float base = PI / 2, alpha = 0;
-
- while(base - alpha > .001){
- minRange += speed * sin(alpha);
- alpha += (base - alpha > rotAngle ? rotAngle : base - alpha);
- }
-
- minRange *= 2;
- }
-
- sol::table posTable = weaponTable[projTableKey]["pos"];
- projPos = Vector3(posTable["x"], posTable["y"], posTable["z"]);
- sol::table rotTable = weaponTable[projTableKey]["rot"];
- projRot = Quaternion(rotTable["w"], rotTable["x"], rotTable["y"], rotTable["z"]);
- }
- }
-
- //TODO implement node child search by name
- FxManager::Fx* Unit::Weapon::initFx(sol::table weaponTable, string fxKey, bool attached){
- sol::optional fxOpt = weaponTable[fxKey];
-
- if(fxOpt == sol::nullopt)
- return nullptr;
-
- sol::table fxTbl = weaponTable[fxKey];
- int numComponents = fxTbl.size();
-
- if(numComponents == 0)
- return nullptr;
-
- vector fxComponents;
-
- for(int i = 0; i < numComponents; i++){
- sol::table compTbl = fxTbl[i + 1];
-
- bool vfx = compTbl["vfx"];
- s64 duration = compTbl["duration"], offset = compTbl["offset"].get_or(0);
-
- if(vfx){
- sol::table meshTbl = compTbl["mesh"];
-
- string meshPath = "";
- Material *mat = nullptr;
- Node *flashNode = nullptr;
-
- sol::optional posOpt = compTbl["pos"], rotOpt = compTbl["rot"];
- Vector3 compPos = Vector3::VEC_ZERO;
- Quaternion compRot = Quaternion::QUAT_W;
- float sc = compTbl["scale"].get_or(1);
-
- if(posOpt != sol::nullopt){
- sol::table posTable = compTbl["pos"];
- compPos = Vector3(posTable["x"], posTable["y"], posTable["z"]);
- }
-
- if(rotOpt != sol::nullopt){
- sol::table rotTable = compTbl["rot"];
- compRot = Quaternion(rotTable["w"], rotTable["x"], rotTable["y"], rotTable["z"]);
- }
-
- sol::optional pathOpt = meshTbl["path"];
- sol::optional numPartOpt = meshTbl["numParticles"];
-
- if(pathOpt != sol::nullopt){
- mat = new Material(Root::getSingleton()->getLibPath() + "texture");
-
- meshPath = meshTbl["path"];
- flashNode = new Model(meshPath);
- ((Model*)flashNode)->setMaterial(mat);
- flashNode->setPosition(compPos);
- flashNode->setOrientation(compRot);
- flashNode->setScale(Vector3(sc, sc, sc));
- }
- else if(numPartOpt != sol::nullopt){
- mat = new Material(Root::getSingleton()->getLibPath() + "particle");
-
- int numParticles = meshTbl["numParticles"];
- ParticleEmitter *pe = new ParticleEmitter(numParticles);
- pe->setMaterial(mat);
- pe->setLowLife(meshTbl["lowLife"]);
- pe->setHighLife(meshTbl["highLife"]);
- pe->setSpeed(0);
-
- sol::table sizeTbl = meshTbl["size"];
- pe->setSize(Vector2(sizeTbl["x"], sizeTbl["y"]));
-
- flashNode = new Node(compPos, compRot, Vector3(sc, sc, sc));
- flashNode->attachParticleEmitter(pe);
- flashNode->lookAt(Vector3::VEC_J, Vector3::VEC_K);
- }
- else{
- mat = new Material(Root::getSingleton()->getLibPath() + "texture");
-
- sol::table sizeTbl = meshTbl["size"];
- Box *box = new Box(Vector3(sizeTbl["x"], sizeTbl["y"], 0));
- box->setMaterial(mat);
-
- flashNode = new Node(compPos, compRot, Vector3(sc, sc, sc), LASER_FLAG);
- flashNode->attachMesh(box);
- }
-
- sol::optional texOpt = meshTbl["texture"];
-
- if(texOpt != sol::nullopt){
- string p[]{meshTbl["texture"]};
- Texture *tex = new Texture(p, 1, false);
- mat->addBoolUniform("texturingEnabled", true);
- mat->addTexUniform("diffuseMap[0]", tex, false);
- }
- else{
- sol::table colorTable = meshTbl["color"];
- mat->addVec4Uniform("diffuseColor", Vector4(colorTable["x"], colorTable["y"], colorTable["z"], colorTable["a"]));
- mat->addBoolUniform("texturingEnabled", false);
- }
-
- flashNode->setVisible(false);
- Node *parNode = (attached ? unit->getModel() : Root::getSingleton()->getRootNode());
- sol::optional parOpt = compTbl["parent"];
-
- if(parOpt != sol::nullopt){
- vector descendants;
- unit->getModel()->getDescendants(descendants);
- string parName = compTbl["parent"];
- parNode = nullptr;
-
- for(Node *desc : descendants)
- if(desc->getName() == parName){
- parNode = desc;
- break;
- }
- }
-
- parNode->attachChild(flashNode);
-
- fxComponents.push_back(FxManager::Fx::Component((void*)flashNode, vfx, duration, compPos, offset));
- }
- else{
- sf::SoundBuffer *sfxBuffer = new sf::SoundBuffer();
- sf::Sound *sfx = GameObject::prepareSfx(sfxBuffer, compTbl["path"]);
- fxComponents.push_back(FxManager::Fx::Component((void*)sfx, vfx, duration, Vector3::VEC_ZERO, offset));
- }
- }
-
- return new FxManager::Fx(fxComponents, attached);
- }
-
- Unit::Weapon::~Weapon(){
- FxManager *fm = FxManager::getSingleton();
-
- if(fireFx) fm->removeFx(fireFx);
- }
-
- void Unit::Weapon::update(){}
-
- void Unit::Weapon::useFx(FxManager::Fx *fx, Vector3 targPos, bool fire){
- if(fx && !fire)
- FxManager::getSingleton()->addFx(fx);
- else if(!fx)
- return;
-
- fx->toggleComponents(true);
-
- Vector3 plCol = unit->getPlayer()->getColor();
-
- for(int i = 0; i < fx->components.size(); i++){
- FxManager::Fx::Component &comp = fx->components[i];
-
- if(comp.vfx){
- if(fire && ((Node*)comp.comp)->getName() == LASER_FLAG){
- Vector3 initPos = unit->getPos(), laserDir = targPos - initPos;
- float targDist = laserDir.getLength();
- float angle = unit->getDirVec().getAngleBetween(laserDir);
- Vector3 crossProd = unit->getDirVec().cross(laserDir);
-
- Node *compNode = (Node*)comp.comp;
- compNode->setOrientation(Quaternion(angle, crossProd) * compNode->getOrientation());
-
- Box *box = (Box*)compNode->getMesh(0);
- Vector3 size = box->getSize();
- box->setSize(Vector3(size.x, size.y, targDist));
- box->updateVerts(box->getMeshBase());
- box->getMaterial()->setVec4Uniform("diffuseColor", Vector4(plCol.x, plCol.y, plCol.z, 1));
-
- compNode->setPosition(comp.pos + .5 * targDist * Vector3::VEC_K);
- }
- else if(!fire)
- ((Node*)comp.comp)->setPosition(targPos);
- }
- }
- }
-
- void Unit::Weapon::fire(Order order){
- if(!canFire()) return;
-
- Unit *targetUnit = order.targets[0].unit;
- Vector3 targPos = (targetUnit ? targetUnit->getPos() : order.targets[0].pos);
-
- if(fireFx) useFx(fireFx, targPos, true);
-
- if(projId == -1){
- sol::table weaponTbl = generateView()["units"][unit->getId() + 1]["weapons"][id + 1];
-
- if(targetUnit){
- targetUnit->takeDamage(damage);
- unit->updateGameStats(targetUnit);
- useFx(initFx(weaponTbl, "unitHitFx", false), targPos, false);
- }
- else{
- Map *map = Map::getSingleton();
- Map::Cell::Type cellType = map->getCells()[map->getCellId(targPos)].type;
- string fxKey = (cellType == Map::Cell::Type::LAND ? "landHitFx" : "waterHitFx");
- useFx(initFx(weaponTbl, fxKey, false), targPos, false);
- }
- }
- else{
- Vector3 leftVec = unit->getLeftVec();
- Vector3 upVec = unit->getUpVec();
- Vector3 dirVec = unit->getDirVec();
- Vector3 p = unit->getPos() + leftVec * projPos.x + upVec * projPos.y + dirVec * projPos.z;
- Quaternion r = unit->getRot() * projRot;
- unit->getPlayer()->addProjectile(GameObjectFactory::createProjectile(unit, projId, p, r));
- }
-
- lastFireTime = getTime();
- }
-
Unit::Unit(Player *player, int id, Vector3 pos, Quaternion rot, State st) : GameObject(GameObject::Type::UNIT, id, player, pos, rot), state(st){
selectable = true;
+ restartTime = 2000;
Unit::initProperties();
initModel();
@@ -303,6 +51,7 @@ namespace battleship{
}
Unit::~Unit() {
+ Map::getSingleton()->unblockCells(this);
removeBar(hpBackgroundNode);
removeBar(hpForegroundNode);
destroyWeapons();
@@ -390,15 +139,22 @@ namespace battleship{
sol::table unitTable = SOL_STATE_VIEW[objType][id + 1];
string tblName = "weapons";
- sol::optional wt = unitTable[tblName];
+ sol::optional weaponsTblOpt = unitTable[tblName];
- if(wt != sol::nullopt){
+ if(weaponsTblOpt != sol::nullopt){
string varName = "numWeapons";
SOL_STATE_VIEW.script(varName + " = #" + objType + "[" + to_string(id + 1) + "]." + tblName);
int numWeapons = SOL_STATE_VIEW[varName];
- for(int i = 0; i < numWeapons; i++)
- weapons.push_back(new Weapon(this, unitTable, i));
+ for(int i = 0; i < numWeapons; i++){
+ int wt = 0;
+ sol::optional wtOpt = unitTable[tblName][i + 1]["type"];
+
+ if(wtOpt != sol::nullopt) wt = unitTable[tblName][i + 1]["type"];
+
+ Weapon *weapon = ((Weapon::Type)wt == Weapon::Type::FREEZER ? new CryoGun(this, unitTable, i) : new Weapon(this, unitTable, i));
+ weapons.push_back(weapon);
+ }
}
}
@@ -492,15 +248,7 @@ namespace battleship{
}
void Unit::launch(Order order){
- for(Weapon *weapon : weapons){
- Vector3 targPos = Vector3(order.targets[0].pos.x, pos.y, order.targets[0].pos.z);
-
- if(weapon->getProjectileId() == 0 && weapon->getMinRange() < targPos.getDistanceFrom(pos)){
- weapon->fire(order);
- break;
- }
- }
-
+ getWeaponsByOrder(Order::TYPE::LAUNCH)[0]->fire(order);
removeOrder(0);
}
@@ -552,6 +300,11 @@ namespace battleship{
void Unit::update() {
GameObject::update();
+ if(condition == Condition::EM_JAMMED && getTime() - lastJamTime > restartTime)
+ condition = Condition::ABLE;
+
+ if(freezeStatus >= 100) condition = Condition::FROZEN;
+
ActiveGameState *activeState = (ActiveGameState*)GameManager::getSingleton()->getStateManager()->getAppStateByType(AppStateType::ACTIVE_STATE);
Player *mainPlayer = (activeState ? activeState->getPlayer() : nullptr);
@@ -572,7 +325,9 @@ namespace battleship{
displayUnitStats(slot.foreground, slot.background, (int)((bool)slot.vehicle), (int)true, renderSelectables, slot.offset);
if (health <= DEATH_HP){
- Game::getSingleton()->explode(pos, 0, 0, deathSfx);
+ sol::table tbl = generateView()[getGameObjTableName()][id + 1]["deathFx"];
+ FxManager::Fx *fx = FxManager::getSingleton()->initFx(tbl, model, false, pos);
+ Environment::explode(fx, Environment::Detonation::EXPLOSION, pos);
remove = true;
}
@@ -601,6 +356,8 @@ namespace battleship{
//TODO remove order argument from action methods
void Unit::executeOrders() {
+ if(condition != Condition::ABLE) return;
+
if (orders.size() > 0) {
Order order = orders[0];
@@ -681,14 +438,20 @@ namespace battleship{
removeOrder(0);
}
+
+ vector attackWeapons = getWeaponsByOrder(Order::TYPE::ATTACK);
+ Vector3 targPos = (order.targets[0].unit ? order.targets[0].unit->getPos() : order.targets[0].pos);
+
+ for(Weapon *weapon : attackWeapons)
+ weapon->trackTarget(targPos);
}
bool Unit::validateOrder(Order order){
switch (order.type) {
case Order::TYPE::ATTACK:
- return !weapons.empty();
+ return !getWeaponsByOrder(Order::TYPE::ATTACK).empty();
case Order::TYPE::BUILD:
- return unitClass == UnitClass::ENGINEER;
+ return (unitClass == UnitClass::ENGINEER || unitClass == UnitClass::FREEZER);
case Order::TYPE::PATROL:
case Order::TYPE::MOVE:
return vehicle;
@@ -697,30 +460,28 @@ namespace battleship{
case Order::TYPE::EJECT:
return !garrisonSlots.empty();
case Order::TYPE::LAUNCH:
- {
- for(Weapon *weapon : weapons)
- if(weapon->getType() == Weapon::Type::CRUISE_MISSILE)
- return true;
-
- return false;
- }
+ return validateLaunchOrder();
case Order::TYPE::SUPPLY:
case Order::TYPE::LOAD:
case Order::TYPE::UNLOAD:
return unitClass == UnitClass::RESOURCE_ROVER;
case Order::TYPE::HACK:
- {
- for(Weapon *weapon : weapons)
- if(weapon->getType() == Weapon::Type::CRUISE_MISSILE)
- return true;
-
- return false;
- }
+ return !getWeaponsByOrder(Order::TYPE::HACK).empty();
default:
return false;
}
}
+ vector Unit::getWeaponsByOrder(Order::TYPE type){
+ vector weaps;
+
+ for(Weapon *w : weapons)
+ if(w->getOrderType() == type)
+ weaps.push_back(w);
+
+ return weaps;
+ }
+
void Unit::receiveOrder(Order order, bool add) {
if(!validateOrder(order)) return;
@@ -752,6 +513,14 @@ namespace battleship{
}
}
+ //TODO select only the closest cells based on unit size
+ void Unit::placeAt(Vector3 p){
+ //check twice in case the unit is warped over a long distance
+ Map::getSingleton()->blockCells(this);
+ GameObject::placeAt(p);
+ Map::getSingleton()->blockCells(this);
+ }
+
vector Unit::getSelectingPlayers(){
vector players = Game::getSingleton()->getPlayers(), selectingPlayers;
diff --git a/unit.h b/unit.h
index 118cd69..1c1bf0e 100755
--- a/unit.h
+++ b/unit.h
@@ -27,6 +27,7 @@ namespace vb01{
namespace battleship{
class Player;
+ class Weapon;
class Unit;
class Vehicle;
class Structure;
@@ -74,6 +75,9 @@ namespace battleship{
CRUISER,
CARRIER,
SUBMARINE,
+ ICEBREAKER,
+ FREEZER,
+ EMP_BOAT,
LAND_FACTORY,
NAVAL_FACTORY,
TRADE_CENTER,
@@ -81,43 +85,12 @@ namespace battleship{
POINT_DEFENSE,
EXTRACTOR,
REFINERY,
- FORT
+ FORT,
+ ICE_SHEET
};
class Unit : public GameObject{
public:
- class Weapon{
- public:
- enum class Type{HITSCAN, SHELL, TORPEDO, CRUISE_MISSILE, HACK};
-
- Weapon(Unit*, sol::table, int);
- ~Weapon();
- virtual void update();
- virtual void fire(Order);
- inline Type getType(){return type;}
- inline int getProjectileId(){return projId;}
- inline int getRateOfFire(){return rateOfFire;}
- inline int getDamage(){return damage;}
- inline int getMinRange(){return minRange;}
- inline int getMaxRange(){return maxRange;}
- inline Unit* getUnit(){return unit;}
- private:
- Type type;
- int id, projId = -1, rateOfFire, damage = 0;
- float minRange = 0, maxRange;
- vb01::Vector3 projPos;
- vb01::Quaternion projRot;
- vb01::s64 lastFireTime = 0;
- Unit *unit = nullptr;
- FxManager::Fx *fireFx = nullptr;
- static std::string LASER_FLAG;
-
- void initProjectileData(sol::table);
- FxManager::Fx* initFx(sol::table, std::string, bool);
- void useFx(FxManager::Fx*, vb01::Vector3, bool);
- inline bool canFire(){return vb01::getTime() - lastFireTime > rateOfFire;}
- };
-
struct GarrisonSlot{
Vehicle *vehicle = nullptr;
int category;
@@ -129,6 +102,7 @@ namespace battleship{
enum class Armor {CAST, COMBINED, MECHANIC, SHELL, STEEL};
enum class State {CHASE, STAND_GROUND, HOLD_FIRE};
+ enum class Condition{ABLE, FROZEN, EM_JAMMED};
Unit(Player*, int, vb01::Vector3, vb01::Quaternion, State = State::STAND_GROUND);
virtual ~Unit();
@@ -154,7 +128,7 @@ namespace battleship{
inline float getLineOfSight() {return lineOfSight;}
inline UnitType getType() {return type;}
inline UnitClass getUnitClass() {return unitClass;}
- inline void takeDamage(int damage) {health -= damage;}
+ inline void takeDamage(int damage) {health -= damage * (1 + (freezeDmgFactor - 1) * freezeStatus * .01f);}
inline int getPlayerId() {return playerId;}
inline int getHealth(){return health;}
inline int getDeathHp(){return DEATH_HP;}
@@ -165,6 +139,14 @@ namespace battleship{
inline std::string getGuiScreen(){return guiScreen;}
inline BuildableUnit getBuildableUnit(int i){return buildableUnits[i];}
inline vb01::Node* getLosLightNode(){return losLightNode;}
+ inline void setFreezeStatus(int fs){this->freezeStatus = std::clamp(fs, 0, 100);}
+ inline int getFreezeStatus(){return freezeStatus;}
+ inline Condition getCondition(){return condition;}
+ inline void setCondition(Condition cond){
+ this->condition = cond;
+
+ if(cond == Condition::EM_JAMMED) lastJamTime = vb01::getTime();
+ }
private:
void renderOrderLine(bool);
void updateScreenCoordinates();
@@ -178,13 +160,14 @@ namespace battleship{
sf::Sound *selectionSfx = nullptr;
vb01::Node *hpBackgroundNode = nullptr, *hpForegroundNode = nullptr, *losLightNode = nullptr;
bool vehicle;
+ Condition condition = Condition::ABLE;
protected:
UnitClass unitClass;
UnitType type;
std::vector orders;
std::string guiScreen = "";
- int health = 0, maxHealth, playerId, lenHpBar = 200;
- vb01::s64 orderLineDispTime = 0, lastFireTime = 0;
+ int health = 0, maxHealth, playerId, lenHpBar = 200, freezeStatus = 0, freezeDmgFactor = 10, restartTime;
+ vb01::s64 orderLineDispTime = 0, lastFireTime = 0, lastJamTime = 0;
float lineOfSight;
std::vector armorTypes;
std::vector weapons;
@@ -192,8 +175,10 @@ namespace battleship{
std::vector buildableUnits;
State state = State::STAND_GROUND;
+ void placeAt(vb01::Vector3);
std::vector getSelectingPlayers();
void removeOrder(int);
+ virtual bool validateLaunchOrder(){return !getWeaponsByOrder(Order::TYPE::LAUNCH).empty();}
virtual bool validateGarrisonOrder(Order){return false;}
virtual void targetUnitsAutomatically();
virtual void reinit();
@@ -211,10 +196,12 @@ namespace battleship{
virtual void launch(Order);
virtual void handleResources(Order){}
virtual void hack(Order){}
+ virtual void freeze(Order){}
float calculateRotation(vb01::Vector3, float, float);
void removeBar(vb01::Node*);
vb01::Node* createBar(vb01::Vector2, vb01::Vector2, vb01::Vector4);
void displayUnitStats(vb01::Node*, vb01::Node*, int, int, bool, vb01::Vector2 offset = vb01::Vector2::VEC_ZERO);
+ std::vector getWeaponsByOrder(Order::TYPE);
inline std::vector getArmorTypes(){return armorTypes;}
};
}
diff --git a/vehicle.cpp b/vehicle.cpp
index 2d1bfcb..1c5eb69 100644
--- a/vehicle.cpp
+++ b/vehicle.cpp
@@ -7,8 +7,10 @@
#include
#include
-#include "vehicle.h"
#include "pathfinder.h"
+#include "structure.h"
+#include "vehicle.h"
+#include "weapon.h"
#include "player.h"
#include "game.h"
#include "map.h"
@@ -246,6 +248,7 @@ namespace battleship{
}
//TODO allow ships to attack land targets and vice versa
+ //TODO recursively search for vacant dest cell neibourghss
void Vehicle::preparePathpoints(Order &order, Vector3 destPos, bool appendDestPos){
removeAllPathpoints();
@@ -263,12 +266,22 @@ namespace battleship{
if(type != UnitType::UNDERWATER && fabs(destPos.y - cells[dest].pos.y) > .1) return;
+ if(cells[dest].blockedBy){
+ vector surrCellIds = map->getSurroundingCells(cells[dest].pos, 1);
+
+ for(int scid : surrCellIds)
+ if(!cells[scid].blockedBy){
+ dest = scid;
+ break;
+ }
+ }
+
vector heuristics;
for(Map::Cell &cell : cells)
heuristics.push_back(145 * (cells[dest].pos.getDistanceFrom(cell.pos)));
- vector path = Pathfinder::getSingleton()->findPath(cells, heuristics, source, dest, (int)type);
+ vector path = Pathfinder::getSingleton()->findPath(cells, heuristics, source, dest, this);
bool pathTruncated = false;
for(int i = 0; i < path.size(); i++){
@@ -316,12 +329,19 @@ namespace battleship{
Unit::attack(order);
int currNumOrders = orders.size();
- if(weapons.empty() || prevNumOrders != currNumOrders) return;
+ if(prevNumOrders != currNumOrders) return;
Order::Target target = order.targets[0];
Vector3 targVec = (target.unit ? target.unit->getPos() : target.pos) - pos;
float distToTarg = targVec.getLength();
- Weapon *weapon = weapons[0];
+
+ vector attackWeapons = getWeaponsByOrder(Order::TYPE::ATTACK);
+ Weapon *weapon = attackWeapons[0];
+
+ for(Weapon *w : attackWeapons)
+ if(w->getMaxRange() > weapon->getMaxRange())
+ weapon = w;
+
float minDist = weapon->getMaxRange();
if(order.playerAssigned || (!order.playerAssigned && state == Unit::State::CHASE)){
@@ -334,17 +354,35 @@ namespace battleship{
removeOrder(0);
return;
}
-
- float angleToTarg = targVec.norm().getAngleBetween(dirVec);
-
- if(distToTarg <= weapon->getMaxRange()){
- if(angleToTarg <= anglePrecision)
- weapon->fire(order);
- else if(angleToTarg > anglePrecision)
- turn(calculateRotation(targVec.norm(), angleToTarg, maxTurnAngle));
- }
}
+ void Vehicle::build(Order order){
+ if(pathPoints.empty()){
+ if(!order.targets[0].unit)
+ player->addUnit(order.targets[0].unit);
+ else {
+ Structure *structure = (Structure*)order.targets[0].unit;
+ sol::table targTable = generateView()["units"][structure->getId()];
+ int costRate = (int)targTable["cost"] / 100, buildRate = (int)targTable["buildTime"] / 100;
+
+ if(structure->getBuildStatus() < 100 && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastBuildTime > buildRate){
+ structure->incrementBuildStatus();
+ player->updateResource(ResourceType::REFINEDS, -costRate, true);
+ lastBuildTime = getTime();
+ }
+ else if(structure->getBuildStatus() >= 100){
+ removeOrder(0);
+ player->incStructuresBuilt();
+ }
+ }
+ }
+ else{
+ navigate(0.5 * Map::getSingleton()->getCellSize().x);
+
+ if(type == UnitType::LAND)
+ alignToSurface();
+ }
+ }
void Vehicle::select(){
if(!garrisonable)
diff --git a/vehicle.h b/vehicle.h
index 40eb0fc..9bbb184 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -23,6 +23,7 @@ namespace battleship{
float speed, maxTurnAngle, anglePrecision;
vb01::Material *debugMat = nullptr;
std::vector debugPathPoints;
+ vb01::s64 lastBuildTime = 0;
inline int getNextPatrolPointId(int numPoints) {return patrolPointId == numPoints - 1 ? 0 : patrolPointId + 1;}
bool validateGarrisonOrder(Order);
@@ -34,6 +35,7 @@ namespace battleship{
void addPathpoint(vb01::Vector3);
void removePathpoint(int = 0);
void removeAllPathpoints();
+ void build(Order);
void select();
void reinit();
protected:
@@ -44,7 +46,7 @@ namespace battleship{
void navigateToTarget(float);
void preparePathpoints(Order&, vb01::Vector3, bool = false);
void alignToSurface();
- void attack(Order);
+ virtual void attack(Order);
void garrison(Order);
void patrol(Order);
virtual void initProperties();
diff --git a/weapon.cpp b/weapon.cpp
new file mode 100644
index 0000000..2c3da98
--- /dev/null
+++ b/weapon.cpp
@@ -0,0 +1,248 @@
+#include
+#include
+#include
+
+#include "map.h"
+#include "weapon.h"
+#include "player.h"
+#include "fxManager.h"
+#include "gameObjectFactory.h"
+#include "projectile.h"
+
+namespace battleship{
+ using namespace std;
+ using namespace vb01;
+ using namespace gameBase;
+
+ Weapon::Weapon(Unit *u, sol::table unitTable, int wid) :
+ unit(u),
+ id(wid),
+ rateOfFire(unitTable["weapons"][wid + 1]["rateOfFire"]),
+ damage(unitTable["weapons"][wid + 1]["damage"].get_or(0))
+ {
+ sol::table weaponTable = unitTable["weapons"][wid + 1];
+ maxRange = weaponTable["maxRange"];
+ orderType = (Order::TYPE)weaponTable["orderType"];
+
+ initProjectileData(weaponTable);
+
+ sol::optional horNodeTblOpt = unitTable["weapons"][wid + 1]["horizontalNode"];
+ sol::optional vertNodeTblOpt = unitTable["weapons"][wid + 1]["verticalNode"];
+
+ if(horNodeTblOpt != sol::nullopt) horNode = initNode(weaponTable, true);
+ if(vertNodeTblOpt != sol::nullopt) vertNode = initNode(weaponTable, false);
+
+ FxManager *fxManager = FxManager::getSingleton();
+ fireFx = fxManager->initFx(weaponTable["fireFx"], unit->getModel(), true);
+ if(fireFx) fxManager->addFx(fireFx);
+ }
+
+
+ Node* Weapon::initNode(sol::table weaponTable, bool horizontal){
+ sol::table nodeTbl = weaponTable[horizontal ? "horizontalNode" : "verticalNode"];
+ maxFireAngle = nodeTbl["maxFireAngle"];
+ rotSpeed = nodeTbl["rotationSpeed"];
+
+ string name = nodeTbl["name"];
+ return unit->getModel()->findDescendant(name, true);
+ }
+
+ void Weapon::initProjectileData(sol::table weaponTable){
+ string projTableKey = "projectile";
+ sol::optional proj = weaponTable[projTableKey];
+
+ if(proj != sol::nullopt){
+ projId = weaponTable[projTableKey]["id"];
+ sol::table projTable = generateView()["projectiles"];
+ ProjectileClass pc = (ProjectileClass)projTable[projId + 1]["projectileClass"];
+
+ if(pc == ProjectileClass::CRUISE_MISSILE){
+ minRange = 0;
+ float rotAngle = projTable[projId + 1]["rotAngle"];
+ float speed = projTable[projId + 1]["speed"];
+ float base = PI / 2, alpha = 0;
+
+ while(base - alpha > .001){
+ minRange += speed * sin(alpha);
+ alpha += (base - alpha > rotAngle ? rotAngle : base - alpha);
+ }
+
+ minRange *= 2;
+ }
+
+ projPar = unit->getModel();
+ sol::optional parNameOpt = weaponTable[projTableKey]["parent"];
+
+ if(parNameOpt != sol::nullopt){
+ string parName = weaponTable[projTableKey]["parent"];
+ projPar = unit->getModel()->findDescendant(parName, true);
+ }
+
+ sol::table posTable = weaponTable[projTableKey]["pos"];
+ projPos = Vector3(posTable["x"], posTable["y"], posTable["z"]);
+ sol::table rotTable = weaponTable[projTableKey]["rot"];
+ projRot = Quaternion(rotTable["w"], rotTable["x"], rotTable["y"], rotTable["z"]);
+ }
+ }
+
+ Weapon::~Weapon(){
+ FxManager *fm = FxManager::getSingleton();
+
+ if(fireFx) fm->removeFx(fireFx);
+ }
+
+ Vector3 Weapon::calcOrientVec(int id){
+ Vector3 orientVec;
+
+ switch(id){
+ case 0:
+ orientVec = unit->getDirVec();
+ break;
+ case 1:
+ orientVec = unit->getLeftVec();
+ break;
+ case 2:
+ orientVec = unit->getUpVec();
+ break;
+ }
+
+ if(horNode) orientVec = horNode->getOrientation() * orientVec;
+ if(vertNode) orientVec = vertNode->getOrientation() * orientVec;
+
+ return orientVec;
+ }
+
+ //TODO replace unit pos with absolute weapon pos for withinAngle
+ void Weapon::update(){
+ if(unit->getCondition() != Unit::Condition::ABLE) return;
+
+ int numOrders = unit->getNumOrders();
+ int ordTp = (numOrders > 0 ? (int)unit->getOrder(0).type : -1);
+ Unit *targUnit = (ordTp != -1 ? unit->getOrder(0).targets[0].unit : nullptr);
+
+ if(ordTp == (int)orderType){
+ Vector3 targPos = (targUnit ? targUnit->getPos() : unit->getOrder(0).targets[0].pos);
+ float targDist = unit->getPos().getDistanceFrom(targPos);
+
+ bool withinRange = (minRange <= targDist && targDist <= maxRange);
+
+ Vector3 dirVec = calcOrientVec(0);
+ bool withinAngle = (horNode ? Vector3(dirVec.x, 0, dirVec.z).norm().getAngleBetween((targPos - unit->getPos()).norm()) <= maxFireAngle : true);
+
+ if((Order::TYPE)ordTp == Order::TYPE::ATTACK && withinRange && withinAngle)
+ fire(unit->getOrder(0));
+ }
+ else
+ trackTarget(unit->getPos() + unit->getDirVec());
+ }
+
+ void Weapon::useFx(FxManager::Fx *fx, Vector3 targPos, bool fire){
+ if(fx && !fire)
+ FxManager::getSingleton()->addFx(fx);
+ else if(!fx)
+ return;
+
+ fx->toggleComponents(true);
+
+ Vector3 plCol = unit->getPlayer()->getColor();
+
+ for(int i = 0; i < fx->components.size(); i++){
+ FxManager::Fx::Component &comp = fx->components[i];
+
+ if(!comp.vfx) continue;
+
+ if(fire && ((Node*)comp.comp)->getName() == "laser"){
+ Vector3 initPos = unit->getPos(), laserDir = targPos - initPos;
+ float targDist = laserDir.getLength();
+ float angle = unit->getDirVec().getAngleBetween(laserDir);
+ Vector3 crossProd = unit->getDirVec().cross(laserDir);
+
+ Node *compNode = (Node*)comp.comp;
+ compNode->setOrientation(Quaternion(angle, crossProd) * compNode->getOrientation());
+
+ Box *box = (Box*)compNode->getMesh(0);
+ Vector3 size = box->getSize();
+ box->setSize(Vector3(size.x, size.y, targDist));
+ box->updateVerts(box->getMeshBase());
+ box->getMaterial()->setVec4Uniform("diffuseColor", Vector4(plCol.x, plCol.y, plCol.z, 1));
+
+ compNode->setPosition(comp.pos + .5 * targDist * Vector3::VEC_K);
+ }
+ else if(!fire)
+ ((Node*)comp.comp)->setPosition(targPos);
+ }
+ }
+
+ void Weapon::updateTargetUnit(Unit *targetUnit){
+ targetUnit->takeDamage(damage);
+ unit->updateGameStats(targetUnit);
+ }
+
+ //TODO replace the 'laser' flag literal
+ void Weapon::fire(Order order){
+ if(!canFire()) return;
+
+ Unit *targetUnit = order.targets[0].unit;
+ Vector3 targPos = (targetUnit ? targetUnit->getPos() : order.targets[0].pos);
+
+ if(fireFx) useFx(fireFx, targPos, true);
+
+ if(projId == -1){
+ sol::table weaponTbl = generateView()["units"][unit->getId() + 1]["weapons"][id + 1];
+ FxManager *fxManager = FxManager::getSingleton();
+ string fxKey = "unitHitFx";
+
+ if(targetUnit)
+ updateTargetUnit(targetUnit);
+ else{
+ Map *map = Map::getSingleton();
+ Map::Cell::Type cellType = map->getCells()[map->getCellId(targPos)].type;
+ fxKey = (cellType == Map::Cell::Type::LAND ? "landHitFx" : "waterHitFx");
+ }
+
+ sol::optional hitFxOpt = weaponTbl[fxKey];
+
+ if(hitFxOpt != sol::nullopt && ((sol::table)weaponTbl[fxKey]).size() > 0)
+ useFx(fxManager->initFx(weaponTbl[fxKey], unit->getModel(), false), targPos, false);
+ }
+ else{
+ Quaternion r = projPar->localToGlobalOrientation(projRot);
+ Vector3 p = projPar->localToGlobalPosition(projPos);
+ unit->getPlayer()->addProjectile(GameObjectFactory::createProjectile(unit, projId, p, r));
+ }
+
+ lastFireTime = getTime();
+ }
+
+ //TODO improve to allow for vertical alignment
+ void Weapon::alignNode(Vector3 targPos, Node *node, bool horizontal){
+ Vector3 targDir = targPos - unit->getPos();
+ Vector3 targDirHor = Vector3(targDir.x, 0, targDir.z).norm(), targDirVert;
+
+ Vector3 dirVec = calcOrientVec(0);
+ Vector3 dirVecHor = Vector3(dirVec.x, 0, dirVec.z).norm(), dirVecVert;
+
+ Vector3 leftVec = calcOrientVec(1);
+ bool negate = (Vector3(leftVec.x, 0, leftVec.z).norm().getAngleBetween(targDirHor) < PI / 2);
+
+ float angle = dirVecHor.getAngleBetween(targDirHor);
+ float rotAngle = (rotSpeed < angle ? rotSpeed : angle);
+
+ Quaternion rot = Quaternion((negate ? 1 : -1) * rotAngle, unit->getUpVec()) * node->getOrientation();
+ node->setOrientation(rot);
+ }
+
+ void Weapon::trackTarget(Vector3 targPos){
+ if(horNode) alignNode(targPos, horNode, true);
+ //if(vertNode) alignNode(targPos, vertNode, false);
+ }
+
+ CryoGun::CryoGun(Unit *u, sol::table unitTable, int wid) : Weapon(u, unitTable, wid){}
+
+ void CryoGun::updateTargetUnit(Unit *targetUnit){
+ if(canFreeze()){
+ targetUnit->setFreezeStatus(targetUnit->getFreezeStatus() + 1);
+ lastFreezeTime = getTime();
+ }
+ }
+}
diff --git a/weapon.h b/weapon.h
new file mode 100644
index 0000000..e734b76
--- /dev/null
+++ b/weapon.h
@@ -0,0 +1,71 @@
+#ifndef WEAPON_H
+#define WEAPON_H
+
+#include
+#include
+#include
+
+#include
+
+#include "unit.h"
+
+namespace vb01{
+ class Node;
+}
+
+namespace battleship{
+ class FxManager;
+
+ class Weapon{
+ public:
+ enum class Type{FREEZER = 1};
+
+ Weapon(Unit*, sol::table, int);
+ ~Weapon();
+ virtual void update();
+ virtual void fire(Order);
+ void trackTarget(vb01::Vector3);
+ inline int getProjectileId(){return projId;}
+ inline int getRateOfFire(){return rateOfFire;}
+ inline int getDamage(){return damage;}
+ inline int getMinRange(){return minRange;}
+ inline int getMaxRange(){return maxRange;}
+ inline Unit* getUnit(){return unit;}
+ inline Order::TYPE getOrderType(){return orderType;}
+ private:
+ Unit *unit = nullptr;
+ Order::TYPE orderType;
+ int id, projId = -1, damage = 0;
+ float minRange = 0, maxRange, rotSpeed, maxFireAngle;
+ vb01::s64 lastFireTime = 0;
+ FxManager::Fx *fireFx = nullptr;
+ vb01::Quaternion projRot;
+ vb01::Vector3 projPos;
+ float horConstraint = 1.57, vertConstraint = 1.57;
+ vb01::Node *horNode = nullptr, *vertNode = nullptr, *projPar = nullptr;
+ static std::string LASER_FLAG;
+
+ vb01::Vector3 calcOrientVec(int);
+ void alignNode(vb01::Vector3, vb01::Node*, bool);
+ void initProjectileData(sol::table);
+ vb01::Node* initNode(sol::table, bool);
+ void useFx(FxManager::Fx*, vb01::Vector3, bool);
+ inline bool canFire(){return vb01::getTime() - lastFireTime > rateOfFire;}
+ protected:
+ int rateOfFire;
+
+ virtual void updateTargetUnit(Unit*);
+ };
+
+ class CryoGun : public Weapon{
+ public:
+ CryoGun(Unit*, sol::table, int);
+ private:
+ vb01::s64 lastFreezeTime = 0;
+
+ void updateTargetUnit(Unit*);
+ inline bool canFreeze(){return vb01::getTime() - lastFreezeTime > rateOfFire;}
+ };
+}
+
+#endif