summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--Magic2/CMakeLists.txt15
-rw-r--r--Magic2/Grid.cpp1
-rw-r--r--Magic2/MagicDoc.cpp319
-rw-r--r--Magic2/MagicDoc.h6
-rw-r--r--Magic2/MaterialDialog.cpp1
-rw-r--r--MagicEx/CMakeLists.txt29
-rw-r--r--MagicEx/include/MagicLoad.h21
-rw-r--r--MagicEx/include/MagicLoad.inl.h32
-rw-r--r--MagicEx/include/ModelFile3DS.h (renamed from Magic2/ModelFile3DS.h)15
-rw-r--r--MagicEx/include/ModelFileMAG.h (renamed from Magic2/ModelFileMAG.h)13
-rw-r--r--MagicEx/include/ModelFileOBJ.h (renamed from Magic2/ModelFileOBJ.h)15
-rw-r--r--MagicEx/src/3ds2mag.cpp23
-rw-r--r--MagicEx/src/MagicLoad.cpp159
-rw-r--r--MagicEx/src/ModelFile3DS.cpp (renamed from Magic2/ModelFile3DS.cpp)19
-rw-r--r--MagicEx/src/ModelFileMAG.cpp (renamed from Magic2/ModelFileMAG.cpp)15
-rw-r--r--MagicEx/src/ModelFileOBJ.cpp (renamed from Magic2/ModelFileOBJ.cpp)35
-rw-r--r--MagicEx/src/convert.h22
-rw-r--r--MagicEx/src/convert.inl.h42
-rw-r--r--MagicEx/src/mag2obj.cpp23
-rw-r--r--MagicEx/src/obj2mag.cpp23
-rw-r--r--NOTICE4
-rw-r--r--NetEx/NetServer.cpp4
-rw-r--r--README.md47
-rw-r--r--README.rst46
-rw-r--r--StarsEx/CMakeLists.txt40
-rw-r--r--StarsEx/Campaign.cpp131
-rw-r--r--StarsEx/Campaign.h16
-rw-r--r--StarsEx/CampaignSaveGame.cpp39
-rw-r--r--StarsEx/Clock.cpp5
-rw-r--r--StarsEx/Clock.h2
-rw-r--r--StarsEx/CmdIntelDlg.cpp15
-rw-r--r--StarsEx/CmdIntelDlg.h1
-rw-r--r--StarsEx/CmpSelectDlg.cpp10
-rw-r--r--StarsEx/D3DXImage.cpp4
-rw-r--r--StarsEx/DebriefDlg.cpp13
-rw-r--r--StarsEx/DumpMissions.cpp10
-rw-r--r--StarsEx/DumpMissions.h10
-rw-r--r--StarsEx/IA3D.H128
-rw-r--r--StarsEx/Mission.cpp2
-rw-r--r--StarsEx/Mission.h4
-rw-r--r--StarsEx/MsnSelectDlg.cpp42
-rw-r--r--StarsEx/NetUnitDlg.cpp29
-rw-r--r--StarsEx/Player.cpp73
-rw-r--r--StarsEx/Player.h3
-rw-r--r--StarsEx/Sim.cpp19
-rw-r--r--StarsEx/SimEvent.cpp52
-rw-r--r--StarsEx/SimEvent.h46
-rw-r--r--StarsEx/StarSystem.cpp75
-rw-r--r--StarsEx/StarSystem.h5
-rw-r--r--StarsEx/Stardate.cpp137
-rw-r--r--StarsEx/Stardate.h43
-rw-r--r--StarsEx/Starshatter.cpp39
-rw-r--r--StarsEx/Weather.cpp6
-rw-r--r--StarsEx/test/ShipStats.cpp29
-rw-r--r--StarsEx/test/Stardate.cpp60
-rw-r--r--Starserver/Main.cpp3
-rw-r--r--Starshatter/Main.cpp2
-rwxr-xr-xci/test.sh2
-rw-r--r--data/content/Campaigns/01/T3.def1
-rw-r--r--data/content/Campaigns/01/T4.def1
-rw-r--r--data/content/Campaigns/01/campaign.def4
-rw-r--r--data/content/Campaigns/02/campaign.def1
-rw-r--r--data/content/Campaigns/03/campaign.def1
-rw-r--r--data/content/Campaigns/04/campaign.def1
-rw-r--r--data/content/Campaigns/05/campaign.def1
-rw-r--r--data/content/Content/content.txt2
-rw-r--r--data/content/Multiplayer/wargames.def100
-rw-r--r--data/content/Ships/Dantari_Ships/Goliath.def68
-rw-r--r--data/shatter/Campaigns/01/campaign.def1
-rw-r--r--data/shatter/Campaigns/02/campaign.def2
-rw-r--r--data/shatter/Campaigns/03/campaign.def2
-rw-r--r--data/shatter/Campaigns/04/campaign.def2
-rw-r--r--data/shatter/Campaigns/05/campaign.def2
-rw-r--r--data/shatter/Multiplayer/wargames.def102
-rw-r--r--data/shatter/Ships/Dantari_Ships/Goliath.def68
-rw-r--r--third-party/CMakeLists.txt1
-rw-r--r--third-party/l3ds/CMakeLists.txt4
-rw-r--r--third-party/l3ds/include/l3ds.h (renamed from Magic2/l3ds.h)2
-rw-r--r--third-party/l3ds/l3ds.cpp (renamed from Magic2/l3ds.cpp)5
80 files changed, 1429 insertions, 967 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ccd32d..be5bb74 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,7 @@ add_subdirectory(data)
add_subdirectory(DefinitionEx)
add_subdirectory(FoundationEx)
add_subdirectory(InfoEx)
+add_subdirectory(MagicEx)
if(MSVC)
add_subdirectory(Magic2)
endif()
diff --git a/Magic2/CMakeLists.txt b/Magic2/CMakeLists.txt
index 3ccd588..186afdf 100644
--- a/Magic2/CMakeLists.txt
+++ b/Magic2/CMakeLists.txt
@@ -8,16 +8,12 @@ add_executable(
Editor.cpp
Grid.cpp
GridProps.cpp
- l3ds.cpp
Magic.cpp
Magic.rc
MagicDoc.cpp
MagicView.cpp
MainFrm.cpp
MaterialDialog.cpp
- ModelFile3DS.cpp
- ModelFileMAG.cpp
- ModelFileOBJ.cpp
ModelView.cpp
Selection.cpp
Selector.cpp
@@ -41,12 +37,5 @@ target_precompile_headers(
Magic2
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/StdAfx.h
)
-target_link_libraries(
- Magic2
- PUBLIC FoundationEx
- PUBLIC StarsEx
- )
-target_compile_definitions(
- Magic2
- PRIVATE _AFXDLL
- )
+target_link_libraries(Magic2 PUBLIC FoundationEx MagicEx StarsEx)
+target_compile_definitions(Magic2 PRIVATE _AFXDLL)
diff --git a/Magic2/Grid.cpp b/Magic2/Grid.cpp
index 0f617e6..e988118 100644
--- a/Magic2/Grid.cpp
+++ b/Magic2/Grid.cpp
@@ -15,6 +15,7 @@
#include "Magic.h"
#include "MagicDoc.h"
+#include "MagicLoad.h"
#include "Grid.h"
#include "ActiveWindow.h"
diff --git a/Magic2/MagicDoc.cpp b/Magic2/MagicDoc.cpp
index 6bd327c..c57d922 100644
--- a/Magic2/MagicDoc.cpp
+++ b/Magic2/MagicDoc.cpp
@@ -15,6 +15,7 @@
#include "Magic.h"
#include "MagicDoc.h"
+#include "MagicLoad.h"
#include "ModelFileMAG.h"
#include "ModelFileOBJ.h"
#include "ModelFile3DS.h"
@@ -22,12 +23,8 @@
#include "Selector.h"
#include "Editor.h"
#include "Command.h"
-
-#include "Bitmap.h"
-#include "Color.h"
#include "D3DXImage.h"
#include "Geometry.h"
-#include "Pcx.h"
#include "Polygon.h"
#include "Solid.h"
@@ -236,146 +233,30 @@ BOOL MagicDoc::OnOpenDocument(LPCTSTR path_name)
return TRUE;
}
+
bool
MagicDoc::ImportFile(LPCTSTR path_name)
{
if (strstr(path_name, ".obj") || strstr(path_name, ".OBJ")) {
- ModelFileOBJ obj_file(path_name);
-
- if (solid->GetModel()) {
- Solid* s = new Solid;
-
- if (s->Load(&obj_file)) {
- // todo: insert command here
- Model* orig = solid->GetModel();
- Model* imported = s->GetModel();
-
- orig->GetMaterials().append(imported->GetMaterials());
- orig->GetSurfaces().append(imported->GetSurfaces());
- orig->OptimizeMaterials();
-
- imported->GetMaterials().clear();
- imported->GetSurfaces().clear();
-
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- delete s;
- return true;
- }
-
- delete s;
- }
- else {
- if (solid->Load(&obj_file)) {
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- return true;
- }
- }
-
- return false;
+ if (!ImportInto<ModelFileOBJ>(path_name, solid))
+ return false;
+ SetModifiedFlag(FALSE);
+ UpdateAllViews(NULL);
+ return true;
}
-
if (strstr(path_name, ".3ds") || strstr(path_name, ".3DS")) {
- ModelFile3DS model_file(path_name);
-
- if (solid->GetModel()) {
- Solid* s = new Solid;
-
- if (s->Load(&model_file)) {
- // todo: insert command here
- Model* orig = solid->GetModel();
- Model* imported = s->GetModel();
-
- orig->GetMaterials().append(imported->GetMaterials());
- orig->GetSurfaces().append(imported->GetSurfaces());
- orig->OptimizeMaterials();
-
- imported->GetMaterials().clear();
- imported->GetSurfaces().clear();
-
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- delete s;
- return true;
- }
-
- delete s;
- }
- else {
- if (solid->Load(&model_file)) {
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- return true;
- }
- }
-
- return false;
- }
-
- FILE* fp = fopen(path_name, "rb");
- if (!fp) {
- ::MessageBox(0, "Import Failed: could not open file", "ERROR", MB_OK);
- return false;
- }
-
- int version = 1;
- char file_id[5];
- fread(file_id, 4, 1, fp);
- file_id[4] = '\0';
- fclose(fp);
-
- if (strncmp(file_id, "MAG", 3)) {
- ::MessageBox(0, "Open Failed: Invalid file type", "ERROR", MB_OK);
- return false;
- }
-
- switch (file_id[3]) {
- case '6': version = 6; break;
- case '5': version = 5; break;
- default: version = 0; break;
+ if (!ImportInto<ModelFile3DS>(path_name, solid))
+ return false;
+ SetModifiedFlag(FALSE);
+ UpdateAllViews(NULL);
+ return true;
}
-
- if (version < 5 || version > 6) {
- ::MessageBox(0, "Open Failed: Unsupported version", "ERROR", MB_OK);
+ if (!ImportInto<ModelFile3DS>(path_name, solid))
return false;
- }
-
- ModelFileMAG mag_file(path_name);
-
- if (solid->GetModel()) {
- Solid* s = new Solid;
- if (s->Load(&mag_file)) {
- // todo: insert command here
- Model* orig = solid->GetModel();
- Model* imported = s->GetModel();
-
- orig->GetMaterials().append(imported->GetMaterials());
- orig->GetSurfaces().append(imported->GetSurfaces());
- orig->OptimizeMaterials();
-
- imported->GetMaterials().clear();
- imported->GetSurfaces().clear();
-
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- delete s;
- return true;
- }
-
- delete s;
- }
- else {
- InitCommandStack();
-
- if (solid->Load(&mag_file)) {
- SetModifiedFlag(FALSE);
- UpdateAllViews(NULL);
- return true;
- }
- }
-
- return false;
+ InitCommandStack();
+ SetModifiedFlag(FALSE);
+ UpdateAllViews(NULL);
+ return true;
}
bool
@@ -405,40 +286,6 @@ MagicDoc::ExportFile(LPCTSTR path_name)
// +--------------------------------------------------------------------+
-int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate)
-{
- buf = 0;
-
- FILE* f = ::fopen(filename, "rb");
-
- if (f) {
- ::fseek(f, 0, SEEK_END);
- int len = ftell(f);
- ::fseek(f, 0, SEEK_SET);
-
- if (null_terminate) {
- buf = new BYTE[len+1];
- if (buf)
- buf[len] = 0;
- }
-
- else {
- buf = new BYTE[len];
- }
-
- if (buf)
- ::fread(buf, len, 1, f);
-
- ::fclose(f);
-
- return len;
- }
-
- return 0;
-}
-
-// +--------------------------------------------------------------------+
-
void MagicDoc::DeleteContents()
{
CDocument::DeleteContents();
@@ -453,138 +300,6 @@ void MagicDoc::DeleteContents()
selection->Clear();
}
-// +--------------------------------------------------------------------+
-
-int LoadTexture(const char* fname, Bitmap*& bitmap, int type)
-{
- int result = 0;
-
- if (!fname || !*fname)
- return result;
-
- bitmap = Bitmap::CheckCache(fname);
-
- if (!bitmap) {
- bool pcx_file = strstr(fname, ".pcx") || strstr(fname, ".PCX");
-
- // handle PCX formats:
- if (pcx_file) {
- PcxImage pcx;
-
- if (pcx.Load((char*) fname) == PCX_OK) {
- bitmap = new Bitmap;
-
- // 32-bit image
- if (pcx.himap) {
- bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap);
- }
-
- // 8-bit image, check for 32-bit image as well
- else if (pcx.bitmap) {
- bitmap->CopyImage(pcx.width, pcx.height, pcx.bitmap);
-
- char tmp[256];
- int len = strlen(fname);
- bool found = false;
-
- ZeroMemory(tmp, sizeof(tmp));
-
- for (int i = 0; i < len && !found; i++) {
- if (strstr(fname + i, ".pcx") == (fname+i)) {
- found = true;
- }
- else {
- tmp[i] = fname[i];
- }
- }
-
- if (found) {
- strcat_s(tmp, "+.pcx");
- if (pcx.Load(tmp) == PCX_OK && pcx.himap != 0) {
- bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap);
- }
- }
- }
- }
- }
-
- // for all other formats, use D3DX:
- else {
- D3DXImage d3dx;
- if (d3dx.Load((char*) fname)) {
- bitmap = new Bitmap;
- bitmap->CopyHighColorImage(d3dx.width, d3dx.height, d3dx.image);
- }
- }
-
- if (bitmap) {
- LoadAlpha(fname, *bitmap, type);
-
- bitmap->SetFilename(fname);
- bitmap->SetType(type);
- bitmap->MakeTexture();
-
- Bitmap::AddToCache(bitmap);
- }
- }
-
- return result;
-}
-
-int LoadAlpha(const char* name, Bitmap& bitmap, int type)
-{
- PcxImage pcx;
- D3DXImage d3dx;
- bool pcx_file = strstr(name, ".pcx") || strstr(name, ".PCX");
- bool bmp_file = strstr(name, ".bmp") || strstr(name, ".BMP");
- bool jpg_file = strstr(name, ".jpg") || strstr(name, ".JPG");
- bool png_file = strstr(name, ".png") || strstr(name, ".PNG");
- bool tga_file = strstr(name, ".tga") || strstr(name, ".TGA");
-
- // check for an associated alpha-only (grayscale) bitmap:
- char filename[256];
- strcpy_s(filename, name);
-
- char* dot = strrchr(filename, '.');
- if (dot && pcx_file)
- strcpy(dot, "@.pcx");
- else if (dot && bmp_file)
- strcpy(dot, "@.bmp");
- else if (dot && jpg_file)
- strcpy(dot, "@.jpg");
- else if (dot && png_file)
- strcpy(dot, "@.png");
- else if (dot && tga_file)
- strcpy(dot, "@.tga");
- else
- return 0;
-
- // first try to load from current directory:
- bool loaded = false;
-
- if (pcx_file)
- loaded = pcx.Load(filename) == PCX_OK;
-
- else
- loaded = d3dx.Load(filename);
-
- // now copy the alpha values into the bitmap:
- if (loaded) {
- if (pcx_file && pcx.bitmap) {
- bitmap.CopyAlphaImage(pcx.width, pcx.height, pcx.bitmap);
- }
- else if (pcx_file && pcx.himap) {
- bitmap.CopyAlphaRedChannel(pcx.width, pcx.height, pcx.himap);
- }
- else if (d3dx.image) {
- bitmap.CopyAlphaRedChannel(d3dx.width, d3dx.height, d3dx.image);
- }
- }
-
- return 0;
-}
-
-
void MagicDoc::OnSurfaceOptimize()
{
if (solid && solid->GetModel()) {
diff --git a/Magic2/MagicDoc.h b/Magic2/MagicDoc.h
index 6242842..f9641f2 100644
--- a/Magic2/MagicDoc.h
+++ b/Magic2/MagicDoc.h
@@ -107,12 +107,6 @@ protected:
// +--------------------------------------------------------------------+
-int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate=false);
-int LoadTexture(const char* name, Bitmap*& bmp, int type=0);
-int LoadAlpha(const char* name, Bitmap& bitmap, int type=0);
-
-// +--------------------------------------------------------------------+
-
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
diff --git a/Magic2/MaterialDialog.cpp b/Magic2/MaterialDialog.cpp
index 4021dab..8359eef 100644
--- a/Magic2/MaterialDialog.cpp
+++ b/Magic2/MaterialDialog.cpp
@@ -15,6 +15,7 @@
#include "Magic.h"
#include "MagicDoc.h"
#include "MagicView.h"
+#include "MagicLoad.h"
#include "MaterialDialog.h"
#include "Selection.h"
#include "Selector.h"
diff --git a/MagicEx/CMakeLists.txt b/MagicEx/CMakeLists.txt
new file mode 100644
index 0000000..8d81e81
--- /dev/null
+++ b/MagicEx/CMakeLists.txt
@@ -0,0 +1,29 @@
+project(MagicEx)
+add_library(
+ ${PROJECT_NAME} STATIC
+ src/MagicLoad.cpp
+ src/ModelFile3DS.cpp
+ src/ModelFileMAG.cpp
+ src/ModelFileOBJ.cpp)
+target_include_directories(${PROJECT_NAME} PUBLIC include/)
+target_link_libraries(${PROJECT_NAME} PUBLIC StarsEx PRIVATE l3ds)
+
+
+add_executable(${PROJECT_NAME}_3ds2mag src/3ds2mag.cpp)
+target_link_libraries(${PROJECT_NAME}_3ds2mag PRIVATE ${PROJECT_NAME})
+set_target_properties(${PROJECT_NAME}_3ds2mag PROPERTIES OUTPUT_NAME 3ds2mag)
+
+
+add_executable(${PROJECT_NAME}_mag2obj src/mag2obj.cpp)
+target_link_libraries(${PROJECT_NAME}_mag2obj PRIVATE ${PROJECT_NAME})
+set_target_properties(${PROJECT_NAME}_mag2obj PROPERTIES OUTPUT_NAME mag2obj)
+
+
+add_executable(${PROJECT_NAME}_obj2mag src/obj2mag.cpp)
+target_link_libraries(${PROJECT_NAME}_obj2mag PRIVATE ${PROJECT_NAME})
+set_target_properties(${PROJECT_NAME}_obj2mag PROPERTIES OUTPUT_NAME obj2mag)
+
+
+install(
+ TARGETS ${PROJECT_NAME}_3ds2mag ${PROJECT_NAME}_mag2obj ${PROJECT_NAME}_obj2mag
+ RUNTIME COMPONENT Tools DESTINATION ${CMAKE_INSTALL_PREFIX})
diff --git a/MagicEx/include/MagicLoad.h b/MagicEx/include/MagicLoad.h
new file mode 100644
index 0000000..c1322bd
--- /dev/null
+++ b/MagicEx/include/MagicLoad.h
@@ -0,0 +1,21 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#pragma once
+
+#include <windows.h>
+
+#include <Bitmap.h>
+#include <Solid.h>
+
+
+int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate=false);
+int LoadTexture(const char* name, Bitmap*& bmp, int type=0);
+int LoadAlpha(const char* name, Bitmap& bitmap, int type=0);
+template <typename ModelLoader> bool ImportInto(const char* pathname, Solid* target);
+
+
+#include "MagicLoad.inl.h"
diff --git a/MagicEx/include/MagicLoad.inl.h b/MagicEx/include/MagicLoad.inl.h
new file mode 100644
index 0000000..e32ba60
--- /dev/null
+++ b/MagicEx/include/MagicLoad.inl.h
@@ -0,0 +1,32 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include <memory>
+
+#include <Solid.h>
+
+
+template <typename ModelLoader>
+bool
+ImportInto(const char* pathname, Solid* target)
+{
+ ModelLoader loader {pathname};
+ if (auto* original = target->GetModel()) {
+ auto solid = std::make_unique<Solid>();
+ if (!solid->Load(&loader))
+ return false;
+ auto* imported = solid->GetModel();
+ original->GetMaterials().append(imported->GetMaterials());
+ original->GetSurfaces().append(imported->GetSurfaces());
+ original->OptimizeMaterials();
+ imported->GetMaterials().clear();
+ imported->GetSurfaces().clear();
+ return true;
+ }
+ return target->Load(&loader);
+}
+
+
diff --git a/Magic2/ModelFile3DS.h b/MagicEx/include/ModelFile3DS.h
index 5424e6c..e539d17 100644
--- a/Magic2/ModelFile3DS.h
+++ b/MagicEx/include/ModelFile3DS.h
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,12 +11,10 @@
File loader for 3DStudio MAX 3DS format models
*/
-#ifndef ModelFile3DS_h
-#define ModelFile3DS_h
+#pragma once
-#include "Solid.h"
+#include <Solid.h>
-// +--------------------------------------------------------------------+
class ModelFile3DS : public ModelFile
{
@@ -26,11 +24,4 @@ public:
virtual bool Load(Model* m, double scale=1.0);
virtual bool Save(Model* m);
-
-protected:
};
-
-// +--------------------------------------------------------------------+
-
-#endif ModelFile3DS_h
-
diff --git a/Magic2/ModelFileMAG.h b/MagicEx/include/ModelFileMAG.h
index a005691..e11d81c 100644
--- a/Magic2/ModelFileMAG.h
+++ b/MagicEx/include/ModelFileMAG.h
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,12 +11,10 @@
File loader for MAG format models
*/
-#ifndef ModelFileMAG_h
-#define ModelFileMAG_h
+#pragma once
-#include "Solid.h"
+#include <Solid.h>
-// +--------------------------------------------------------------------+
class ModelFileMAG : public ModelFile
{
@@ -31,8 +29,3 @@ protected:
virtual bool LoadMag5(FILE* fp, Model* m, double scale);
virtual bool LoadMag6(FILE* fp, Model* m, double scale);
};
-
-// +--------------------------------------------------------------------+
-
-#endif ModelFileMAG_h
-
diff --git a/Magic2/ModelFileOBJ.h b/MagicEx/include/ModelFileOBJ.h
index 5d0f9a9..3d9089c 100644
--- a/Magic2/ModelFileOBJ.h
+++ b/MagicEx/include/ModelFileOBJ.h
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,12 +11,10 @@
File loader for Wavefront/OBJ format models
*/
-#ifndef ModelFileOBJ_h
-#define ModelFileOBJ_h
+#pragma once
-#include "Solid.h"
+#include <Solid.h>
-// +--------------------------------------------------------------------+
class ModelFileOBJ : public ModelFile
{
@@ -26,11 +24,4 @@ public:
virtual bool Load(Model* m, double scale=1.0);
virtual bool Save(Model* m);
-
-protected:
};
-
-// +--------------------------------------------------------------------+
-
-#endif ModelFileOBJ_h
-
diff --git a/MagicEx/src/3ds2mag.cpp b/MagicEx/src/3ds2mag.cpp
new file mode 100644
index 0000000..3bf9460
--- /dev/null
+++ b/MagicEx/src/3ds2mag.cpp
@@ -0,0 +1,23 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include <string>
+
+#include <ModelFile3DS.h>
+#include <ModelFileMAG.h>
+
+#include "convert.h"
+
+
+int
+main(int argc, char* argv[])
+{
+ if (argc < 2)
+ return 2;
+ const std::string input {argv[1]};
+ const auto output = input + ".mag";
+ return starshatter::convert<ModelFile3DS, ModelFileMAG>(input, output);
+}
diff --git a/MagicEx/src/MagicLoad.cpp b/MagicEx/src/MagicLoad.cpp
new file mode 100644
index 0000000..f398ab3
--- /dev/null
+++ b/MagicEx/src/MagicLoad.cpp
@@ -0,0 +1,159 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+*/
+
+#include <windows.h>
+
+#include <cstring>
+#include <fstream>
+#include <ios>
+#include <iostream>
+#include <limits>
+#include <vector>
+
+#include <MagicLoad.h>
+
+#include <Bitmap.h>
+#include <Color.h>
+#include <D3DXImage.h>
+#include <Geometry.h>
+#include <Pcx.h>
+
+
+int
+LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate)
+{
+ buf = nullptr;
+ std::fstream file {filename, file.binary | file.in};
+ if (!file.is_open())
+ return 0;
+ file.ignore(std::numeric_limits<std::streamsize>::max());
+ const auto size = file.gcount();
+ file.clear();
+ file.seekg(0);
+ if (null_terminate) {
+ buf = new BYTE[size + 1];
+ if (buf)
+ buf[size] = 0;
+ }
+ else {
+ buf = new BYTE[size];
+ }
+ if (buf) {
+ file.read(reinterpret_cast<char*>(buf), size);
+ return file.gcount();
+ }
+ return 0;
+}
+
+
+int
+LoadTexture(const char* fname, Bitmap*& bitmap, int type)
+{
+ if (fname == nullptr || fname[0] == 0)
+ return 0;
+ bitmap = Bitmap::CheckCache(fname);
+ if (bitmap)
+ return 0; // legacy behaviour
+ const bool is_pcx = std::strstr(fname, ".pcx") || std::strstr(fname, ".PCX");
+ if (is_pcx) {
+ PcxImage pcx;
+ if (pcx.Load((char*) fname) != PCX_OK) // Casting away const!
+ return 0;
+ bitmap = new Bitmap;
+ if (bitmap == nullptr)
+ return 0;
+ if (pcx.himap) {
+ bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap);
+ }
+ else if (pcx.bitmap) {
+ bitmap->CopyImage(pcx.width, pcx.height, pcx.bitmap);
+ std::vector<char> buf(std::strlen(fname) + 2);
+ std::strcpy(buf.data(), fname);
+ if (auto* ext = std::strstr(buf.data(), ".pcx"))
+ *ext = 0;
+ std::strcat(buf.data(), "+.pcx");
+ if (pcx.Load(buf.data()) == PCX_OK && pcx.himap != 0)
+ bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap);
+ }
+ else {
+ // legacy no-op
+ }
+ }
+ else {
+ D3DXImage d3dx;
+ bitmap = new Bitmap;
+ if (d3dx.Load((char*) fname)) {
+ std::cout << "d3dx done" << std::endl;
+ bitmap = new Bitmap;
+ bitmap->CopyHighColorImage(d3dx.width, d3dx.height, d3dx.image);
+ }
+ }
+ if (bitmap) {
+ LoadAlpha(fname, *bitmap, type);
+ bitmap->SetFilename(fname);
+ bitmap->SetType(type);
+ bitmap->MakeTexture();
+ Bitmap::AddToCache(bitmap);
+ }
+ return 0;
+}
+
+
+int
+LoadAlpha(const char* name, Bitmap& bitmap, int type)
+{
+ PcxImage pcx;
+ D3DXImage d3dx;
+ bool pcx_file = strstr(name, ".pcx") || strstr(name, ".PCX");
+ bool bmp_file = strstr(name, ".bmp") || strstr(name, ".BMP");
+ bool jpg_file = strstr(name, ".jpg") || strstr(name, ".JPG");
+ bool png_file = strstr(name, ".png") || strstr(name, ".PNG");
+ bool tga_file = strstr(name, ".tga") || strstr(name, ".TGA");
+
+ // check for an associated alpha-only (grayscale) bitmap:
+ char filename[256];
+ strcpy_s(filename, name);
+
+ char* dot = strrchr(filename, '.');
+ if (dot && pcx_file)
+ strcpy(dot, "@.pcx");
+ else if (dot && bmp_file)
+ strcpy(dot, "@.bmp");
+ else if (dot && jpg_file)
+ strcpy(dot, "@.jpg");
+ else if (dot && png_file)
+ strcpy(dot, "@.png");
+ else if (dot && tga_file)
+ strcpy(dot, "@.tga");
+ else
+ return 0;
+
+ // first try to load from current directory:
+ bool loaded = false;
+
+ if (pcx_file)
+ loaded = pcx.Load(filename) == PCX_OK;
+
+ else
+ loaded = d3dx.Load(filename);
+
+ // now copy the alpha values into the bitmap:
+ if (loaded) {
+ if (pcx_file && pcx.bitmap) {
+ bitmap.CopyAlphaImage(pcx.width, pcx.height, pcx.bitmap);
+ }
+ else if (pcx_file && pcx.himap) {
+ bitmap.CopyAlphaRedChannel(pcx.width, pcx.height, pcx.himap);
+ }
+ else if (d3dx.image) {
+ bitmap.CopyAlphaRedChannel(d3dx.width, d3dx.height, d3dx.image);
+ }
+ }
+
+ return 0;
+}
diff --git a/Magic2/ModelFile3DS.cpp b/MagicEx/src/ModelFile3DS.cpp
index fb07a82..aca54de 100644
--- a/Magic2/ModelFile3DS.cpp
+++ b/MagicEx/src/ModelFile3DS.cpp
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,16 +11,15 @@
File loader for 3DStudio MAX 3DS format models
*/
-#include "StdAfx.h"
-#include "Magic.h"
-#include "MagicDoc.h"
-#include "ModelFile3DS.h"
+#include <ModelFile3DS.h>
-#include "Bitmap.h"
-#include "Polygon.h"
-#include "Text.h"
-#include "List.h"
-#include "l3ds.h"
+#include <Bitmap.h>
+#include <l3ds.h>
+#include <List.h>
+#include <Polygon.h>
+#include <Text.h>
+
+#include <MagicLoad.h>
// +--------------------------------------------------------------------+
diff --git a/Magic2/ModelFileMAG.cpp b/MagicEx/src/ModelFileMAG.cpp
index 70c7b43..72e6b5b 100644
--- a/Magic2/ModelFileMAG.cpp
+++ b/MagicEx/src/ModelFileMAG.cpp
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,14 +11,13 @@
File loader for MAG format models
*/
-#include "StdAfx.h"
-#include "Magic.h"
-#include "MagicDoc.h"
-#include "ModelFileMAG.h"
+#include <ModelFileMAG.h>
-#include "Bitmap.h"
-#include "Polygon.h"
-#include "List.h"
+#include <Bitmap.h>
+#include <List.h>
+#include <Polygon.h>
+
+#include <MagicLoad.h>
// +--------------------------------------------------------------------+
diff --git a/Magic2/ModelFileOBJ.cpp b/MagicEx/src/ModelFileOBJ.cpp
index 33591bd..03c8cde 100644
--- a/Magic2/ModelFileOBJ.cpp
+++ b/MagicEx/src/ModelFileOBJ.cpp
@@ -1,5 +1,5 @@
/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
Copyright (c) 1997-2006, Destroyer Studios LLC.
@@ -11,15 +11,14 @@
File loader for Wavefront/OBJ format models
*/
-#include "StdAfx.h"
-#include "Magic.h"
-#include "MagicDoc.h"
-#include "ModelFileOBJ.h"
+#include <ModelFileOBJ.h>
-#include "Bitmap.h"
-#include "Polygon.h"
-#include "List.h"
-#include "Text.h"
+#include <Bitmap.h>
+#include <Polygon.h>
+#include <List.h>
+#include <Text.h>
+
+#include <MagicLoad.h>
// +--------------------------------------------------------------------+
@@ -213,6 +212,20 @@ static int LoadMatls(const char* lpszPathName, Model* m)
LoadTexture(src, mtl->tex_diffuse, Bitmap::BMP_SOLID);
}
+
+ else if (strstr(line, "map_Ks")) {
+ const char* src = strstr(line, "map_Ks") + 7;
+ while (!isalnum(*src)) src++;
+
+ LoadTexture(src, mtl->tex_specular, Bitmap::BMP_SOLID);
+ }
+
+ else if (strstr(line, "map_Ke")) {
+ const char* src = strstr(line, "map_Ke") + 7;
+ while (!isalnum(*src)) src++;
+
+ LoadTexture(src, mtl->tex_emissive, Bitmap::BMP_SOLID);
+ }
}
fclose(fp);
@@ -642,6 +655,10 @@ SaveWaveFrontMatLib(const char* path, const char* root, Model* model)
fprintf(f, "illum 2\n");
if (mtl->tex_diffuse)
fprintf(f, "map_Kd %s\n", mtl->tex_diffuse->GetFilename());
+ if (mtl->tex_specular)
+ fprintf(f, "map_Ks %s\n", mtl->tex_specular->GetFilename());
+ if (mtl->tex_emissive)
+ fprintf(f, "map_Ke %s\n", mtl->tex_emissive->GetFilename());
fprintf(f, "\n");
}
diff --git a/MagicEx/src/convert.h b/MagicEx/src/convert.h
new file mode 100644
index 0000000..9bba5b8
--- /dev/null
+++ b/MagicEx/src/convert.h
@@ -0,0 +1,22 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#pragma once
+
+#include <string>
+
+
+namespace starshatter
+{
+
+
+template <typename Input, typename Output> int convert(const std::string& input, const std::string& output);
+
+
+} // namespace starshatter
+
+
+#include "convert.inl.h"
diff --git a/MagicEx/src/convert.inl.h b/MagicEx/src/convert.inl.h
new file mode 100644
index 0000000..4dbe771
--- /dev/null
+++ b/MagicEx/src/convert.inl.h
@@ -0,0 +1,42 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include <memory>
+#include <string>
+
+#include <Clock.h>
+#include <DataLoader.h>
+#include <Solid.h>
+
+#include <MagicLoad.h>
+
+
+namespace starshatter
+{
+
+
+template <typename Input, typename Output>
+int
+convert(const std::string& input, const std::string& output)
+{
+ Clock::Init();
+ DataLoader::Initialize();
+ auto solid = std::make_unique<Solid>();
+ if (!ImportInto<Input>(input.c_str(), solid.get()))
+ return 1;
+ Output exporter {output.c_str()};
+ auto* model = solid->GetModel();
+ if (model == nullptr)
+ return 1;
+ if (!exporter.Save(model))
+ return 1;
+ DataLoader::Close();
+ Clock::Close();
+ return 0;
+}
+
+
+} // namespace starshatter
diff --git a/MagicEx/src/mag2obj.cpp b/MagicEx/src/mag2obj.cpp
new file mode 100644
index 0000000..1439ac7
--- /dev/null
+++ b/MagicEx/src/mag2obj.cpp
@@ -0,0 +1,23 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include <string>
+
+#include <ModelFileMAG.h>
+#include <ModelFileOBJ.h>
+
+#include "convert.h"
+
+
+int
+main(int argc, char* argv[])
+{
+ if (argc < 2)
+ return 2;
+ const std::string input {argv[1]};
+ const auto output = input + ".obj";
+ return starshatter::convert<ModelFileMAG, ModelFileOBJ>(input, output);
+}
diff --git a/MagicEx/src/obj2mag.cpp b/MagicEx/src/obj2mag.cpp
new file mode 100644
index 0000000..5b71bb5
--- /dev/null
+++ b/MagicEx/src/obj2mag.cpp
@@ -0,0 +1,23 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include <string>
+
+#include <ModelFileMAG.h>
+#include <ModelFileOBJ.h>
+
+#include "convert.h"
+
+
+int
+main(int argc, char* argv[])
+{
+ if (argc < 2)
+ return 2;
+ const std::string input {argv[1]};
+ const auto output = input + ".mag";
+ return starshatter::convert<ModelFileOBJ, ModelFileMAG>(input, output);
+}
diff --git a/NOTICE b/NOTICE
index 20af89c..19edc8d 100644
--- a/NOTICE
+++ b/NOTICE
@@ -62,3 +62,7 @@ Starshatter: The Open Source Project uses googletest:
Copyright 2008, Google Inc.
googletest is reeleased under BSD 3-Clause license.
See <third-party/gtest/LICENSE>.
+
+
+Starshatter: The Open Source Project uses l3ds:
+Copyright (c) 2001, Lev Povalahev
diff --git a/NetEx/NetServer.cpp b/NetEx/NetServer.cpp
index 8d7efb2..61711cd 100644
--- a/NetEx/NetServer.cpp
+++ b/NetEx/NetServer.cpp
@@ -44,10 +44,10 @@ NetServer::NetServer(std::uint16_t port, int nthreads)
std::memset(conn, 0, poolsize * sizeof(NetSock*));
for (int i = 0; i < poolsize; i++) {
- pool[i] = std::thread([&]{ Reader(i); });
+ pool[i] = std::thread([this, i]{ Reader(i); });
}
- hreader = std::thread([&]{ Listener(); });
+ hreader = std::thread([this]{ Listener(); });
}
}
diff --git a/README.md b/README.md
deleted file mode 100644
index a451cec..0000000
--- a/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Starshatter: Open
-Starshatter is a space combat simulator.
-
-
-## Building
-To build Starshatter you need CMake and a C++ compiler. The only supported target platform as of now is Windows and it
-must be a 32-bit build. Both MinGW and MSVC are supported.
-
-
-### Windows
-#### MSVC
-To build Starshatter with MSVC you will need Windows SDK and old stand-alone DirectX SDK. To point CMake to the Windows
-SDK use the cache variables `WINDOWSSDK_LIBPATH` and `WINDOWSSDK_PATH`. In addition to these your environment is
-expected to have `DXSDK_DIR` variable defined.
-
-After that follow your regular workflow with CMake. You can use IDE to run everything for you, e.g., Visual Studio and
-Qt Creator both support CMake building. You can also use the CMake directly in command prompt or GUI and build it the
-project manually.
-
-
-#### MinGW
-Make sure that you use 32-bit MinGW compiler - it is usually prefixed with "i686". IDEs also support this approach but
-you need to properly configure toolchain/kit that the IDE will use.
-
-
-### Linux
-#### MinGW
-To build Starshatter on Linux you will need to use MinGW. Just in the previous cases make sure that you use 32-bit
-version that is usually prefixed with "i686". Use your host's CMake with `--toolchain` argument to configure the
-project. After that follow the regular workflow.
-
-
-## Installation
-Installation targets are not fully configured as of now.
-
-
-## Running
-Once you build you should be able to run the game assuming that all shared objects (dynamic libraries) can be found
-inside by the dynamic linker. If you are trying to run on Linux it means that you use `WINEPATH` to point to the MinGW's
-bin directory and to the build directories that contain shared objects. For Windows it usually works right away or you
-need to copy the libraries along the executable to one directory.
-
-To be able to play the game you also need the dat packages containing game resources.
-
-
-## License
-See <COPYING> and <NOTICE> files for licensing details.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..3807497
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,46 @@
+Starshatter: The Open Source Project
+====================================
+Starshatter is a military space combat simulator set in a distant future.
+
+
+Where to start
+^^^^^^^^^^^^^^
+Starshatter is a game. Start by enjoying it for a bit. Prebuilt game is available on itch.io_. Download the full game
+package, unpack it, and run *Starshatter.exe*. There is a tutorial available along with storyline dynamic campaigns, and
+one-off missions.
+
+
+Contributing
+^^^^^^^^^^^^
+You may contribute in various ways: writing and reviewing documents and lore, suggesting game balance changes, creating
+new assets, coming up with ship names, and finally writing code. Whatever you want to do, start by saying hi on
+discord_.
+
+
+Building
+^^^^^^^^
+Build systems are configured with CMake. Distributed prebuilt packages are built with MinGW and Makefiles, so you can
+expect them to work. To run the game, install it after building with ``--install`` option. Running in build tree is not
+supported at the moment.
+
+
+MinGW
+-----
+You will need 32-bit MinGW compiler. Run CMake with ``--toolchain`` option or ``CMAKE_TOOLCHAIN_FILE`` variable to point
+at included *cmake/toolchains/i686-w64-mingw32.cmake* or another appropriate toolchain definition. After initial
+generation you can follow regular workflow.
+
+
+MSVC
+----
+You will need Windows SDK and old stand-alone DirectX SDK. Configure ``WINDOWSSDK_LIBPATH`` and ``WINDOWSSDK_PATH``
+CMake variables and ``DXSDK_DIR`` environment variable to point at their respective targets.
+
+
+License
+^^^^^^^
+See *COPYING* and *NOTICE* files for licensing details.
+
+
+.. _itch.io: https://nthirtyone.itch.io/starshatter-open
+.. _discord: https://discord.com/invite/6GFacfuyBP
diff --git a/StarsEx/CMakeLists.txt b/StarsEx/CMakeLists.txt
index 4541191..2f66d84 100644
--- a/StarsEx/CMakeLists.txt
+++ b/StarsEx/CMakeLists.txt
@@ -39,18 +39,18 @@ add_library(
CmpCompleteDlg.cpp
CmpFileDlg.cpp
CmpLoadDlg.cpp
+ CmpnScreen.cpp
CmpSceneDlg.cpp
CmpSelectDlg.cpp
- CmpnScreen.cpp
Color.cpp
CombatAction.cpp
+ Combatant.cpp
CombatAssignment.cpp
CombatEvent.cpp
CombatGroup.cpp
CombatRoster.cpp
CombatUnit.cpp
CombatZone.cpp
- Combatant.cpp
ComboBox.cpp
ComboList.cpp
Component.cpp
@@ -70,11 +70,11 @@ add_library(
DriveSprite.cpp
Drone.cpp
DropShipAI.cpp
+ DumpMissions.cpp
EditBox.cpp
Element.cpp
Encrypt.cpp
EngDlg.cpp
- UIEventDispatch.cpp
ExceptionHandler.cpp
ExitDlg.cpp
Explosion.cpp
@@ -89,9 +89,9 @@ add_library(
FltDlg.cpp
Font.cpp
FontMgr.cpp
+ FormatUtil.cpp
FormDef.cpp
FormWindow.cpp
- FormatUtil.cpp
Galaxy.cpp
Game.cpp
GameScreen.cpp
@@ -100,20 +100,20 @@ add_library(
Graphic.cpp
Grid.cpp
GroundAI.cpp
- HUDSounds.cpp
- HUDView.cpp
Hangar.cpp
HardPoint.cpp
Hoop.cpp
+ HUDSounds.cpp
+ HUDView.cpp
ImageBox.cpp
ImgView.cpp
Instruction.cpp
Intel.cpp
JoyDlg.cpp
Joystick.cpp
+ Keyboard.cpp
KeyDlg.cpp
KeyMap.cpp
- Keyboard.cpp
LandingGear.cpp
Layout.cpp
Light.cpp
@@ -121,8 +121,8 @@ add_library(
LoadDlg.cpp
LoadScreen.cpp
Locale_ss.cpp
- MCIWave.cpp
MapView.cpp
+ MCIWave.cpp
Menu.cpp
MenuDlg.cpp
MenuScreen.cpp
@@ -135,8 +135,8 @@ add_library(
ModDlg.cpp
ModInfo.cpp
ModInfoDlg.cpp
- Mouse.cpp
MouseController.cpp
+ Mouse.cpp
MsnDlg.cpp
MsnEditDlg.cpp
MsnEditNavDlg.cpp
@@ -150,7 +150,6 @@ add_library(
MultiController.cpp
MusicDirector.cpp
MusicTrack.cpp
- NPClientWraps.cpp
NavAI.cpp
NavDlg.cpp
NavLight.cpp
@@ -162,11 +161,11 @@ add_library(
NetClientConfig.cpp
NetClientDlg.cpp
NetData.cpp
- NetGame.cpp
NetGameClient.cpp
+ NetGame.cpp
NetGameServer.cpp
- NetLobby.cpp
NetLobbyClient.cpp
+ NetLobby.cpp
NetLobbyDlg.cpp
NetLobbyServer.cpp
NetPacket.cpp
@@ -177,11 +176,12 @@ add_library(
NetUnitDlg.cpp
NetUser.cpp
NetUtil.cpp
+ NPClientWraps.cpp
OptDlg.cpp
- Pcx.cpp
Panic.cpp
ParseUtil.cpp
Particles.cpp
+ Pcx.cpp
Physical.cpp
PlanScreen.cpp
Player.cpp
@@ -194,7 +194,6 @@ add_library(
QuantumFlash.cpp
QuantumView.cpp
QuitView.cpp
- RLoc.cpp
RadioHandler.cpp
RadioMessage.cpp
RadioTraffic.cpp
@@ -203,6 +202,7 @@ add_library(
Random.cpp
Res.cpp
RichTextBox.cpp
+ RLoc.cpp
Scene.cpp
Screen.cpp
ScrollWindow.cpp
@@ -211,8 +211,8 @@ add_library(
Shadow.cpp
Shield.cpp
ShieldRep.cpp
- Ship.cpp
ShipAI.cpp
+ Ship.cpp
ShipCtrl.cpp
ShipDesign.cpp
ShipKiller.cpp
@@ -225,23 +225,24 @@ add_library(
Sky.cpp
Slider.cpp
Solid.cpp
- Sound.cpp
SoundCard.cpp
+ Sound.cpp
SoundD3D.cpp
Sprite.cpp
- StarSystem.cpp
+ Stardate.cpp
Starshatter.cpp
StarshipAI.cpp
StarshipTacticalAI.cpp
+ StarSystem.cpp
SteerAI.cpp
System.cpp
SystemDesign.cpp
TacRefDlg.cpp
TacticalAI.cpp
TacticalView.cpp
- Terrain.cpp
TerrainApron.cpp
TerrainClouds.cpp
+ Terrain.cpp
TerrainHaze.cpp
TerrainPatch.cpp
TerrainRegion.cpp
@@ -250,6 +251,7 @@ add_library(
Thruster.cpp
TrackIR.cpp
Trail.cpp
+ UIEventDispatch.cpp
VidDlg.cpp
Video.cpp
VideoDX9.cpp
@@ -331,6 +333,8 @@ endif()
add_executable(
${PROJECT_NAME}_test
test/AudioConfig.cpp
+ test/ShipStats.cpp
+ test/Stardate.cpp
)
generate_emulator(${PROJECT_NAME}_test LIBS Opcode ArchiveEx)
target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME} GTest::gtest_main)
diff --git a/StarsEx/Campaign.cpp b/StarsEx/Campaign.cpp
index 70846f0..3751db8 100644
--- a/StarsEx/Campaign.cpp
+++ b/StarsEx/Campaign.cpp
@@ -12,33 +12,34 @@
*/
#include "Campaign.h"
-#include "CampaignPlanStrategic.h"
+
+#include "Bitmap.h"
#include "CampaignPlanAssignment.h"
#include "CampaignPlanEvent.h"
#include "CampaignPlanMission.h"
#include "CampaignPlanMovement.h"
-#include "CampaignSituationReport.h"
+#include "CampaignPlanStrategic.h"
#include "CampaignSaveGame.h"
-#include "Combatant.h"
+#include "CampaignSituationReport.h"
+#include "Clock.h"
#include "CombatAction.h"
+#include "Combatant.h"
#include "CombatEvent.h"
#include "CombatGroup.h"
#include "CombatRoster.h"
#include "CombatUnit.h"
#include "CombatZone.h"
-#include "Galaxy.h"
-#include "Mission.h"
-#include "StarSystem.h"
-#include "Starshatter.h"
-#include "Player.h"
-
#include "ContentBundle.h"
-#include "Bitmap.h"
-#include "Clock.h"
#include "DataLoader.h"
+#include "FormatUtil.h"
+#include "Galaxy.h"
+#include "Mission.h"
#include "ParseUtil.h"
+#include "Player.h"
#include "Random.h"
-#include "FormatUtil.h"
+#include "Stardate.h"
+#include "Starshatter.h"
+#include "StarSystem.h"
const int TIME_NEVER = (int) 1e9;
@@ -108,7 +109,7 @@ static Campaign* current_campaign = 0;
Campaign::Campaign(int id, const char* n)
: campaign_id(id), name(n), mission_id(-1), mission(0), net_mission(0),
- scripted(false), sequential(false), time(0), startTime(0), loadTime(0),
+ scripted(false), sequential(false), time(0), load_time(0), start_time(0),
player_group(0), player_unit(0), status(CAMPAIGN_INIT), lockout(0),
loaded_from_savegame(false)
{
@@ -118,7 +119,7 @@ Campaign::Campaign(int id, const char* n)
Campaign::Campaign(int id, const char* n, const char* p)
: campaign_id(id), name(n), mission_id(-1), mission(0), net_mission(0),
- scripted(false), sequential(false), time(0), startTime(0), loadTime(0),
+ scripted(false), sequential(false), time(0), load_time(0), start_time(0),
player_group(0), player_unit(0), status(CAMPAIGN_INIT), lockout(0),
loaded_from_savegame(false)
{
@@ -316,8 +317,6 @@ Campaign::Clear()
player_group = 0;
player_unit = 0;
-
- updateTime = time;
}
// +--------------------------------------------------------------------+
@@ -408,11 +407,10 @@ Campaign::Unload()
{
SetStatus(CAMPAIGN_INIT);
+ starshatter::engine::SetOperationStart();
+ starshatter::engine::SetMissionStart();
Clock::GetInstance()->ResetGameTime();
- StarSystem::SetBaseTime(0);
- startTime = Stardate();
- loadTime = startTime;
lockout = 0;
for (int i = 0; i < NUM_IMAGES; i++)
@@ -489,6 +487,9 @@ Campaign::LoadCampaign(DataLoader* loader, bool full)
orders = ContentBundle::GetInstance()->GetText(orders);
}
}
+ else if (def->name()->value() == "stardate") {
+ GetDefNumber(start_time, def, filename);
+ }
else if (def->name()->value() == "scripted") {
if (def->term() && def->term()->isBool()) {
scripted = def->term()->isBool()->value();
@@ -1849,7 +1850,7 @@ Campaign::SetMissionId(int id)
long double
Campaign::Stardate()
{
- return StarSystem::Stardate();
+ return starshatter::engine::OperationTime();
}
// +--------------------------------------------------------------------+
@@ -1882,7 +1883,9 @@ Campaign::Prep()
LoadCampaign(loader, true);
}
- StarSystem::SetBaseTime(loadTime);
+ starshatter::engine::SetOperationStart(start_time);
+ starshatter::engine::SetMissionStart();
+ Clock::GetInstance()->ResetGameTime(load_time);
// load scripted missions:
if (IsScripted() && actions.isEmpty()) {
@@ -1917,7 +1920,7 @@ Campaign::ExecFrame()
if (InCutscene())
return;
- time = Stardate() - startTime;
+ time = Stardate();
if (status < CAMPAIGN_ACTIVE)
return;
@@ -1936,12 +1939,10 @@ Campaign::ExecFrame()
::Print("Campaign::ExecFrame() destroying mission list after completion...\n");
missions.destroy();
- if (!player_group || player_group->IsFighterGroup())
- time += 10 * 3600;
- else
- time += 20 * 3600;
-
- StarSystem::SetBaseTime(startTime + time - Clock::GetInstance()->GameTime()/1000.0);
+ const auto factor = (!player_group || player_group->IsFighterGroup()) ? 10.0 : 20.0;
+ Clock::GetInstance()->ResetGameTime(starshatter::engine::OperationTime() + 3600.0 * factor);
+ starshatter::engine::SetMissionStart();
+ time = Stardate();
}
else {
m.reset();
@@ -2043,20 +2044,10 @@ Campaign::StartMission()
::Print("\n\nCampaign Start Mission - %d. '%s'\n", m->Identity(), m->Name());
if (!scripted) {
- long double gtime = (long double) Clock::GetInstance()->GameTime() / 1000.0;
- long double base = startTime + m->Start() - 15 - gtime;
-
- StarSystem::SetBaseTime(base);
-
- long double current_time = Stardate() - startTime;
-
- char buffer[32];
- FormatDayTime(buffer, current_time);
- ::Print(" current time: %s\n", buffer);
-
- FormatDayTime(buffer, m->Start());
- ::Print(" mission start: %s\n", buffer);
- ::Print("\n");
+ const auto now = starshatter::engine::OperationTime().Format();
+ const auto mission_start = starshatter::engine::Stardate{m->Start()}.Format();
+ ::Print(" current time: %s\n", now.data());
+ ::Print(" mission start: %s\n", mission_start.data());
}
}
}
@@ -2070,14 +2061,10 @@ Campaign::RollbackMission()
if (m) {
if (!scripted) {
- long double gtime = (long double) Clock::GetInstance()->GameTime() / 1000.0;
- long double base = startTime + m->Start() - 60 - gtime;
-
- StarSystem::SetBaseTime(base);
-
- long double current_time = Stardate() - startTime;
- ::Print(" mission start: %d\n", m->Start());
- ::Print(" current time: %d\n", (int) current_time);
+ const auto now = starshatter::engine::OperationTime().Format();
+ const auto mission_start = starshatter::engine::Stardate{m->Start()}.Format();
+ ::Print(" current time: %s\n", now.data());
+ ::Print(" mission start: %s\n", mission_start.data());
}
m->SetActive(false);
@@ -2085,6 +2072,34 @@ Campaign::RollbackMission()
}
}
+
+long double
+Campaign::LoadTime() const
+{
+ return load_time;
+}
+
+
+void
+Campaign::SetLoadTime(long double value)
+{
+ load_time = value;
+}
+
+
+long double
+Campaign::StartTime() const
+{
+ return start_time;
+}
+
+
+void
+Campaign::SetStartTime(long double value)
+{
+ start_time = value;
+}
+
// +--------------------------------------------------------------------+
bool
@@ -2229,22 +2244,6 @@ Campaign::FindStrikeTarget(int iff, CombatGroup* strike_group)
// +--------------------------------------------------------------------+
-void
-Campaign::CommitExpiredActions()
-{
- ListIter<CombatAction> iter = actions;
- while (++iter) {
- CombatAction* a = iter.value();
-
- if (a->IsAvailable())
- a->SetStatus(CombatAction::COMPLETE);
- }
-
- updateTime = time;
-}
-
-// +--------------------------------------------------------------------+
-
int
Campaign::GetPlayerTeamScore()
{
diff --git a/StarsEx/Campaign.h b/StarsEx/Campaign.h
index c9bc534..e3548fb 100644
--- a/StarsEx/Campaign.h
+++ b/StarsEx/Campaign.h
@@ -130,7 +130,6 @@ public:
virtual void Unload();
virtual void Clear();
- virtual void CommitExpiredActions();
virtual void LockoutEvents(int seconds);
virtual void CheckPlayerGroup();
void CreatePlanners();
@@ -190,12 +189,10 @@ public:
int GetMissionId() const { return mission_id; }
Bitmap* GetImage(int n) { return &image[n]; }
long double GetTime() const { return time; }
- long double GetStartTime() const { return startTime; }
- void SetStartTime(long double t) { startTime = t; }
- long double GetLoadTime() const { return loadTime; }
- void SetLoadTime(long double t) { loadTime = t; }
- long double GetUpdateTime() const { return updateTime; }
- void SetUpdateTime(long double t) { updateTime = t; }
+ long double LoadTime() const;
+ void SetLoadTime(long double value);
+ long double StartTime() const;
+ void SetStartTime(long double value);
bool InCutscene() const;
bool IsDynamic() const;
@@ -272,9 +269,8 @@ protected:
Mission* net_mission;
long double time;
- long double loadTime;
- long double startTime;
- long double updateTime;
+ long double load_time;
+ long double start_time;
int lockout;
};
diff --git a/StarsEx/CampaignSaveGame.cpp b/StarsEx/CampaignSaveGame.cpp
index b959f01..0c6d655 100644
--- a/StarsEx/CampaignSaveGame.cpp
+++ b/StarsEx/CampaignSaveGame.cpp
@@ -13,22 +13,24 @@
*/
#include "CampaignSaveGame.h"
+
#include "Campaign.h"
-#include "Combatant.h"
+#include "Clock.h"
#include "CombatAction.h"
+#include "Combatant.h"
#include "CombatEvent.h"
#include "CombatGroup.h"
#include "CombatUnit.h"
#include "CombatZone.h"
+#include "DataLoader.h"
+#include "FormatUtil.h"
#include "Galaxy.h"
-#include "Mission.h"
-#include "StarSystem.h"
-#include "Player.h"
-
#include "Game.h"
-#include "DataLoader.h"
+#include "Mission.h"
#include "ParseUtil.h"
-#include "FormatUtil.h"
+#include "Player.h"
+#include "Stardate.h"
+#include "StarSystem.h"
static const char* SAVE_DIR = "SaveGame";
@@ -190,8 +192,8 @@ CampaignSaveGame::Load(const char* filename)
int grp_type = 0;
int grp_id = 0;
int status = 0;
- double baseTime = 0;
- double time = 0;
+ long double load_time = 0;
+ long double start_time = 0;
Text unit;
Text sitrep;
Text orders;
@@ -253,11 +255,11 @@ CampaignSaveGame::Load(const char* filename)
}
else if (def->name()->value() == "basetime") {
- GetDefNumber(baseTime, def, filename);
+ GetDefNumber(start_time, def, filename);
}
else if (def->name()->value() == "time") {
- GetDefNumber(time, def, filename);
+ GetDefNumber(load_time, def, filename);
}
else if (def->name()->value() == "sitrep") {
@@ -470,8 +472,8 @@ CampaignSaveGame::Load(const char* filename)
campaign->SetStatus(status);
if (sitrep.length()) campaign->SetSituation(sitrep);
if (orders.length()) campaign->SetOrders(orders);
- campaign->SetStartTime(baseTime);
- campaign->SetLoadTime(baseTime + time);
+ campaign->SetLoadTime(load_time);
+ campaign->SetStartTime(start_time);
campaign->LockoutEvents(3600);
campaign->Start();
@@ -567,9 +569,6 @@ CampaignSaveGame::Save(const char* name)
fopen_s(&f, s, "wb");
if (f) {
- char timestr[32];
- FormatDayTime(timestr, campaign->GetTime());
-
CombatGroup* player_group = campaign->GetPlayerGroup();
CombatUnit* player_unit = campaign->GetPlayerUnit();
@@ -582,10 +581,10 @@ CampaignSaveGame::Save(const char* name)
fprintf(f, "unit: \"%s\"\n", player_unit->Name().data());
fprintf(f, "status: %d\n", (int) campaign->GetStatus());
- fprintf(f, "basetime: %Lf\n", campaign->GetStartTime());
- fprintf(f, "time: %Lf // %s\n\n",
- campaign->GetTime(),
- timestr);
+ fprintf(f, "basetime: %.1Lf\n", starshatter::engine::OperationStart());
+ const auto operation_time = starshatter::engine::OperationTime();
+ const auto formatted_time = operation_time.Format();
+ fprintf(f, "time: %.1Lf // %s\n\n", operation_time.value, formatted_time.data());
fprintf(f, "sitrep: \"%s\"\n", campaign->Situation());
fprintf(f, "orders: \"%s\"\n\n", campaign->Orders());
diff --git a/StarsEx/Clock.cpp b/StarsEx/Clock.cpp
index 60e6f67..252cc69 100644
--- a/StarsEx/Clock.cpp
+++ b/StarsEx/Clock.cpp
@@ -80,9 +80,10 @@ Clock::Step()
void
-Clock::ResetGameTime()
+Clock::ResetGameTime(double seconds)
{
- m_game_elapsed = inner_clock::duration::zero();
+ const std::chrono::duration<double> target {seconds};
+ m_game_elapsed = std::chrono::duration_cast<inner_clock::duration>(target);
}
diff --git a/StarsEx/Clock.h b/StarsEx/Clock.h
index 40b5262..08e5005 100644
--- a/StarsEx/Clock.h
+++ b/StarsEx/Clock.h
@@ -22,7 +22,7 @@ public:
void Set();
double Step();
- void ResetGameTime();
+ void ResetGameTime(double seconds={});
void SkipGameTime(double seconds);
double Delta() const;
diff --git a/StarsEx/CmdIntelDlg.cpp b/StarsEx/CmdIntelDlg.cpp
index fb0c83b..f7ed247 100644
--- a/StarsEx/CmdIntelDlg.cpp
+++ b/StarsEx/CmdIntelDlg.cpp
@@ -49,15 +49,11 @@ DEF_MAP_CLIENT(CmdIntelDlg, OnPlay);
CmdIntelDlg::CmdIntelDlg(Screen* s, FormDef& def, CmpnScreen* mgr)
: FormWindow(s, 0, 0, s->Width(), s->Height()), CmdDlg(mgr), manager(mgr),
- stars(0), campaign(0), update_time(0), start_scene(0),
+ stars(0), campaign(0), start_scene(0),
cam_view(0), dsp_view(0)
{
stars = Starshatter::GetInstance();
campaign = Campaign::GetCampaign();
-
- if (campaign)
- update_time = campaign->GetUpdateTime();
-
Init(def);
}
@@ -140,15 +136,12 @@ CmdIntelDlg::ExecFrame()
{
CmdDlg::ExecFrame();
- if (campaign != Campaign::GetCampaign() || campaign->GetUpdateTime() != update_time) {
- campaign = Campaign::GetCampaign();
- update_time = campaign->GetUpdateTime();
-
+ if (campaign != Campaign::GetCampaign()) {
+ campaign = Campaign::GetCampaign();
lst_news->ClearItems();
txt_news->SetText("");
-
if (img_news)
- img_news->SetPicture(bmp_default);
+ img_news->SetPicture(bmp_default);
}
if (campaign) {
diff --git a/StarsEx/CmdIntelDlg.h b/StarsEx/CmdIntelDlg.h
index 8ff5fe7..98bae4f 100644
--- a/StarsEx/CmdIntelDlg.h
+++ b/StarsEx/CmdIntelDlg.h
@@ -66,7 +66,6 @@ protected:
Starshatter* stars;
Campaign* campaign;
- double update_time;
int start_scene;
Text event_scene;
};
diff --git a/StarsEx/CmpSelectDlg.cpp b/StarsEx/CmpSelectDlg.cpp
index 941c53a..028dc17 100644
--- a/StarsEx/CmpSelectDlg.cpp
+++ b/StarsEx/CmpSelectDlg.cpp
@@ -23,6 +23,7 @@
#include "CombatGroup.h"
#include "ShipDesign.h"
#include "Player.h"
+#include "Stardate.h"
#include "Clock.h"
#include "ContentBundle.h"
@@ -147,14 +148,9 @@ CmpSelectDlg::ExecFrame()
campaign->Description());
}
else {
- char time_buf[32];
char score_buf[32];
-
- double t = campaign->GetLoadTime() - campaign->GetStartTime();
- FormatDayTime(time_buf, t);
-
+ const auto load_time = starshatter::engine::Stardate{campaign->LoadTime()}.Format();
sprintf_s(score_buf, "%d", campaign->GetPlayerTeamScore());
-
Text desc = Text("<font Limerick12><color ffffff>") +
campaign->Name() +
Text("<font Verdana>\n\n") +
@@ -165,7 +161,7 @@ CmpSelectDlg::ExecFrame()
Text("\n\n<color ffff80>") +
ContentBundle::GetInstance()->GetText("CmpSelectDlg.campaign-time") +
Text("<color ffffff>\n\t") +
- time_buf +
+ load_time +
Text("\n\n<color ffff80>") +
ContentBundle::GetInstance()->GetText("CmpSelectDlg.assignment") +
Text("<color ffffff>\n\t");
diff --git a/StarsEx/D3DXImage.cpp b/StarsEx/D3DXImage.cpp
index 21b1fae..5145ac5 100644
--- a/StarsEx/D3DXImage.cpp
+++ b/StarsEx/D3DXImage.cpp
@@ -11,7 +11,6 @@
D3DX image file loader
*/
-
#include "D3DXImage.h"
#include "VideoDX9.h"
@@ -66,7 +65,6 @@ bool D3DXImage::Load(char *filename)
if (buf) {
fread(buf, len, 1, f);
fclose(f);
-
success = LoadBuffer(buf, len);
}
@@ -100,6 +98,8 @@ bool D3DXImage::LoadBuffer(BYTE* buf, int len)
IDirect3DSurface9* surf = 0;
IDirect3DDevice9* dev = VideoDX9::GetD3DDevice9();
+ if (dev == nullptr)
+ return success;
hr = dev->CreateOffscreenPlainSurface( width,
diff --git a/StarsEx/DebriefDlg.cpp b/StarsEx/DebriefDlg.cpp
index 1cd919b..b613e3c 100644
--- a/StarsEx/DebriefDlg.cpp
+++ b/StarsEx/DebriefDlg.cpp
@@ -185,16 +185,9 @@ DebriefDlg::Show()
ShipStats* stats = ShipStats::GetStats(i);
if (stats && !strcmp(ship->Name(), stats->GetName())) {
stats->Summarize();
-
- Player* player = Player::GetCurrentPlayer();
- int points = stats->GetPoints() + stats->GetCommandPoints();
-
- if (player && sim)
- points = player->GetMissionPoints(stats, sim->StartTime()) + stats->GetCommandPoints();
-
- char score[32];
- sprintf_s(score, "%d %s", points, ContentBundle::GetInstance()->GetText("DebriefDlg.points").data());
- mission_score->SetText(score);
+ const auto points = stats->EffectivePoints();
+ mission_score->SetText(Text::format(
+ "%d %s", points, ContentBundle::GetInstance()->GetText("DebriefDlg.points").data()));
break;
}
}
diff --git a/StarsEx/DumpMissions.cpp b/StarsEx/DumpMissions.cpp
new file mode 100644
index 0000000..d502d46
--- /dev/null
+++ b/StarsEx/DumpMissions.cpp
@@ -0,0 +1,10 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include "DumpMissions.h"
+
+
+int dump_missions = 0;
diff --git a/StarsEx/DumpMissions.h b/StarsEx/DumpMissions.h
new file mode 100644
index 0000000..41ad313
--- /dev/null
+++ b/StarsEx/DumpMissions.h
@@ -0,0 +1,10 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#pragma once
+
+
+extern int dump_missions;
diff --git a/StarsEx/IA3D.H b/StarsEx/IA3D.H
deleted file mode 100644
index 9e4e319..0000000
--- a/StarsEx/IA3D.H
+++ /dev/null
@@ -1,128 +0,0 @@
-/*---------------------------------------------------------------------
-*
-* ia3d.h
-*
-*---------------------------------------------------------------------
-*
-* $Id: ia3d.h%v 1.1 1996/09/02 10:50:35 mike Exp mike $
-*
-*---------------------------------------------------------------------
-*
-* ia3d header file. It's the part the outside world needs to see.
-*
-*---------------------------------------------------------------------
-*
-* AUREAL SEMICONDUCTOR, INC. PROPRIETARY AND CONFIDENTIAL
-* Copyright (c) 1996 Aureal Semiconductor, Inc. - All rights
-* reserved.
-*
-*---------------------------------------------------------------------
-*/
-
-
-#ifndef _IA3D_H_
-#define _IA3D_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
- // A3d Class ID! {D8F1EEE0-F634-11cf-8700-00A0245D918B}
- DEFINE_GUID(CLSID_A3d,
- 0xd8f1eee0, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b);
-
- // A3d Interface ID! {D8F1EEE1-F634-11cf-8700-00A0245D918B}
- DEFINE_GUID(IID_IA3d,
- 0xd8f1eee1, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b);
-
-
- // Bits for manipulating output modes
-
- // Values for bOutputMode
-#define OUTPUT_MODE_STEREO 0x00000001
-#define OUTPUT_MODE_QUAD 0x00000002
-
- // Values for FrontXtalkMode and bRearXtalkMode
-#define OUTPUT_HEADPHONES 0x00000001 // headphones
-#define OUTPUT_SPEAKERS_WIDE 0x00000002
-#define OUTPUT_SPEAKERS_NARROW 0x00000003
-
- // Values for Resource Management Mode
-#define A3D_RESOURCE_MODE_OFF 0x00000000
-#define A3D_RESOURCE_MODE_NOTIFY 0x00000001
-#define A3D_RESOURCE_MODE_DYNAMIC 0x00000002
-
- // Declare the IA3d Interface. It's not very complex at all.
-
-#undef INTERFACE
-#define INTERFACE IA3d
-
- typedef struct IA3d *LPIA3D;
-
- DECLARE_INTERFACE_(IA3d, IUnknown)
- {
- // IUnknown
- STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
- STDMETHOD_(ULONG,AddRef) (THIS) PURE;
- STDMETHOD_(ULONG,Release) (THIS) PURE;
-
- // IA3d
- STDMETHOD(SetOutputMode)(THIS_ DWORD dwFrontXtalkMode, DWORD dwBackXtalkMode, DWORD dwQuadMode) PURE;
- STDMETHOD(GetOutputMode)(THIS_ DWORD *lpdwFrontXtalkMode, DWORD *lpdwBackXtalkMode, DWORD *lpdwQuadMode) PURE;
-
- STDMETHOD(SetResourceManagerMode) (THIS_ DWORD ) PURE;
- STDMETHOD(GetResourceManagerMode) (THIS_ DWORD *) PURE;
-
- STDMETHOD(SetHFAbsorbFactor)(THIS_ FLOAT ) PURE;
- STDMETHOD(GetHFAbsorbFactor)(THIS_ FLOAT *) PURE;
-
- };
-
-
-
-
- // The library function that gets things going. It returns an interface
- // pointer to DirectSound.
-
-#define A3D_OK 1 // A3dCreate returns this upon detection of A3D enabled hardware.
-
- _declspec (dllexport) HRESULT WINAPI
- A3dCreate(GUID * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter );
-
- // Usefull Macros for C folks.
-
-#if !defined(__cplusplus) || defined(CINTERFACE)
-#define IA3d_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
-#define IA3d_AddRef(p) (p)->lpVtbl->AddRef(p)
-#define IA3d_Release(p) (p)->lpVtbl->Release(p)
-#define IA3d_SetOutputMode(p,a,b,c) (p)->lpVtbl->SetOutputMode(p,a,b,c)
-#define IA3d_GetOutputMode(p,a,b,c) (p)->lpVtbl->GetOutputMode(p,a,b,c)
-#define IA3d_SetResourceManagerMode(p,a) (p)->lpVtbl->SetResourceManagerMode(p,a)
-#define IA3d_GetResourceManagerMode(p,a) (p)->lpVtbl->GetResourceManagerMode(p,a)
-#define IA3d_SetHFAbsorbFactor(p,a) (p)->lpVtbl->SetHFAbsorbFactor(p,a)
-#define IA3d_GetHFAbsorbFactor(p,a) (p)->lpVtbl->GetHFAbsorbFactor(p,a)
-
-
-#else
-#define IA3d_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
-#define IA3d_AddRef(p) (p)->AddRef()
-#define IA3d_Release(p) (p)->Release()
-#define IA3d_SetOutputMode(p,a,b,c) (p)->SetOutputMode(a,b,c)
-#define IA3d_GetOutputMode(p,a,b,c) (p)->GetOutputMode(a,b,c)
-#define IA3d_SetResourceManagerMode(p,a) (p)->SetResourceManagerMode(a)
-#define IA3d_GetResourceManagerMode(p,a) (p)->GetResourceManagerMode(a)
-#define IA3d_SetHFAbsorbFactor(p,a) (p)->SetHFAbsorbFactor(a)
-#define IA3d_GetHFAbsorbFactor(p,a) (p)->GetHFAbsorbFactor(a)
-
-#endif
-
-
-
-#ifdef __cplusplus
-};
-#endif
-
-
-
-#endif // _IA3D_H_
diff --git a/StarsEx/Mission.cpp b/StarsEx/Mission.cpp
index 2350a8d..f794335 100644
--- a/StarsEx/Mission.cpp
+++ b/StarsEx/Mission.cpp
@@ -1409,6 +1409,8 @@ Mission::Serialize(const char* player_elem, int player_index)
s += "\"\n\n";
}
+ s += Text::format("stardate: %.1Lf\n", Stardate());
+
char buffer[256];
FormatTime(buffer, Start());
diff --git a/StarsEx/Mission.h b/StarsEx/Mission.h
index 5bcffa7..0b8c0a6 100644
--- a/StarsEx/Mission.h
+++ b/StarsEx/Mission.h
@@ -104,7 +104,7 @@ public:
const char* Objective() const { return objective; }
const char* Subtitles() const;
int Start() const { return start; }
- double Stardate() const { return stardate; }
+ long double Stardate() const { return stardate; }
int Type() const { return type; }
const char* TypeName() const { return RoleName(type); }
int Team() const { return team; }
@@ -174,7 +174,7 @@ protected:
int type;
int team;
int start;
- double stardate;
+ long double stardate;
bool ok;
bool active;
bool complete;
diff --git a/StarsEx/MsnSelectDlg.cpp b/StarsEx/MsnSelectDlg.cpp
index 8c720c8..1f61d9a 100644
--- a/StarsEx/MsnSelectDlg.cpp
+++ b/StarsEx/MsnSelectDlg.cpp
@@ -12,25 +12,27 @@
*/
#include "MsnSelectDlg.h"
-#include "MsnEditDlg.h"
-#include "MsnEditNavDlg.h"
-#include "ConfirmDlg.h"
-#include "MenuScreen.h"
-#include "Starshatter.h"
-#include "Campaign.h"
-#include "Mission.h"
-#include "Game.h"
-#include "ContentBundle.h"
#include "Button.h"
+#include "Campaign.h"
+#include "Clock.h"
#include "ComboBox.h"
-#include "ListBox.h"
-#include "Slider.h"
-#include "Video.h"
+#include "ConfirmDlg.h"
+#include "ContentBundle.h"
+#include "FormatUtil.h"
+#include "Game.h"
#include "Keyboard.h"
+#include "ListBox.h"
+#include "MenuScreen.h"
+#include "Mission.h"
#include "Mouse.h"
+#include "MsnEditDlg.h"
+#include "MsnEditNavDlg.h"
#include "ParseUtil.h"
-#include "FormatUtil.h"
+#include "Slider.h"
+#include "Stardate.h"
+#include "Starshatter.h"
+#include "Video.h"
// +--------------------------------------------------------------------+
// DECLARE MAPPING FUNCTIONS:
@@ -393,6 +395,9 @@ MsnSelectDlg::OnNew(AWEvent* event)
navdlg->SetMission(info->mission);
navdlg->SetMissionInfo(info);
}
+ starshatter::engine::SetOperationStart(info->mission->Stardate());
+ starshatter::engine::SetMissionStart(info->mission->Start());
+ Clock::GetInstance()->ResetGameTime();
}
void
@@ -418,6 +423,9 @@ MsnSelectDlg::OnEdit(AWEvent* event)
editor->SetMissionInfo(c->GetMissionInfo(mission_id));
editor->SetMission(m);
+ starshatter::engine::SetOperationStart(m->Stardate());
+ starshatter::engine::SetMissionStart(m->Start());
+ Clock::GetInstance()->ResetGameTime();
manager->ShowMsnEditDlg();
}
}
@@ -479,11 +487,13 @@ MsnSelectDlg::OnAccept(AWEvent* event)
{
if (selected_mission >= 0) {
Mouse::Show(false);
-
- int id = campaign->GetMissionList()[selected_mission]->id;
+ const auto id = campaign->GetMissionList()[selected_mission]->id;
campaign->SetMissionId(id);
campaign->ReloadMission(id);
-
+ const auto* mission = campaign->GetMission();
+ starshatter::engine::SetOperationStart(mission->Stardate());
+ starshatter::engine::SetMissionStart(mission->Start());
+ Clock::GetInstance()->ResetGameTime();
stars->SetGameMode(Game::PREP_MODE);
}
}
diff --git a/StarsEx/NetUnitDlg.cpp b/StarsEx/NetUnitDlg.cpp
index 26b2af7..d9d7144 100644
--- a/StarsEx/NetUnitDlg.cpp
+++ b/StarsEx/NetUnitDlg.cpp
@@ -12,27 +12,27 @@
*/
#include "NetUnitDlg.h"
-#include "NetClientConfig.h"
+
+#include "Campaign.h"
+#include "Campaign.h"
+#include "Clock.h"
#include "ConfirmDlg.h"
+#include "ContentBundle.h"
+#include "Keyboard.h"
#include "MenuScreen.h"
-#include "Starshatter.h"
-#include "Campaign.h"
#include "Mission.h"
-#include "Ship.h"
-#include "Player.h"
-#include "Campaign.h"
-#include "ShipDesign.h"
-
#include "NetAddr.h"
+#include "NetChat.h"
+#include "NetClientConfig.h"
#include "NetLobbyClient.h"
#include "NetLobbyServer.h"
#include "NetUser.h"
-#include "NetChat.h"
-
-#include "ContentBundle.h"
+#include "Player.h"
+#include "ShipDesign.h"
+#include "Ship.h"
+#include "Stardate.h"
+#include "Starshatter.h"
#include "Video.h"
-#include "Keyboard.h"
-#include "Clock.h"
// +--------------------------------------------------------------------+
// DECLARE MAPPING FUNCTIONS:
@@ -619,6 +619,9 @@ NetUnitDlg::OnApply(AWEvent* event)
Mission* mission = net_lobby->GetSelectedMission();
if (mission) {
+ starshatter::engine::SetOperationStart(mission->Stardate());
+ starshatter::engine::SetMissionStart(mission->Start());
+ Clock::GetInstance()->ResetGameTime();
net_lobby->GameStart();
ok = true;
}
diff --git a/StarsEx/Player.cpp b/StarsEx/Player.cpp
index fffa9a6..f299079 100644
--- a/StarsEx/Player.cpp
+++ b/StarsEx/Player.cpp
@@ -13,25 +13,25 @@
#include "Player.h"
+#include <algorithm>
#include <cstdint>
-#include "NetLobbyServer.h"
-#include "NetLayer.h"
-#include "Ship.h"
-#include "SimEvent.h"
+#include "Bitmap.h"
#include "Campaign.h"
#include "CampaignSaveGame.h"
-#include "Random.h"
-#include "HUDView.h"
-#include "Mfd.h"
-
+#include "Clock.h"
+#include "ContentBundle.h"
#include "DataLoader.h"
#include "Encrypt.h"
-#include "ParseUtil.h"
#include "FormatUtil.h"
-#include "Bitmap.h"
-#include "Clock.h"
-#include "ContentBundle.h"
+#include "HUDView.h"
+#include "Mfd.h"
+#include "NetLayer.h"
+#include "NetLobbyServer.h"
+#include "ParseUtil.h"
+#include "Random.h"
+#include "Ship.h"
+#include "SimEvent.h"
// +-------------------------------------------------------------------+
@@ -634,56 +634,19 @@ Player::CommandRankRequired(int ship_class)
// +-------------------------------------------------------------------+
-int
-Player::GetMissionPoints(ShipStats* s, std::uint32_t start_time)
-{
- int result = 0;
-
- if (s) {
- result = s->GetPoints();
-
- int flight_time = (Clock::GetInstance()->GameTime() - start_time) / 1000;
-
- // if player survived mission, award one experience point
- // for each minute of action, in ten point blocks:
- if (!s->GetDeaths() && !s->GetColls()) {
- int minutes = flight_time / 60;
- minutes /= 10;
- minutes *= 10;
- result += minutes;
-
- if (s->HasEvent(SimEvent::DOCK))
- result += 100;
- }
- else {
- result -= (int) (2.5 * Ship::Value(s->GetShipClass()));
- }
-
- if (result < 0)
- result = 0;
- }
-
- return result;
-}
-
-// +-------------------------------------------------------------------+
-
void
-Player::ProcessStats(ShipStats* s, std::uint32_t start_time)
+Player::ProcessStats(ShipStats* s)
{
- if (!s) return;
-
+ if (!s)
+ return;
int old_rank = Rank();
- int pts = GetMissionPoints(s, start_time);
-
- AddPoints(pts);
- AddPoints(s->GetCommandPoints());
+ AddMissions(1);
+ AddPoints(s->EffectivePoints());
AddKills(s->GetGunKills());
AddKills(s->GetMissileKills());
AddLosses(s->GetDeaths());
AddLosses(s->GetColls());
- AddMissions(1);
- AddFlightTime((Clock::GetInstance()->GameTime() - start_time) / 1000);
+ AddFlightTime(s->FlightTime());
int rank = Rank();
diff --git a/StarsEx/Player.h b/StarsEx/Player.h
index c0a9b6c..867e2ca 100644
--- a/StarsEx/Player.h
+++ b/StarsEx/Player.h
@@ -116,8 +116,7 @@ public:
Text EncodeStats();
void DecodeStats(const char* stats);
- int GetMissionPoints(ShipStats* stats, std::uint32_t start_time);
- void ProcessStats(ShipStats* stats, std::uint32_t start_time);
+ void ProcessStats(ShipStats* stats);
bool EarnedAward(AwardInfo* a, ShipStats* s);
static const char* RankName(int rank);
diff --git a/StarsEx/Sim.cpp b/StarsEx/Sim.cpp
index bdf843b..965ee76 100644
--- a/StarsEx/Sim.cpp
+++ b/StarsEx/Sim.cpp
@@ -71,6 +71,7 @@
#include "Solid.h"
#include "Sound.h"
#include "Sprite.h"
+#include "Stardate.h"
#include "Starshatter.h"
#include "StarSystem.h"
#include "Terrain.h"
@@ -122,8 +123,7 @@ Sim* Sim::sim = 0;
Sim::Sim(MotionController* c)
: ctrl(c), test_mode(false), grid_shown(false), dust(0),
- star_system(0), active_region(0), mission(0), netgame(0),
- start_time(0)
+ star_system(0), active_region(0), mission(0), netgame(0)
{
Drive::Initialize();
Explosion::Initialize();
@@ -206,7 +206,8 @@ Sim::CommitMission()
if (s->IsPlayer()) {
Player* p = Player::GetCurrentPlayer();
- p->ProcessStats(s, start_time);
+ s->SetFlightTime(starshatter::engine::MissionTime());
+ p->ProcessStats(s);
if (mission && mission->Type() == Mission::TRAINING &&
s->GetDeaths() == 0 && s->GetColls() == 0)
@@ -368,8 +369,10 @@ Sim::ExecMission()
if (cam_dir)
cam_dir->Reset();
- if (mission->Stardate() > 0)
- StarSystem::SetBaseTime(mission->Stardate(), true);
+ if (mission->Stardate() > 0.0l)
+ starshatter::engine::SetOperationStart(mission->Stardate());
+ starshatter::engine::SetMissionStart(mission->Start());
+ Clock::GetInstance()->ResetGameTime();
star_system = mission->GetStarSystem();
star_system->Activate(scene);
@@ -395,7 +398,6 @@ Sim::ExecMission()
}
first_frame = true;
- start_time = Clock::GetInstance()->GameTime();
AudioConfig::SetTraining(mission->Type() == Mission::TRAINING);
}
@@ -1662,6 +1664,7 @@ Sim::ResolveHyperList()
}
ProcessEventTrigger(MissionEvent::TRIGGER_JUMP, 0, s->Name());
+ NetUtil::SendObjHyper(s, dest->Name(), jump->loc, jump->fc_src, jump->fc_dst, jump->type);
}
}
@@ -1896,7 +1899,7 @@ Sim::ProcessEventTrigger(int type, int event_id, const char* ship, int param)
double
Sim::MissionClock() const
{
- return (Clock::GetInstance()->GameTime() - start_time) / 1000.0;
+ return starshatter::engine::MissionTime();
}
// +--------------------------------------------------------------------+
@@ -1931,7 +1934,7 @@ Sim::SkipCutscene()
}
}
- double skip_time = end_time - MissionClock();
+ const auto skip_time = end_time - MissionClock();
if (skip_time > 0) {
Clock::GetInstance()->SkipGameTime(skip_time);
}
diff --git a/StarsEx/SimEvent.cpp b/StarsEx/SimEvent.cpp
index 35eb117..42ce240 100644
--- a/StarsEx/SimEvent.cpp
+++ b/StarsEx/SimEvent.cpp
@@ -12,9 +12,11 @@
*/
#include "SimEvent.h"
-#include "Sim.h"
+
#include "Clock.h"
#include "ContentBundle.h"
+#include "Ship.h"
+#include "Sim.h"
// +====================================================================+
@@ -191,6 +193,52 @@ ShipStats::Summarize()
}
}
+
+long double
+ShipStats::FlightTime() const
+{
+ return flight_time;
+}
+
+
+void
+ShipStats::SetFlightTime(long double seconds)
+{
+ flight_time = seconds;
+}
+
+
+static int
+FlightTimeBonus(const ShipStats* stats)
+{
+ static constexpr long double TEN_MINUTES {600.0l};
+ return static_cast<int>(stats->FlightTime() / TEN_MINUTES) * 10;
+}
+
+
+static int
+DockBonus(const ShipStats* stats)
+{
+ return stats->HasEvent(SimEvent::DOCK) ? 100 : 0;
+}
+
+
+static int
+LossPenalty(const ShipStats* stats)
+{
+ return 2.5 * Ship::Value(stats->GetShipClass());
+}
+
+
+int
+ShipStats::EffectivePoints() const
+{
+ const auto whole {GetPoints() + GetCommandPoints()};
+ if (GetDeaths() > 0 || GetColls() > 0)
+ return std::max(0, whole - LossPenalty(this));
+ return whole + FlightTimeBonus(this) + DockBonus(this);
+}
+
// +--------------------------------------------------------------------+
SimEvent*
@@ -209,7 +257,7 @@ ShipStats::AddEvent(int event, const char* tgt, const char* info)
}
bool
-ShipStats::HasEvent(int event)
+ShipStats::HasEvent(int event) const
{
for (int i = 0; i < events.size(); i++)
if (events[i]->GetEvent() == event)
diff --git a/StarsEx/SimEvent.h b/StarsEx/SimEvent.h
index 66d6342..c8bd092 100644
--- a/StarsEx/SimEvent.h
+++ b/StarsEx/SimEvent.h
@@ -11,14 +11,11 @@
Simulation Universe and Region classes
*/
-#ifndef SimEvent_h
-#define SimEvent_h
+#pragma once
-#include "Types.h"
-#include "List.h"
-#include "Text.h"
+#include <List.h>
+#include <Text.h>
-// +--------------------------------------------------------------------+
class Sim;
class SimRegion;
@@ -28,19 +25,32 @@ class SimHyper;
class CombatGroup;
class CombatUnit;
-// +--------------------------------------------------------------------+
class SimEvent
{
public:
static const char* TYPENAME() { return "SimEvent"; }
- enum EVENT { LAUNCH=1, DOCK, LAND, EJECT, CRASH, COLLIDE, DESTROYED,
- MAKE_ORBIT, BREAK_ORBIT, QUANTUM_JUMP,
- LAUNCH_SHIP, RECOVER_SHIP,
- FIRE_GUNS, FIRE_MISSILE, DROP_DECOY,
- GUNS_KILL, MISSILE_KILL,
- LAUNCH_PROBE, SCAN_TARGET
+ enum EVENT {
+ LAUNCH=1,
+ DOCK,
+ LAND,
+ EJECT,
+ CRASH,
+ COLLIDE,
+ DESTROYED,
+ MAKE_ORBIT,
+ BREAK_ORBIT,
+ QUANTUM_JUMP,
+ LAUNCH_SHIP,
+ RECOVER_SHIP,
+ FIRE_GUNS,
+ FIRE_MISSILE,
+ DROP_DECOY,
+ GUNS_KILL,
+ MISSILE_KILL,
+ LAUNCH_PROBE,
+ SCAN_TARGET,
};
SimEvent(int event, const char* tgt=0, const char* info=0);
@@ -66,7 +76,6 @@ private:
int count;
};
-// +--------------------------------------------------------------------+
class ShipStats
{
@@ -104,6 +113,8 @@ public:
int GetGunHits() const { return gun_hits; }
int GetMissileShots() const { return missile_shots; }
int GetMissileHits() const { return missile_hits; }
+ long double FlightTime() const;
+ int EffectivePoints() const;
bool IsPlayer() const { return player; }
@@ -111,7 +122,7 @@ public:
GetEvents() { return events; }
SimEvent* AddEvent(SimEvent* e);
SimEvent* AddEvent(int event, const char* tgt=0, const char* info=0);
- bool HasEvent(int event);
+ bool HasEvent(int event) const;
void SetShipClass(int c) { ship_class = c; }
void SetIFF(int i) { iff = i; }
@@ -129,6 +140,7 @@ public:
void AddMissileHit() { missile_hits++; }
void AddPoints(int p) { points += p; }
void AddCommandPoints(int p) { cmd_points += p; }
+ void SetFlightTime(long double seconds);
private:
Text name;
@@ -155,8 +167,6 @@ private:
int points;
int cmd_points;
+ long double flight_time;
List<SimEvent> events;
};
-
-#endif // SimEvent_h
-
diff --git a/StarsEx/StarSystem.cpp b/StarsEx/StarSystem.cpp
index b8340f6..6641b63 100644
--- a/StarsEx/StarSystem.cpp
+++ b/StarsEx/StarSystem.cpp
@@ -12,71 +12,31 @@
*/
#include "StarSystem.h"
-#include "Galaxy.h"
-#include "Sky.h"
-#include "Starshatter.h"
-#include "TerrainRegion.h"
-#include "TerrainHaze.h"
-#include "Weather.h"
+#include "Bitmap.h"
+#include "Clock.h"
+#include "DataLoader.h"
+#include "Galaxy.h"
#include "Game.h"
#include "GameWinDX9.h"
-#include "Clock.h"
-#include "Sound.h"
-#include "Solid.h"
#include "Light.h"
-#include "Bitmap.h"
-#include "DataLoader.h"
-#include "Scene.h"
#include "ParseUtil.h"
+#include "Scene.h"
+#include "Sky.h"
+#include "Solid.h"
+#include "Sound.h"
+#include "Stardate.h"
+#include "Starshatter.h"
+#include "TerrainHaze.h"
+#include "TerrainRegion.h"
#include "Video.h"
-
-const long double epoch = 0.5e9;
-long double StarSystem::stardate = 0;
+#include "Weather.h"
// +====================================================================+
-static long double base_time = 0;
static WORD oldcw = 0;
static WORD fpcw = 0;
-void StarSystem::SetBaseTime(long double t, bool absolute)
-{
- if (absolute) {
- base_time = t;
- CalcStardate();
- }
-
- else if (t > 0) {
- if (t > epoch) t -= epoch;
- base_time = t;
- CalcStardate();
- }
-}
-
-long double StarSystem::GetBaseTime()
-{
- return base_time;
-}
-
-void StarSystem::CalcStardate()
-{
- if (base_time < 1) {
- time_t clock_seconds;
- time(&clock_seconds);
-
- base_time = clock_seconds;
-
- while (base_time < 0)
- base_time += epoch;
- }
-
- long double gtime = Clock::GetInstance()->GameTime<long double>() / 1000.0;
- long double sdate = gtime + base_time + epoch;
-
- stardate = sdate;
-}
-
static const double GRAV = 6.673e-11;
static const int NAMELEN = 64;
@@ -119,7 +79,6 @@ static OrbitalBody* primary_moon = 0;
void
StarSystem::Load()
{
- CalcStardate();
active_region = 0;
BYTE* block = 0;
@@ -1386,8 +1345,6 @@ static BYTE min3(BYTE a, BYTE b, BYTE c)
void
StarSystem::ExecFrame()
{
- CalcStardate();
-
ListIter<OrbitalBody> star = bodies;
while (++star)
star->Update();
@@ -1843,7 +1800,7 @@ Orbital::Update()
double grade = (retro) ? -1 : 1;
// orbits are counter clockwise:
- phase = -2 * PI * grade * StarSystem::Stardate() / period;
+ phase = PI * -2.0 * grade * starshatter::engine::CurrentTime() / period;
loc = primary->Location() + Point((double) (orbit * cos(phase)),
(double) (orbit * sin(phase)),
@@ -1871,7 +1828,7 @@ Orbital::PredictLocation(double delta_t)
double grade = (retro) ? -1 : 1;
// orbits are(?) counter clockwise:
- double predicted_phase = (double) (-2 * PI * grade * (StarSystem::Stardate()+delta_t) / period);
+ const auto predicted_phase = PI * -2.0 * grade * (starshatter::engine::CurrentTime() + delta_t) / period;
predicted_loc += Point((double) (orbit * cos(predicted_phase)),
(double) (orbit * sin(predicted_phase)),
@@ -1917,7 +1874,7 @@ OrbitalBody::Update()
theta = 0;
if (rotation > 0)
- theta = -2 * PI * StarSystem::Stardate() / rotation;
+ theta = PI * -2.0 * starshatter::engine::CurrentTime() / rotation;
ListIter<OrbitalBody> body = satellites;
while (++body)
diff --git a/StarsEx/StarSystem.h b/StarsEx/StarSystem.h
index bdd37ec..6770f4a 100644
--- a/StarsEx/StarSystem.h
+++ b/StarsEx/StarSystem.h
@@ -78,10 +78,6 @@ public:
void SetActiveRegion(OrbitalRegion* rgn);
- static void SetBaseTime(long double t, bool absolute=false);
- static long double GetBaseTime();
- static long double Stardate() { return stardate; }
- static void CalcStardate();
double Radius() const { return radius; }
void SetSunlight(Color color, double brightness=1);
@@ -109,7 +105,6 @@ protected:
int affiliation;
int seq;
Point loc;
- static long double stardate;
double radius;
bool instantiated;
diff --git a/StarsEx/Stardate.cpp b/StarsEx/Stardate.cpp
new file mode 100644
index 0000000..f57205a
--- /dev/null
+++ b/StarsEx/Stardate.cpp
@@ -0,0 +1,137 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include "Stardate.h"
+
+#include <cstdint>
+
+#include <Text.h>
+
+#include "Clock.h"
+
+
+namespace starshatter
+{
+namespace engine
+{
+
+
+static constexpr long double EPOCH {0.5e9l};
+static constexpr long double MINUTE {60};
+static constexpr long double HOUR {60 * MINUTE};
+static constexpr long double DAY {24 * HOUR};
+static long double operation_start {};
+static long double mission_start {};
+
+
+Stardate::Stardate() :
+ value {0}
+{
+}
+
+
+Stardate::Stardate(long double value_) :
+ value {value_}
+{
+}
+
+
+Stardate::operator long double() const
+{
+ return value;
+}
+
+
+Text
+Stardate::Format(bool short_format) const
+{
+ auto time = value;
+ std::int_fast32_t day = 1, hours = 0, minutes = 0, seconds = 0;
+ while (time >= DAY) {
+ time -= DAY;
+ ++day;
+ }
+ while (time >= HOUR) {
+ time -= HOUR;
+ ++hours;
+ }
+ while (time >= MINUTE) {
+ time -= MINUTE;
+ ++minutes;
+ }
+ seconds = time;
+ return Text::format(
+ short_format ? "%02d/%02d:%02d:%02d" : "Day %d, %02d:%02d:%02d",
+ day, hours, minutes, seconds);
+}
+
+
+Stardate
+CurrentTime()
+{
+ return Epoch() + OperationStart() + OperationTime();
+}
+
+
+Stardate
+OperationTime()
+{
+ return MissionStart() + MissionTime();
+}
+
+
+Stardate
+MissionTime()
+{
+ if (const auto* clock = Clock::GetInstance())
+ return clock->GameTime<long double>() / 1000.0l;
+ throw "game clock not initialized";
+}
+
+
+long double
+Epoch()
+{
+ return EPOCH;
+}
+
+
+long double
+OperationStart()
+{
+ return operation_start;
+}
+
+
+long double
+MissionStart()
+{
+ return mission_start;
+}
+
+
+void
+SetOperationStart(long double value, bool relative)
+{
+ if (relative)
+ operation_start += value;
+ else
+ operation_start = value;
+}
+
+
+void
+SetMissionStart(long double value, bool relative)
+{
+ if (relative)
+ mission_start += value;
+ else
+ mission_start = value;
+}
+
+
+} // namespace engine
+} // namespace starshatter
diff --git a/StarsEx/Stardate.h b/StarsEx/Stardate.h
new file mode 100644
index 0000000..cc696c8
--- /dev/null
+++ b/StarsEx/Stardate.h
@@ -0,0 +1,43 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#pragma once
+
+#include <Text.h>
+
+
+namespace starshatter
+{
+namespace engine
+{
+
+
+struct Stardate
+{
+ long double value = {};
+
+ Stardate();
+ Stardate(long double value_);
+
+ operator long double() const;
+
+ Text Format(bool short_format=false) const;
+};
+
+
+Stardate CurrentTime();
+Stardate OperationTime();
+Stardate MissionTime();
+
+long double Epoch();
+long double OperationStart();
+long double MissionStart();
+void SetOperationStart(long double value={}, bool relative=false);
+void SetMissionStart(long double value={}, bool relative=false);
+
+
+} // namespace engine
+} // namespace starshatter
diff --git a/StarsEx/Starshatter.cpp b/StarsEx/Starshatter.cpp
index 7663148..1a373cc 100644
--- a/StarsEx/Starshatter.cpp
+++ b/StarsEx/Starshatter.cpp
@@ -7,7 +7,6 @@
*/
-
#include "Starshatter.h"
#include "MenuScreen.h"
@@ -108,6 +107,7 @@
#include "Universe.h"
#include "Video.h"
#include "VideoSettings.h"
+#include "Stardate.h"
// +--------------------------------------------------------------------+
@@ -121,7 +121,9 @@ Starshatter* Starshatter::instance {nullptr};
static Mission* current_mission = 0;
static Mission* cutscene_mission = 0;
-static double cutscene_basetime = 0;
+static long double cutscene_operation_start = 0;
+static long double cutscene_mission_start = 0;
+static double cutscene_game_time = 0;
static int cut_efx_volume = 100;
static int cut_wrn_volume = 100;
static double time_til_change = 0;
@@ -592,7 +594,7 @@ Starshatter::SetGameMode(int m)
Clock::GetInstance()->SetTimeCompression(1.0);
Pause(false);
- Print(" Stardate: %.1Lf\n", StarSystem::GetBaseTime());
+ Print(" Stardate: %.1Lf\n", starshatter::engine::CurrentTime().value);
}
else if (m == PLAN_MODE) {
@@ -603,7 +605,7 @@ Starshatter::SetGameMode(int m)
StopNetGame();
Pause(true);
- Print(" Stardate: %.1Lf\n", StarSystem::GetBaseTime());
+ Print(" Stardate: %.1Lf\n", starshatter::engine::CurrentTime().value);
}
}
@@ -630,7 +632,7 @@ Starshatter::SetGameMode(int m)
StopNetGame();
}
- Print(" Stardate: %.1Lf\n", StarSystem::GetBaseTime());
+ Print(" Stardate: %.1Lf\n", starshatter::engine::CurrentTime().value);
Print(" Bitmap Cache Footprint: %d KB\n", Bitmap::CacheMemoryFootprint() / 1024);
paused = true;
@@ -1600,11 +1602,11 @@ Starshatter::DoGameKeys()
/*** For Debug Convenience Only: ***/
else if (KeyDown(KEY_INC_STARDATE)) {
- StarSystem::SetBaseTime(StarSystem::GetBaseTime() + 600, true);
+ starshatter::engine::SetOperationStart(300.0, true);
}
else if (KeyDown(KEY_DEC_STARDATE)) {
- StarSystem::SetBaseTime(StarSystem::GetBaseTime() - 600, true);
+ starshatter::engine::SetOperationStart(-300.0, true);
}
/***/
}
@@ -2556,7 +2558,9 @@ Starshatter::ExecCutscene(const char* msn_file, const char* path)
CreateWorld();
cutscene_mission = new Mission(0);
- cutscene_basetime = StarSystem::GetBaseTime();
+ cutscene_operation_start = starshatter::engine::OperationStart();
+ cutscene_mission_start = starshatter::engine::MissionStart();
+ cutscene_game_time = Clock::GetInstance()->GameTime<double>() / 1000.0;
if (cutscene_mission->Load(msn_file, path)) {
Sim* sim = (Sim*) world;
@@ -2582,7 +2586,9 @@ Starshatter::ExecCutscene(const char* msn_file, const char* path)
else {
delete cutscene_mission;
cutscene_mission = 0;
- cutscene_basetime = 0;
+ cutscene_operation_start = 0;
+ cutscene_mission_start = 0;
+ cutscene_game_time = 0;
}
}
@@ -2659,15 +2665,14 @@ Starshatter::EndMission()
if (sim && sim->GetMission() == cutscene_mission) {
ShipStats::Initialize();
sim->UnloadMission();
-
- // restore world clock (true => absolute time reference)
- if (cutscene_basetime != 0)
- StarSystem::SetBaseTime(cutscene_basetime, true);
-
+ starshatter::engine::SetOperationStart(cutscene_operation_start);
+ starshatter::engine::SetMissionStart(cutscene_mission_start);
+ Clock::GetInstance()->ResetGameTime(cutscene_game_time);
delete cutscene_mission;
- cutscene_mission = 0;
- cutscene_basetime = 0;
-
+ cutscene_mission = nullptr;
+ cutscene_operation_start = 0;
+ cutscene_mission_start = 0;
+ cutscene_game_time = 0;
return;
}
}
diff --git a/StarsEx/Weather.cpp b/StarsEx/Weather.cpp
index 8d3ded6..ffbdaff 100644
--- a/StarsEx/Weather.cpp
+++ b/StarsEx/Weather.cpp
@@ -12,9 +12,9 @@
*/
#include "Weather.h"
-#include "StarSystem.h"
-#include "Game.h"
+
#include "ContentBundle.h"
+#include "Stardate.h"
// +--------------------------------------------------------------------+
@@ -94,7 +94,7 @@ Weather::Update()
{
NormalizeChances();
- double weather = (sin(StarSystem::Stardate() * 2 * PI / period)+1)/2;
+ const auto weather = (sin(starshatter::engine::CurrentTime() * 2.0 * PI / period) + 1.0) / 2.0;
state = active_states[0];
diff --git a/StarsEx/test/ShipStats.cpp b/StarsEx/test/ShipStats.cpp
new file mode 100644
index 0000000..1430573
--- /dev/null
+++ b/StarsEx/test/ShipStats.cpp
@@ -0,0 +1,29 @@
+#include <gtest/gtest.h>
+
+#include <Clock.h>
+#include <SimEvent.h>
+
+
+TEST(StarsEx, EffectivePoints)
+{
+ Clock::Init();
+ ShipStats::Initialize();
+ auto* first = ShipStats::Find("first");
+ ASSERT_NE(nullptr, first);
+ EXPECT_EQ(0, first->EffectivePoints());
+ first->SetFlightTime(590.0l);
+ EXPECT_EQ(0, first->EffectivePoints());
+ first->SetFlightTime(610.0l);
+ EXPECT_EQ(10, first->EffectivePoints());
+ first->SetFlightTime(1210.0l);
+ EXPECT_EQ(20, first->EffectivePoints());
+ const auto* destroyed = first->AddEvent(SimEvent::DESTROYED);
+ first->Summarize();
+ EXPECT_EQ(0, first->EffectivePoints());
+ auto* second = ShipStats::Find("second");
+ ASSERT_NE(nullptr, second);
+ const auto* docked = second->AddEvent(SimEvent::DOCK);
+ EXPECT_EQ(100, second->EffectivePoints());
+ ShipStats::Close();
+ Clock::Close();
+}
diff --git a/StarsEx/test/Stardate.cpp b/StarsEx/test/Stardate.cpp
new file mode 100644
index 0000000..fb95562
--- /dev/null
+++ b/StarsEx/test/Stardate.cpp
@@ -0,0 +1,60 @@
+#include <gtest/gtest.h>
+
+#include <Clock.h>
+#include <Stardate.h>
+
+namespace ng = starshatter::engine;
+
+
+TEST(StarsEx, MissionTimeIsGameTime)
+{
+ ASSERT_TRUE(Clock::Init());
+ auto* clock = Clock::GetInstance();
+ EXPECT_NEAR(0.0l, ng::MissionTime(), 0.001l);
+ clock->SkipGameTime(0.05);
+ EXPECT_NEAR(0.05l, ng::MissionTime(), 0.001l);
+ clock->SkipGameTime(0.05);
+ EXPECT_NEAR(0.10l, ng::MissionTime(), 0.001l);
+ Clock::Close();
+}
+
+
+TEST(StarsEx, OperationTimeIsMissionOffset)
+{
+ ASSERT_TRUE(Clock::Init());
+ auto* clock = Clock::GetInstance();
+ EXPECT_NEAR(0.0l, ng::OperationTime(), 0.001l);
+ ng::SetMissionStart(1000.0l);
+ EXPECT_NEAR(1000.0l, ng::OperationTime(), 0.001l);
+ clock->SkipGameTime(0.05);
+ EXPECT_NEAR(1000.05l, ng::OperationTime(), 0.001l);
+ ng::SetMissionStart(1000.0l, true);
+ EXPECT_NEAR(2000.05l, ng::OperationTime(), 0.001l);
+ Clock::Close();
+}
+
+
+TEST(StarsEx, CurrentTimeIsOperationAndEpoch)
+{
+ ASSERT_TRUE(Clock::Init());
+ auto* clock = Clock::GetInstance();
+ EXPECT_NEAR(ng::Epoch(), ng::CurrentTime(), 0.001l);
+ ng::SetOperationStart(1000.0l);
+ EXPECT_NEAR(ng::Epoch() + 1000.0l, ng::CurrentTime(), 0.001l);
+ ng::SetMissionStart(500.0l);
+ EXPECT_NEAR(ng::Epoch() + 1500.0l, ng::CurrentTime(), 0.001l);
+ clock->SkipGameTime(0.05);
+ EXPECT_NEAR(ng::Epoch() + 1500.05l, ng::CurrentTime(), 0.001l);
+ ng::SetOperationStart(1000.0l, true);
+ EXPECT_NEAR(ng::Epoch() + 2500.05l, ng::CurrentTime(), 0.001l);
+ Clock::Close();
+}
+
+
+TEST(StarsEx, FormatOperationTime)
+{
+ ASSERT_TRUE(Clock::Init());
+ auto* clock = Clock::GetInstance();
+ EXPECT_EQ("Day 1, 00:00:00", ng::OperationTime().Format());
+ Clock::Close();
+}
diff --git a/Starserver/Main.cpp b/Starserver/Main.cpp
index 43a567e..d9d409c 100644
--- a/Starserver/Main.cpp
+++ b/Starserver/Main.cpp
@@ -14,9 +14,6 @@
#include "StarServer.h"
-int dump_missions = 0;
-
-
int
main(int, char*[])
{
diff --git a/Starshatter/Main.cpp b/Starshatter/Main.cpp
index 58fb891..88f052a 100644
--- a/Starshatter/Main.cpp
+++ b/Starshatter/Main.cpp
@@ -21,6 +21,7 @@
#include "Color.h"
#include "DataLoader.h"
+#include "DumpMissions.h"
#include "Pcx.h"
#include "Encrypt.h"
#include "FormatUtil.h"
@@ -31,7 +32,6 @@
extern int VD3D_describe_things;
-int dump_missions = 0;
static void
diff --git a/ci/test.sh b/ci/test.sh
index 3f1e3f9..2650f70 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-ctest --test-dir $builddir
+ctest --test-dir $builddir "$@"
diff --git a/data/content/Campaigns/01/T3.def b/data/content/Campaigns/01/T3.def
index 11e0b1f..1f63e4e 100644
--- a/data/content/Campaigns/01/T3.def
+++ b/data/content/Campaigns/01/T3.def
@@ -9,7 +9,6 @@ objective: "c01.t03.obj"
sitrep: "c01.t03.sitrep"
start: "01/13:23:00"
-stardate: 1084144000
degrees: true
diff --git a/data/content/Campaigns/01/T4.def b/data/content/Campaigns/01/T4.def
index 4e2e44c..0dcc1f8 100644
--- a/data/content/Campaigns/01/T4.def
+++ b/data/content/Campaigns/01/T4.def
@@ -9,7 +9,6 @@ objective: "c01.t04.obj"
sitrep: "c01.t04.sitrep"
start: "02/05:35:00"
-stardate: 1084170240
degrees: true
diff --git a/data/content/Campaigns/01/campaign.def b/data/content/Campaigns/01/campaign.def
index 4e86a1f..4bcd2d1 100644
--- a/data/content/Campaigns/01/campaign.def
+++ b/data/content/Campaigns/01/campaign.def
@@ -4,8 +4,8 @@ name: "c01.name"
desc: "c01.desc"
situation: "c01.sitrep"
orders: "c01.orders"
-
-scripted: true
+stardate: 1084144000.0
+scripted: true
action: {
id: 0,
diff --git a/data/content/Campaigns/02/campaign.def b/data/content/Campaigns/02/campaign.def
index 4c20601..843e17b 100644
--- a/data/content/Campaigns/02/campaign.def
+++ b/data/content/Campaigns/02/campaign.def
@@ -4,6 +4,7 @@ name: "c02.name"
desc: "c02.desc"
situation: "c02.sitrep"
orders: "c02.orders"
+stardate: 17280000.0
combatant: {
name: "Terellian Alliance",
diff --git a/data/content/Campaigns/03/campaign.def b/data/content/Campaigns/03/campaign.def
index 0966a78..70afdfa 100644
--- a/data/content/Campaigns/03/campaign.def
+++ b/data/content/Campaigns/03/campaign.def
@@ -4,6 +4,7 @@ name: "c03.name"
desc: "c03.desc"
situation: "c03.sitrep"
orders: "c03.orders"
+stardate: 22464000.0
combatant: {
name: "Terellian Alliance",
diff --git a/data/content/Campaigns/04/campaign.def b/data/content/Campaigns/04/campaign.def
index 7262b90..684a2c8 100644
--- a/data/content/Campaigns/04/campaign.def
+++ b/data/content/Campaigns/04/campaign.def
@@ -4,6 +4,7 @@ name: "c04.name"
desc: "c04.desc"
situation: "c04.sitrep"
orders: "c04.orders"
+stardate: 27648000.0
combatant: {
name: "Terellian Alliance",
diff --git a/data/content/Campaigns/05/campaign.def b/data/content/Campaigns/05/campaign.def
index cd4ba28..049b331 100644
--- a/data/content/Campaigns/05/campaign.def
+++ b/data/content/Campaigns/05/campaign.def
@@ -4,6 +4,7 @@ name: "c05.name"
desc: "c05.desc"
situation: "c05.sitrep"
orders: "c05.orders"
+stardate: 32832000.0
/*******
diff --git a/data/content/Content/content.txt b/data/content/Content/content.txt
index 98bd477..d0bb664 100644
--- a/data/content/Content/content.txt
+++ b/data/content/Content/content.txt
@@ -1610,7 +1610,7 @@ msn.m03.obj = * Fleet Engagement - Engage the Destroyer Squadron led by DD-7
msn.m04.name = M4. War Games
msn.m04.desc = Fleet war game scenario designed for the persistent multiplayer server mode.
-msn.m04.sitrep = Welcome to the Force:Space fleet war game exercises in Janus System. For this scenario, two equal star fleets will face off in unlimited combat. The entire system is in bounds for this exercise.\n \n Fleet 1 (BLUE) consists of the Archon CVBG including twenty Stormhawk fighters, and Spectre-Class DESRON 43 'Shadow'.\n \n Fleet 2 (RED) includes the Titan CVBG with twenty Stormhawk fighters, and Spectre-Class DESRON 45 'Warlock'.\n \n The goal of the exercise is to destroy the enemy carrier. The exercise will end when either the Archon or the Titan has been destroyed.
+msn.m04.sitrep = Welcome to the Force:Space fleet war game exercises in Janus System. For this scenario, two equal star fleets will face off in unlimited combat. The entire system is in bounds for this exercise.\n \n Fleet 1 (BLUE) consists of the Archon CVBG and Spectre-Class DESRON 43 'Shadow'.\n \n Fleet 2 (RED) includes the Titan CVBG and Spectre-Class DESRON 45 'Warlock'.\n \n The goal of the exercise is to destroy the enemy carrier. The exercise will end when either the Archon or the Titan has been destroyed.
msn.m04.obj = * Destroy enemy carrier\n* Protect ownside carrier from enemy fleet
msn.m04.e01 = ARCHON DESTROYED - RED TEAM VICTORY!
msn.m04.e07 = TITAN DESTROYED - BLUE TEAM VICTORY!
diff --git a/data/content/Multiplayer/wargames.def b/data/content/Multiplayer/wargames.def
index 3d6a6d8..956d424 100644
--- a/data/content/Multiplayer/wargames.def
+++ b/data/content/Multiplayer/wargames.def
@@ -38,7 +38,55 @@ element: {
mission: "Flight Ops",
intel: "Secret",
- count: 20,
+ count: 24,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Avengers",
+ design: "Falcon",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 32,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Diamondbacks",
+ design: "Eagle",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 24,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Warbirds",
+ design: "Thunderbolt",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 16,
iff: 1,
region: "Janek",
loc: (5000, 0, 0),
@@ -136,6 +184,22 @@ element: {
}
element: {
+ name: "Windriders",
+ design: "Falcon",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 32,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
name: "Chargers",
design: "Stormhawk",
carrier: "Titan",
@@ -143,7 +207,7 @@ element: {
mission: "Flight Ops",
intel: "Secret",
- count: 20,
+ count: 24,
iff: 2,
region: "Alystra",
loc: (5000, 0, 0),
@@ -152,6 +216,38 @@ element: {
}
element: {
+ name: "Wolfhounds",
+ design: "Eagle",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 24,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Short Range" },
+}
+
+element: {
+ name: "Razorbacks",
+ design: "Thunderbolt",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 20,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "Ship Strike" },
+}
+
+element: {
name: "Defender",
design: "Courageous",
commander: "Titan",
diff --git a/data/content/Ships/Dantari_Ships/Goliath.def b/data/content/Ships/Dantari_Ships/Goliath.def
index 6992605..d9642a8 100644
--- a/data/content/Ships/Dantari_Ships/Goliath.def
+++ b/data/content/Ships/Dantari_Ships/Goliath.def
@@ -184,18 +184,20 @@ flightdeck: {
name: "Deck 1",
abrv: "Deck 1",
design: "Flight Deck",
- loc: ( 0, -85, 192),
- cam: (-20, -85, 192),
- start: ( 0, -85, 170),
- end: (2e3,-200, 2500),
+ loc: ( 0, 6, 480),
+ cam: ( 0, 20, 520),
+ start: ( 0, 6, 480),
+ end: ( 0, 6, 2500),
- spot: { loc: ( 16, -85, 160), filter: 0x7 },
- spot: { loc: (-16, -85, 160), filter: 0x7 },
- spot: { loc: ( 0, -85, 160), filter: 0x8 },
+ spot: { loc: ( 50, 6, 460), filter: 0x7 },
+ spot: { loc: (-50, 6, 460), filter: 0x7 },
+ spot: { loc: ( 50, 6, 420), filter: 0x7 },
+ spot: { loc: (-50, 6, 420), filter: 0x7 },
+ spot: { loc: ( 0, 6, 480), filter: 0x8 },
launch: true,
- max_ships: 2,
- cycle_time: 15,
+ max_ships: 4,
+ cycle_time: 12,
size: 28,
hull_factor: 0.5,
@@ -206,22 +208,48 @@ flightdeck: {
name: "Deck 2",
abrv: "Deck 2",
design: "Flight Deck",
- loc: ( 0, -82, -92),
- cam: (-20, -72, -92),
- start: ( 0, -90, -1e3),
- end: ( 0, -82, -92),
- spot: ( 0, -82, -92),
+ azimuth: 90,
+ loc: ( -65, 10, 359),
+ start: (-1.4e3, 10, 359),
+ end: ( -65, 10, 359),
+ spot: ( -65, 10, 359),
+ cam: ( -20, 21, 382),
+
+ approach: (-2000, 10, 359),
+ approach: (-1200, 10, 359),
+ approach: ( -400, 10, 1559),
+ approach: ( -400, 10,-1141),
- approach: ( 0,-90, -2000),
- approach: (1000, 0, -1000),
- approach: (1000, 0, 1000),
- approach: ( 250, 0, 2500),
+ recovery: true,
+ max_ships: 1,
+ cycle_time: 12,
+
+ size: 80,
+ hull_factor: 0.5,
+}
+
+
+flightdeck: {
+ name: "Deck 3",
+ abrv: "Deck 3",
+ design: "Flight Deck",
+ azimuth: -90,
+ loc: ( 65, 10, 359),
+ start: (1.4e3, 10, 359),
+ end: ( 65, 10, 359),
+ spot: ( 65, 10, 359),
+ cam: ( 20, 21, 382),
+
+ approach: (2000, 10, 359),
+ approach: (1200, 10, 359),
+ approach: ( 400, 10, 1559),
+ approach: ( 400, 10,-1141),
recovery: true,
max_ships: 1,
- cycle_time: 15,
+ cycle_time: 12,
- size: 40,
+ size: 80,
hull_factor: 0.5,
}
diff --git a/data/shatter/Campaigns/01/campaign.def b/data/shatter/Campaigns/01/campaign.def
index 6c2e727..6e93bc0 100644
--- a/data/shatter/Campaigns/01/campaign.def
+++ b/data/shatter/Campaigns/01/campaign.def
@@ -27,6 +27,7 @@ situation:
orders:
"\t* Execute all of the training missions in this campaign."
+stardate: 1084144000.0
scripted: true
action: {
diff --git a/data/shatter/Campaigns/02/campaign.def b/data/shatter/Campaigns/02/campaign.def
index 3e4eae8..ff79036 100644
--- a/data/shatter/Campaigns/02/campaign.def
+++ b/data/shatter/Campaigns/02/campaign.def
@@ -31,6 +31,8 @@ orders:
"\t* Apprehend or destroy military units of the Dantari Separatists.\n"
"\t* Determine the extent of Hegemony involvement in this conflict.\n"
+stardate: 17280000.0
+
combatant: {
name: "Terellian Alliance",
group: { type: carrier_group, id: 6 },
diff --git a/data/shatter/Campaigns/03/campaign.def b/data/shatter/Campaigns/03/campaign.def
index d7ba6ca..9a0e103 100644
--- a/data/shatter/Campaigns/03/campaign.def
+++ b/data/shatter/Campaigns/03/campaign.def
@@ -29,6 +29,8 @@ orders:
"\t* Evacuate civilians and government personnel as necessary.\n"
"\t* Stop the Hegemony advance until a counterattack can be mounted.\n"
+stardate: 22464000.0
+
combatant: {
name: "Terellian Alliance",
group: { type: fleet, id: 4 },
diff --git a/data/shatter/Campaigns/04/campaign.def b/data/shatter/Campaigns/04/campaign.def
index 8b3d928..9471d89 100644
--- a/data/shatter/Campaigns/04/campaign.def
+++ b/data/shatter/Campaigns/04/campaign.def
@@ -20,6 +20,8 @@ orders:
"\t* Prepare the region for a general invasion of Tarsus.\n"
"\t* Protect Alliance assets in the area.\n"
+stardate: 27648000.0
+
combatant: {
name: "Terellian Alliance",
group: { type: fleet, id: 6 }, // Ostara, Tarsus, Kolchev
diff --git a/data/shatter/Campaigns/05/campaign.def b/data/shatter/Campaigns/05/campaign.def
index 19ee3dc..acfc11b 100644
--- a/data/shatter/Campaigns/05/campaign.def
+++ b/data/shatter/Campaigns/05/campaign.def
@@ -29,6 +29,8 @@ orders:
"\t* Second Fleet: Secure the Radix system.\n"
"\t* Both fleets to converge on the Garrison system as soon as possible.\n"
+stardate: 32832000.0
+
/*******
ISHAM
diff --git a/data/shatter/Multiplayer/wargames.def b/data/shatter/Multiplayer/wargames.def
index 37de971..e3fdfe0 100644
--- a/data/shatter/Multiplayer/wargames.def
+++ b/data/shatter/Multiplayer/wargames.def
@@ -9,7 +9,7 @@ region: "Janek"
objective: "Unspecified"
-sitrep: "Welcome to the Force:Space fleet war game exercises in Janus System. For this scenario, two equal star fleets will face off in unlimited combat. The entire system is in bounds for this exercise.\n \n Fleet 1 (BLUE) consists of the Archon CVBG including twenty Stormhawk fighters, and Spectre-Class DESRON 43 'Shadow'.\n \n Fleet 2 (RED) includes the Titan CVBG with twenty Stormhawk fighters, and Spectre-Class DESRON 45 'Warlock'.\n \n The goal of the exercise is to destroy the enemy carrier. The exercise will end when either the Archon or the Titan has been destroyed."
+sitrep: "Welcome to the Force:Space fleet war game exercises in Janus System. For this scenario, two equal star fleets will face off in unlimited combat. The entire system is in bounds for this exercise.\n \n Fleet 1 (BLUE) consists of the Archon CVBG and Spectre-Class DESRON 43 'Shadow'.\n \n Fleet 2 (RED) includes the Titan CVBG and Spectre-Class DESRON 45 'Warlock'.\n \n The goal of the exercise is to destroy the enemy carrier. The exercise will end when either the Archon or the Titan has been destroyed."
start: "33:00:00"
@@ -38,7 +38,55 @@ element: {
mission: "Flight Ops",
intel: "Secret",
- count: 20,
+ count: 24,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Avengers",
+ design: "Falcon",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 32,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Diamondbacks",
+ design: "Eagle",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 24,
+ iff: 1,
+ region: "Janek",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
+ name: "Warbirds",
+ design: "Thunderbolt",
+ carrier: "Archon",
+ commander: "Archon",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 16,
iff: 1,
region: "Janek",
loc: (5000, 0, 0),
@@ -136,6 +184,22 @@ element: {
}
element: {
+ name: "Windriders",
+ design: "Falcon",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 32,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Medium Range" },
+}
+
+element: {
name: "Chargers",
design: "Stormhawk",
carrier: "Titan",
@@ -143,7 +207,7 @@ element: {
mission: "Flight Ops",
intel: "Secret",
- count: 20,
+ count: 24,
iff: 2,
region: "Alystra",
loc: (5000, 0, 0),
@@ -152,6 +216,38 @@ element: {
}
element: {
+ name: "Wolfhounds",
+ design: "Eagle",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 24,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "ACM Short Range" },
+}
+
+element: {
+ name: "Razorbacks",
+ design: "Thunderbolt",
+ carrier: "Titan",
+ commander: "Titan",
+ mission: "Flight Ops",
+
+ intel: "Secret",
+ count: 20,
+ iff: 2,
+ region: "Alystra",
+ loc: (5000, 0, 0),
+
+ loadout: { ship: -1, name: "Ship Strike" },
+}
+
+element: {
name: "Defender",
design: "Courageous",
commander: "Titan",
diff --git a/data/shatter/Ships/Dantari_Ships/Goliath.def b/data/shatter/Ships/Dantari_Ships/Goliath.def
index 588b7ed..e45c5fd 100644
--- a/data/shatter/Ships/Dantari_Ships/Goliath.def
+++ b/data/shatter/Ships/Dantari_Ships/Goliath.def
@@ -184,18 +184,20 @@ flightdeck: {
name: "Deck 1",
abrv: "Deck 1",
design: "Flight Deck",
- loc: ( 0, -85, 192),
- cam: (-20, -85, 192),
- start: ( 0, -85, 170),
- end: (2e3,-200, 2500),
+ loc: ( 0, 6, 480),
+ cam: ( 0, 20, 520),
+ start: ( 0, 6, 480),
+ end: ( 0, 6, 2500),
- spot: { loc: ( 16, -85, 160), filter: 0x7 },
- spot: { loc: (-16, -85, 160), filter: 0x7 },
- spot: { loc: ( 0, -85, 160), filter: 0x8 },
+ spot: { loc: ( 50, 6, 460), filter: 0x7 },
+ spot: { loc: (-50, 6, 460), filter: 0x7 },
+ spot: { loc: ( 50, 6, 420), filter: 0x7 },
+ spot: { loc: (-50, 6, 420), filter: 0x7 },
+ spot: { loc: ( 0, 6, 480), filter: 0x8 },
launch: true,
- max_ships: 2,
- cycle_time: 15,
+ max_ships: 4,
+ cycle_time: 12,
size: 28,
hull_factor: 0.5,
@@ -206,22 +208,48 @@ flightdeck: {
name: "Deck 2",
abrv: "Deck 2",
design: "Flight Deck",
- loc: ( 0, -82, -92),
- cam: (-20, -72, -92),
- start: ( 0, -90, -1e3),
- end: ( 0, -82, -92),
- spot: ( 0, -82, -92),
+ azimuth: 90,
+ loc: ( -65, 10, 359),
+ start: (-1.4e3, 10, 359),
+ end: ( -65, 10, 359),
+ spot: ( -65, 10, 359),
+ cam: ( -20, 21, 382),
+
+ approach: (-2000, 10, 359),
+ approach: (-1200, 10, 359),
+ approach: ( -400, 10, 1559),
+ approach: ( -400, 10,-1141),
- approach: ( 0,-90, -2000),
- approach: (1000, 0, -1000),
- approach: (1000, 0, 1000),
- approach: ( 250, 0, 2500),
+ recovery: true,
+ max_ships: 1,
+ cycle_time: 12,
+
+ size: 80,
+ hull_factor: 0.5,
+}
+
+
+flightdeck: {
+ name: "Deck 3",
+ abrv: "Deck 3",
+ design: "Flight Deck",
+ azimuth: -90,
+ loc: ( 65, 10, 359),
+ start: (1.4e3, 10, 359),
+ end: ( 65, 10, 359),
+ spot: ( 65, 10, 359),
+ cam: ( 20, 21, 382),
+
+ approach: (2000, 10, 359),
+ approach: (1200, 10, 359),
+ approach: ( 400, 10, 1559),
+ approach: ( 400, 10,-1141),
recovery: true,
max_ships: 1,
- cycle_time: 15,
+ cycle_time: 12,
- size: 40,
+ size: 80,
hull_factor: 0.5,
}
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 2c9f2f1..5b1d796 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -10,6 +10,7 @@ add_subdirectory(zlib)
make_available(gtest infoware libpng ogg vorbis zlib)
add_subdirectory(Opcode)
add_subdirectory(sha1)
+add_subdirectory(l3ds)
install(
TARGETS png15 Opcode
RUNTIME
diff --git a/third-party/l3ds/CMakeLists.txt b/third-party/l3ds/CMakeLists.txt
new file mode 100644
index 0000000..89c13d2
--- /dev/null
+++ b/third-party/l3ds/CMakeLists.txt
@@ -0,0 +1,4 @@
+project(l3ds)
+add_library(${PROJECT_NAME} SHARED l3ds.cpp)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+install(TARGETS ${PROJECT_NAME} RUNTIME COMPONENT Runtime DESTINATION ${CMAKE_INSTALL_PREFIX})
diff --git a/Magic2/l3ds.h b/third-party/l3ds/include/l3ds.h
index ea0a032..69a8e6d 100644
--- a/Magic2/l3ds.h
+++ b/third-party/l3ds/include/l3ds.h
@@ -454,4 +454,4 @@ protected:
//---------------------------------------------------------
-#endif \ No newline at end of file
+#endif
diff --git a/Magic2/l3ds.cpp b/third-party/l3ds/l3ds.cpp
index c23075c..50b27b8 100644
--- a/Magic2/l3ds.cpp
+++ b/third-party/l3ds/l3ds.cpp
@@ -1,8 +1,5 @@
// copyright (c) 2001 Lev Povalahev
-
-#include "StdAfx.h"
-
#include "l3ds.h"
#include <stdio.h>
@@ -1790,4 +1787,4 @@ long L3DS::ReadKeyheader()
ReadFloat();
}
return frame;
-} \ No newline at end of file
+}