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