diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..ddb6ff8
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ "recommendations": [
+ "visualstudiotoolsforunity.vstuc"
+ ]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..da60e25
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,10 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Attach to Unity",
+ "type": "vstuc",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c165bdd
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,60 @@
+{
+ "files.exclude": {
+ "**/.DS_Store": true,
+ "**/.git": true,
+ "**/.vs": true,
+ "**/.gitmodules": true,
+ "**/.vsconfig": true,
+ "**/*.booproj": true,
+ "**/*.pidb": true,
+ "**/*.suo": true,
+ "**/*.user": true,
+ "**/*.userprefs": true,
+ "**/*.unityproj": true,
+ "**/*.dll": true,
+ "**/*.exe": true,
+ "**/*.pdf": true,
+ "**/*.mid": true,
+ "**/*.midi": true,
+ "**/*.wav": true,
+ "**/*.gif": true,
+ "**/*.ico": true,
+ "**/*.jpg": true,
+ "**/*.jpeg": true,
+ "**/*.png": true,
+ "**/*.psd": true,
+ "**/*.tga": true,
+ "**/*.tif": true,
+ "**/*.tiff": true,
+ "**/*.3ds": true,
+ "**/*.3DS": true,
+ "**/*.fbx": true,
+ "**/*.FBX": true,
+ "**/*.lxo": true,
+ "**/*.LXO": true,
+ "**/*.ma": true,
+ "**/*.MA": true,
+ "**/*.obj": true,
+ "**/*.OBJ": true,
+ "**/*.asset": true,
+ "**/*.cubemap": true,
+ "**/*.flare": true,
+ "**/*.mat": true,
+ "**/*.meta": true,
+ "**/*.prefab": true,
+ "**/*.unity": true,
+ "build/": true,
+ "Build/": true,
+ "Library/": true,
+ "library/": true,
+ "obj/": true,
+ "Obj/": true,
+ "Logs/": true,
+ "logs/": true,
+ "ProjectSettings/": true,
+ "UserSettings/": true,
+ "temp/": true,
+ "Temp/": true
+ },
+ "dotnet.defaultSolution": "rebellion2.sln"
+}
\ No newline at end of file
diff --git a/Assets/Resources/Configs/NewGameConfig.json b/Assets/Resources/Configs/NewGameConfig.json
index 5a1389b..ae2efc1 100644
--- a/Assets/Resources/Configs/NewGameConfig.json
+++ b/Assets/Resources/Configs/NewGameConfig.json
@@ -51,7 +51,7 @@
},
"Buildings": {
"InitialBuildings": {
- "GameIDs": [
+ "TypeIDs": [
"BDFA01",
"BDFA02",
"BDFA03",
@@ -85,29 +85,29 @@
"GalaxySize": {
"Small": [
{
- "OwnerGameID": "FNEMP1",
- "InitialParentGameID": "PLSEW05",
- "GameID": "CSEM006"
+ "OwnerTypeID": "FNEMP1",
+ "InitialParentTypeID": "PLSEW05",
+ "TypeID": "CSEM006"
},
{
- "OwnerGameID": "FNEMP1",
- "GameID": "CSEM005"
+ "OwnerTypeID": "FNEMP1",
+ "TypeID": "CSEM005"
},
{
- "OwnerGameID": "FNALL1",
- "GameID": "CSAL002"
+ "OwnerTypeID": "FNALL1",
+ "TypeID": "CSAL002"
},
{
- "OwnerGameID": "FNALL1",
- "GameID": "ALCS003"
+ "OwnerTypeID": "FNALL1",
+ "TypeID": "ALCS003"
},
{
- "OwnerGameID": "FNALL1",
- "GameID": "ALCS006"
+ "OwnerTypeID": "FNALL1",
+ "TypeID": "ALCS006"
},
{
- "OwnerGameID": "FNALL1",
- "GameID": "ALCS006"
+ "OwnerTypeID": "FNALL1",
+ "TypeID": "ALCS006"
}
],
"Medium": [
diff --git a/Assets/Resources/Data/Buildings.xml b/Assets/Resources/Data/Buildings.xml
index bfb048c..86d3542 100644
--- a/Assets/Resources/Data/Buildings.xml
+++ b/Assets/Resources/Data/Buildings.xml
@@ -4,7 +4,7 @@
- BDFA01
+ BDFA01
Construction Facility
Ground
10
@@ -14,7 +14,7 @@
0
- BDFA02
+ BDFA02
Training Facility
Ground
10
@@ -24,7 +24,7 @@
0
- BDFA03
+ BDFA03
Orbital Shipyard
Orbit
20
@@ -34,7 +34,7 @@
0
- BDFA04
+ BDFA04
Mining Facility
Ground
20
@@ -44,7 +44,7 @@
0
- BDFA05
+ BDFA05
Refinery
Ground
20
@@ -54,7 +54,7 @@
0
- BDFA06
+ BDFA06
Advanced Training Facility
Ground
10
@@ -64,7 +64,7 @@
1
- BDFA07
+ BDFA07
Advanced Orbital Shipyard
Orbit
20
@@ -77,7 +77,7 @@
- BDDF01
+ BDDF01
LNR Series I
Ground
7
@@ -88,7 +88,7 @@
0
- BDDF02
+ BDDF02
GenCore Level I
Ground
12
@@ -99,7 +99,7 @@
0
- BDDF03
+ BDDF03
KDY-150
Ground
4
@@ -110,7 +110,7 @@
0
- BDDF04
+ BDDF04
Death Star Shield
Ground
25
@@ -121,7 +121,7 @@
3
- BDDF05
+ BDDF05
LNR Series II
Ground
10
@@ -132,7 +132,7 @@
4
- BDDF06
+ BDDF06
GenCore Level II
Ground
20
@@ -146,7 +146,7 @@
- BDUT01
+ BDUT01
Orbital Telescope
Orbit
10
@@ -157,7 +157,7 @@
0
- BDUT02
+ BDUT02
Orbital Minefield
Orbit
35
@@ -168,7 +168,7 @@
7
- BDUT03
+ BDUT03
Advanced Orbital Telescope
Orbit
111
diff --git a/Assets/Resources/Data/CapitalShips.xml b/Assets/Resources/Data/CapitalShips.xml
index 8f861b4..ee3a21d 100644
--- a/Assets/Resources/Data/CapitalShips.xml
+++ b/Assets/Resources/Data/CapitalShips.xml
@@ -4,11 +4,11 @@
- CSEM001
+ CSEM001
Imperial Dreadnaught
-
+
FNEMP1
-
+
44
33
0
@@ -74,11 +74,11 @@
10
- CSEM002
+ CSEM002
Galleon
-
+
FNEMP1
-
+
10
10
0
@@ -144,11 +144,11 @@
10
- CSEM003
+ CSEM003
Imperial Escort Carrier
-
+
FNEMP1
-
+
34
30
0
@@ -214,11 +214,11 @@
4
- CSEM004
+ CSEM004
Carrack Light Cruiser
-
+
FNEMP1
-
+
26
24
0
@@ -284,11 +284,11 @@
20
- CSEM005
+ CSEM005
Victory Destroyer
-
+
FNEMP1
-
+
68
44
0
@@ -354,11 +354,11 @@
10
- CSEM006
+ CSEM006
Imperial Star Destroyer
-
+
FNEMP1
-
+
112
71
0
@@ -427,11 +427,11 @@
- CSAL001
+ CSAL001
Alliance Dreadnaught
-
+
FNALL1
-
+
44
33
0
@@ -497,11 +497,11 @@
10
- CSAL002
+ CSAL002
Bulk Cruiser
-
+
FNALL1
-
+
30
30
0
@@ -567,11 +567,11 @@
10
- ALCS003
+ ALCS003
Medium Transport
-
+
FNALL1
-
+
10
12
0
@@ -637,11 +637,11 @@
5
- ALCS004
+ ALCS004
Bulk Transport
-
+
FNALL1
-
+
24
22
0
@@ -707,11 +707,11 @@
1
- ALCS005
+ ALCS005
Alliance Escourt Carrier
-
+
FNALL1
-
+
32
29
0
@@ -777,11 +777,11 @@
10
- ALCS006
+ ALCS006
Corellian Corvette
-
+
FNALL1
-
+
14
23
0
@@ -848,10 +848,10 @@
Nebulon-B Frigate
- ALCS007
-
+ ALCS007
+
FNALL1
-
+
34
35
0
@@ -917,11 +917,11 @@
30
- ALCS008
+ ALCS008
Mon Calamari Cruiser
-
+
FNALL1
-
+
92
70
0
diff --git a/Assets/Resources/Data/Events.xml b/Assets/Resources/Data/Events.xml
new file mode 100644
index 0000000..a13f373
--- /dev/null
+++ b/Assets/Resources/Data/Events.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+ LUKE_VISITS_YODA
+ Luke Visits Yoda
+ false
+
+
+
+ LUKE_SKYWALKER
+
+
+ 30
+
+
+
+
+
+
+
+ LUKE_SKYWALKER
+ YODA
+
+ DAGOBAH
+
+
+
+
+
+
+
+
+
+ LUKE_CONFRONTS_VADER
+ Luke Confronts Vader
+ true
+
+
+
+ LUKE_SKYWALKER
+ DARTH_VADER
+
+
+
+
+
+ LUKE_SKYWALKER
+
+
+ DARTH_VADER
+
+
+
+
+
+
+
+
+
+
+
+
+ LUKE_DISCOVERS_HERITAGE
+ Luke Discovers Heritage
+ false
+
+
+
+
+
+
diff --git a/Assets/Resources/Data/Factions.xml b/Assets/Resources/Data/Factions.xml
index e7bf6f1..6b0d03e 100644
--- a/Assets/Resources/Data/Factions.xml
+++ b/Assets/Resources/Data/Factions.xml
@@ -1,13 +1,13 @@
- FNALL1
+ FNALL1
Alliance
- PLSUM06
+ PLSUM06
- FNEMP1
+ FNEMP1
Empire
- PLSEW05
+ PLSEW05
diff --git a/Assets/Resources/Data/Officers.xml b/Assets/Resources/Data/Officers.xml
index 28a9624..5906c48 100644
--- a/Assets/Resources/Data/Officers.xml
+++ b/Assets/Resources/Data/Officers.xml
@@ -4,11 +4,12 @@
- OFEM001
+ OFEM001
+ EMPEROR_PALPATINE
Emperor Palpatine
- FNEMP1
+ FNEMP1
true
- PLSEW05
+ PLSEW05
30
20
50
@@ -35,9 +36,10 @@
None
- OFEM002
+ OFEM002
+ DARTH_VADER
Darth Vader
- FNEMP1
+ FNEMP1
true
19
100
@@ -65,11 +67,12 @@
None
- OFEM003
+ OFEM003
+ JERJERROD
Jerjerrod
-
+
FNEMP1
-
+
false
70
0
@@ -97,11 +100,12 @@
None
- OFEM004
+ OFEM004
+ PIETT
Piett
-
+
FNEMP1
-
+
false
70
0
@@ -129,11 +133,12 @@
None
- OFEM005
+ OFEM005
+ VEERS
Veers
-
+
FNEMP1
-
+
false
00
0
@@ -161,11 +166,12 @@
None
- OFEM006
+ OFEM006
+ BRANDEI
Brandei
-
+
FNEMP1
-
+
false
0
70
@@ -193,11 +199,12 @@
None
- OFEM007
+ OFEM007
+ DORJA
Dorja
-
+
FNEMP1
-
+
false
0
70
@@ -225,11 +232,12 @@
None
- OFEM008
+ OFEM008
+ BIN_ESSADA
Bin Essada
-
+
FNEMP1
-
+
false
70
0
@@ -257,11 +265,12 @@
None
- OFEM009
+ OFEM009
+ NILES_FERRIER
Niles Ferrier
-
+
FNEMP1
-
+
false
0
80
@@ -289,11 +298,12 @@
None
- OFEM010
+ OFEM010
+ GRAMMEL
Grammel
-
+
FNEMP1
-
+
false
0
70
@@ -321,11 +331,12 @@
None
- OFEM011
+ OFEM011
+ GRIFF
Griff
-
+
FNEMP1
-
+
false
0
70
@@ -353,11 +364,12 @@
None
- OFEM012
+ OFEM012
+ KLEV
Klev
-
+
FNEMP1
-
+
false
0
0
@@ -385,11 +397,12 @@
None
- OFEM013
+ OFEM013
+ NEEDA
Needa
-
+
FNEMP1
-
+
false
0
70
@@ -417,11 +430,12 @@
None
- OFEM014
+ OFEM014
+ BANE_NOTHOS
Bane Nothos
-
+
FNEMP1
-
+
false
0
70
@@ -449,11 +463,12 @@
None
- OFEM015
+ OFEM015
+ ORLOK
Orlok
-
+
FNEMP1
-
+
false
0
0
@@ -481,11 +496,12 @@
None
- OFEM016
+ OFEM016
+ PALLAEON
Pallaeon
-
+
FNEMP1
-
+
false
70
0
@@ -513,11 +529,12 @@
None
- OFEM017
+ OFEM017
+ SCREED
Screed
-
+
FNEMP1
-
+
false
0
0
@@ -545,11 +562,12 @@
None
- OFEM018
+ OFEM018
+ THRAWN
Thrawn
-
+
FNEMP1
-
+
false
0
0
@@ -577,11 +595,12 @@
None
- OFEM019
+ OFEM019
+ ZUGGS
Zuggs
-
+
FNEMP1
-
+
false
0
70
@@ -609,11 +628,12 @@
None
- OFEM020
+ OFEM020
+ DAALA
Daala
-
+
FNEMP1
-
+
false
0
70
@@ -641,11 +661,12 @@
None
- OFEM021
+ OFEM021
+ THANAS
Pter Thanas
-
+
FNEMP1
-
+
false
70
0
@@ -676,9 +697,10 @@
- OFAL001
+ OFAL001
+ MON_MOTHMA
Mon Mothma
- FNALL1
+ FNALL1
true
100
10
@@ -705,9 +727,10 @@
None
- OFAL002
+ OFAL002
+ LEIA_ORGANA
Leia Organa
- FNALL1
+ FNALL1
true
120
30
@@ -734,9 +757,10 @@
None
- OFAL003
+ OFAL003
+ LUKE_SKYWALKER
Luke Skywalker
- FNALL1
+ FNALL1
true
50
50
@@ -764,9 +788,10 @@
None
- OFAL004
+ OFAL004
+ HAN_SOLO
Han Solo
- FNALL1
+ FNALL1
true
19
100
@@ -794,11 +819,12 @@
None
- OFAL005
+ OFAL005
+ ACKBAR
Ackbar
-
+
FNALL1
-
+
false
0
0
@@ -826,11 +852,12 @@
None
- OFAL006
+ OFAL006
+ WEDGE_ANTILLES
Wedge Antilles
-
+
FNALL1
-
+
false
0
70
@@ -858,11 +885,12 @@
None
- OFAL007
+ OFAL007
+ LANDO_CALRISSIAN
Lando Calrissian
-
+
FNALL1
-
+
false
70
70
@@ -890,11 +918,12 @@
None
- OFAL008
+ OFAL008
+ CHEWBACCA
Chewbacca
-
+
FNALL1
-
+
false
0
90
@@ -922,11 +951,12 @@
None
- OFAL009
+ OFAL009
+ JAN_DODONNA
Jan Dodonna
-
+
FNALL1
-
+
false
70
0
@@ -954,11 +984,12 @@
None
- OFAL010
+ OFAL010
+ CRIX_MADINE
Crix Madine
-
+
FNALL1
-
+
false
0
70
@@ -986,11 +1017,12 @@
None
- OFAL011
+ OFAL011
+ CARLIST_RIEEKAN
Carlist Rieekan
-
+
FNALL1
-
+
false
0
0
@@ -1018,11 +1050,12 @@
None
- OFAL012
+ OFAL012
+ AFYON
Afyon
-
+
FNALL1
-
+
false
0
70
@@ -1050,11 +1083,12 @@
None
- OFAL0113
+ OFAL0113
+ DRAYSON
Drayson
-
+
FNALL1
-
+
false
70
0
@@ -1082,11 +1116,12 @@
None
- OFAL014
+ OFAL014
+ BORSK_FEYLA
Borsk Fey'la
-
+
FNALL1
-
+
false
80
70
@@ -1114,11 +1149,12 @@
None
- OFAL015
+ OFAL015
+ TURA_RAFTICAN
Tura Raftican
-
+
FNALL1
-
+
false
0
90
@@ -1146,11 +1182,12 @@
None
- OFAL016
+ OFAL016
+ BREN_DERLIN
Bren Derlin
-
+
FNALL1
-
+
false
0
70
@@ -1178,11 +1215,12 @@
None
- OFAL017
+ OFAL017
+ GARM_BEL_IBLIS
Garm Bel Iblis
-
+
FNALL1
-
+
false
0
30
@@ -1210,11 +1248,12 @@
None
- OFAL018
+ OFAL018
+ TALON_KARRDE
Talon Karrde
-
+
FNALL1
-
+
false
80
0
@@ -1242,11 +1281,12 @@
None
- OFAL019
+ OFAL019
+ NARRA
Narra
-
+
FNALL1
-
+
false
0
70
@@ -1274,11 +1314,12 @@
None
- OFAL020
+ OFAL020
+ HUOBA_NEVA
Huoba Neva
-
+
FNALL1
-
+
false
0
80
@@ -1306,11 +1347,12 @@
None
- OFAL021
+ OFAL021
+ PAGE
Page
-
+
FNALL1
-
+
false
0
90
diff --git a/Assets/Resources/Data/PlanetSystems.xml b/Assets/Resources/Data/PlanetSystems.xml
index e295070..3178dcf 100644
--- a/Assets/Resources/Data/PlanetSystems.xml
+++ b/Assets/Resources/Data/PlanetSystems.xml
@@ -8,46 +8,56 @@
CoreSystem
Small
High
- PSSEW
+ PSSEW
- PLSEW01
+ PLSEW01
+ YAGA_MINOR
Yaga Minor
- PLSEW02
+ PLSEW02
+ CHANDRILA
Chandrila
- PLSEW03
+ PLSEW03
+ GHORMAN
Ghorman
- PLSEW04
+ PLSEW04
+ AVARAM
Averam
- PLSEW05
+ PLSEW05
+ CORUSCANT
Coruscant
- PLSEW06
+ PLSEW06
+ BALMORRA
Balmorra
- PLSEW07
+ PLSEW07
+ CORSIN
Corsin
- PLSEW08
+ PLSEW08
+ UVENA
Uvena
- PLSEW09
+ PLSEW09
+ SVIVREN
Svivren
- PLSEW10
+ PLSEW10
+ YAGA_MAJOR
Bortras
@@ -57,46 +67,56 @@
CoreSystem
Small
High
- PSCOR
+ PSCOR
- PLCOR01
+ PLCOR01
+ XYQUINE
Xyquine
- PLCOR02
+ PLCOR02
+ DRALL
Drall
- PLCOR03
+ PLCOR03
+ TALUS
Talus
- PLCOR04
+ PLCOR04
+ CORFAI
Corfai
- PLCOR05
+ PLCOR05
+ COMMENOR
Commenor
- PLCOR06
+ PLCOR06
+ SELONIA
Selonia
- PLCOR07
+ PLCOR07
+ VAGRAN
Vagran
- PLCOR08
+ PLCOR08
+ CORELLIA
Corellia
- PLCOR09
+ PLCOR09
+ DUROS
Duros
- PLCOR10
+ PLCOR10
+ TRALUS
Tralus
@@ -106,47 +126,57 @@
CoreSystem
Large
High
- PSFAK
+ PSFAK
+ PLFAK01
+ DELAYA
Delaya
- PLFAK01
+ PLFAK02
+ MRISST
Mrisst
- PLFAK02
+ PLFAK03
+ BIMMISAARI
Bimmisaari
- PLFAK03
+ PLFAK04
+ OBROA_SKAI
Obroa-skai
- PLFAK04
+ PLFAK05
+ CARIDA
Carida
- PLFAK05
+ PLFAK06
+ PALANHI
Palanhi
- PLFAK06
+ PLFAK07
+ ANDO
Ando
- PLFAK07
+ PLFAK08
+ BERCHEST
Berchest
- PLFAK08
+ PLFAK09
+ HALOWAN
Halowan
- PLFAK09
+ PLFAK10
+ RALLTIIR
Ralltiir
- PLFAK10
@@ -155,47 +185,57 @@
CoreSystem
Small
High
- PLDOL
+ PLDOL
+ PLDOL01
+ SULLUST
Sullust
- PLDOL01
+ PLDOL02
+ ORTO
Orto
- PLDOL02
+ PLDOL03
+ BPFASSH
Bpfassh
- PLDOL03
+ PLDOL04
+ BOTHAWUI
Bothawui
- PLDOL04
+ PLDOL05
+ KOTHLIS
Kothlis
- PLDOL05
+ PLDOL06
+ MON_CALAMARI
Mon Calamari
- PLDOL06
+ PLDOL07
+ PRAESITLYN
Praesitlyn
- PLDOL07
+ PLDOL08
+ SLUIS_VAN
Sluis Van
- PLDOL08
+ PLDOL09
+ UMGUL
Umgul
- PLDOL08
+ PLDOL10
+ DENAB
Denab
- PLDOL10
@@ -204,47 +244,57 @@
CoreSystem
Medium
High
- PLFAR
+ PLFAR
+ PLFAR01
+ WISTRIL
Wistril
- PLFAR01
+ PLFAR02
+ BILBRINGI
Bilbringi
- PLFAR02
+ PLFAR03
+ BYSS
Byss
- PLFAR03
+ PLFAR04
+ KHOMM
Khomm
- PLFAR04
+ PLFAR05
+ PHRAETISS
Phraetiss
- PLFAR05
+ PLFAR06
+ KINYEN
Kinyen
- PLFAR06
+ PLFAR07
+ RISHI
Rishi
- PLFAR07
+ PLFAR08
+ FIRRO
Firro
- PLFAR08
+ PLFAR09
+ TAANAB
Taanab
- PLFAR09
+ PLFAR10
+ CHARMATH
Charmath
- PLFAR10
@@ -253,46 +303,56 @@
CoreSystem
Large
High
- PLSLU
+ PLSLU
- PLSLU01
+ PLSLU01
+ PHORLISS
Phorliss
- PLSLU02
+ PLSLU02
+ KAMPARAS
Kamparas
- PLSLU03
+ PLSLU03
+ KETARIS
Ketaris
- PLSLU04
+ PLSLU04
+ BALFRON
Balfron
- PLSLU05
+ PLSLU05
+ PANTOLOMIN
Pantolomin
- PLSLU06
+ PLSLU06
+ TANGRENE
Tangrene
- PLSLU07
+ PLSLU07
+ OMWAT
Omwat
- PLSLU08
+ PLSLU08
+ WOR_TANDELL
Wor Tandell
- PLSLU09
+ PLSLU09
+ SARKA
Sarka
- PLSLU10
+ PLSLU10
+ CAPRIONRIL
Caprionril
@@ -305,47 +365,57 @@
OuterRim
Large
Low
- PLATR
+ PLATR
+ PLATR01
+ ZEFFLIFFL
Zeffliffl
- PLATR01
+ PLATR02
+ MOLTOK
Moltok
- PLATR02
+ PLATR03
+ TOGORIA
Togoria
- PLATR03
+ PLATR04
+ NAMTA
Nam'ta
- PLATR04
+ PLATR05
+ TIBRIN
Tibrin
- PLATR05
+ PLATR06
+ DESPAYRE
Despayre
- PLATR06
+ PLATR07
+ SPEFIK
Spefik
- PLATR07
+ PLATR08
+ TRAMMIS
Trammis
- PLATR08
+ PLATR09
+ FEDJE
Fedje
- PLATR09
+ PLATR10
+ GENERIS
Generis
- PLATR10
@@ -354,47 +424,57 @@
OuterRim
Small
Low
- PLMOD
+ PLMOD
+ PLMOD01
+ ADEGA
Adega
- PLMOD01
+ PLMOD02
+ BASILISK
Basilisk
- PLMOD02
+ PLMOD03
+ ANNAJ
Annaj
- PLMOD03
+ PLMOD04
+ KHUIUMIN
Khuiumin
- PLMOD04
+ PLMOD05
+ PZOB
Pzob
- PLMOD05
+ PLMOD06
+ GANDOLO_IV
Gandolo IV
- PLMOD06
+ PLMOD07
+ AGRILAT
Agrilat
- PLMOD07
+ PLMOD08
+ VJUN
Vjun
- PLMOD08
+ PLMOD09
+ ENDOR
Endor
- PLMOD09
+ PLMOD10
+ HOZREL_XI
Hozrel XI
- PLMOD10
@@ -403,47 +483,57 @@
OuterRim
Medium
Low
- PLQUE
+ PLQUE
+ PLQUE01
+ RAFA
Rafa
- PLQUE01
+ PLQUE02
+ PIL_DILLER
Pil Diller
- PLQUE02
+ PLQUE03
+ KIRREK
Kirrek
- PLQUE03
+ PLQUE04
+ VARN
Varn
- PLQUE04
+ PLQUE05
+ DATHOMIR
Dathomir
- PLQUE05
+ PLQUE06
+ THRAKIA
Thrakia
- PLQUE06
+ PLQUE07
+ VINSOTH
Vinsoth
- PLQUE07
+ PLQUE08
+ AMORRIS
Amorris
- PLQUE08
+ PLQUE09
+ CORSTRIS
Corstris
- PLQUE09
+ PLQUE10
+ SELAGGIS
Selaggis
- PLQUE10
@@ -452,48 +542,58 @@
OuterRim
Small
Medium
- PLCHU
+ PLCHU
+ PLCHU01
+ LELMRA
Lelmra
- PLCHU01
+ PLCHU02
+ GENTES
Gentes
- PLCHU02
+ PLCHU03
+ ALLYUEN
Allyuen
- PLCHU03
+ PLCHU04
+ STORTHUS
Storthus
- PLCHU04
+ PLCHU05
+ TOKMIA
Tokmia
- PLCHU05
+ PLCHU06
+ DEYER
Deyer
- PLCHU06
+ PLCHU07
+ HOTH
Hoth
- PLCHU07
+ PLCHU08
+ ANOAT
Anoat
- PLCHU08
+ PLCHU09
+ BESPIN
Bespin
- PLCHU09
true
+ PLCHU10
+ NEW_COV
New Cov
- PLCHU10
@@ -502,47 +602,57 @@
OuterRim
Medium
Medium
- PLKAN
+ PLKAN
+ PLKAN01
+ XA_FEL
Xa Fel
- PLKAN01
+ PLKAN02
+ VODRAN
Vodran
- PLKAN02
+ PLKAN03
+ MUNTO_CODRU
Munto Codru
- PLKAN03
+ PLKAN04
+ DAVNAR
Davnar
- PLKAN04
+ PLKAN05
+ DERRA_IV
Derra IV
- PLKAN05
+ PLKAN06
+ MINDAR
Mindar
- PLKAN06
+ PLKAN07
+ CULROON_III
Culroon III
- PLKAN07
+ PLKAN08
+ SPUMA
Spuma
- PLKAN08
+ PLKAN09
+ SMARTEEL
Smarteel
- PLKAN09
+ PLKAN10
+ NAL_HUTTA
Nal Hutta
- PLKAN10
@@ -551,47 +661,57 @@
OuterRim
Small
Medium
- PLDUF
+ PLDUF
+ PLDUF01
+ ZEBITROPE_IV
Zebitrope IV
- PLDUF01
+ PLDUF02
+ WOMRIK
Womrik
- PLDUF02
+ PLDUF03
+ KLATOOINE
Klatooine
- PLDUF03
+ PLDUF04
+ ORD_TRASI
Ord Trasi
- PLDUF04
+ PLDUF05
+ ALGARIAN
Algarian
- PLDUF05
+ PLDUF06
+ FILVE
Filve
- PLDUF06
+ PLDUF07
+ TOPRAWA
Toprawa
- PLDUF07
+ PLDUF08
+ ORD_MANTELL
Ord Mantell
- PLDUF08
+ PLDUF09
+ GAMORR
Gamorr
- PLDUF09
+ PLDUF10
+ ORD_PARDON
Ord Pardon
- PLDUF10
@@ -600,47 +720,57 @@
OuterRim
Small
Medium
- PLABR
+ PLABR
+ PLABR01
+ HISHYIM
Hishyim
- PLABR01
+ PLABR02
+ UKIO
Ukio
- PLABR02
+ PLABR03
+ HEFI
Hefi
- PLABR03
+ PLABR04
+ ABREGADO
Abregado
- PLABR04
+ PLABR05
+ DA_SOOCHA
Da Soocha
- PLABR05
+ PLABR06
+ TIEOS
Tieos
- PLABR06
+ PLABR07
+ CATHAR
Cathar
- PLABR07
+ PLABR08
+ GALPOS_II
Galpos II
- PLABR08
+ PLABR09
+ GARBAN
Garban
- PLABR09
+ PLABR10
+ INTUCI
Intuci
- PLABR10
@@ -649,47 +779,57 @@
OuterRim
Large
Low
- PLXAP
+ PLXAP
+ PLXAP01
+ THANTA_ZILBRA
Thanta Zilbra
- PLXAP01
+ PLXAP02
+ NORULAC
Norulac
- PLXAP02
+ PLXAP03
+ NORULAC
Norulac
- PLXAP03
+ PLXAP04
+ AMBRIA
Ambria
- PLXAP04
+ PLXAP05
+ STIC
Stic
- PLXAP05
+ PLXAP06
+ KIRDO_III
Kirdo III
- PLXAP06
+ PLXAP07
+ GRHO
G'rho
- PLXAP07
+ PLXAP08
+ RUURIA
Ruuria
- PLXAP08
+ PLXAP09
+ TUND
Tund
- PLXAP09
+ PLXAP10
+ NEELGAIMON
Neelgaimon
- PLXAP10
@@ -698,47 +838,57 @@
OuterRim
Small
Low
- PLORU
+ PLORU
+ PLORU01
+ LAFRA
Lafra
- PLORU01
+ PLORU02
+ TATOOINE
Tatooine
- PLORU02
+ PLORU03
+ KIMANAN
Kimanan
- PLORU03
+ PLORU04
+ CHAZWA
Chazwa
- PLORU04
+ PLORU05
+ MANTESSA
Mantessa
- PLORU05
+ PLORU06
+ BAKURA
Bakura
- PLORU06
+ PLORU07
+ JOIOL
Joiol
- PLORU07
+ PLORU08
+ DALTAR
Daltar
- PLORU08
+ PLORU09
+ RYLOTH
Ryloth
- PLORU09
+ PLORU10
+ PODERIS
Poderis
- PLORU10
@@ -747,47 +897,57 @@
OuterRim
Small
Low
- PLJOS
+ PLJOS
+ PLJOS01
+ CHRONDRE
Chrondre
- PLJOS01
+ PLJOS02
+ WASKIRO
Waskiro
- PLJOS02
+ PLJOS03
+ ENGIRA
Engira
- PLJOS03
+ PLJOS04
+ CARDOOINE
Cardooine
- PLJOS04
+ PLJOS05
+ DAROR
Dar'Or
- PLJOS05
+ PLJOS06
+ JOMARK
Jomark
- PLJOS06
+ PLJOS07
+ DOUGLAS_III
Douglas III
- PLJOS07
+ PLJOS08
+ KIFFEX
Kiffex
- PLJOS08
+ PLJOS09
+ TROGAN
Trogan
- PLJOS09
+ PLJOS10
+ AZBIAN
Azbian
- PLJOS10
@@ -796,47 +956,57 @@
OuterRim
Small
Low
- PLSUM
+ PLSUM
+ PLSUM01
+ TIERFON
Tierfon
- PLSUM01
+ PLSUM02
+ FLAX
Flax
- PLSUM02
+ PLSUM03
+ ALKLELLISH_III
Alk'lellish III
- PLSUM03
+ PLSUM04
+ KASHYYYK
Kashyyyk
- PLSUM04
+ PLSUM05
+ GEEDON_V
Geedon V
- PLSUM05
+ PLSUM06
+ YAVIN
Yavin
- PLSUM06
+ PLSUM07
+ BOORDII
Boordii
- 07
+ PLSUM08
+ LINURI
Linuri
- PLSUM08
+ PLSUM09
+ QAT_CHRYSTAC
Qat Chrystac
- 09
+ PLSUM10
+ WOOSTRI
Woostri
- PLSUM10
@@ -845,47 +1015,57 @@
OuterRim
Medium
Medium
- PLGLY
+ PLGLY
+ PLGLY01
+ NENTAN
Nentan
- PLGLY01
+ PLGLY02
+ ELROOD
Elrood
- PLGLY02
+ PLGLY03
+ YAGDHUL
Yag'Dhul
- PLGLY03
+ PLGLY04
+ SEDRI
Sedri
- PLGLY04
+ PLGLY05
+ VORTEX
Vortex
- PLGLY05
+ PLGLY06
+ VALRAR
Valrar
- PLGLY06
+ PLGLY07
+ FORNAX
Fornax
- PLGLY07
+ PLGLY08
+ ALTARRN
Altarrn
- PLGLY08
+ PLGLY09
+ ARKANIA
Arkania
- PLGLY09
+ PLGLY10
+ FEF
Fef
- PLGLY10
@@ -894,47 +1074,57 @@
OuterRim
Small
Medium
- PLMAY
+ PLMAY
+ PLMAY01
+ KABAL
Kabal
- PLMAY01
+ PLMAY02
+ TRITON
Triton
- PLMAY02
+ PLMAY03
+ CLAKDOR_VII
Clak'dor VII
- PLMAY03
+ PLMAY04
+ HNEMTHE
H'nemthe
- PLMAY04
+ PLMAY05
+ CONA
Cona
- PLMAY05
+ PLMAY06
+ URDUR
Urdur
- PLMAY06
+ PLMAY07
+ OETRAGO
Oetrago
- PLMAY07
+ PLMAY08
+ CHALCEDON
Chalcedon
- PLMAY08
+ PLMAY09
+ DANTOOINE
Dantooine
- PLMAY09
+ PLMAY10
+ ANCHORON
Anchoron
- PLMAY10
@@ -943,47 +1133,58 @@
OuterRim
Small
Medium
+ PLCAL
+ AKRIT_TAR
Akrit'tar
- PLCAL01
+ PLCAL01
+ KESSEL
Kessel
- PLCAL02
+ PLCAL02
+ NORVAL_II
Norval II
- PLCAL03
+ PLCAL03
+ MORVOGODINE
Morvogodine
- PLCAL04
+ PLCAL04
+ ITHOR
Ithor
- PLCAL05
+ PLCAL05
+ SKOR_II
Skor II
- PLCAL06
+ PLCAL06
+ FWILLSVING
Fwillsving
- PLCAL07
+ PLCAL07
+ KUBINDI
Kubindi
- PLCAL08
+ PLCAL08
+ JERIJADOR
Jerijador
- PLCAL09
+ PLCAL09
+ F_TRAL
F'tral
- PLCAL10
+ PLCAL10
-
\ No newline at end of file
+
diff --git a/Assets/Resources/Data/Regiments.xml b/Assets/Resources/Data/Regiments.xml
index 43530c5..a627142 100644
--- a/Assets/Resources/Data/Regiments.xml
+++ b/Assets/Resources/Data/Regiments.xml
@@ -4,11 +4,11 @@
- REEM001
+ REEM001
Imperial Fleet Regiment
-
+
FNEMP1
-
+
7
5
5
@@ -18,11 +18,11 @@
0
- REEM002
+ REEM002
Imperial Army Regiment
-
+
FNEMP1
-
+
6
3
3
@@ -32,11 +32,11 @@
0
- REEM003
+ REEM003
Stormtrooper Regiment
-
+
FNEMP1
-
+
9
6
6
@@ -46,11 +46,11 @@
0
- REEM004
+ REEM004
War Droid Regiment
-
+
FNEMP1
-
+
9
8
8
@@ -60,11 +60,11 @@
1
- REEM005
+ REEM005
Dark Trooper Regiment
-
+
FNEMP1
-
+
12
8
8
@@ -77,11 +77,11 @@
- REAL001
+ REAL001
Alliance Fleet Regiment
-
+
FNALL1
-
+
8
6
6
@@ -91,11 +91,11 @@
0
- REAL002
+ REAL002
Alliance Army Regiment
-
+
FNALL1
-
+
6
3
3
@@ -105,11 +105,11 @@
0
- REAL003
+ REAL003
Sullustan Regiment
-
+
FNALL1
-
+
3
1
1
@@ -119,11 +119,11 @@
1
- REAL004
+ REAL004
Mon Calamari regiment
-
+
FNALL1
-
+
6
4
2
@@ -133,11 +133,11 @@
2
- REAL005
+ REAL005
Wookie Regiment
-
+
FNALL1
-
+
10
8
8
diff --git a/Assets/Resources/Data/Starfighters.xml b/Assets/Resources/Data/Starfighters.xml
index f90bb8a..536e335 100644
--- a/Assets/Resources/Data/Starfighters.xml
+++ b/Assets/Resources/Data/Starfighters.xml
@@ -4,11 +4,11 @@
- SFEM01
+ SFEM01
TIE Fighter Squadron
-
+
FNEMP1
-
+
3
3
12
@@ -27,11 +27,11 @@
0
- SFEM02
+ SFEM02
TIE Bomber Squadron
-
+
FNEMP1
-
+
3
3
12
@@ -50,11 +50,11 @@
1
- SFEM03
+ SFEM03
TIE Interceptor Squadron
-
+
FNALL1
-
+
3
3
12
@@ -73,11 +73,11 @@
3
- SFEM04
+ SFEM04
TIE Defender Squadron
-
+
FNEMP1
-
+
5
7
12
@@ -99,11 +99,11 @@
- SFAL01
+ SFAL01
Y-Wing Squadron
-
+
FNALL1
-
+
5
4
12
@@ -122,11 +122,11 @@
0
- SFAL02
+ SFAL02
X-Wing Squadron
-
+
FNALL1
-
+
5
4
12
@@ -145,7 +145,7 @@
0
- SFAL03
+ SFAL03
A-Wing Squadron
5
4
@@ -165,11 +165,11 @@
3
- SFAL04
+ SFAL04
B-Wing Squadron
-
+
FNALL1
-
+
7
8
12
diff --git a/Assets/Scripts/Configs/NewGameConfig.cs b/Assets/Scripts/Configs/NewGameConfig.cs
index 01534a2..e57fe3d 100644
--- a/Assets/Scripts/Configs/NewGameConfig.cs
+++ b/Assets/Scripts/Configs/NewGameConfig.cs
@@ -92,7 +92,7 @@ public NewGameOfficerConfig() { }
[Serializable]
public class NewGameInitialBuildingsConfig : Config
{
- public string[] GameIDs;
+ public string[] TypeIDs;
public double[] Frequency;
public NewGameInitialBuildingsConfig() { }
@@ -113,9 +113,9 @@ public NewGameBuildingConfig() { }
[Serializable]
public class NewGameCapitalShipOptions : Config
{
- public string OwnerGameID;
- public string GameID;
- public string InitialParentGameID;
+ public string OwnerTypeID;
+ public string TypeID;
+ public string InitialParentTypeID;
public NewGameCapitalShipOptions() { }
}
diff --git a/Assets/Scripts/Core/GameEntity.cs b/Assets/Scripts/Core/GameEntity.cs
index 72d03f2..d62b4c7 100644
--- a/Assets/Scripts/Core/GameEntity.cs
+++ b/Assets/Scripts/Core/GameEntity.cs
@@ -1,39 +1,64 @@
-using System.Xml.Serialization;
using System;
+using System.Collections.Generic;
+using System.Xml.Serialization;
[Serializable]
public class GameEntity
{
private string _instanceId;
+ private string _ownerTypeID;
- // Set the InstaceID property.
- // This is a unique ID set for each node.
+ ///
+ /// InstanceID is a unique identifier for the object. If not set, it will be generated automatically.
+ /// Its primar
+ ///
[CloneIgnore]
public string InstanceID
{
- get
+ get => _instanceId ??= Guid.NewGuid().ToString().Replace("-", "");
+ set => _instanceId ??= value;
+ }
+
+ ///
+ /// TypeID is a non-unique identifier for specific types of objects, such as starfighters, ships, regiments, etc.
+ ///
+ ///
+ public string TypeID { get; set; }
+
+ // Owner Info
+ public string DisplayName { get; set; }
+ public string Description { get; set; }
+ [CloneIgnore]
+ public string OwnerTypeID
+ {
+ get => _ownerTypeID;
+ set => SetOwnerTypeID(value);
+ }
+ public List AllowedOwnerTypeIDs { get; set; }
+
+ ///
+ /// Sets the owner type id. If the ID is not in the allowed list, throws an exception.
+ ///
+ /// The owner type id to set.
+ /// Thrown when the owner type id is invalid.
+ private void SetOwnerTypeID(string value)
+ {
+ if (AllowedOwnerTypeIDs == null || AllowedOwnerTypeIDs.Count == 0 || AllowedOwnerTypeIDs.Contains(value))
{
- // Generate a new instance ID if it is not set.
- if (_instanceId == null)
- {
- _instanceId = Guid.NewGuid().ToString().Replace("-", "");
- }
- return _instanceId;
+ _ownerTypeID = value;
}
- set
+ else
{
- // Set the instance ID if it is not set.
- if (_instanceId == null)
- {
- _instanceId = value;
- }
+ throw new ArgumentException($"Invalid owner type id: {value}");
}
}
- // Set the GameID property.
- // This is a non-unique ID set for each specific types of objects, such as planets, ships, etc.
- public string GameID { get; set; }
- // Game Info
- public string DisplayName { get; set; }
- public string Description { get; set; }
-}
\ No newline at end of file
+ ///
+ ///
+ ///
+ ///
+ public SceneNode GetShallowCopy()
+ {
+ return (SceneNode)MemberwiseClone();
+ }
+}
diff --git a/Assets/Scripts/Core/LeafNode.cs b/Assets/Scripts/Core/LeafNode.cs
index 5515cec..4276327 100644
--- a/Assets/Scripts/Core/LeafNode.cs
+++ b/Assets/Scripts/Core/LeafNode.cs
@@ -12,11 +12,20 @@ public abstract class LeafNode : SceneNode
///
protected LeafNode() { }
+ ///
+ /// Shallow copies the node. This operation is used to create a copy of the node.
+ ///
+ ///
+ public LeafNode ShallowCopy()
+ {
+ return (LeafNode)MemberwiseClone();
+ }
+
///
/// Adds a child to the node. For leaf nodes, this operation does nothing.
///
/// The child node to add.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
// Do nothing (leaf nodes do not have children).
}
@@ -25,8 +34,7 @@ protected internal override void AddChild(SceneNode child)
/// Removes a child from the node. For leaf nodes, this operation does nothing.
///
/// The child node to remove.
-
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
// Do nothing (leaf nodes do not have children).
}
diff --git a/Assets/Scripts/Core/ReferenceNode.cs b/Assets/Scripts/Core/ReferenceNode.cs
index 2710420..5e57035 100644
--- a/Assets/Scripts/Core/ReferenceNode.cs
+++ b/Assets/Scripts/Core/ReferenceNode.cs
@@ -2,13 +2,12 @@
using System.Xml.Serialization;
///
-/// A simple container which acts as a reference for a GameNode. Its primary purpose is to get around an issue
+/// A simple container which acts as a reference for a SceneNode. Its primary purpose is to get around an issue
/// preventing the serialization of subclasses within a collection. After an exhausting search, I could find
/// no other way to perform the required serialization. This strongly coupled approach was the result.
///
[XmlInclude(typeof(Building))]
[XmlInclude(typeof(CapitalShip))]
-[XmlInclude(typeof(Mission))]
[XmlInclude(typeof(Regiment))]
[XmlInclude(typeof(SpecialForces))]
[XmlInclude(typeof(Starfighter))]
@@ -17,16 +16,25 @@ public class ReferenceNode
public SceneNode Node { get; set; }
///
- ///
+ /// Default constructor.
///
public ReferenceNode() { }
///
- ///
+ /// Initializes the reference node with a scene node, which is the object to be referenced.
///
- ///
+ /// The scene node to reference.
public ReferenceNode(SceneNode node)
{
Node = node;
}
+
+ ///
+ ///
+ ///
+ ///
+ public SceneNode GetReference()
+ {
+ return Node;
+ }
}
diff --git a/Assets/Scripts/Core/SceneNode.cs b/Assets/Scripts/Core/SceneNode.cs
index ce0e88d..b5c487f 100644
--- a/Assets/Scripts/Core/SceneNode.cs
+++ b/Assets/Scripts/Core/SceneNode.cs
@@ -8,8 +8,10 @@ public abstract class SceneNode : GameEntity
{
// Parent Info
[CloneIgnore]
- public string ParentGameID { get; set; }
+ public string ParentTypeID { get; set; }
+ public string LastParentTypeID { get; set; }
protected SceneNode ParentNode;
+ protected SceneNode LastParentNode;
///
/// Default constructor.
@@ -22,8 +24,10 @@ public SceneNode() { }
/// The parent scene node.
public void SetParent(SceneNode parentNode)
{
+ LastParentNode = ParentNode;
ParentNode = parentNode;
- ParentGameID = parentNode?.GameID;
+ LastParentTypeID = ParentTypeID;
+ ParentTypeID = parentNode?.TypeID;
}
///
@@ -35,17 +39,65 @@ public SceneNode GetParent()
return ParentNode;
}
+ ///
+ ///
+ ///
+ ///
+ public SceneNode GetLastParent()
+ {
+ return LastParentNode;
+ }
+
+ /// Gets the closest parent scene node of the specified type.
+ ///
+ /// The type of the parent scene node.
+ /// The closest parent scene node of the specified type.
+ public T GetClosestParentOfType() where T : SceneNode
+ {
+ SceneNode parent = ParentNode;
+ while (parent != null)
+ {
+ if (parent is T)
+ {
+ return (T)parent;
+ }
+ parent = parent.GetParent();
+ }
+ return null;
+ }
+
+ ///
+ /// Gets all children of the current scene node that match the specified game owner id and type.
+ ///
+ /// The type of the children to retrieve.
+ /// The game owner id to match.
+ /// An enumerable collection of children that match the specified game owner id and type.
+ public IEnumerable GetChildrenByOwnerTypeID(string ownerTypeId) where T : SceneNode
+ {
+ List matchingChildren = new List();
+
+ Traverse(node =>
+ {
+ if (node is T && node.OwnerTypeID == ownerTypeId)
+ {
+ matchingChildren.Add((T)node);
+ }
+ });
+
+ return matchingChildren;
+ }
+
///
///
///
///
- protected internal abstract void AddChild(SceneNode child);
+ public abstract void AddChild(SceneNode child);
///
///
///
///
- protected internal abstract void RemoveChild(SceneNode child);
+ public abstract void RemoveChild(SceneNode child);
///
/// Gets an enumerable collection of child scene nodes.
diff --git a/Assets/Scripts/Events/ActionFactory.cs b/Assets/Scripts/Events/ActionFactory.cs
new file mode 100644
index 0000000..73c824e
--- /dev/null
+++ b/Assets/Scripts/Events/ActionFactory.cs
@@ -0,0 +1,57 @@
+// using System.Collections.Generic;
+// using System.Linq;
+// using System;
+// using DependencyInjectionExtensions;
+
+// ///
+// /// Static class that contains methods for evaluating game conditionals.
+// ///
+// static class Actions
+// {
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static void CreateMission(IServiceLocator locator, SerializableDictionary parameters)
+// {
+// MissionService missionService = locator.GetService();
+// LookupService lookupService = locator.GetService();
+
+// // Get the parameters for the action.
+// List mainParticipantIds = (List)parameters["MainParticipantInstanceIDs"];
+// string missionType = (string)parameters["MissionType"];
+// string targetId = (string)parameters["TargetInstanceID"];
+// }
+// }
+
+// ///
+// /// Static class that contains methods for creating game conditionals.
+// ///
+// public static class ActionFactory
+// {
+// private delegate GameAction ActionCreator(SerializableDictionary parameters);
+// private static readonly SerializableDictionary actionCreators = new SerializableDictionary
+// {
+// { "CreateMission", (parameters) => new GenericAction(Actions.CreateMission, parameters) },
+// };
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static GameAction CreateAction(string actionType, SerializableDictionary parameters)
+// {
+// if (actionCreators.TryGetValue(actionType, out var creator))
+// {
+// return creator(parameters);
+// }
+// else
+// {
+// throw new ArgumentException($"Invalid condition type: {actionType}");
+// }
+// }
+// }
diff --git a/Assets/Scripts/Events/ConditionalFactory.cs b/Assets/Scripts/Events/ConditionalFactory.cs
new file mode 100644
index 0000000..43f25ad
--- /dev/null
+++ b/Assets/Scripts/Events/ConditionalFactory.cs
@@ -0,0 +1,195 @@
+// using System.Collections.Generic;
+// using System.Linq;
+// using System;
+// using DependencyInjectionExtensions;
+
+// ///
+// /// Static class that contains methods for evaluating game conditionals.
+// ///
+// static class Conditionals
+// {
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool And(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// List conditionals = (List)parameters["Conditionals"];
+// return conditionals.All(conditional => conditional.IsMet(serviceLocator));
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool Or(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// List conditionals = (List)parameters["Conditionals"];
+// return conditionals.Any(conditional => conditional.IsMet(serviceLocator));
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool Not(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// List conditionals = (List)parameters["Conditionals"];
+// return conditionals.All(conditional => !conditional.IsMet(serviceLocator));
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool Xor(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// List conditionals = (List)parameters["Conditionals"];
+// return conditionals.Count(conditional => conditional.IsMet(serviceLocator)) == 1;
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool AreOnSamePlanet(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// LookupService lookupService = serviceLocator.GetService();
+
+// List instanceIDs = (List)parameters["UnitInstanceIDs"];
+// List sceneNodes = lookupService.GetSceneNodesByInstanceIDs(instanceIDs);
+// Planet comparator = null;
+
+// // Check if all units are on the same planet.
+// foreach (SceneNode node in sceneNodes)
+// {
+// if (node == null)
+// {
+// return false;
+// }
+
+// Planet planet = node.GetClosestParentOfType();
+// comparator ??= planet;
+
+// if (comparator != planet)
+// {
+// return false;
+// }
+// }
+
+// return true;
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool AreOnOpposingFactions(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// LookupService lookupService = serviceLocator.GetService();
+
+// List instanceIDs = (List)parameters["UnitInstanceIDs"];
+
+// // Get the scene nodes for the units.
+// List sceneNodes = lookupService.GetSceneNodesByInstanceIDs(instanceIDs);
+
+// // Check if the units are on opposing factions.
+// return sceneNodes.Count == 2 && sceneNodes[0].OwnerTypeID != sceneNodes[1].OwnerTypeID;
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool IsOnMission(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// LookupService lookupService = serviceLocator.GetService();
+
+// string instanceID = (string)parameters["UnitInstanceID"];
+// SceneNode sceneNode = lookupService.GetSceneNodeByInstanceID(instanceID);
+
+// // Check if the unit is on a mission.
+// return sceneNode != null && sceneNode.GetParent() is Mission;
+// }
+
+// ///
+// ///
+// ///
+// ///
+// ///
+// ///
+// public static bool AreOnPlanet(IServiceLocator serviceLocator, SerializableDictionary parameters)
+// {
+// LookupService lookupService = serviceLocator.GetService();
+
+// // Get the instance IDs of the units to check.
+// List instanceIDs = (List)parameters["UnitInstanceIDs"];
+
+// // Check if all units are on a planet.
+// return instanceIDs.All((string instanceID) => {
+// SceneNode sceneNode = lookupService.GetSceneNodeByInstanceID(instanceID);
+// return sceneNode.GetClosestParentOfType() != null;
+// });
+// }
+// }
+
+// ///
+// /// Factory class for creating conditionals used in game events.
+// ///
+// ///
+// /// The ConditionalFactory is responsible for constructing conditionals that evaluate specific game conditions,
+// /// such as whether two units are on the same planet or are engaged in a mission. Conditionals can also be operators
+// /// like "And", "Or", and "Not" to combine multiple conditionals into one.
+// ///
+// public static class ConditionalFactory
+// {
+// private delegate GameConditional ConditionalCreator(SerializableDictionary parameters);
+// private static readonly Dictionary conditionCreators = new Dictionary
+// {
+// // Operators
+// { "And", (parameters) => new GenericConditional(Conditionals.And, parameters) },
+// { "Xor", (parameters) => new GenericConditional(Conditionals.Xor, parameters) },
+// { "Or", (parameters) => new GenericConditional(Conditionals.Or, parameters) },
+// { "Not", (parameters) => new GenericConditional(Conditionals.Not, parameters) },
+
+// // Unit Conditionals
+// { "AreOnSamePlanet", (parameters) => new GenericConditional(Conditionals.AreOnSamePlanet, parameters) },
+// { "AreOnOpposingFactions", (parameters) => new GenericConditional(Conditionals.AreOnOpposingFactions, parameters) },
+// { "IsOnMission", (parameters) => new GenericConditional(Conditionals.IsOnMission, parameters) },
+
+// // Game State Conditionals
+// };
+
+// ///
+// /// Creates a conditional based on the specified type and parameters.
+// ///
+// /// The type of the conditional (e.g., "OnSamePlanet").
+// /// The parameters required by the conditional.
+// /// A GameConditional object that can evaluate the specified condition.
+// /// Thrown when an invalid condition type is passed.
+// public static GameConditional CreateConditional(string conditionType, SerializableDictionary parameters)
+// {
+// if (conditionCreators.TryGetValue(conditionType, out var creator))
+// {
+// return creator(parameters);
+// }
+// else
+// {
+// throw new ArgumentException($"Invalid condition type: {conditionType}");
+// }
+// }
+// }
diff --git a/Assets/Scripts/Events/GameAction.cs b/Assets/Scripts/Events/GameAction.cs
new file mode 100644
index 0000000..cf75207
--- /dev/null
+++ b/Assets/Scripts/Events/GameAction.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Xml.Serialization;
+using DependencyInjectionExtensions;
+
+///
+/// The GameAction class defines a contract for actions that modify the game state when executed.
+///
+///
+/// GameActions encapsulate specific operations triggered by events, user interactions,
+/// or other game mechanics. They rely on the ServiceLocator to retrieve necessary
+/// services at execution, ensuring flexibility and reusability.
+///
+/// Unlike GameEvents, which encapsulate the occurrence of a specific scenario or trigger
+/// within the game, Actions focus solely on the execution of a specific operation. Events
+/// may trigger Actions, but Actions are concerned with the actual changes made to the game
+/// state.
+///
+[Serializable]
+[XmlInclude(typeof(StartMissionAction))]
+public abstract class GameAction
+{
+ [XmlAttribute("Type")]
+ public string ActionType { get; set; }
+ public SerializableDictionary Parameters { get; set; }
+
+ ///
+ /// Default constructor used for serialization.
+ ///
+ public GameAction() { }
+
+ ///
+ ///
+ ///
+ ///
+ public GameAction(SerializableDictionary parameters)
+ {
+ Parameters = parameters;
+ }
+
+ ///
+ /// Executes the action, using the provided game instance and service locator.
+ ///
+ /// The service locator for retrieving necessary services during execution.
+ public abstract void Execute(IServiceLocator locator);
+}
diff --git a/Assets/Scripts/Events/GameActions.cs b/Assets/Scripts/Events/GameActions.cs
new file mode 100644
index 0000000..1d4fc72
--- /dev/null
+++ b/Assets/Scripts/Events/GameActions.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using DependencyInjectionExtensions;
+
+///
+///
+///
+public class StartMissionAction : GameAction
+{
+ public StartMissionAction() : base() { }
+
+ public StartMissionAction(SerializableDictionary parameters) : base(parameters) { }
+
+ ///
+ ///
+ ///
+ ///
+ public override void Execute(IServiceLocator locator)
+ {
+ IMissionService missionService = locator.GetService();
+ ILookupService lookupService = locator.GetService();
+
+ // Get the parameters for the action.
+ List mainParticipantIds = (List)Parameters["MainParticipantInstanceIDs"];
+ List decoyParticipantIds = (List)Parameters["DecoyParticipantInstanceIDs"];
+ string missionType = (string)Parameters["MissionType"];
+ string targetId = (string)Parameters["TargetInstanceID"];
+
+ // Execute the mission.
+ missionService.StartMission(missionType, mainParticipantIds, decoyParticipantIds, targetId);
+ }
+}
+
+///
+///
+///
+public class ExecuteMissionAction : GameAction
+{
+ public ExecuteMissionAction() : base() { }
+
+ public ExecuteMissionAction(SerializableDictionary parameters) : base(parameters) { }
+
+ public override void Execute(IServiceLocator locator)
+ {
+ IMissionService missionService = locator.GetService();
+ ILookupService lookupService = locator.GetService();
+
+ // Get the parameters for the action.
+ string missionId = (string)Parameters["MissionInstanceID"];
+ Mission mission = lookupService.GetSceneNodeByInstanceID(missionId);
+
+ // @TODO: Execute the mission.
+ }
+}
diff --git a/Assets/Scripts/Events/GameConditional.cs b/Assets/Scripts/Events/GameConditional.cs
new file mode 100644
index 0000000..6e7e1d7
--- /dev/null
+++ b/Assets/Scripts/Events/GameConditional.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Xml.Serialization;
+using DependencyInjectionExtensions;
+
+///
+/// Represents a condition that must be met for an event.
+///
+///
+/// Conditions are critical to the event system, as they determine when an event is
+/// eligible to be executed. Conditions are evaluated at the time the event is scheduled
+/// to occur, and if all conditions are met, the event is executed.
+///
+[Serializable]
+public abstract class GameConditional : GameEntity
+{
+ [XmlAttribute("Type")]
+ public string ConditionalType { get; set; }
+ public SerializableDictionary Parameters { get; set; }
+
+ ///
+ /// Default constructor used for serialization.
+ ///
+ public GameConditional() { }
+
+ ///
+ ///
+ ///
+ ///
+ public GameConditional(SerializableDictionary parameters)
+ {
+ Parameters = parameters;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public abstract bool IsMet(IServiceLocator serviceLocator);
+}
diff --git a/Assets/Scripts/Events/GameConditionals.cs b/Assets/Scripts/Events/GameConditionals.cs
new file mode 100644
index 0000000..88c220b
--- /dev/null
+++ b/Assets/Scripts/Events/GameConditionals.cs
@@ -0,0 +1,157 @@
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using DependencyInjectionExtensions;
+
+///
+///
+///
+public class AndConditional : GameConditional
+{
+ public AndConditional() : base() { }
+
+ public AndConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ List conditionals = (List)Parameters["Conditionals"];
+ return conditionals.All(conditional => conditional.IsMet(serviceLocator));
+ }
+}
+
+///
+///
+///
+public class OrConditional : GameConditional
+{
+ public OrConditional() : base() { }
+
+ public OrConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ List conditionals = (List)Parameters["Conditionals"];
+ return conditionals.Any(conditional => conditional.IsMet(serviceLocator));
+ }
+}
+
+///
+///
+///
+public class NotConditional : GameConditional
+{
+ public NotConditional() : base() { }
+
+ public NotConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ List conditionals = (List)Parameters["Conditionals"];
+ return conditionals.All(conditional => !conditional.IsMet(serviceLocator));
+ }
+}
+
+public class XorConditional : GameConditional
+{
+ public XorConditional() : base() { }
+
+ public XorConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ List conditionals = (List)Parameters["Conditionals"];
+ return conditionals.Count(conditional => conditional.IsMet(serviceLocator)) == 1;
+ }
+}
+
+public class AreOnSamePlanetConditional : GameConditional
+{
+ public AreOnSamePlanetConditional() : base() { }
+
+ public AreOnSamePlanetConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ ILookupService lookupService = serviceLocator.GetService();
+
+ List instanceIDs = (List)Parameters["UnitInstanceIDs"];
+ List sceneNodes = lookupService.GetSceneNodesByInstanceIDs(instanceIDs);
+ Planet comparator = null;
+
+ // Check if all units are on the same planet.
+ foreach (SceneNode node in sceneNodes)
+ {
+ if (node == null)
+ {
+ return false;
+ }
+
+ Planet planet = node.GetClosestParentOfType();
+ comparator ??= planet;
+
+ if (comparator != planet)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+public class AreOnOpposingFactionsConditional : GameConditional
+{
+ public AreOnOpposingFactionsConditional() : base() { }
+
+ public AreOnOpposingFactionsConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ LookupService lookupService = serviceLocator.GetService();
+
+ List instanceIDs = (List)Parameters["UnitInstanceIDs"];
+
+ // Get the scene nodes for the units.
+ List sceneNodes = lookupService.GetSceneNodesByInstanceIDs(instanceIDs);
+
+ // Check if the units are on opposing factions.
+ return sceneNodes.Count == 2 && sceneNodes[0].OwnerTypeID != sceneNodes[1].OwnerTypeID;
+ }
+}
+
+public class IsOnMissionConditional : GameConditional
+{
+ public IsOnMissionConditional() : base() { }
+
+ public IsOnMissionConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ LookupService lookupService = serviceLocator.GetService();
+
+ string instanceID = (string)Parameters["UnitInstanceID"];
+ SceneNode sceneNode = lookupService.GetSceneNodeByInstanceID(instanceID);
+
+ // Check if the unit is on a mission.
+ return sceneNode != null && sceneNode.GetParent() is Mission;
+ }
+}
+
+public class AreOnPlanetConditional : GameConditional
+{
+ public AreOnPlanetConditional() : base() { }
+
+ public AreOnPlanetConditional(SerializableDictionary parameters) : base(parameters) { }
+
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ LookupService lookupService = serviceLocator.GetService();
+
+ // Get the instance IDs of the units to check.
+ List instanceIDs = (List)Parameters["UnitInstanceIDs"];
+ List sceneNodes = lookupService.GetSceneNodesByInstanceIDs(instanceIDs);
+
+ // Check if all units are on a planet.
+ return sceneNodes.All(node => node.GetClosestParentOfType() != null);
+ }
+}
diff --git a/Assets/Scripts/Events/GameEvent.cs b/Assets/Scripts/Events/GameEvent.cs
index 8ada1b1..c5f6750 100644
--- a/Assets/Scripts/Events/GameEvent.cs
+++ b/Assets/Scripts/Events/GameEvent.cs
@@ -1,4 +1,6 @@
+using System.Collections.Generic;
using System;
+using DependencyInjectionExtensions;
///
/// Represents a base class for all game events within the game.
@@ -10,43 +12,55 @@
/// are executed.
///
/// Unlike Actions, which directly represent a specific operation or change in the game
-/// state, Game Events focus on the occurrence of a particular scenario or trigger.
+/// state, game events focus on the occurrence of a particular scenario or trigger.
/// Events can lead to the execution of one or more Actions but are primarily concerned
/// with the context and timing of those actions.
///
-public abstract class GameEvent : GameEntity
+public class GameEvent : GameEntity
{
- public int ScheduledTick { get; set; }
+ // Event Properties
+ public bool IsRepeatable { get; set; }
+ public List Conditionals { get; set; }
+ public List Actions { get; set; }
+
+ // Event Callbacks
public event Action OnEventTriggered;
///
- /// Initializes a new instance of the class with the specified parameters.
+ /// Default constructor used for serialization.
///
- /// The tick at which the event is scheduled to occur.
- protected GameEvent(int scheduledTick)
- {
- ScheduledTick = scheduledTick;
- }
+ public GameEvent() { }
///
- /// Executes the event, applying any relevant logic or actions to the game state.
+ ///
///
- /// The current game instance in which the event is executed.
- ///
- /// The `Execute` method is the core of the `GameEvent` class. When the event is triggered,
- /// this method is called to perform the event's logic. This might include evaluating conditions,
- /// triggering actions, or scheduling follow-up events.
- ///
- public void Execute(Game game)
+ ///
+ ///
+ public bool AreConditionsMet(IServiceLocator serviceLocator)
{
- TriggerEvent(game);
- OnEventTriggered?.Invoke(this);
+ foreach (GameConditional conditional in Conditionals)
+ {
+ if (!conditional.IsMet(serviceLocator))
+ {
+ return false;
+ }
+ }
+ return true;
}
///
///
///
- ///
- protected abstract void TriggerEvent(Game game);
-
+ ///
+ public void Execute(IServiceLocator serviceLocator)
+ {
+ // Evaluate the event's actions.
+ foreach (GameAction action in Actions)
+ {
+ action.Execute(serviceLocator);
+ }
+
+ // Trigger the event callback.
+ OnEventTriggered?.Invoke(this);
+ }
}
diff --git a/Assets/Scripts/Events/GenericAction.cs b/Assets/Scripts/Events/GenericAction.cs
index 2cb4f44..9944150 100644
--- a/Assets/Scripts/Events/GenericAction.cs
+++ b/Assets/Scripts/Events/GenericAction.cs
@@ -1,27 +1,36 @@
using System;
+using DependencyInjectionExtensions;
///
/// Represents a generic action that can be executed on a game.
///
-public class GenericAction : IAction
+public class GenericAction : GameAction
{
- private Action action;
+ private readonly Action> callback;
+ public SerializableDictionary parameters;
///
- /// Initializes a new instance of the class.
+ /// Default constructor used for serialization.
///
- /// The action to be executed on the game.
- public GenericAction(Action action)
+ public GenericAction() { }
+
+ ///
+ /// Initializes a new instance of the GenericAction class.
+ ///
+ ///
+ /// The parameters required for the condition.
+ public GenericAction(Action> callback, SerializableDictionary parameters)
{
- this.action = action;
+ this.callback = callback;
+ this.parameters = parameters;
}
///
- /// Executes the generic action on the specified game.
+ ///
///
- /// The game on which the action is to be executed.
- public void Execute(Game game)
+ ///
+ public override void Execute(IServiceLocator locator)
{
- action.Invoke(game);
+ callback.Invoke(locator, parameters);
}
}
diff --git a/Assets/Scripts/Events/GenericConditional.cs b/Assets/Scripts/Events/GenericConditional.cs
new file mode 100644
index 0000000..7c8f5ea
--- /dev/null
+++ b/Assets/Scripts/Events/GenericConditional.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using System.Xml.Serialization;
+using System;
+using DependencyInjectionExtensions;
+
+///
+/// A generic conditional that uses a callback to determine if the condition is met.
+///
+[Serializable]
+public class GenericConditional : GameConditional
+{
+ public SerializableDictionary parameters;
+ private readonly Func, bool> callback;
+
+ ///
+ /// Default constructor used for serialization.
+ ///
+ public GenericConditional() { }
+
+ ///
+ /// Initializes a new instance of the GenericConditional class.
+ ///
+ /// The function that evaluates whether the condition is met.
+ /// The parameters required for the condition.
+ public GenericConditional(Func, bool> callback, SerializableDictionary parameters)
+ {
+ this.callback = callback;
+ this.parameters = parameters;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool IsMet(IServiceLocator serviceLocator)
+ {
+ return callback.Invoke(serviceLocator, parameters);
+ }
+}
diff --git a/Assets/Scripts/Events/IAction.cs b/Assets/Scripts/Events/IAction.cs
deleted file mode 100644
index c937144..0000000
--- a/Assets/Scripts/Events/IAction.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-///
-/// The IAction interface defines a contract for actions that can be executed within the game.
-///
-///
-/// Actions in this design represent discrete tasks or operations that affect the game state.
-/// They are meant to be flexible, allowing developers to encapsulate specific behaviors that
-/// can be triggered by events, user interactions, or other game mechanics.
-///
-/// Unlike Game Events, which encapsulate the occurrence of a specific scenario or trigger
-/// within the game, Actions focus solely on the execution of a specific operation. Events
-/// may trigger Actions, but Actions are concerned with the actual changes made to the game
-/// state.
-///
-public interface IAction
-{
- //
- /// Executes the action within the context of the provided game instance.
- ///
- /// The current game instance in which the action should be executed.
- ///
- /// The Execute method is the core of the IAction interface. When an action is executed, it typically
- /// performs one or more operations on the game state. For example, an action might move a unit,
- /// update a resource count, or trigger another event.
- ///
- void Execute(Game game);
-}
diff --git a/Assets/Scripts/Events/ICondition.cs b/Assets/Scripts/Events/ICondition.cs
deleted file mode 100644
index a9b0293..0000000
--- a/Assets/Scripts/Events/ICondition.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-///
-/// Represents a condition that must be met for an event or action to proceed.
-///
-public interface ICondition
-{
- ///
- /// Evaluates the condition in the context of the provided game instance.
- ///
- /// The current game instance to evaluate the condition against.
- /// True if the condition is met, otherwise false.
- bool IsMet(Game game);
-}
diff --git a/Assets/Scripts/Events/MissionEvent.cs b/Assets/Scripts/Events/MissionEvent.cs
deleted file mode 100644
index b766c28..0000000
--- a/Assets/Scripts/Events/MissionEvent.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-///
-///
-///
-public class MissionEvent : GameEvent
-{
- public Mission Mission { get; private set; }
-
- ///
- /// Initializes a new instance of the MissionEvent class.
- ///
- /// The tick at which the event is scheduled to occur.
- /// The mission that is being executed.
- public MissionEvent(int scheduledTick, Mission mission) : base(scheduledTick)
- {
- Mission = mission;
- }
-
- ///
- /// Executes the mission.
- ///
- ///
- protected override void TriggerEvent(Game game)
- {
- // Execute the mission.
- Mission.Perform(game);
- }
-}
diff --git a/Assets/Scripts/Events/ScheduledEvent.cs b/Assets/Scripts/Events/ScheduledEvent.cs
new file mode 100644
index 0000000..bb4ca38
--- /dev/null
+++ b/Assets/Scripts/Events/ScheduledEvent.cs
@@ -0,0 +1,41 @@
+///
+/// Represents a scheduled event within the game.
+/// A ScheduledEvent is a wrapper around a GameEvent, responsible for tracking
+/// when (at what game tick) the event should be executed.
+///
+///
+/// The purpose of the ScheduledEvent class is to separate the timing aspect from the logic of the GameEvent itself.
+///
+/// This allows the GameEvent class to be immutable and stateless after creation, while the ScheduledEvent class
+/// can be modified to change the execution time of the event, in addition to anything else that might be needed.
+///
+public class ScheduledEvent
+{
+ public GameEvent Event { get; }
+ public int ScheduledTick { get; set; }
+
+ ///
+ /// Default constructor used for serialization.
+ ///
+ public ScheduledEvent() { }
+
+ ///
+ /// Initializes a new instance of the ScheduledEvent class with a given event and tick.
+ ///
+ /// The GameEvent to be executed.
+ /// The tick at which the event should execute.
+ public ScheduledEvent(GameEvent gameEvent, int scheduledTick)
+ {
+ Event = gameEvent;
+ ScheduledTick = scheduledTick;
+ }
+
+ ///
+ /// Gets the GameEvent associated with this ScheduledEvent.
+ ///
+ ///
+ public GameEvent GetEvent()
+ {
+ return Event;
+ }
+}
diff --git a/Assets/Scripts/Events/UnitMovedEvent.cs b/Assets/Scripts/Events/UnitMovedEvent.cs
deleted file mode 100644
index 701a15d..0000000
--- a/Assets/Scripts/Events/UnitMovedEvent.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-///
-/// Represents an event that occurs when a unit is moved.
-///
-public class UnitMovedEvent : GameEvent
-{
- public string UnitInstanceID { get; private set; }
- public string DestinationInstanceID { get; private set; }
-
- ///
- /// Initializes a new instance of the UnitMovedEvent class.
- ///
- /// The tick at which the event is scheduled to occur.
- /// The instance ID of the unit that is moved.
- /// The instance ID of the destination to which the unit is moved.
- public UnitMovedEvent(int scheduledTick, string unitInstanceId, string destinationInstanceId) : base(scheduledTick)
- {
- UnitInstanceID = unitInstanceId;
- DestinationInstanceID = destinationInstanceId;
- }
-
- ///
- /// Moves the unit to the destination. If the destination is not accessible,
- /// the unit is returned to the nearest location.
- ///
- /// The game in which the event occurs.
- protected override void TriggerEvent(Game game)
- {
- SceneNode unit = game.GetSceneNodeByInstanceID(UnitInstanceID);
- SceneNode destination = game.GetSceneNodeByInstanceID(DestinationInstanceID);
-
- // Move the unit to the destination.
- try
- {
- // Move the unit to the destination.
- if (unit.GetParent() != destination)
- {
- game.MoveNode(unit, destination);
- }
- // Update the unit's movement status.
- if (unit is IMovable movableUnit)
- {
- movableUnit.MovementStatus = MovementStatus.Stationary;
- }
- }
- catch (SceneAccessException ex)
- {
- // @TODO: Return unit to nearest location.
- }
- }
-}
diff --git a/Assets/Scripts/Game/Building.cs b/Assets/Scripts/Game/Building.cs
index 3cc53de..16400ba 100644
--- a/Assets/Scripts/Game/Building.cs
+++ b/Assets/Scripts/Game/Building.cs
@@ -26,6 +26,10 @@ public class Building : LeafNode, IManufacturable
public int ShieldStrength;
public BuildingSlot Slot;
+ // Status Info
+ public ManufacturingStatus ManufacturingStatus { get; set; }
+ public MovementStatus MovementStatus { get; set; }
+
///
/// Default constructor.
///
diff --git a/Assets/Scripts/Game/CapitalShip.cs b/Assets/Scripts/Game/CapitalShip.cs
index f1a1ec6..5a3b17b 100644
--- a/Assets/Scripts/Game/CapitalShip.cs
+++ b/Assets/Scripts/Game/CapitalShip.cs
@@ -1,7 +1,7 @@
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System;
using ICollectionExtensions;
public enum PrimaryWeaponType
@@ -53,6 +53,10 @@ public class CapitalShip : SceneNode, IManufacturable
public int WeaponRecharge;
public int Bombardment;
+ // Status Info
+ public ManufacturingStatus ManufacturingStatus { get; set; }
+ public MovementStatus MovementStatus { get; set; }
+
// Misc Info
public int TractorBeamPower;
public int TractorBeamnRange;
@@ -60,10 +64,7 @@ public class CapitalShip : SceneNode, IManufacturable
public int DetectionRating;
// Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
- public string InitialParentGameID { get; set; }
+ public string InitialParentTypeID { get; set; }
///
/// Default constructor.
@@ -109,7 +110,7 @@ public void AddRegiment(Regiment regiment)
/// Thrown when the officer is not allowed to be added.
public void AddOfficer(Officer officer)
{
- if (this.OwnerGameID != officer.OwnerGameID)
+ if (this.OwnerTypeID != officer.OwnerTypeID)
{
throw new SceneAccessException(officer, this);
}
@@ -121,7 +122,7 @@ public void AddOfficer(Officer officer)
///
/// The child to add
/// Thrown when the child is not allowed to be added.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
if (child is Starfighter starfighter)
{
@@ -141,7 +142,7 @@ protected internal override void AddChild(SceneNode child)
/// Adds a child to the capital ship.
///
/// The child to remove
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
if (child is Starfighter starfighter)
{
@@ -163,9 +164,8 @@ protected internal override void RemoveChild(SceneNode child)
///
public override IEnumerable GetChildren()
{
- List combinedList = new List();
- combinedList.AddAll(Officers, Starfighters, Regiments);
-
- return combinedList.ToArray();
+ return Officers.Cast()
+ .Concat(Starfighters.Cast())
+ .Concat(Regiments.Cast());
}
}
diff --git a/Assets/Scripts/Game/Faction.cs b/Assets/Scripts/Game/Faction.cs
index b58e212..29bcccf 100644
--- a/Assets/Scripts/Game/Faction.cs
+++ b/Assets/Scripts/Game/Faction.cs
@@ -18,7 +18,7 @@ public class Faction : LeafNode
{ MessageType.Resource, new List() }
};
public int ResearchLevel;
- public string HQGameID;
+ public string HQTypeID;
///
/// Default constructor.
diff --git a/Assets/Scripts/Game/Fleet.cs b/Assets/Scripts/Game/Fleet.cs
index 0f7ef4e..15d36f8 100644
--- a/Assets/Scripts/Game/Fleet.cs
+++ b/Assets/Scripts/Game/Fleet.cs
@@ -6,11 +6,6 @@ public class Fleet : SceneNode
{
public List CapitalShips = new List();
- // Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
-
///
/// Default constructor.
///
@@ -23,7 +18,7 @@ public Fleet() { }
/// Thrown when the capital ship is not allowed to be added.
private void AddCapitalShip(CapitalShip capitalShip)
{
- if (this.OwnerGameID != capitalShip.OwnerGameID)
+ if (this.OwnerTypeID != capitalShip.OwnerTypeID)
{
throw new SceneAccessException(capitalShip, this);
}
@@ -37,7 +32,7 @@ private void AddCapitalShip(CapitalShip capitalShip)
/// Thrown when the officer is not allowed to be added.
private void AddOfficer(Officer officer)
{
- if (this.OwnerGameID != officer.OwnerGameID)
+ if (this.OwnerTypeID != officer.OwnerTypeID)
{
throw new SceneAccessException(officer, this);
}
@@ -49,7 +44,7 @@ private void AddOfficer(Officer officer)
///
/// The child node to add.
/// Thrown when the child is not allowed to be added.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
if (child is CapitalShip)
{
@@ -65,7 +60,7 @@ protected internal override void AddChild(SceneNode child)
/// Removes a child from the node.
///
/// The child node to remove.
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
if (child is CapitalShip capitalShip)
{
diff --git a/Assets/Scripts/Game/GalaxyMap.cs b/Assets/Scripts/Game/GalaxyMap.cs
index ea18a50..5b1d253 100644
--- a/Assets/Scripts/Game/GalaxyMap.cs
+++ b/Assets/Scripts/Game/GalaxyMap.cs
@@ -19,7 +19,7 @@ public GalaxyMap() {}
/// Adds a child to the node.
///
/// The child node to add.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
if (child is PlanetSystem planetSystem)
{
@@ -31,7 +31,7 @@ protected internal override void AddChild(SceneNode child)
/// Removes a child from the node.
///
/// The child node to remove.
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
if (child is PlanetSystem planetSystem)
{
diff --git a/Assets/Scripts/Game/Game.cs b/Assets/Scripts/Game/Game.cs
index 9876a2a..7013ca7 100644
--- a/Assets/Scripts/Game/Game.cs
+++ b/Assets/Scripts/Game/Game.cs
@@ -11,22 +11,25 @@ public class Game
// Game Details
public GameSummary Summary { get; set; }
- // Child Nodes
- public List Factions = new List();
- public List UnrecruitedOfficers = new List(); // @TODO: Convert to dictionary for faster lookups.
- public SerializableDictionary> GameEventDictionary =
- new SerializableDictionary>();
+ // Game Events
+ public SerializableDictionary> ScheduledEvents =
+ new SerializableDictionary>();
+ public List EventPool = new List();
+ public SerializableHashSet CompletedEventIDs = new SerializableHashSet();
// Reference List
- public SerializableDictionary ReferenceDictionary =
+ public SerializableDictionary NodesByTypeID =
new SerializableDictionary();
// Scene Nodes
[XmlIgnore]
- public SerializableDictionary SceneNodeRegistry =
+ public SerializableDictionary NodesByInstanceID =
new SerializableDictionary();
- // Galaxy Map
+
+ // Game Objects
+ public List Factions = new List();
+ public List UnrecruitedOfficers = new List(); // @TODO: Convert to dictionary for faster lookups.
private GalaxyMap _galaxy;
public GalaxyMap Galaxy
{
@@ -36,9 +39,7 @@ public GalaxyMap Galaxy
}
set
{
- _galaxy = value;
- // Connect the scene graph (children to parents).
- connectSceneGraph(_galaxy);
+ _galaxy ??= value;
}
}
@@ -75,7 +76,7 @@ public void AttachNode(SceneNode parent, SceneNode node)
if (node.GetParent() != null)
{
throw new InvalidSceneOperationException(
- $"Cannot attach node \"{node.GameID}\" to parent \"{parent.GameID}\" because it already has a parent."
+ $"Cannot attach node \"{node.TypeID}\" to parent \"{parent.TypeID}\" because it already has a parent."
);
}
@@ -83,7 +84,7 @@ public void AttachNode(SceneNode parent, SceneNode node)
node.SetParent(parent);
// Register the node and its children.
- node.Traverse(RegisterSceneNode);
+ node.Traverse(AddNodeByInstanceID);
}
///
@@ -96,7 +97,7 @@ public void DetachNode(SceneNode node)
if (node.GetParent() == null)
{
throw new InvalidSceneOperationException(
- $"Cannot detach node \"{node.GameID}\" because it does not have a parent."
+ $"Cannot detach node \"{node.TypeID}\" because it does not have a parent."
);
}
@@ -104,7 +105,7 @@ public void DetachNode(SceneNode node)
node.SetParent(null);
// Deregister the node and its children.
- node.Traverse(DeregisterSceneNode);
+ node.Traverse(RemoveNodeByInstanceID);
}
///
@@ -112,12 +113,13 @@ public void DetachNode(SceneNode node)
///
/// The node to move.
/// The new parent to move the node to.
+ /// Whether to move the node's children as well.
public void MoveNode(SceneNode node, SceneNode parent, bool? recurse = false)
{
if (node.GetParent() == null)
{
throw new InvalidSceneOperationException(
- $"Cannot move node \"{node.GameID}\" because it does not have a parent."
+ $"Cannot move node \"{node.TypeID}\" because it does not have a parent."
);
}
@@ -142,40 +144,40 @@ public void MoveNode(SceneNode node, SceneNode parent, bool? recurse = false)
/// Adds a reference node to the game.
///
/// The game node to add as a reference.
- public void AddReferenceNode(SceneNode node)
+ public void AddNodeByTypeID(SceneNode node)
{
- ReferenceDictionary.Add(node.GameID, new ReferenceNode(node));
+ NodesByTypeID.Add(node.TypeID, new ReferenceNode(node));
}
///
/// Removes a reference node from the game.
///
/// The game node to remove as a reference.
- public void RegisterSceneNode(SceneNode node)
+ public void AddNodeByInstanceID(SceneNode node)
{
- SceneNodeRegistry.TryAdd(node.InstanceID, node);
+ NodesByInstanceID.TryAdd(node.InstanceID, node);
}
///
/// Deregisters a scene node from the game.
///
/// The scene node to deregister.
- public void DeregisterSceneNode(SceneNode node)
+ public void RemoveNodeByInstanceID(SceneNode node)
{
- SceneNodeRegistry.Remove(node.InstanceID);
+ NodesByInstanceID.Remove(node.InstanceID);
}
-
///
- /// Gets a node in the scene by its game ID.
+ ///
///
- ///
- /// The scene node with the specified game ID, or null if not found.
- public SceneNode GetSceneNodeByGameID(string gameId)
+ ///
+ ///
+ ///
+ public T GetSceneNodeByTypeID(string typeId) where T : SceneNode
{
- if (SceneNodeRegistry.TryGetValue(gameId, out SceneNode node))
+ if (NodesByTypeID.TryGetValue(typeId, out ReferenceNode referenceNode))
{
- return node;
+ return referenceNode.GetReference() as T;
} else
{
return null;
@@ -183,76 +185,91 @@ public SceneNode GetSceneNodeByGameID(string gameId)
}
///
- /// Gets a node in the scene by its instance ID.
+ ///
///
- ///
- /// The scene node with the specified instance ID, or null if not found.
- public SceneNode GetSceneNodeByInstanceID(string instanceId)
+ ///
+ ///
+ ///
+ public T GetSceneNodeByInstanceID(string instanceId) where T : SceneNode
{
- if (SceneNodeRegistry.TryGetValue(instanceId, out SceneNode node))
+ if (NodesByInstanceID.TryGetValue(instanceId, out SceneNode node))
{
- return node;
+ return node as T;
} else
{
return null;
}
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List GetSceneNodesByInstanceIDs(List instanceIDs)
+ {
+ List matchingNodes = new List();
+
+ foreach (var instanceId in instanceIDs)
+ {
+ if (NodesByInstanceID.TryGetValue(instanceId, out SceneNode node))
+ {
+ matchingNodes.Add(node);
+ }
+ }
+
+ return matchingNodes;
+ }
+
///
/// Adds a game event to the game event dictionary.
///
/// The tick at which the game event occurs.
/// The game event to add.
- public void AddGameEvent(int tick, GameEvent gameEvent)
+ public void ScheduleGameEvent(int tick, GameEvent gameEvent)
{
- List eventList = GameEventDictionary.GetOrAddValue(tick, new List());
- eventList.Add(gameEvent);
+ ScheduledEvent scheduledEvent = new ScheduledEvent(gameEvent, tick);
+ ScheduledEvents[tick].Add(scheduledEvent);
}
///
///
///
///
- ///
- public void RemoveGameEvent(int tick, GameEvent gameEvent)
+ ///
+ public void RemoveScheduledEvent(int tick, ScheduledEvent scheduledEvent)
{
- if (GameEventDictionary.ContainsKey(tick))
+ if (ScheduledEvents.ContainsKey(tick))
{
- GameEventDictionary[tick].Remove(gameEvent);
+ ScheduledEvents[tick].Remove(scheduledEvent);
}
}
///
- ///
+ /// Adds a game event to the list of completed event IDs.
///
- ///
- ///
- public List GetUnrecruitedOfficers(string ownerGameID)
+ ///
+ public void AddCompletedEventID(GameEvent gameEvent)
{
- return UnrecruitedOfficers.Where(officer => officer.OwnerGameID == ownerGameID).ToList();
+ CompletedEventIDs.Add(gameEvent.InstanceID);
}
///
///
///
- ///
- public void RemoveUnrecruitedOfficer(Officer officer)
+ ///
+ ///
+ public List GetUnrecruitedOfficers(string ownerTypeID)
{
- UnrecruitedOfficers.Remove(officer);
+ return UnrecruitedOfficers.Where(officer => officer.OwnerTypeID == ownerTypeID).ToList();
}
///
- /// Connects the scene graph by setting the parent of each node.
+ ///
///
- ///
- private void connectSceneGraph(GalaxyMap galaxy)
+ ///
+ public void RemoveUnrecruitedOfficer(Officer officer)
{
- galaxy.Traverse((SceneNode node) => {
- foreach (SceneNode child in node.GetChildren())
- {
- child.SetParent(node);
- }
- RegisterSceneNode(node);
- });
+ UnrecruitedOfficers.Remove(officer);
}
}
diff --git a/Assets/Scripts/Game/IManufacturable.cs b/Assets/Scripts/Game/IManufacturable.cs
index e8fe35d..a9bd08c 100644
--- a/Assets/Scripts/Game/IManufacturable.cs
+++ b/Assets/Scripts/Game/IManufacturable.cs
@@ -2,10 +2,17 @@
using System.Collections.Generic;
using UnityEngine;
+public enum ManufacturingStatus
+{
+ Building,
+ Queued,
+ Complete
+}
+
///
///
///
-public interface IManufacturable
+public interface IManufacturable : IMovable
{
// Construction Info
public int ConstructionCost { get; set; }
@@ -14,4 +21,6 @@ public interface IManufacturable
// Research Info
public int RequiredResearchLevel { get; set; }
+
+ public ManufacturingStatus ManufacturingStatus { get; set; }
}
diff --git a/Assets/Scripts/Game/IMovable.cs b/Assets/Scripts/Game/IMovable.cs
new file mode 100644
index 0000000..5df5711
--- /dev/null
+++ b/Assets/Scripts/Game/IMovable.cs
@@ -0,0 +1,16 @@
+///
+///
+///
+public enum MovementStatus
+{
+ InTransit,
+ Idle,
+}
+
+///
+///
+///
+public interface IMovable
+{
+ public MovementStatus MovementStatus { get; set; }
+}
diff --git a/Assets/Scripts/Game/IMoveable.cs b/Assets/Scripts/Game/IMoveable.cs
deleted file mode 100644
index d7b4696..0000000
--- a/Assets/Scripts/Game/IMoveable.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-public enum MovementStatus
-{
- Stationary,
- InTransit,
-}
-
-///
-/// Represents an object that can be moved.
-///
-public interface IMovable
-{
- MovementStatus MovementStatus { get; set; }
-}
\ No newline at end of file
diff --git a/Assets/Scripts/Game/Officer.cs b/Assets/Scripts/Game/Officer.cs
index 0db71df..7dc8af1 100644
--- a/Assets/Scripts/Game/Officer.cs
+++ b/Assets/Scripts/Game/Officer.cs
@@ -2,6 +2,9 @@
using System.Collections.Generic;
using System.Xml.Serialization;
+///
+///
+///
public enum OfficerRank
{
None,
@@ -10,30 +13,14 @@ public enum OfficerRank
Admiral,
}
-public enum OfficerStatus
+public class Officer : MissionParticipant, IMovable
{
- Available,
- Injured,
- Captured,
- OnMission,
- InTransit,
-}
-
-public class Officer : MissionParticipant
-{
- // Mission Stats
- public int Diplomacy { get; set; }
- public int Espionage { get; set; }
- public int Combat { get; set; }
- public int Leadership { get; set; }
-
// Research Info
public int ShipResearch;
public int TroopResearch;
public int FacilityResearch;
- // Character Status
- public OfficerStatus Status;
+ // Officer Info
public bool IsMain;
public bool CanBetray;
public bool IsTraitor;
@@ -51,10 +38,7 @@ public class Officer : MissionParticipant
public OfficerRank CurrentRank;
// Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
- public string InitialParentGameID;
+ public string InitialParentTypeID;
// Variance Info
[XmlIgnoreAttribute]
@@ -81,6 +65,9 @@ public class Officer : MissionParticipant
[XmlIgnoreAttribute]
public int ShipResearchVariance;
+ // Status Info
+ public MovementStatus MovementStatus { get; set; }
+
///
/// Default constructor
///
diff --git a/Assets/Scripts/Game/Planet.cs b/Assets/Scripts/Game/Planet.cs
index 004d4da..9c97462 100644
--- a/Assets/Scripts/Game/Planet.cs
+++ b/Assets/Scripts/Game/Planet.cs
@@ -36,11 +36,6 @@ public class Planet : SceneNode
{ BuildingSlot.Orbit, new List() },
};
- // Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
-
///
/// Default constructor used for serialization.
///
@@ -49,47 +44,43 @@ public Planet() { }
///
/// Returns the popular support for a faction on the planet.
///
- ///
- public int GetPopularSupport(string factionGameId)
+ ///
+ public int GetPopularSupport(string factionTypeID)
{
- return PopularSupport.TryGetValue(factionGameId, out int support) ? support : 0;
+ return PopularSupport.TryGetValue(factionTypeID, out int support) ? support : 0;
}
///
/// Sets the popular support for a faction on the planet.
///
- /// The game ID of the faction.
+ /// The type id of the faction.
/// The level of support.
- public void SetPopularSupport(string factionGameId, int support)
+ public void SetPopularSupport(string factionTypeID, int support)
{
- if (!PopularSupport.ContainsKey(factionGameId))
+ if (!PopularSupport.ContainsKey(factionTypeID))
{
- PopularSupport.Add(factionGameId, support);
+ PopularSupport.Add(factionTypeID, support);
}
- PopularSupport[factionGameId] = support;
+ PopularSupport[factionTypeID] = support;
}
///
- /// Gets the available slots for a specific building slot.
+ /// Adds a fleet to the planet.
///
- /// The building slot.
- /// The number of available slots.
- public int GetAvailableSlots(BuildingSlot slot)
+ /// The fleet to add.
+ public void AddFleet(Fleet fleet)
{
- int numUsedSlots = Buildings[slot].Count(building => building.Slot == slot);
- int maxSlots = slot == BuildingSlot.Ground ? GroundSlots : OrbitSlots;
-
- return maxSlots - numUsedSlots;
+ Fleets.Add(fleet);
}
///
- /// Adds a fleet to the planet.
+ ///
///
- /// The fleet to add.
- public void AddFleet(Fleet fleet)
+ ///
+ public void RemoveFleet(Fleet fleet)
{
- Fleets.Add(fleet);
+ Fleets.Remove(fleet);
}
///
@@ -121,13 +112,46 @@ private void AddBuilding(Building building)
Buildings[slot].Add(building);
}
+ ///
+ /// Removes a building from the planet.
+ ///
+ /// The building to remove.
+ private void RemoveBuilding(Building building)
+ {
+ BuildingSlot slot = building.Slot;
+ Buildings[slot].Remove(building);
+ }
+
+ ///
+ /// Gets the buildings in a specific slot.
+ ///
+ /// The building slot.
+ /// An array of buildings.
+ public Building[] GetBuildings(BuildingSlot slot)
+ {
+ return Buildings[slot].ToArray();
+ }
+
+ ///
+ /// Gets the available slots for a specific building slot.
+ ///
+ /// The building slot.
+ /// The number of available slots.
+ public int GetAvailableSlots(BuildingSlot slot)
+ {
+ int numUsedSlots = Buildings[slot].Count(building => building.Slot == slot);
+ int maxSlots = slot == BuildingSlot.Ground ? GroundSlots : OrbitSlots;
+
+ return maxSlots - numUsedSlots;
+ }
+
///
/// Adds an officer to the planet.
///
/// The officer to add.
private void AddOfficer(Officer officer)
{
- if (this.OwnerGameID != officer.OwnerGameID)
+ if (this.OwnerTypeID != officer.OwnerTypeID)
{
throw new SceneAccessException(officer, this);
}
@@ -135,21 +159,21 @@ private void AddOfficer(Officer officer)
}
///
- /// Adds a mission to the planet.
+ ///
///
- /// The mission to add.
- private void AddMission(Mission mission)
+ ///
+ private void RemoveOfficer(Officer officer)
{
- Missions.Add(mission);
+ Officers.Remove(officer);
}
///
- /// Adds a regiment to the planet.
+ /// Adds a mission to the planet.
///
- /// The regiment to add.
- private void AddRegiment(Regiment regiment)
+ /// The mission to add.
+ private void AddMission(Mission mission)
{
- Regiments.Add(regiment);
+ Missions.Add(mission);
}
///
@@ -162,13 +186,12 @@ private void RemoveMission(Mission mission)
}
///
- /// Removes a building from the planet.
+ /// Adds a regiment to the planet.
///
- /// The building to remove.
- private void RemoveBuilding(Building building)
+ /// The regiment to add.
+ private void AddRegiment(Regiment regiment)
{
- BuildingSlot slot = building.Slot;
- Buildings[slot].Remove(building);
+ Regiments.Add(regiment);
}
///
@@ -180,21 +203,11 @@ private void RemoveRegiment(Regiment regiment)
Regiments.Remove(regiment);
}
- ///
- /// Gets the buildings in a specific slot.
- ///
- /// The building slot.
- /// An array of buildings.
- public Building[] GetBuildings(BuildingSlot slot)
- {
- return Buildings[slot].ToArray();
- }
-
///
/// Adds a reference node to the game.
///
/// The game node to add as a reference.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
if (child is Fleet fleet)
{
@@ -222,15 +235,15 @@ protected internal override void AddChild(SceneNode child)
/// Removes a child node from the planet.
///
/// The child node to remove.
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
if (child is Fleet fleet)
{
- Fleets.Remove(fleet);
+ RemoveFleet(fleet);
}
else if (child is Officer officer)
{
- Officers.Remove(officer);
+ RemoveOfficer(officer);
}
else if (child is Building building)
{
@@ -252,10 +265,12 @@ protected internal override void RemoveChild(SceneNode child)
/// An array of child nodes.
public override IEnumerable GetChildren()
{
- List combinedList = new List();
- Building[] buildings = Buildings.Values.SelectMany(building => building).ToArray();
- combinedList.AddAll(Fleets, Officers, Missions, Regiments, buildings);
+ IEnumerable buildings = Buildings.Values.SelectMany(buildingList => buildingList).Cast();
- return combinedList.ToArray();
+ return Fleets.Cast()
+ .Concat(Officers.Cast())
+ .Concat(Missions.Cast())
+ .Concat(Regiments.Cast())
+ .Concat(buildings);
}
}
diff --git a/Assets/Scripts/Game/PlanetSystem.cs b/Assets/Scripts/Game/PlanetSystem.cs
index 5a06308..19872a2 100644
--- a/Assets/Scripts/Game/PlanetSystem.cs
+++ b/Assets/Scripts/Game/PlanetSystem.cs
@@ -45,7 +45,7 @@ public PlanetSystem() { }
/// Adds a planet to the planet system.
///
/// The planet to add.
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
if (child is Planet planet)
{
@@ -57,7 +57,7 @@ protected internal override void AddChild(SceneNode child)
/// Removes a planet from the planet system.
///
/// The planet to remove.
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
if (child is Planet planet)
{
diff --git a/Assets/Scripts/Game/Regiment.cs b/Assets/Scripts/Game/Regiment.cs
index f838c08..028787b 100644
--- a/Assets/Scripts/Game/Regiment.cs
+++ b/Assets/Scripts/Game/Regiment.cs
@@ -18,10 +18,10 @@ public class Regiment : LeafNode, IManufacturable
public int DetectionRating;
public int BombardmentDefense;
- // Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
+ // Status Info
+ public ManufacturingStatus ManufacturingStatus { get; set; }
+ public MovementStatus MovementStatus { get; set; }
+
///
/// Default constructor used for serialization.
diff --git a/Assets/Scripts/Game/SpecialForces.cs b/Assets/Scripts/Game/SpecialForces.cs
index 8a81ee4..60ad88c 100644
--- a/Assets/Scripts/Game/SpecialForces.cs
+++ b/Assets/Scripts/Game/SpecialForces.cs
@@ -12,20 +12,26 @@ public class SpecialForces : MissionParticipant, IManufacturable
public int BaseBuildSpeed { get; set; }
public int RequiredResearchLevel { get; set; }
- // Mission Stats
- public int Diplomacy { get; set; }
- public int Espionage { get; set; }
- public int Combat { get; set; }
- public int Leadership { get; set; }
-
- // Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
+ // Status Info
+ public ManufacturingStatus ManufacturingStatus { get; set; }
+ public MovementStatus MovementStatus { get; set; }
///
/// Default constructor used for serialization.
///
public SpecialForces() { }
+ ///
+ /// Determines if the unit is currently on a mission.
+ ///
+ /// True if the unit is on a mission, otherwise false.
+ public bool IsOnMission()
+ {
+ return GetParent() is Mission;
+ }
+
+ public override void SetMissionSkillValue(MissionParticipantSkill skill, int value)
+ {
+ throw new InvalidSceneOperationException("Special forces units cannot set mission skills.");
+ }
}
diff --git a/Assets/Scripts/Game/Starfighter.cs b/Assets/Scripts/Game/Starfighter.cs
index f2be006..bcb5902 100644
--- a/Assets/Scripts/Game/Starfighter.cs
+++ b/Assets/Scripts/Game/Starfighter.cs
@@ -32,11 +32,10 @@ public class Starfighter : LeafNode, IManufacturable
public int LaserRange;
public int IonRange;
public int TorpedoRange;
-
- // Owner Info
- [CloneIgnore]
- public string OwnerGameID { get; set; }
- public string[] AllowedOwnerGameIDs;
+
+ // Status Info
+ public ManufacturingStatus ManufacturingStatus { get; set; }
+ public MovementStatus MovementStatus { get; set; }
///
/// Default constructor used for serialization.
diff --git a/Assets/Scripts/Generation/BuildingGenerator.cs b/Assets/Scripts/Generation/BuildingGenerator.cs
index 77786f3..1d8332e 100644
--- a/Assets/Scripts/Generation/BuildingGenerator.cs
+++ b/Assets/Scripts/Generation/BuildingGenerator.cs
@@ -15,24 +15,24 @@ public class BuildingGenerator : UnitGenerator
///
/// The GameSummary options selected by the player.
/// The resource manager from which to load game data.
- public BuildingGenerator(GameSummary summary, IResourceManager resourceManager)
+ public BuildingGenerator(GameSummary summary, IAssetManager resourceManager)
: base(summary, resourceManager) { }
///
/// Creates a Dictionary out of the frequency data stored in the new game config.
///
- /// A Dictionary with building GameIDs as keys as its percentage frequency.
+ /// A Dictionary with building TypeIDs as keys as its percentage frequency.
public Dictionary getConfigMapping()
{
IConfig config = GetConfig();
- string[] gameIds = config.GetValue("Buildings.InitialBuildings.GameIDs");
+ string[] typeIds = config.GetValue("Buildings.InitialBuildings.TypeIDs");
double[] frequencies = config.GetValue("Buildings.InitialBuildings.Frequency");
Dictionary configMapping = new Dictionary();
- // Map each building's GameID with its percentage frequency, represented as a double.
- for (int i = 0; i < gameIds.Length; i++)
+ // Map each building's TypeID with its percentage frequency, represented as a double.
+ for (int i = 0; i < typeIds.Length; i++)
{
- configMapping[gameIds[i]] = frequencies[i];
+ configMapping[typeIds[i]] = frequencies[i];
}
return configMapping;
@@ -89,10 +89,10 @@ public override Building[] DeployUnits(Building[] buildings, PlanetSystem[] dest
foreach (Planet planet in colonizedPlanets)
{
// Shuffle the array to randomize the priority.
- foreach (string buildingGameId in configMapping.Keys.ToArray().Shuffle())
+ foreach (string buildingTypeID in configMapping.Keys.ToArray().Shuffle())
{
Building building = buildingList.Find(
- building => building.GameID == buildingGameId
+ building => building.TypeID == buildingTypeID
);
int numAvailableSlots = planet.GetAvailableSlots(building.Slot);
@@ -106,7 +106,7 @@ public override Building[] DeployUnits(Building[] buildings, PlanetSystem[] dest
// Add this building each time its frequency exceeds a random value.
// Halt this process after the first failure, as frequency is calculated per system.
IEnumerable initialBuildings = filledBuildings.TakeWhile(
- x => UnityEngine.Random.value < configMapping[buildingGameId]
+ x => UnityEngine.Random.value < configMapping[buildingTypeID]
);
// Add the generated buildings to the planet.
diff --git a/Assets/Scripts/Generation/CapitalShipGenerator.cs b/Assets/Scripts/Generation/CapitalShipGenerator.cs
index 7839f53..6a4e18b 100644
--- a/Assets/Scripts/Generation/CapitalShipGenerator.cs
+++ b/Assets/Scripts/Generation/CapitalShipGenerator.cs
@@ -14,7 +14,7 @@ public class CapitalShipGenerator : UnitGenerator
///
/// The GameSummary options selected by the player.
/// The resource manager from which to load game data.
- public CapitalShipGenerator(GameSummary summary, IResourceManager resourceManager)
+ public CapitalShipGenerator(GameSummary summary, IAssetManager resourceManager)
: base(summary, resourceManager) { }
///
@@ -61,12 +61,12 @@ IConfig[] capitalShipConfigs
foreach (IConfig capitalShipConfig in capitalShipConfigs)
{
CapitalShip capitalShip = capitalShips.First(
- (capitalShip) => capitalShip.GameID == capitalShipConfig.GetValue("GameID")
+ (capitalShip) => capitalShip.TypeID == capitalShipConfig.GetValue("TypeID")
);
- capitalShip.InitialParentGameID = capitalShipConfig.GetValue(
- "InitialParentGameID"
+ capitalShip.InitialParentTypeID = capitalShipConfig.GetValue(
+ "InitialParentTypeID"
);
- capitalShip.OwnerGameID = capitalShipConfig.GetValue("OwnerGameID");
+ capitalShip.OwnerTypeID = capitalShipConfig.GetValue("OwnerTypeID");
mappedCapitalShips.Add(capitalShip);
}
@@ -86,30 +86,30 @@ private CapitalShip[] deployUnits(CapitalShip[] capitalShips, PlanetSystem[] pla
(planetSystem) => planetSystem.Planets
);
- // Create a dictionary of planet GameIDs to planets, containing only HQs.
+ // Create a dictionary of planet TypeIDs to planets, containing only HQs.
Dictionary hqs = flattenedPlanets
.Where((planet) => planet.IsHeadquarters)
- .ToDictionary((planet) => planet.GameID, planet => planet);
+ .ToDictionary((planet) => planet.TypeID, planet => planet);
// Create a dictionary of factions to their owned planets (sans HQs).
Dictionary planets = flattenedPlanets
- .Where((planet) => planet.OwnerGameID != null && !planet.IsHeadquarters)
- .GroupBy((planet) => planet.OwnerGameID, planet => planet)
+ .Where((planet) => planet.OwnerTypeID != null && !planet.IsHeadquarters)
+ .GroupBy((planet) => planet.OwnerTypeID, planet => planet)
.ToDictionary((grouping) => grouping.Key, (grouping) => grouping.ToArray());
foreach (CapitalShip capitalShip in capitalShips)
{
// Handle case where capital ship has pre-defined parent.
// We can only assign to HQs, as planets are randomly generated.
- if (capitalShip.InitialParentGameID != null)
+ if (capitalShip.InitialParentTypeID != null)
{
- Planet planet = hqs[capitalShip.InitialParentGameID];
+ Planet planet = hqs[capitalShip.InitialParentTypeID];
planet.AddChild(capitalShip);
}
// Otherwise, randomly assign to a planet.
else
{
- Planet planet = planets[capitalShip.OwnerGameID].Shuffle().First();
+ Planet planet = planets[capitalShip.OwnerTypeID].Shuffle().First();
planet.AddChild(capitalShip);
}
}
diff --git a/Assets/Scripts/Generation/FactionGenerator.cs b/Assets/Scripts/Generation/FactionGenerator.cs
index 0a72eca..62ed2fa 100644
--- a/Assets/Scripts/Generation/FactionGenerator.cs
+++ b/Assets/Scripts/Generation/FactionGenerator.cs
@@ -13,7 +13,7 @@ public class FactionGenerator : UnitGenerator
///
/// The GameSummary options selected by the player.
/// The resource manager from which to load game data.
- public FactionGenerator(GameSummary summary, IResourceManager resourceManager)
+ public FactionGenerator(GameSummary summary, IAssetManager resourceManager)
: base(summary, resourceManager) { }
///
@@ -27,7 +27,7 @@ private void setFactionHQs(Faction[] factions, PlanetSystem[] planetSystems)
new Dictionary(),
(dict, nextFaction) =>
{
- dict.Add(nextFaction.HQGameID, nextFaction);
+ dict.Add(nextFaction.HQTypeID, nextFaction);
return dict;
}
);
@@ -37,11 +37,11 @@ private void setFactionHQs(Faction[] factions, PlanetSystem[] planetSystems)
{
foreach (Planet planet in planetSystem.Planets)
{
- if (hqs.Keys.ToList().Contains(planet.GameID))
+ if (hqs.Keys.ToList().Contains(planet.TypeID))
{
planet.IsHeadquarters = true;
- planet.OwnerGameID = hqs[planet.GameID].GameID;
- filledHQs.Add(planet.OwnerGameID);
+ planet.OwnerTypeID = hqs[planet.TypeID].TypeID;
+ filledHQs.Add(planet.OwnerTypeID);
}
// Return if we have filled our array already.
@@ -80,8 +80,8 @@ private void setStartingPlanets(Faction[] factions, PlanetSystem[] planetSystems
IEnumerable factionStartingPlanets = startingPlanets.Take(numStartingPlanets);
foreach (Planet planet in factionStartingPlanets)
{
- planet.OwnerGameID = faction.GameID;
- planet.SetPopularSupport(faction.GameID, 100);
+ planet.OwnerTypeID = faction.TypeID;
+ planet.SetPopularSupport(faction.TypeID, 100);
}
}
}
diff --git a/Assets/Scripts/Generation/GameBuilder.cs b/Assets/Scripts/Generation/GameBuilder.cs
index 4f7c842..85f22c1 100644
--- a/Assets/Scripts/Generation/GameBuilder.cs
+++ b/Assets/Scripts/Generation/GameBuilder.cs
@@ -23,7 +23,7 @@ public sealed class GameBuilder
/// The summary of the game.
public GameBuilder(GameSummary summary)
{
- IResourceManager resourceManager = ResourceManager.Instance;
+ IAssetManager resourceManager = AssetManager.Instance;
// Initialize our unit generators.
_psGenerator = new PlanetSystemGenerator(summary, resourceManager);
@@ -50,7 +50,7 @@ private SerializableDictionary getReferenceMap(params Sce
foreach (SceneNode node in referenceNodes)
{
ReferenceNode reference = new ReferenceNode(node);
- referenceMap[node.GameID] = reference;
+ referenceMap[node.TypeID] = reference;
}
return referenceMap;
@@ -62,11 +62,11 @@ private SerializableDictionary getReferenceMap(params Sce
/// The built game.
public Game BuildGame()
{
- // First, generate our galaxy map with stat decorated planets.
+ // Generate our galaxy map with stat decorated planets.
IUnitGenerationResults psResults = _psGenerator.GenerateUnits();
PlanetSystem[] galaxyMap = psResults.SelectedUnits;
- // Then decorate the galaxy map with units.
+ // Decorate the galaxy map with units.
Building[] buildings = _buildingGenerator.GenerateUnits(galaxyMap).UnitPool;
Faction[] factions = _factionGenerator.GenerateUnits(galaxyMap).UnitPool;
CapitalShip[] capitalShips = _csGenerator.GenerateUnits(galaxyMap).UnitPool;
@@ -95,7 +95,7 @@ public Game BuildGame()
Galaxy = Galaxy,
Factions = factions.ToList(),
UnrecruitedOfficers = unrecruitedOfficers.ToList(),
- ReferenceDictionary = referenceMap,
+ NodesByTypeID = referenceMap,
};
return game;
diff --git a/Assets/Scripts/Generation/OfficerGenerator.cs b/Assets/Scripts/Generation/OfficerGenerator.cs
index 6ac808d..9bfeb12 100644
--- a/Assets/Scripts/Generation/OfficerGenerator.cs
+++ b/Assets/Scripts/Generation/OfficerGenerator.cs
@@ -16,7 +16,7 @@ public class OfficerGenerator : UnitGenerator
///
/// The GameSummary options selected by the player.
/// The Config containing new game configurations and settings.
- public OfficerGenerator(GameSummary summary, IResourceManager resourceManager)
+ public OfficerGenerator(GameSummary summary, IAssetManager resourceManager)
: base(summary, resourceManager) { }
///
@@ -32,16 +32,16 @@ private Officer[] selectInitialOfficers(Dictionary> office
.GetValue($"Officers.NumInitialOfficers.GalaxySize.{galaxySize}");
// Set the finalized list of officers for each faction.
- foreach (string ownerGameId in officersByFaction.Keys.ToArray())
+ foreach (string ownerTypeID in officersByFaction.Keys.ToArray())
{
- IEnumerable reducedOfficers = officersByFaction[ownerGameId]
+ IEnumerable reducedOfficers = officersByFaction[ownerTypeID]
// Take a random selection of officers for the game start.
.TakeWhile((officer, index) => officer.IsMain || index < numAllowedOfficers)
- // Set the OwnerGameID for each officer.
+ // Set the OwnerTypeID for each officer.
.Select(
(officer) =>
{
- officer.OwnerGameID = ownerGameId;
+ officer.OwnerTypeID = ownerTypeID;
return officer;
}
);
@@ -58,10 +58,10 @@ private Officer[] selectInitialOfficers(Dictionary> office
private Dictionary> getDestinationMapping(PlanetSystem[] planetSystems)
{
// Flatten the list of planets from planet systems.
- // Only pull those planets with a OwnerGameID assigned.
+ // Only pull those planets with a OwnerTypeID assigned.
IEnumerable flattenedPlanets = planetSystems
.SelectMany((planetSystem) => planetSystem.Planets)
- .Where((planet) => planet.OwnerGameID != null);
+ .Where((planet) => planet.OwnerTypeID != null);
// Create an array of fleets and planets.
List fleetsAndPlanets = new List();
@@ -76,14 +76,14 @@ private Dictionary> getDestinationMapping(PlanetSystem[]
new Dictionary>(),
(destinationMap, nextDestination) =>
{
- string ownerGameId =
+ string ownerTypeID =
nextDestination
.GetType()
- .GetProperty("OwnerGameID")
+ .GetProperty("OwnerTypeID")
.GetValue(nextDestination, null) as string;
List destinations = destinationMap.GetOrAddValue(
- ownerGameId,
+ ownerTypeID,
new List()
);
destinations.Add(nextDestination);
@@ -106,19 +106,19 @@ public override Officer[] SelectUnits(Officer[] units)
foreach (Officer officer in shuffledUnits)
{
- // Add officers which already have an assigned OwnerGameID to the front.
+ // Add officers which already have an assigned OwnerTypeID to the front.
// These are the officers that will always be assigned at start.
- if (officer.OwnerGameID != null)
+ if (officer.OwnerTypeID != null)
{
officersByFaction
- .GetOrAddValue(officer.OwnerGameID, new List())
+ .GetOrAddValue(officer.OwnerTypeID, new List())
.Insert(0, officer); // Add to front of list.
}
// Ignore officers allowed by both factions.
- else if (officer.AllowedOwnerGameIDs.Length == 1)
+ else if (officer.AllowedOwnerTypeIDs.Count == 1)
{
officersByFaction
- .GetOrAddValue(officer.AllowedOwnerGameIDs[0], new List())
+ .GetOrAddValue(officer.AllowedOwnerTypeIDs[0], new List())
.Add(officer); // Add to end of list.
}
}
@@ -135,11 +135,13 @@ public override Officer[] DecorateUnits(Officer[] units)
{
foreach (Officer officer in units)
{
- // Set core attributes.
- officer.Diplomacy += Random.Range(0, officer.DiplomacyVariance);
- officer.Espionage += Random.Range(0, officer.EspionageVariance);
- officer.Combat += Random.Range(0, officer.CombatVariance);
- officer.Leadership += Random.Range(0, officer.CombatVariance);
+ // Set mission skills.
+ officer.Skills[MissionParticipantSkill.Diplomacy] += Random.Range(0, officer.DiplomacyVariance);
+ officer.Skills[MissionParticipantSkill.Espionage] += Random.Range(0, officer.EspionageVariance);
+ officer.Skills[MissionParticipantSkill.Combat] += Random.Range(0, officer.CombatVariance);
+ officer.Skills[MissionParticipantSkill.Leadership] += Random.Range(0, officer.LeadershipVariance);
+
+ // Set loyalty.
officer.Loyalty += Random.Range(0, officer.LoyaltyVariance);
// Set research attributes
@@ -168,13 +170,13 @@ public override Officer[] DeployUnits(Officer[] officers, PlanetSystem[] planetS
foreach (Officer officer in officers)
{
- List destinations = destinationMapping[officer.OwnerGameID];
+ List destinations = destinationMapping[officer.OwnerTypeID];
SceneNode destination;
- if (officer.InitialParentGameID != null)
+ if (officer.InitialParentTypeID != null)
{
destination = destinations.First(
- (sceneNode) => sceneNode.GameID == officer.InitialParentGameID
+ (sceneNode) => sceneNode.TypeID == officer.InitialParentTypeID
);
}
else
diff --git a/Assets/Scripts/Generation/PlanetSystemGenerator.cs b/Assets/Scripts/Generation/PlanetSystemGenerator.cs
index 11e2705..c44f078 100644
--- a/Assets/Scripts/Generation/PlanetSystemGenerator.cs
+++ b/Assets/Scripts/Generation/PlanetSystemGenerator.cs
@@ -13,7 +13,7 @@ public class PlanetSystemGenerator : UnitGenerator
///
/// The GameSummary options selected by the player.
/// The resource manager from which to load game data.
- public PlanetSystemGenerator(GameSummary summary, IResourceManager resourceManager)
+ public PlanetSystemGenerator(GameSummary summary, IAssetManager resourceManager)
: base(summary, resourceManager) { }
///
diff --git a/Assets/Scripts/Generation/UnitGenerator.cs b/Assets/Scripts/Generation/UnitGenerator.cs
index 4b622f3..e03a154 100644
--- a/Assets/Scripts/Generation/UnitGenerator.cs
+++ b/Assets/Scripts/Generation/UnitGenerator.cs
@@ -27,7 +27,7 @@ public abstract class UnitGenerator : IUnitGenerator
where TUnit : SceneNode
{
private GameSummary _summary;
- private IResourceManager _resourceManager;
+ private IAssetManager _resourceManager;
private IConfig _config;
///
@@ -35,7 +35,7 @@ public abstract class UnitGenerator : IUnitGenerator
///
///
///
- public UnitGenerator(GameSummary summary, IResourceManager resourceManager)
+ public UnitGenerator(GameSummary summary, IAssetManager resourceManager)
{
_summary = summary;
_resourceManager = resourceManager;
diff --git a/Assets/Scripts/Initialization/GameInitializer.cs b/Assets/Scripts/Initialization/GameInitializer.cs
new file mode 100644
index 0000000..5b08844
--- /dev/null
+++ b/Assets/Scripts/Initialization/GameInitializer.cs
@@ -0,0 +1,45 @@
+using DependencyInjectionExtensions;
+
+public class GameInitializer
+{
+ private Game game;
+
+ ///
+ ///
+ ///
+ ///
+ public GameInitializer(Game game)
+ {
+ this.game = game;
+ }
+
+ ///
+ ///
+ ///
+ public void Initialize()
+ {
+ IServiceLocator serviceLocator = getServiceLocator();
+
+ GameManager manager = new GameManager(serviceLocator, game);
+ }
+
+ ///
+ ///
+ ///
+ private IServiceLocator getServiceLocator()
+ {
+ // Create the service container for which to build out services.
+ ServiceContainer serviceContainer = new ServiceContainer();
+
+ // Add services.
+ serviceContainer.AddSingleton();
+ serviceContainer.AddSingleton();
+ serviceContainer.AddSingleton();
+
+ // Add the Game object.
+ serviceContainer.AddSingletonInstance(game);
+
+ // Build and return the service locator.
+ return serviceContainer.BuildServiceLocator();
+ }
+}
diff --git a/Assets/Scripts/Managers/ResourceManager.cs b/Assets/Scripts/Managers/AssetManager.cs
similarity index 70%
rename from Assets/Scripts/Managers/ResourceManager.cs
rename to Assets/Scripts/Managers/AssetManager.cs
index 18969fc..c6e6240 100644
--- a/Assets/Scripts/Managers/ResourceManager.cs
+++ b/Assets/Scripts/Managers/AssetManager.cs
@@ -8,10 +8,32 @@
using UnityEngine;
///
-/// The ResourceManagerImpl class is responsible for managing the retrieval of
+///
+///
+public interface IAssetManager
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ public T GetConfig()
+ where T : IConfig;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public T[] GetSceneNodeData()
+ where T : SceneNode;
+}
+
+///
+/// The AssetManagerImpl class is responsible for managing the retrieval of
/// configuration data and scene node data from files in the Resources directory.
///
-class ResourceManagerImpl : IResourceManager
+class AssetManagerImpl : IAssetManager
{
///
/// Retrieves the configuration data of type T.
@@ -58,14 +80,17 @@ public T[] GetSceneNodeData()
}
}
-public class ResourceManager
+///
+/// The AssetManager class is a singleton class that provides a single point of access to the AssetManagerImpl class.
+///
+public class AssetManager
{
- private static IResourceManager _resourceManager = new ResourceManagerImpl();
+ private static IAssetManager _resourceManager = new AssetManagerImpl();
///
///
///
- public static IResourceManager Instance
+ public static IAssetManager Instance
{
get { return _resourceManager; }
}
diff --git a/Assets/Scripts/Managers/GameEventManager.cs b/Assets/Scripts/Managers/GameEventManager.cs
index 63971bc..300e59d 100644
--- a/Assets/Scripts/Managers/GameEventManager.cs
+++ b/Assets/Scripts/Managers/GameEventManager.cs
@@ -1,76 +1,86 @@
-using System;
using System.Collections.Generic;
+using System.Linq;
+using System;
+using DependencyInjectionExtensions;
///
/// Manages game events and their scheduling.
///
-public class EventManager
+public class GameEventManager
{
- private readonly Game game;
+ private readonly IServiceLocator locator;
+ private readonly IEventService eventService;
- public EventManager(Game game)
+ ///
+ ///
+ ///
+ ///
+ public GameEventManager(IServiceLocator locator)
{
- this.game = game;
+ this.locator = (ServiceLocator)locator;
+ this.eventService = locator.GetService();
}
///
- /// Retrieves all game events of the specified type.
+ /// Processes the game events for the specified tick.
///
- /// The type of game event to retrieve.
- /// A list of game events of the specified type.
- public List GetEventsByType() where T : GameEvent
+ /// The current tick.
+ public void ProcessEvents(int currentTick)
{
- List events = new List();
+ List scheduledEvents = eventService.GetScheduledEvents(currentTick);
- // Iterate through all events in the dictionary.
- foreach (var eventList in game.GameEventDictionary.Values)
+ // Check if there are any events scheduled for this tick.
+ if (scheduledEvents.Any())
{
- // Check if the event is of the specified type.
- foreach (var gameEvent in eventList)
+ // Execute each event.
+ foreach (ScheduledEvent scheduledEvent in scheduledEvents)
{
- // Add the event to the list if it is of the specified type.
- if (gameEvent is T)
- {
- events.Add(gameEvent);
- }
+ GameEvent gameEvent = scheduledEvent.GetEvent();
+
+ gameEvent.Execute(locator);
+
+ // Add the event to the list of completed events.
+ eventService.AddCompletedEvent(gameEvent);
+
+ // Remove processed events for this tick.
+ eventService.RemoveScheduledEvent(currentTick, scheduledEvent);
}
}
-
- return events;
}
///
- /// Schedules a game event.
+ ///
///
- /// The game event to schedule.
- public void ScheduleEvent(GameEvent gameEvent)
+ ///
+
+ public void Initialize(Game game)
{
- // Add the event to the dictionary.
- if (!game.GameEventDictionary.ContainsKey(gameEvent.ScheduledTick))
- {
- game.GameEventDictionary[gameEvent.ScheduledTick] = new List();
- }
+ // List mappedConditionals = new List();
+ // List mappedActions = new List();
+ // List gameEvents = game.EventPool;
- // Add the event to the list of events for this tick.
- game.GameEventDictionary[gameEvent.ScheduledTick].Add(gameEvent);
- }
+ // foreach(GameEvent gameEvent in gameEvents)
+ // {
+ // foreach (GameConditional conditional in gameEvent.Conditionals)
+ // {
+ // // Assuming conditional has a 'ClassName' or similar property
+ // string type = ((GameConditional)conditional).ConditionalType;
- ///
- /// Processes the game events for the specified tick.
- ///
- /// The current tick.
- public void ProcessEvents(int currentTick)
- {
- // Check if there are any events scheduled for this tick.
- if (game.GameEventDictionary.ContainsKey(currentTick))
- {
- foreach (var gameEvent in game.GameEventDictionary[currentTick])
- {
- gameEvent.Execute(game);
- }
+ // GameConditional mappedConditional = ConditionalFactory.CreateConditional(type);
+ // mappedConditionals.Add(mappedConditional);
+ // }
- // Remove processed events for this tick
- game.GameEventDictionary.Remove(currentTick);
- }
+ // foreach (GameAction action in gameEvent.Actions)
+ // {
+ // string type = ((GameAction)action).ActionType;
+
+ // GameAction mappedAction = ActionFactory.CreateAction(type);
+ // mappedActions.Add(mappedAction);
+ // }
+
+ // // Replace placeholders with the real mapped objects
+ // gameEvent.Conditionals = mappedConditionals.Cast().ToList();
+ // gameEvent.Actions = mappedActions.Cast().ToList();
+ // }
}
}
diff --git a/Assets/Scripts/Managers/GameManager.cs b/Assets/Scripts/Managers/GameManager.cs
index 6d25f97..e0b8f07 100644
--- a/Assets/Scripts/Managers/GameManager.cs
+++ b/Assets/Scripts/Managers/GameManager.cs
@@ -1,3 +1,5 @@
+using DependencyInjectionExtensions;
+
///
/// Specifies different speeds for the game tick processing.
///
@@ -16,28 +18,36 @@ public enum TickSpeed
///
public class GameManager
{
- private Game currentGame;
- public EventManager EventManager { get; private set; }
- public MissionManager MissionManager { get; private set; }
+ private Game game;
+ private GameEventManager eventManager;
+ private MissionManager missionManager;
+ private IServiceLocator serviceLocator;
private float? tickInterval;
private float tickTimer;
///
- /// Constructor that initializes the GameManager with a given game.
+ ///
///
- /// The game instance that this manager will control.
- public GameManager(Game game)
+ ///
+ ///
+ public GameManager(IServiceLocator serviceLocator, Game game)
{
- currentGame = game;
- EventManager = new EventManager(game);
- MissionManager = new MissionManager(EventManager);
+ // Initialize private variables.
+ this.serviceLocator = serviceLocator;
+ this.game = game;
+
+ // Initialize other managers.
+ eventManager = new GameEventManager(serviceLocator);
+ missionManager = new MissionManager(serviceLocator, game);
+
+ Initialize(game);
}
///
/// Gets the current game instance.
///
/// The current Game object.
- public Game GetGame() => currentGame;
+ public Game GetGame() => game;
///
/// Sets the speed of the game ticks.
@@ -86,7 +96,27 @@ public void Update(float deltaTime)
///
private void ProcessTick()
{
- currentGame.CurrentTick++; // Increment the current game's tick counter
- EventManager.ProcessEvents(currentGame.CurrentTick); // Process any events scheduled for this tick
+ // Increment the current game's tick counter.
+ game.CurrentTick++;
+
+ // Process any events scheduled for this tick.
+ eventManager.ProcessEvents(game.CurrentTick);
+ }
+
+ ///
+ /// Initializes the game by adding all nodes to the game's node registry.
+ ///
+ ///
+ public void Initialize(Game game)
+ {
+ GalaxyMap galaxy = game.Galaxy;
+
+ galaxy.Traverse((SceneNode node) => {
+ foreach (SceneNode child in node.GetChildren())
+ {
+ child.SetParent(node);
+ }
+ game.AddNodeByInstanceID(node);
+ });
}
}
diff --git a/Assets/Scripts/Managers/IResourceManager.cs b/Assets/Scripts/Managers/IResourceManager.cs
deleted file mode 100644
index 29d8df2..0000000
--- a/Assets/Scripts/Managers/IResourceManager.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-///
-///
-///
-public interface IResourceManager
-{
- ///
- ///
- ///
- ///
- ///
- public T GetConfig()
- where T : IConfig;
-
- ///
- ///
- ///
- ///
- ///
- public T[] GetSceneNodeData()
- where T : SceneNode;
-}
diff --git a/Assets/Scripts/Managers/MissionManager.cs b/Assets/Scripts/Managers/MissionManager.cs
index 43de2d4..7032964 100644
--- a/Assets/Scripts/Managers/MissionManager.cs
+++ b/Assets/Scripts/Managers/MissionManager.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System;
+using DependencyInjectionExtensions;
///
/// Manager for handling missions in the game.
@@ -8,62 +9,12 @@
///
public class MissionManager
{
- protected EventManager eventManager;
+ protected Game game;
+ protected IServiceLocator serviceLocator;
- ///
- /// Initializes a new instance of the class.
- ///
- /// The event manager.
- public MissionManager(EventManager eventManager)
+ public MissionManager(IServiceLocator serviceLocator, Game game)
{
- this.eventManager = eventManager;
- InitializeMissions();
- }
-
- ///
- /// Starts a mission by generating a random tick for the mission and scheduling a mission event.
- ///
- /// The mission to start.
- private void InitializeMissions()
- {
- // Register event handlers for mission events.
- List missionEvents = eventManager
- .GetEventsByType()
- .OfType()
- .ToList();
-
- // Register event handlers for mission events.
- foreach (MissionEvent missionEvent in missionEvents)
- {
- missionEvent.OnEventTriggered += RescheduleEvent;
- }
- }
-
- ///
- /// Starts a mission by generating a random tick for the mission and scheduling a mission event.
- ///
- /// The mission to start.
- public void StartMission(Mission mission)
- {
- // Generate a random tick for the mission.
- int tick = new Random().Next(mission.MinTicks, mission.MaxTicks + 1);
- MissionEvent missionEvent = new MissionEvent(tick, mission);
-
- // Schedule next mission event.
- eventManager.ScheduleEvent(missionEvent);
- }
-
- ///
- /// Reschedules a mission event (when the mission is repeatable).
- ///
- /// The game event to reschedule.
- protected void RescheduleEvent(GameEvent gameEvent)
- {
- MissionEvent missionEvent = gameEvent as MissionEvent;
- if (missionEvent != null)
- {
- // Reschedule the mission event.
- eventManager.ScheduleEvent(missionEvent);
- }
+ this.game = game;
+ this.serviceLocator = serviceLocator;
}
}
diff --git a/Assets/Scripts/Missions/AbductionMission.cs b/Assets/Scripts/Missions/AbductionMission.cs
index ef622c5..a432897 100644
--- a/Assets/Scripts/Missions/AbductionMission.cs
+++ b/Assets/Scripts/Missions/AbductionMission.cs
@@ -3,6 +3,8 @@
public class AbductionMission : Mission
{
+ public Officer TargetOfficer { get; set; }
+
///
/// Default constructor used for serialization.
///
@@ -24,13 +26,14 @@ public AbductionMission() : base()
/// Constructor used when initializing the AbductionMission with participants and owner.
///
public AbductionMission(
- string ownerGameID,
+ string ownerTypeID,
List mainParticipants,
- List covertParticipants
+ List covertParticipants,
+ Officer targetOfficer
// @TODO: Move the success probability variables to configs.
) : base(
"Abduction",
- ownerGameID,
+ ownerTypeID,
mainParticipants,
covertParticipants,
MissionParticipantSkill.Combat,
@@ -42,6 +45,7 @@ List covertParticipants
minTicks: 15,
maxTicks: 20)
{
+ TargetOfficer = targetOfficer;
}
///
diff --git a/Assets/Scripts/Missions/DiplomacyMission.cs b/Assets/Scripts/Missions/DiplomacyMission.cs
index d1b9f74..ba81e59 100644
--- a/Assets/Scripts/Missions/DiplomacyMission.cs
+++ b/Assets/Scripts/Missions/DiplomacyMission.cs
@@ -24,13 +24,13 @@ public DiplomacyMission() : base()
/// Constructor used when initializing the DiplomacyMission with participants and owner.
///
public DiplomacyMission(
- string ownerGameID,
+ string ownerTypeID,
List mainParticipants,
List covertParticipants
// @TODO: Move the success probability variables to configs.
) : base(
"Diplomacy",
- ownerGameID,
+ ownerTypeID,
mainParticipants,
covertParticipants,
MissionParticipantSkill.Diplomacy,
@@ -49,7 +49,7 @@ protected override void OnSuccess(Game game)
{
if (GetParent() is Planet planet)
{
- planet.SetPopularSupport(OwnerGameID, planet.GetPopularSupport(OwnerGameID) + 1);
+ planet.SetPopularSupport(OwnerTypeID, planet.GetPopularSupport(OwnerTypeID) + 1);
}
}
}
\ No newline at end of file
diff --git a/Assets/Scripts/Missions/Mission.cs b/Assets/Scripts/Missions/Mission.cs
index 6f1484a..06068fd 100644
--- a/Assets/Scripts/Missions/Mission.cs
+++ b/Assets/Scripts/Missions/Mission.cs
@@ -9,7 +9,6 @@
public abstract class Mission : SceneNode
{
public string Name;
- public string OwnerGameID;
public List MainParticipants = new List();
public List DecoyParticipants = new List();
public MissionParticipantSkill ParticipantSkill;
@@ -54,7 +53,7 @@ protected Mission() {}
///
///
///
- ///
+ ///
///
///
///
@@ -68,7 +67,7 @@ protected Mission() {}
///
protected Mission(
string name,
- string ownerGameID,
+ string ownerTypeID,
List mainParticipants,
List decoyParticipants,
MissionParticipantSkill participantSkill,
@@ -83,7 +82,7 @@ int maxTicks
{
// Set mission fields.
Name = name ?? throw new ArgumentNullException(nameof(name));
- OwnerGameID = ownerGameID;
+ OwnerTypeID = ownerTypeID;
MainParticipants = mainParticipants ?? new List();
DecoyParticipants = decoyParticipants ?? new List();
ParticipantSkill = participantSkill;
@@ -100,10 +99,11 @@ int maxTicks
MaxTicks = maxTicks;
}
+ ///
/// Initializes a new instance of the class.
///
/// The name of the mission.
- /// The owner game ID.
+ /// The owner type id.
/// The main participants of the mission.
/// The decoy participants of the mission.
/// The skill level of the mission participants.
@@ -127,7 +127,7 @@ private double CalculateProbability(double score, double quadraticCoefficient, d
protected double GetAgentProbability(MissionParticipant agent)
{
// Get the agent's skill score and calculate the success probability.
- double agentScore = agent.GetSkill(ParticipantSkill);
+ double agentScore = agent.GetMissionSkillValue(ParticipantSkill);
double agentProbability = CalculateProbability(agentScore, QuadraticCoefficient, LinearCoefficient, ConstantTerm);
@@ -142,7 +142,7 @@ protected double GetAgentProbability(MissionParticipant agent)
protected double GetDecoyProbability(MissionParticipant decoy)
{
// Get the agent's skill score and calculate the success probability.
- double decoyScore = decoy.GetSkill(DecoyParticipantSkill);
+ double decoyScore = decoy.GetMissionSkillValue(DecoyParticipantSkill);
return CalculateProbability(decoyScore, DecoyQuadraticCoefficient, DecoyLinearCoefficient, DecoyConstantTerm);
}
@@ -158,7 +158,7 @@ protected double GetFoilProbability(double defenseScore)
if (GetParent() is Planet planet)
{
// If the planet is not owned by the mission owner, the foil probability is 0.
- if (planet.OwnerGameID == OwnerGameID)
+ if (planet.OwnerTypeID == OwnerTypeID)
{
return 0;
}
@@ -268,10 +268,10 @@ protected bool CheckMissionFoiled(double foilProbability)
}
///
- /// Performs the mission, determining if it succeeds or fails.
+ /// Executes the mission, determining if it succeeds or fails.
///
/// The game instance.
- public void Perform(Game game)
+ public void Execute(Game game)
{
// Get the defense score and calculate the foil probability.
double defenseScore = GetDefenseScore();
@@ -296,13 +296,14 @@ public void Perform(Game game)
///
public override IEnumerable GetChildren()
{
- return MainParticipants.Concat(DecoyParticipants);
+ return MainParticipants.Cast()
+ .Concat(DecoyParticipants.Cast());
}
///
/// No-op (missions cannot have children added).
///
- protected internal override void AddChild(SceneNode child)
+ public override void AddChild(SceneNode child)
{
// No-op: Missions cannot have children added.
}
@@ -310,7 +311,7 @@ protected internal override void AddChild(SceneNode child)
///
/// No-op (missions cannot have children removed).
///
- protected internal override void RemoveChild(SceneNode child)
+ public override void RemoveChild(SceneNode child)
{
// No-op: Missions cannot have children removed.
}
diff --git a/Assets/Scripts/Missions/MissionParticipant.cs b/Assets/Scripts/Missions/MissionParticipant.cs
index 70f2f4a..771cbdf 100644
--- a/Assets/Scripts/Missions/MissionParticipant.cs
+++ b/Assets/Scripts/Missions/MissionParticipant.cs
@@ -1,6 +1,7 @@
+using System;
+
public enum MissionParticipantSkill
{
- None,
Diplomacy,
Espionage,
Combat,
@@ -15,37 +16,36 @@ public enum MissionParticipantSkill
public class MissionParticipant : LeafNode
{
// Mission Stats.
- public SerializableDictionary Skills = new SerializableDictionary()
+ public SerializableDictionary Skills { get; set; }
+
+ public MissionParticipant()
+ {
+ Skills = new SerializableDictionary
{
{ MissionParticipantSkill.Diplomacy, 0 },
{ MissionParticipantSkill.Espionage, 0 },
- /// { MissionParticipantSkill.Combat, 0 },
+ { MissionParticipantSkill.Combat, 0 },
{ MissionParticipantSkill.Leadership, 0 }
};
-
- ///
- /// Default constructor.
- ///
- public MissionParticipant() { }
-
+ }
+
///
///
///
///
- public int GetSkill(MissionParticipantSkill skill)
+ ///
+ public virtual void SetMissionSkillValue(MissionParticipantSkill skill, int value)
{
- return Skills[skill];
+ Skills[skill] = value;
}
///
- /// Sets the value of a skill.
+ ///
///
- /// The skill to set.
- /// The value to set the skill to.
- /// The new value of the skill.
- public int SetSkill(MissionParticipantSkill skill, int value)
+ ///
+ ///
+ public int GetMissionSkillValue(MissionParticipantSkill skill)
{
- return Skills[skill] = value;
+ return Skills[skill];
}
-
}
diff --git a/Assets/Scripts/Missions/RecruitmentMission.cs b/Assets/Scripts/Missions/RecruitmentMission.cs
index 16f2332..a07f8b5 100644
--- a/Assets/Scripts/Missions/RecruitmentMission.cs
+++ b/Assets/Scripts/Missions/RecruitmentMission.cs
@@ -25,13 +25,13 @@ public RecruitmentMission() : base()
/// Creates a new RecruitmentMission with the specified owner and participants.
///
public RecruitmentMission(
- string ownerGameID,
+ string ownerTypeID,
List mainParticipants,
List covertParticipants
// @TODO: Move the success probability variables to configs.
) : base(
"Recruitment",
- ownerGameID,
+ ownerTypeID,
mainParticipants,
covertParticipants,
MissionParticipantSkill.Leadership,
@@ -42,8 +42,7 @@ List covertParticipants
maxSuccessProbability: 100,
minTicks: 15,
maxTicks: 20)
- {
- }
+ { }
///
/// Adds a new officer to the factions's roster.
@@ -53,7 +52,7 @@ protected override void OnSuccess(Game game)
{
Planet planet = GetParent() as Planet;
- List unrecruitedOfficers = game.GetUnrecruitedOfficers(OwnerGameID);
+ List unrecruitedOfficers = game.GetUnrecruitedOfficers(OwnerTypeID);
Officer recruitedOfficer = unrecruitedOfficers.RandomElement();
game.RemoveUnrecruitedOfficer(recruitedOfficer);
diff --git a/Assets/Scripts/Services/AutomationService.cs b/Assets/Scripts/Services/AutomationService.cs
new file mode 100644
index 0000000..56a0720
--- /dev/null
+++ b/Assets/Scripts/Services/AutomationService.cs
@@ -0,0 +1,10 @@
+// public interface IAutomationService
+// {
+// public void AddNewUnits(List unitIds, Planet destination);
+// }
+
+// public class AutomationService : GameService, IAutomationService
+// {
+// public AutomationService(Game game) : base(game) { }
+
+// }
\ No newline at end of file
diff --git a/Assets/Scripts/Services/EventService.cs b/Assets/Scripts/Services/EventService.cs
new file mode 100644
index 0000000..ec958bb
--- /dev/null
+++ b/Assets/Scripts/Services/EventService.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+///
+///
+///
+public interface IEventService
+{
+ public void ScheduleGameEvent(int tick, GameEvent gameEvent);
+ public List GetScheduledEvents(int tick);
+ public void RemoveScheduledEvent(int tick, ScheduledEvent scheduledEvent);
+ public void AddCompletedEvent(GameEvent gameEvent);
+}
+
+///
+///
+///
+public class EventService : IEventService
+{
+ private Game game;
+
+ ///
+ /// Default constructor.
+ ///
+ /// The service locator.
+ /// The game instance.
+ public EventService(Game game)
+ {
+ this.game = game;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void ScheduleGameEvent(int tick, GameEvent gameEvent)
+ {
+ game.ScheduleGameEvent(tick, gameEvent);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List GetScheduledEvents(int tick)
+ {
+ if (game.ScheduledEvents.TryGetValue(tick, out List scheduledEvents))
+ {
+ return scheduledEvents;
+ }
+ else
+ {
+ return new List();
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RemoveScheduledEvent(int tick, ScheduledEvent scheduledEvent)
+ {
+ game.RemoveScheduledEvent(tick, scheduledEvent);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void AddCompletedEvent(GameEvent gameEvent)
+ {
+ game.AddCompletedEventID(gameEvent);
+ }
+}
diff --git a/Assets/Scripts/Services/LookupService.cs b/Assets/Scripts/Services/LookupService.cs
new file mode 100644
index 0000000..3f7dbdc
--- /dev/null
+++ b/Assets/Scripts/Services/LookupService.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+
+public interface ILookupService
+{
+ public T GetSceneNodeByTypeID(string typeId) where T : SceneNode;
+
+ public T GetSceneNodeByInstanceID(string instanceId) where T : SceneNode;
+
+ public List GetSceneNodesByInstanceIDs(List instanceIDs);
+}
+
+///
+///
+///
+public class LookupService : ILookupService
+{
+ private Game game;
+
+ public LookupService(Game game)
+ {
+ this.game = game;
+ }
+
+ ///
+ /// Returns the scene node with the given type ID.
+ ///
+ /// The type ID of the scene node.
+ /// The scene node with the given type ID.
+ public T GetSceneNodeByTypeID(string typeId) where T : SceneNode
+ {
+ return game.GetSceneNodeByTypeID(typeId);
+ }
+
+ ///
+ /// Returns the scene node with the given instance ID.
+ ///
+ /// The instance ID of the scene node.
+ /// The scene node with the given instance ID.
+ public T GetSceneNodeByInstanceID(string instanceId) where T : SceneNode
+ {
+ return game.GetSceneNodeByInstanceID(instanceId);
+ }
+
+ ///
+ /// Returns the scene nodes with the given instance IDs.
+ ///
+ ///
+ ///
+ public List GetSceneNodesByInstanceIDs(List instanceIDs)
+ {
+ return game.GetSceneNodesByInstanceIDs(instanceIDs);
+ }
+}
diff --git a/Assets/Scripts/Services/MissionService.cs b/Assets/Scripts/Services/MissionService.cs
new file mode 100644
index 0000000..de5a365
--- /dev/null
+++ b/Assets/Scripts/Services/MissionService.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+
+public interface IMissionService
+{
+ public void StartMission(string missionType, List mainParticipantInstanceIds, List decoyParticipantInstanceIds, string targetInstanceId);
+}
+
+///
+///
+///
+public class MissionService : IMissionService
+{
+ private Game game;
+
+ ///
+ ///
+ ///
+ ///
+ public MissionService(Game game)
+ {
+ this.game = game;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void StartMission(string missionType, List mainParticipantInstanceIds, List decoyParticipantInstanceIds, string targetInstanceId)
+ {
+
+ }
+}
diff --git a/Assets/Scripts/Util/Collections/SerializableHashSet.cs b/Assets/Scripts/Util/Collections/SerializableHashSet.cs
new file mode 100644
index 0000000..7284089
--- /dev/null
+++ b/Assets/Scripts/Util/Collections/SerializableHashSet.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Serialization;
+using System;
+
+[Serializable]
+public class SerializableHashSet : HashSet, IXmlSerializable
+{
+ // No need for additional members since we inherit from HashSet
+
+ public XmlSchema GetSchema() => null; // No schema required
+
+ ///
+ /// Reads the XML representation of the object from the provided reader.
+ ///
+ /// The stream from which the object is deserialized.
+ public void ReadXml(XmlReader reader)
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(T));
+ reader.ReadStartElement();
+
+ while (reader.NodeType != XmlNodeType.EndElement)
+ {
+ T item = (T)serializer.Deserialize(reader);
+ this.Add(item);
+ }
+
+ reader.ReadEndElement();
+ }
+
+ ///
+ /// Converts the object into its XML representation and writes it to the provided writer.
+ ///
+ /// The stream to which the object is serialized.
+ public void WriteXml(XmlWriter writer)
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(T));
+
+ foreach (T item in this)
+ {
+ serializer.Serialize(writer, item);
+ }
+ }
+}
diff --git a/Assets/Scripts/Util/Extensions/DependencyInjectionExtensions.cs b/Assets/Scripts/Util/Extensions/DependencyInjectionExtensions.cs
new file mode 100644
index 0000000..53e483b
--- /dev/null
+++ b/Assets/Scripts/Util/Extensions/DependencyInjectionExtensions.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace DependencyInjectionExtensions
+{
+ ///
+ ///
+ ///
+ public interface IServiceLocator
+ {
+ T GetService();
+ }
+
+ ///
+ ///
+ ///
+ internal class ServiceLocator : IServiceLocator
+ {
+ private readonly Dictionary singletonInstances;
+ private readonly Dictionary> transientServices;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ServiceLocator(Dictionary singletonInstances, Dictionary> transientServices)
+ {
+ this.singletonInstances = singletonInstances;
+ this.transientServices = transientServices;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public T GetService()
+ {
+ var serviceType = typeof(T);
+
+ // Handle singleton services.
+ if (singletonInstances.ContainsKey(serviceType))
+ {
+ // Lazy creation of singleton instance.
+ if (singletonInstances[serviceType] == null)
+ {
+ var factory = transientServices[serviceType];
+ singletonInstances[serviceType] = factory(this);
+ }
+ return (T)singletonInstances[serviceType];
+ }
+
+ // Handle transient services.
+ if (transientServices.ContainsKey(serviceType))
+ {
+ var factory = transientServices[serviceType];
+ return (T)factory(this);
+ }
+
+ throw new Exception($"Service of type {serviceType.Name} is not registered.");
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class ServiceContainer
+ {
+ private Dictionary> transientServices = new Dictionary>();
+ private Dictionary singletonInstances = new Dictionary();
+
+ ///
+ /// Adds a singleton service and its implementation.
+ ///
+ ///
+ ///
+ public void AddSingleton() where TImplementation : TService
+ {
+ singletonInstances[typeof(TService)] = null; // Lazy initialization of singleton
+ transientServices[typeof(TService)] = (locator) => CreateInstance(typeof(TImplementation), locator);
+ }
+
+ ///
+ /// Adds a transient service and its implementation.
+ ///
+ ///
+ ///
+ public void AddTransient() where TImplementation : TService
+ {
+ transientServices[typeof(TService)] = (locator) => CreateInstance(typeof(TImplementation), locator);
+ }
+
+ ///
+ /// Adds an already created singleton instance to the container.
+ ///
+ ///
+ ///
+ public void AddSingletonInstance(TService instance)
+ {
+ singletonInstances[typeof(TService)] = instance;
+ }
+
+ ///
+ /// Builds the service locator based on the registered services.
+ ///
+ ///
+ public IServiceLocator BuildServiceLocator()
+ {
+ return new ServiceLocator(singletonInstances, transientServices);
+ }
+
+ ///
+ /// Helper method to create an instance of the implementation with constructor injection.
+ ///
+ ///
+ ///
+ ///
+ private object CreateInstance(Type implementationType, IServiceLocator locator)
+ {
+ // Get the first constructor of the implementation type.
+ ConstructorInfo constructor = implementationType.GetConstructors().First();
+
+ // Resolve constructor parameters.
+ ParameterInfo[] parameters = constructor.GetParameters();
+ object[] parameterInstances = new object[parameters.Length];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ // Get the parameter type.
+ Type parameterType = parameters[i].ParameterType;
+
+ // Use reflection to dynamically invoke the generic GetService() method.
+ MethodInfo genericGetService = typeof(IServiceLocator)
+ .GetMethod("GetService")
+ .MakeGenericMethod(parameterType);
+ parameterInstances[i] = genericGetService.Invoke(locator, null);
+ }
+
+ // Create the instance with resolved parameters.
+ return Activator.CreateInstance(implementationType, parameterInstances);
+ }
+ }
+}
diff --git a/Assets/Scripts/Util/Extensions/IEnumerableExtensions.cs b/Assets/Scripts/Util/Extensions/IEnumerableExtensions.cs
index 5fa9940..e1e3c07 100644
--- a/Assets/Scripts/Util/Extensions/IEnumerableExtensions.cs
+++ b/Assets/Scripts/Util/Extensions/IEnumerableExtensions.cs
@@ -27,6 +27,13 @@ public static IEnumerable Shuffle(this IEnumerable source)
}
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public static T RandomElement(this List list)
{
if (list == null || list.Count == 0)
diff --git a/Assets/Tests/EditMode/Core/GameEntityTests.cs b/Assets/Tests/EditMode/Core/GameEntityTests.cs
index 5572287..d80716f 100644
--- a/Assets/Tests/EditMode/Core/GameEntityTests.cs
+++ b/Assets/Tests/EditMode/Core/GameEntityTests.cs
@@ -1,5 +1,6 @@
using NUnit.Framework;
using System;
+using System.Collections.Generic;
[TestFixture]
public class GameEntityTests
@@ -9,6 +10,74 @@ public void TestInstanceIDCreated()
{
GameEntity entity = new GameEntity();
Assert.IsNotNull(entity.InstanceID, "InstanceID should not be null.");
+
+ // Ensure the InstanceID is a valid GUID.
Assert.IsTrue(Guid.TryParse(entity.InstanceID, out _), "InstanceID should be a valid GUID.");
}
-}
+
+ [Test]
+ public void TestTypeID()
+ {
+ GameEntity entity = new GameEntity();
+ string typeId = "TestTypeID";
+ entity.TypeID = typeId;
+
+ // Ensure the TypeID is set correctly.
+ Assert.AreEqual(typeId, entity.TypeID, "TypeID should be set correctly.");
+ }
+
+ [Test]
+ public void TestDisplayName()
+ {
+ GameEntity entity = new GameEntity();
+ string displayName = "TestDisplayName";
+ entity.DisplayName = displayName;
+
+ // Ensure the DisplayName is set correctly.
+ Assert.AreEqual(displayName, entity.DisplayName, "DisplayName should be set correctly.");
+ }
+
+ [Test]
+ public void TestDescription()
+ {
+ GameEntity entity = new GameEntity();
+ string description = "TestDescription";
+ entity.Description = description;
+
+ // Ensure the Description is set correctly.
+ Assert.AreEqual(description, entity.Description, "Description should be set correctly.");
+ }
+
+ [Test]
+ public void TestOwnerTypeID()
+ {
+ GameEntity entity = new GameEntity();
+ string ownerTypeID = "TestOwnerTypeID";
+ entity.AllowedOwnerTypeIDs = new List { ownerTypeID };
+ entity.OwnerTypeID = ownerTypeID;
+
+ // Ensure the OwnerTypeID is set correctly.
+ Assert.AreEqual(ownerTypeID, entity.OwnerTypeID, "OwnerTypeID should be set correctly.");
+ }
+
+ [Test]
+ public void TestInvalidOwnerTypeID()
+ {
+ GameEntity entity = new GameEntity();
+ entity.AllowedOwnerTypeIDs = new List { "ValidOwnerTypeID" };
+
+ // Ensure an invalid OwnerTypeID throws an exception.
+ Assert.Throws(() => entity.OwnerTypeID = "InvalidOwnerTypeID", "Setting an invalid OwnerTypeID should throw an ArgumentException.");
+ }
+
+ [Test]
+ public void TestAllowedOwnerTypeIDs()
+ {
+ GameEntity entity = new GameEntity();
+ var allowedOwnerTypeIDs = new List { "Owner1", "Owner2" };
+ entity.AllowedOwnerTypeIDs = allowedOwnerTypeIDs;
+
+ // Ensure the AllowedOwnerTypeIDs is set correctly.
+ Assert.AreEqual(allowedOwnerTypeIDs, entity.AllowedOwnerTypeIDs, "AllowedOwnerTypeIDs should be set correctly.");
+ }
+}
\ No newline at end of file
diff --git a/Assets/Tests/EditMode/Core/SceneNodeTests.cs b/Assets/Tests/EditMode/Core/SceneNodeTests.cs
new file mode 100644
index 0000000..4e476ac
--- /dev/null
+++ b/Assets/Tests/EditMode/Core/SceneNodeTests.cs
@@ -0,0 +1,154 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+
+// Dummy concrete class to test SceneNode.
+class TestSceneNode : SceneNode
+{
+ private List children = new List();
+
+ public override void AddChild(SceneNode child)
+ {
+ children.Add(child);
+ }
+
+ public override void RemoveChild(SceneNode child)
+ {
+ children.Remove(child);
+ }
+
+ public override IEnumerable GetChildren()
+ {
+ return children;
+ }
+}
+
+// Another concrete class to test different types of SceneNode.
+class SpecialSceneNode : SceneNode
+{
+ private List children = new List();
+
+ public override void AddChild(SceneNode child)
+ {
+ children.Add(child);
+ }
+
+ public override void RemoveChild(SceneNode child)
+ {
+ children.Remove(child);
+ }
+
+ public override IEnumerable GetChildren()
+ {
+ return children;
+ }
+}
+
+[TestFixture]
+public class SceneNodeTests
+{
+ [Test]
+ public void TestSetParent()
+ {
+ // Create parent and child nodes
+ SceneNode parent = new TestSceneNode();
+ SceneNode child = new TestSceneNode();
+
+ // Set parent node
+ child.SetParent(parent);
+
+ // Validate that the parent is set correctly
+ Assert.AreEqual(parent, child.GetParent(), "Parent should be set correctly.");
+ Assert.AreEqual(parent.TypeID, child.ParentTypeID, "ParentTypeID should match the parent's TypeID.");
+ }
+
+ [Test]
+ public void TestGetParent()
+ {
+ // Create parent and child nodes
+ SceneNode parent = new TestSceneNode();
+ SceneNode child = new TestSceneNode();
+
+ // Set parent node
+ child.SetParent(parent);
+
+ // Validate that the parent is retrieved correctly
+ Assert.AreEqual(parent, child.GetParent(), "GetParent should return the correct parent.");
+ }
+
+ [Test]
+ public void TestGetClosestParentOfType()
+ {
+ // Create hierarchy: specialNode -> parentNode -> childNode
+ SceneNode specialNode = new SpecialSceneNode();
+ SceneNode parentNode = new TestSceneNode();
+ SceneNode childNode = new TestSceneNode();
+
+ // Set up the hierarchy
+ parentNode.SetParent(specialNode);
+ childNode.SetParent(parentNode);
+
+ // Get the closest parent of the specified type (SpecialSceneNode)
+ var closestSpecialNode = childNode.GetClosestParentOfType();
+
+ // Validate that the closest parent is the specialNode
+ Assert.AreEqual(specialNode, closestSpecialNode, "GetClosestParentOfType should return specialNode.");
+
+ // Now test finding TestSceneNode as the closest parent of the child node
+ var closestTestNode = childNode.GetClosestParentOfType();
+ Assert.AreEqual(parentNode, closestTestNode, "GetClosestParentOfType should return parentNode.");
+ }
+
+ [Test]
+ public void TestAddChild()
+ {
+ // Create parent and child nodes
+ SceneNode parent = new TestSceneNode();
+ SceneNode child = new TestSceneNode();
+
+ // Add child to the parent node
+ parent.AddChild(child);
+
+ // Validate that the child is added correctly
+ CollectionAssert.Contains(parent.GetChildren(), child, "Child should be added to the parent node.");
+ }
+
+ [Test]
+ public void TestRemoveChild()
+ {
+ // Create parent and child nodes
+ SceneNode parent = new TestSceneNode();
+ SceneNode child = new TestSceneNode();
+
+ // Add and then remove child from the parent node
+ parent.AddChild(child);
+ parent.RemoveChild(child);
+
+ // Validate that the child is removed correctly
+ CollectionAssert.DoesNotContain(parent.GetChildren(), child, "Child should be removed from the parent node.");
+ }
+
+ [Test]
+ public void TestTraverse()
+ {
+ // Create root, child1, and child2 nodes
+ SceneNode root = new TestSceneNode();
+ SceneNode child1 = new TestSceneNode();
+ SceneNode child2 = new TestSceneNode();
+
+ // Set up the hierarchy
+ root.AddChild(child1);
+ root.AddChild(child2);
+
+ // List to track visited nodes during traversal
+ var visitedNodes = new List();
+
+ // Traverse the scene graph
+ root.Traverse(node => visitedNodes.Add(node));
+
+ // Validate that all nodes are visited
+ Assert.Contains(root, visitedNodes, "Traverse should visit the root node.");
+ Assert.Contains(child1, visitedNodes, "Traverse should visit child1.");
+ Assert.Contains(child2, visitedNodes, "Traverse should visit child2.");
+ }
+}
diff --git a/Assets/Tests/EditMode/Events/ConditionalFactoryTests.cs b/Assets/Tests/EditMode/Events/ConditionalFactoryTests.cs
new file mode 100644
index 0000000..7971f68
--- /dev/null
+++ b/Assets/Tests/EditMode/Events/ConditionalFactoryTests.cs
@@ -0,0 +1,270 @@
+// using NUnit.Framework;
+// using System.Collections.Generic;
+
+// // [TestFixture]
+// public class ConditionalFactoryTests
+// {
+// private Game mockGame;
+// private IServiceLocator serviceLocator;
+// private Planet tatooine;
+// private Officer luke;
+// private Officer vader;
+// private Officer han;
+
+// [SetUp]
+// public void SetUp()
+// {
+// // Initialize a mock game instance.
+// mockGame = new Game();
+
+// // Initialize a mock planet.
+// tatooine = new Planet
+// {
+// InstanceID = "TATOOINE",
+// DisplayName = "Tatooine",
+// OwnerTypeID = "FNALL1"
+// };
+
+// // Initialize mock officers.
+// luke = new Officer
+// {
+// InstanceID = "LUKE_SKYWALKER",
+// DisplayName = "Luke Skywalker",
+// OwnerTypeID = "FNALL1"
+// };
+
+// vader = new Officer
+// {
+// InstanceID = "DARTH_VADER",
+// DisplayName = "Darth Vader",
+// OwnerTypeID = "FNEMP1"
+// };
+
+// han = new Officer
+// {
+// InstanceID = "HAN_SOLO",
+// DisplayName = "Han Solo",
+// OwnerTypeID = "FNALL1"
+// };
+
+// // Add Luke and Han to the planet.
+// tatooine.AddChild(luke);
+// tatooine.AddChild(han);
+
+// // Add the officers and planet to the game's NodesByInstanceID.
+// mockGame.NodesByInstanceID.Add(tatooine.InstanceID, tatooine);
+// mockGame.NodesByInstanceID.Add(luke.InstanceID, luke);
+// mockGame.NodesByInstanceID.Add(vader.InstanceID, vader);
+// mockGame.NodesByInstanceID.Add(han.InstanceID, han);
+
+// // Initialize the service locator.
+// serviceLocator = ServiceLocatorHelper.GetServiceLocator(mockGame);
+// }
+
+// // [Test]
+// // public void TestAreOnSamePlanetConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet conditional (Luke and Han are on the same planet)
+// // SerializableDictionary parameters = new SerializableDictionary
+// // {
+// // { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } }
+// // };
+
+// // // Create the conditional using the factory
+// // GameConditional conditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", parameters);
+
+// // // Verify that the conditional is met (Luke and Han are on Tatooine)
+// // Assert.IsTrue(conditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestAreOnOpposingFactionsConditional()
+// // {
+// // // Create parameters for AreOnOpposingFactions conditional
+// // SerializableDictionary parameters = new SerializableDictionary
+// // {
+// // { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } }
+// // };
+
+// // // Create the conditional using the factory
+// // GameConditional conditional = ConditionalFactory.CreateConditional("AreOnOpposingFactions", parameters);
+
+// // // Verify that the conditional is met (Luke and Vader are from opposing factions)
+// // Assert.IsTrue(conditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestAndConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet and AreOnOpposingFactions conditionals
+// // SerializableDictionary samePlanetParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } } };
+// // SerializableDictionary opposingFactionsParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } } };
+
+// // GameConditional samePlanetConditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", samePlanetParams);
+// // GameConditional opposingFactionsConditional = ConditionalFactory.CreateConditional("AreOnOpposingFactions", opposingFactionsParams);
+
+// // // Combine these into an And conditional
+// // SerializableDictionary andParameters = new SerializableDictionary
+// // {
+// // { "Conditionals", new List { samePlanetConditional, opposingFactionsConditional } }
+// // };
+
+// // GameConditional andConditional = ConditionalFactory.CreateConditional("And", andParameters);
+
+// // // Verify that the combined conditional is not met (Han and Luke are on the same planet, but Han and Vader are not)
+// // Assert.IsFalse(andConditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestOrConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet and AreOnOpposingFactions conditionals
+// // SerializableDictionary samePlanetParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } } };
+// // SerializableDictionary opposingFactionsParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } } };
+
+// // GameConditional samePlanetConditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", samePlanetParams);
+// // GameConditional opposingFactionsConditional = ConditionalFactory.CreateConditional("AreOnOpposingFactions", opposingFactionsParams);
+
+// // // Combine these into an Or conditional
+// // SerializableDictionary orParameters = new SerializableDictionary
+// // {
+// // { "Conditionals", new List { samePlanetConditional, opposingFactionsConditional } }
+// // };
+
+// // GameConditional orConditional = ConditionalFactory.CreateConditional("Or", orParameters);
+
+// // // Verify that the combined conditional is met (Luke and Han are on the same planet, or Luke and Vader are from opposing factions)
+// // Assert.IsTrue(orConditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestNotConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet conditional
+// // SerializableDictionary samePlanetParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } } };
+
+// // GameConditional samePlanetConditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", samePlanetParams);
+
+// // // Combine this into a Not conditional
+// // SerializableDictionary notParameters = new SerializableDictionary
+// // {
+// // { "Conditionals", samePlanetConditional }
+// // };
+
+// // GameConditional notConditional = ConditionalFactory.CreateConditional("Not", notParameters);
+
+// // // Verify that the Not conditional is not met (Luke and Han are on the same planet, so negating this should return false)
+// // Assert.IsFalse(notConditional.IsMet(mockGame));
+// // }
+
+// // // [Test]
+// // // public void TestNotConditional()
+// // // {
+// // // var innerParameters = new SerializableDictionary();
+// // // var innerConditional = new GenericConditional(Conditionals.AreOnSamePlanet, innerParameters);
+
+// // // var parameters = new SerializableDictionary
+// // // {
+// // // { "Condition", innerConditional }
+// // // };
+// // // var notConditional = new GenericConditional(Conditionals.Not, parameters);
+
+// // // var game = new Game();
+// // // Assert.IsFalse(notConditional.IsMet(game));
+// // // }
+
+
+// // [Test]
+// // public void TestXorConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet and AreOnOpposingFactions conditionals
+// // SerializableDictionary samePlanetParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } } };
+// // SerializableDictionary opposingFactionsParams = new SerializableDictionary { { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } } };
+
+// // GameConditional samePlanetConditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", samePlanetParams);
+// // GameConditional opposingFactionsConditional = ConditionalFactory.CreateConditional("AreOnOpposingFactions", opposingFactionsParams);
+
+// // // Combine these into an Xor conditional
+// // SerializableDictionary xorParameters = new SerializableDictionary
+// // {
+// // { "Conditionals", new List { samePlanetConditional, opposingFactionsConditional } }
+// // };
+
+// // GameConditional xorConditional = ConditionalFactory.CreateConditional("Xor", xorParameters);
+
+// // // Verify that the XOR conditional is met (only one of these is true: Luke and Han are on the same planet, but Luke and Vader are from opposing factions).
+// // Assert.IsTrue(xorConditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestSerializeAndDeserializeAreOnSamePlanetConditional()
+// // {
+// // // Create parameters for AreOnSamePlanet conditional (Luke and Han are on the same planet).
+// // SerializableDictionary parameters = new SerializableDictionary
+// // {
+// // { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } }
+// // };
+
+// // // Create the conditional using the factory.
+// // GameConditional conditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", parameters);
+
+// // // Serialize the conditional.
+// // string xml = SerializationHelper.Serialize(conditional);
+
+// // // Deserialize the conditional.
+// // GameConditional deserializedConditional = SerializationHelper.Deserialize(xml);
+
+// // // Verify that the deserialized conditional still works.
+// // Assert.IsTrue(deserializedConditional.IsMet(mockGame));
+// // }
+
+// // [Test]
+// // public void TestSerializeAndDeserializeAreOnOpposingFactionsConditional()
+// // {
+// // // Create parameters for AreOnOpposingFactions conditional (Luke and Vader).
+// // SerializableDictionary parameters = new SerializableDictionary
+// // {
+// // { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "DARTH_VADER" } }
+// // };
+
+// // // Create the conditional using the factory.
+// // GameConditional conditional = ConditionalFactory.CreateConditional("AreOnOpposingFactions", parameters);
+
+// // // Serialize the conditional.
+// // string xml = SerializationHelper.Serialize(conditional);
+
+// // // Deserialize the conditional.
+// // GameConditional deserializedConditional = SerializationHelper.Deserialize(xml);
+
+// // // Verify that the deserialized conditional still works
+// // Assert.IsTrue(deserializedConditional.IsMet(mockGame));
+// // }
+
+// [Test]
+// public void TestSerializeAndDeserializeAndConditional()
+// {
+// // Create a sample And conditional.
+// SerializableDictionary samePlanetParams = new SerializableDictionary
+// {
+// { "UnitInstanceIDs", new List { "LUKE_SKYWALKER", "HAN_SOLO" } }
+// };
+
+// GameConditional samePlanetConditional = ConditionalFactory.CreateConditional("AreOnSamePlanet", samePlanetParams);
+
+// List conditionalList = new List { samePlanetConditional };
+// SerializableDictionary andParams = new SerializableDictionary
+// {
+// { "Conditionals", conditionalList }
+// };
+
+// GameConditional conditional = ConditionalFactory.CreateConditional("And", andParams);
+
+// // Serialize and then deserialize the conditional.
+// string serializedConditional = SerializationHelper.Serialize(conditional);
+// GameConditional deserializedConditional = SerializationHelper.Deserialize(serializedConditional);
+
+// // Ensure the deserialized conditional is not null and is of the expected type.
+// Assert.IsNotNull(deserializedConditional);
+// Assert.IsInstanceOf(deserializedConditional);
+// }
+// }
diff --git a/Assets/Tests/EditMode/Game/CapitalShipTests.cs b/Assets/Tests/EditMode/Game/CapitalShipTests.cs
index 1bc0b21..06cb5a4 100644
--- a/Assets/Tests/EditMode/Game/CapitalShipTests.cs
+++ b/Assets/Tests/EditMode/Game/CapitalShipTests.cs
@@ -5,75 +5,174 @@
public class CapitalShipTests
{
private CapitalShip capitalShip;
- private Game game;
[SetUp]
public void Setup()
{
+ // Initialize a new instance of CapitalShip for each test with defined capacities and owner.
capitalShip = new CapitalShip
{
- OwnerGameID = "FNALL1",
- InitialParentGameID = "Fleet1",
- RequiredResearchLevel = 2
+ StarfighterCapacity = 2,
+ RegimentCapacity = 3,
+ OwnerTypeID = "FNALL1"
};
+ }
- // Generate a game given a summary.
- GameSummary summary = new GameSummary
- {
- GalaxySize = GameSize.Large,
- Difficulty = GameDifficulty.Easy,
- VictoryCondition = GameVictoryCondition.Headquarters,
- ResourceAvailability = GameResourceAvailability.Abundant,
- PlayerFactionID = "FNALL1",
- };
+ [Test]
+ public void TestAddStarfighter()
+ {
+ // Create a starfighter and add it to the capital ship.
+ Starfighter starfighter = new Starfighter();
+ capitalShip.AddStarfighter(starfighter);
- // Save the file to disk for testing.
- game = new Game
- {
- Summary = summary,
- Galaxy = new GalaxyMap(),
- };
+ // Ensure the starfighter is added to the capital ship's list.
+ Assert.Contains(starfighter, capitalShip.Starfighters, "Starfighter should be added to the capital ship.");
+ }
+
+ [Test]
+ public void TestAddStarfighterExceedsCapacity()
+ {
+ // Add two starfighters within capacity.
+ Starfighter starfighter1 = new Starfighter();
+ Starfighter starfighter2 = new Starfighter();
+ capitalShip.AddStarfighter(starfighter1);
+ capitalShip.AddStarfighter(starfighter2);
+
+ // Attempt to add a third starfighter, which should exceed capacity and throw an exception.
+ Starfighter starfighter3 = new Starfighter();
+ Assert.Throws(() => capitalShip.AddStarfighter(starfighter3),
+ "Adding starfighters beyond capacity should throw an exception.");
+ }
+
+ [Test]
+ public void TestAddRegiment()
+ {
+ // Create a regiment and add it to the capital ship.
+ Regiment regiment = new Regiment();
+ capitalShip.AddRegiment(regiment);
+
+ // Ensure the regiment is added to the capital ship's list.
+ Assert.Contains(regiment, capitalShip.Regiments, "Regiment should be added to the capital ship.");
+ }
+
+ [Test]
+ public void TestAddRegimentExceedsCapacity()
+ {
+ // Add regiments to reach the capacity limit.
+ Regiment regiment1 = new Regiment();
+ Regiment regiment2 = new Regiment();
+ Regiment regiment3 = new Regiment();
+ capitalShip.AddRegiment(regiment1);
+ capitalShip.AddRegiment(regiment2);
+ capitalShip.AddRegiment(regiment3);
+
+ // Attempt to add another regiment, which should exceed the capacity and throw an exception.
+ Regiment regiment4 = new Regiment();
+ Assert.Throws(() => capitalShip.AddRegiment(regiment4),
+ "Adding regiments beyond capacity should throw an exception.");
}
[Test]
public void TestAddOfficer()
{
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
- game.AttachNode(capitalShip, officer);
+ // Create an officer and add it to the capital ship.
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ capitalShip.AddOfficer(officer);
- Assert.Contains(officer, capitalShip.Officers);
+ // Ensure the officer is added to the capital ship's list.
+ Assert.Contains(officer, capitalShip.Officers, "Officer should be added to the capital ship.");
+ }
+
+ [Test]
+ public void TestAddOfficerInvalidOwner()
+ {
+ // Attempt to add an officer with an invalid owner, which should throw an exception.
+ Officer officer = new Officer { OwnerTypeID = "INVALID" };
+ Assert.Throws(() => capitalShip.AddOfficer(officer),
+ "Adding an officer with an invalid owner should throw a SceneAccessException.");
}
[Test]
- public void TestAddOfficerWithDifferentOwner()
+ public void TestRemoveStarfighter()
{
- Officer officer = new Officer { OwnerGameID = "FNEMP1" };
+ // Add and then remove a starfighter from the capital ship.
+ Starfighter starfighter = new Starfighter();
+ capitalShip.AddStarfighter(starfighter);
+ capitalShip.RemoveChild(starfighter);
- Assert.Throws(() => game.AttachNode(capitalShip, officer));
+ // Ensure the starfighter is removed from the capital ship's list.
+ Assert.IsFalse(capitalShip.Starfighters.Contains(starfighter),
+ "Starfighter should be removed from the capital ship.");
+ }
+
+ [Test]
+ public void TestRemoveRegiment()
+ {
+ // Add and then remove a regiment from the capital ship.
+ Regiment regiment = new Regiment();
+ capitalShip.AddRegiment(regiment);
+ capitalShip.RemoveChild(regiment);
+
+ // Ensure the regiment is removed from the capital ship's list.
+ Assert.IsFalse(capitalShip.Regiments.Contains(regiment),
+ "Regiment should be removed from the capital ship.");
}
[Test]
public void TestRemoveOfficer()
{
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
- game.AttachNode(capitalShip, officer);
- game.DetachNode(officer);
+ // Add and then remove an officer from the capital ship.
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ capitalShip.AddOfficer(officer);
+ capitalShip.RemoveChild(officer);
- Assert.IsFalse(capitalShip.Officers.Contains(officer));
+ // Ensure the officer is removed from the capital ship's list.
+ Assert.IsFalse(capitalShip.Officers.Contains(officer),
+ "Officer should be removed from the capital ship.");
}
[Test]
public void TestGetChildren()
{
- Officer officer1 = new Officer { OwnerGameID = "FNALL1" };
- Officer officer2 = new Officer { OwnerGameID = "FNALL1" };
-
- game.AttachNode(capitalShip, officer1);
- game.AttachNode(capitalShip, officer2);
+ // Add various child nodes to the capital ship.
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ Starfighter starfighter = new Starfighter();
+ Regiment regiment = new Regiment();
+ capitalShip.AddOfficer(officer);
+ capitalShip.AddStarfighter(starfighter);
+ capitalShip.AddRegiment(regiment);
+ // Retrieve the children of the capital ship.
IEnumerable children = capitalShip.GetChildren();
- List expectedChildren = new List { officer1, officer2 };
- CollectionAssert.AreEquivalent(expectedChildren, children);
+ // Ensure all added child nodes are returned as children.
+ List expectedChildren = new List { officer, starfighter, regiment };
+ CollectionAssert.AreEquivalent(expectedChildren, children, "CapitalShip should return correct children.");
+ }
+
+ [Test]
+ public void TestSerializeAndDeserialize()
+ {
+ // Add components to the CapitalShip.
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ Starfighter starfighter = new Starfighter();
+ Regiment regiment = new Regiment();
+ capitalShip.AddOfficer(officer);
+ capitalShip.AddStarfighter(starfighter);
+ capitalShip.AddRegiment(regiment);
+
+ // Serialize the CapitalShip object to a string.
+ string serialized = SerializationHelper.Serialize(capitalShip);
+
+ // Deserialize the string back to a CapitalShip object.
+ CapitalShip deserialized = SerializationHelper.Deserialize(serialized);
+
+ // Check that the deserialized object contains the same properties and children.
+ Assert.AreEqual(capitalShip.StarfighterCapacity, deserialized.StarfighterCapacity, "StarfighterCapacity should be correctly deserialized.");
+ Assert.AreEqual(capitalShip.RegimentCapacity, deserialized.RegimentCapacity, "RegimentCapacity should be correctly deserialized.");
+ Assert.AreEqual(capitalShip.OwnerTypeID, deserialized.OwnerTypeID, "OwnerTypeID should be correctly deserialized.");
+ Assert.AreEqual(capitalShip.Officers.Count, deserialized.Officers.Count, "Officers should be correctly deserialized.");
+ Assert.AreEqual(capitalShip.Starfighters.Count, deserialized.Starfighters.Count, "Starfighters should be correctly deserialized.");
+ Assert.AreEqual(capitalShip.Regiments.Count, deserialized.Regiments.Count, "Regiments should be correctly deserialized.");
}
}
diff --git a/Assets/Tests/EditMode/Game/GameTests.cs b/Assets/Tests/EditMode/Game/GameTests.cs
index d34f5a0..3f44bf7 100644
--- a/Assets/Tests/EditMode/Game/GameTests.cs
+++ b/Assets/Tests/EditMode/Game/GameTests.cs
@@ -42,7 +42,7 @@ public void TestSceneGraphReconstitutionAfterSerialization()
// Create officers.
List officers = new List
{
- new Officer { OwnerGameID = "FNALL1" }
+ new Officer { OwnerTypeID = "FNALL1" }
};
// Create capital ships.
@@ -50,7 +50,7 @@ public void TestSceneGraphReconstitutionAfterSerialization()
{
new CapitalShip
{
- OwnerGameID = "FNALL1",
+ OwnerTypeID = "FNALL1",
Officers = officers
}
};
@@ -60,7 +60,7 @@ public void TestSceneGraphReconstitutionAfterSerialization()
{
new Fleet
{
- OwnerGameID = "FNALL1",
+ OwnerTypeID = "FNALL1",
CapitalShips = capitalShips
}
};
@@ -70,7 +70,7 @@ public void TestSceneGraphReconstitutionAfterSerialization()
{
new Planet
{
- OwnerGameID = "FNALL1",
+ OwnerTypeID = "FNALL1",
Fleets = fleets
}
};
@@ -98,7 +98,7 @@ public void TestSceneGraphReconstitutionAfterSerialization()
game.Galaxy.Traverse((SceneNode node) => {
string instanceID = node.InstanceID;
- SceneNode sceneNode = game.GetSceneNodeByInstanceID(instanceID);
+ SceneNode sceneNode = game.GetSceneNodeByInstanceID(instanceID);
// Check if the node is registered by instance ID.
Assert.AreEqual(node.InstanceID, sceneNode.InstanceID, "Node should be registered by instance ID.");
@@ -134,8 +134,8 @@ public void TestAttachAndDetachNode()
};
// Create our scene.
- Planet planet = new Planet { OwnerGameID = "FNALL1" };
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
+ Planet planet = new Planet { OwnerTypeID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
// Attach the nodes.
game.AttachNode(planetSystem, planet);
@@ -156,14 +156,13 @@ public void TestAttachAndDetachNode()
public void TestMoveNode()
{
- // Create the game.
Game game = new Game();
// Create our scene.
PlanetSystem planetSystem = new PlanetSystem();
- Planet planet1 = new Planet { OwnerGameID = "FNALL1" };
- Planet planet2 = new Planet { OwnerGameID = "FNALL1" };
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
+ Planet planet1 = new Planet { OwnerTypeID = "FNALL1" };
+ Planet planet2 = new Planet { OwnerTypeID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
// Attach the nodes.
game.AttachNode(planetSystem, planet1);
@@ -189,8 +188,8 @@ public void TestThrowsExceptionWhenAttachingNodeWithParent()
Game game = new Game();
// Create our scene.
- Planet planet = new Planet { OwnerGameID = "FNALL1" };
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
+ Planet planet = new Planet { OwnerTypeID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
// Attach the fleet to the planet.
game.AttachNode(fleet, planet);
@@ -205,14 +204,14 @@ public void TestThrowsExceptionWhenDetachingNodeWithoutParent()
Game game = new Game();
// Create our scene.
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
// Check if an exception is thrown when detaching a node without a parent.
Assert.Throws(() => game.DetachNode(fleet), "Exception should be thrown when detaching a node without a parent.");
}
[Test]
- public void TestRegisterAndDeregisterSceneNode()
+ public void TestRegisterAndRemoveNodeByInstanceID()
{;
Game game = new Game
{
@@ -220,7 +219,7 @@ public void TestRegisterAndDeregisterSceneNode()
};
// Create our scene.
- Planet planet = new Planet { OwnerGameID = "FNALL1" };
+ Planet planet = new Planet { OwnerTypeID = "FNALL1" };
PlanetSystem planetSystem = new PlanetSystem()
{
Planets = new List { planet },
@@ -230,15 +229,15 @@ public void TestRegisterAndDeregisterSceneNode()
game.AttachNode(game.Galaxy, planetSystem);
// Check if the fleet is registered.
- Assert.AreEqual(game.GetSceneNodeByInstanceID(planetSystem.InstanceID), planetSystem, "Planet System should be registered.");
- Assert.AreEqual(game.GetSceneNodeByInstanceID(planet.InstanceID), planet, "Planet should be registered.");
+ Assert.AreEqual(game.GetSceneNodeByInstanceID(planetSystem.InstanceID), planetSystem, "Planet System should be registered.");
+ Assert.AreEqual(game.GetSceneNodeByInstanceID(planet.InstanceID), planet, "Planet should be registered.");
// Detach the fleet from the planet.
game.DetachNode(planetSystem);
// Check if the fleet is deregistered.
- Assert.IsNull(game.GetSceneNodeByInstanceID(planetSystem.InstanceID), "Planet System should be deregistered.");
- Assert.IsNull(game.GetSceneNodeByInstanceID(planet.InstanceID), "Planet should be deregistered.");
+ Assert.IsNull(game.GetSceneNodeByInstanceID(planetSystem.InstanceID), "Planet System should be deregistered.");
+ Assert.IsNull(game.GetSceneNodeByInstanceID(planet.InstanceID), "Planet should be deregistered.");
}
}
diff --git a/Assets/Tests/EditMode/Game/PlanetTests.cs b/Assets/Tests/EditMode/Game/PlanetTests.cs
index 779259e..45e1ee2 100644
--- a/Assets/Tests/EditMode/Game/PlanetTests.cs
+++ b/Assets/Tests/EditMode/Game/PlanetTests.cs
@@ -1,11 +1,10 @@
using NUnit.Framework;
using System.Collections.Generic;
-using System.Linq;
+[TestFixture]
public class PlanetTests
{
private Planet planet;
- private Game game;
[SetUp]
public void Setup()
@@ -15,99 +14,82 @@ public void Setup()
IsColonized = true,
GroundSlots = 5,
OrbitSlots = 3,
- OwnerGameID = "FNALL1"
- };
-
- // Generate a game given a summary.
- GameSummary summary = new GameSummary
- {
- GalaxySize = GameSize.Large,
- Difficulty = GameDifficulty.Easy,
- VictoryCondition = GameVictoryCondition.Headquarters,
- ResourceAvailability = GameResourceAvailability.Abundant,
- PlayerFactionID = "FNALL1",
- };
-
- // Save the file to disk for testing.
- game = new Game
- {
- Summary = summary,
- Galaxy = new GalaxyMap(),
+ OwnerTypeID = "FNALL1"
};
}
[Test]
public void TestAddFleet()
{
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
- game.AttachNode(planet, fleet);
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
+ planet.AddChild(fleet);
- Assert.Contains(fleet, planet.Fleets);
+ Assert.Contains(fleet, planet.Fleets, "Fleet should be added to the planet.");
}
[Test]
public void TestAddOfficer()
{
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
- game.AttachNode(planet, officer);
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ planet.AddChild(officer);
- Assert.Contains(officer, planet.Officers);
+ Assert.Contains(officer, planet.Officers, "Officer should be added to the planet.");
}
[Test]
public void TestAddBuilding()
{
Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" };
- game.AttachNode(planet, building);
+ planet.AddChild(building);
Building[] buildings = planet.GetBuildings(BuildingSlot.Ground);
- Assert.Contains(building, buildings);
+ Assert.Contains(building, buildings, "Building should be added to the ground slots of the planet.");
}
[Test]
public void TestRemoveFleet()
{
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
- game.AttachNode(planet, fleet);
- game.DetachNode(fleet);
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
+ planet.AddChild(fleet);
+ planet.RemoveChild(fleet);
- Assert.IsFalse(planet.Fleets.Contains(fleet));
+ Assert.IsFalse(planet.Fleets.Contains(fleet), "Fleet should be removed from the planet.");
}
[Test]
public void TestRemoveOfficer()
{
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
- game.AttachNode(planet, officer);
- game.DetachNode(officer);
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
+ planet.AddChild(officer);
+ planet.RemoveChild(officer);
- Assert.IsFalse(planet.Officers.Contains(officer));
+ Assert.IsFalse(planet.Officers.Contains(officer), "Officer should be removed from the planet.");
}
[Test]
public void TestRemoveBuilding()
{
Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" };
- game.AttachNode(planet, building);
- game.DetachNode(building);
+ planet.AddChild(building);
+ planet.RemoveChild(building);
- Assert.IsFalse(planet.Buildings[BuildingSlot.Ground].Contains(building));
+ Assert.IsFalse(planet.Buildings[BuildingSlot.Ground].Contains(building), "Building should be removed from the planet.");
}
[Test]
public void TestGetChildren()
{
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" };
- game.AttachNode(planet, fleet);
- game.AttachNode(planet, officer);
- game.AttachNode(planet, building);
+ planet.AddChild(fleet);
+ planet.AddChild(officer);
+ planet.AddChild(building);
IEnumerable children = planet.GetChildren();
List expectedChildren = new List { fleet, officer, building };
- CollectionAssert.AreEquivalent(expectedChildren, children);
+ CollectionAssert.AreEquivalent(expectedChildren, children, "Planet should return correct children.");
}
}
diff --git a/Assets/Tests/EditMode/Generation/GameBuilderTests.cs b/Assets/Tests/EditMode/Generation/GameBuilderTests.cs
index 417ac1d..ff935f9 100644
--- a/Assets/Tests/EditMode/Generation/GameBuilderTests.cs
+++ b/Assets/Tests/EditMode/Generation/GameBuilderTests.cs
@@ -68,10 +68,10 @@ public void TestAllFactionsHaveHQs()
bool hasHQ = game.Galaxy
.PlanetSystems
.SelectMany(ps => ps.Planets)
- .Any(planet => planet.OwnerGameID == faction.GameID && planet.IsHeadquarters);
+ .Any(planet => planet.OwnerTypeID == faction.TypeID && planet.IsHeadquarters);
// Assert that the faction has a headquarters
- Assert.IsTrue(hasHQ, $"Faction {faction.GameID} should have a headquarters.");
+ Assert.IsTrue(hasHQ, $"Faction {faction.TypeID} should have a headquarters.");
}
}
}
diff --git a/Assets/Tests/EditMode/Helpers/ServiceLocatorHelper.cs b/Assets/Tests/EditMode/Helpers/ServiceLocatorHelper.cs
new file mode 100644
index 0000000..b6e4f2d
--- /dev/null
+++ b/Assets/Tests/EditMode/Helpers/ServiceLocatorHelper.cs
@@ -0,0 +1,25 @@
+// using System;
+// using System.Collections.Generic;
+
+// public static class ServiceLocatorHelper
+// {
+// public static IServiceLocator GetServiceLocator(Game game)
+// {
+// ServiceLocator serviceLocator = new ServiceLocator();
+
+// List services = new List()
+// {
+// new LookupService(serviceLocator, game),
+// new MissionService(serviceLocator, game),
+// new UnitService(serviceLocator, game),
+// new EventService(serviceLocator, game),
+// };
+
+// foreach (BaseService service in services)
+// {
+// serviceLocator.RegisterService(service);
+// }
+
+// return serviceLocator;
+// }
+// }
diff --git a/Assets/Tests/EditMode/Managers/GameManagerTests.cs b/Assets/Tests/EditMode/Managers/GameManagerTests.cs
index 9fd9d12..64e208b 100644
--- a/Assets/Tests/EditMode/Managers/GameManagerTests.cs
+++ b/Assets/Tests/EditMode/Managers/GameManagerTests.cs
@@ -1,67 +1,89 @@
-using NUnit.Framework;
-using UnityEngine.TestTools;
-using System.Collections;
-
-// Mock GameEvent for testing
-public class MockEvent : GameEvent
-{
- public bool WasExecuted { get; private set; }
-
- public MockEvent(int scheduledTick) : base(scheduledTick)
- {
- WasExecuted = false;
- }
-
- protected override void TriggerEvent(Game game)
- {
- WasExecuted = true; // Mark the event as executed when this method is called
- }
-}
-
-[TestFixture]
-public class GameManagerTests
-{
- private GameManager gameManager;
- private MockEvent mockEvent;
-
- [SetUp]
- public void Setup()
- {
- // Create a GameSummary and a new Game for the test
- GameSummary summary = new GameSummary
- {
- GalaxySize = GameSize.Large,
- Difficulty = GameDifficulty.Medium,
- VictoryCondition = GameVictoryCondition.Headquarters,
- ResourceAvailability = GameResourceAvailability.Normal,
- PlayerFactionID = "FNALL1"
- };
-
- Game game = new Game(summary);
-
- // Initialize GameManager with the game instance
- gameManager = new GameManager(game);
- }
-
- [Test]
- public void TestEventExecutesAtScheduledTick()
- {
- // Create a mock event scheduled to occur at tick 5
- mockEvent = new MockEvent(5);
-
- gameManager.EventManager.ScheduleEvent(mockEvent);
- gameManager.SetTickSpeed(TickSpeed.Fast);
-
- // Simulate 4 ticks (the event should not trigger yet)
- for (int i = 0; i < 4; i++)
- {
- gameManager.Update(1f); // Simulate 1 second of game time (1 tick)
- Assert.IsFalse(mockEvent.WasExecuted, "Event should not have been executed yet.");
- }
-
- // Simulate 1 more tick (the 5th tick, where the event is scheduled)
- gameManager.Update(1f); // Simulate 1 second of game time (1 tick)
-
- Assert.IsTrue(mockEvent.WasExecuted, "Event should have been executed at tick 5.");
- }
-}
+// using NUnit.Framework;
+
+// [TestFixture]
+// public class GameManagerTests
+// {
+// private GameManager gameManager;
+// private Game game;
+
+// [SetUp]
+// public void Setup()
+// {
+// // Initialize the game and GameManager before each test
+// game = new Game();
+// gameManager = new GameManager(game);
+// }
+
+// [Test]
+// public void TestSetTickSpeedFastProcessesTickEvery1Second()
+// {
+// // Set tick speed to Fast (1 second per tick)
+// gameManager.SetTickSpeed(TickSpeed.Fast);
+
+// // Simulate 1 second passing
+// gameManager.Update(1f);
+
+// // Assert that one tick has been processed
+// Assert.AreEqual(1, game.CurrentTick, "Game should process one tick after 1 second at Fast speed.");
+// }
+
+// [Test]
+// public void TestSetTickSpeedMediumProcessesTickEvery10Seconds()
+// {
+// // Set tick speed to Medium (10 seconds per tick)
+// gameManager.SetTickSpeed(TickSpeed.Medium);
+
+// // Simulate 9 seconds passing (should not trigger a tick yet)
+// gameManager.Update(9f);
+// Assert.AreEqual(0, game.CurrentTick, "Game should not process a tick before 10 seconds at Medium speed.");
+
+// // Simulate 1 more second (total 10 seconds, which should trigger a tick)
+// gameManager.Update(1f);
+// Assert.AreEqual(1, game.CurrentTick, "Game should process one tick after 10 seconds at Medium speed.");
+// }
+
+// [Test]
+// public void TestSetTickSpeedSlowProcessesTickEvery60Seconds()
+// {
+// // Set tick speed to Slow (60 seconds per tick)
+// gameManager.SetTickSpeed(TickSpeed.Slow);
+
+// // Simulate 59 seconds passing (should not trigger a tick yet)
+// gameManager.Update(59f);
+// Assert.AreEqual(0, game.CurrentTick, "Game should not process a tick before 60 seconds at Slow speed.");
+
+// // Simulate 1 more second (total 60 seconds, which should trigger a tick)
+// gameManager.Update(1f);
+// Assert.AreEqual(1, game.CurrentTick, "Game should process one tick after 60 seconds at Slow speed.");
+// }
+
+// [Test]
+// public void TestSetTickSpeedPausedNoTicksProcessed()
+// {
+// // Set tick speed to Paused (no ticking)
+// gameManager.SetTickSpeed(TickSpeed.Paused);
+
+// // Simulate some time passing (should not trigger any ticks)
+// gameManager.Update(100f);
+// Assert.AreEqual(0, game.CurrentTick, "Game should not process any ticks when the tick speed is paused.");
+// }
+
+// [Test]
+// public void TestSetTickSpeedSwitchSpeedsDuringGame()
+// {
+// // Set tick speed to Fast and simulate 1 second
+// gameManager.SetTickSpeed(TickSpeed.Fast);
+// gameManager.Update(1f);
+// Assert.AreEqual(1, game.CurrentTick, "Game should process one tick after 1 second at Fast speed.");
+
+// // Switch to Medium speed and simulate 10 seconds
+// gameManager.SetTickSpeed(TickSpeed.Medium);
+// gameManager.Update(10f);
+// Assert.AreEqual(2, game.CurrentTick, "Game should process one tick after 10 seconds at Medium speed.");
+
+// // Switch to Slow speed and simulate 60 seconds
+// gameManager.SetTickSpeed(TickSpeed.Slow);
+// gameManager.Update(60f);
+// Assert.AreEqual(3, game.CurrentTick, "Game should process one tick after 60 seconds at Slow speed.");
+// }
+// }
diff --git a/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs b/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs
index bb15b09..d416dd7 100644
--- a/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs
+++ b/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using UnityEngine;
-using UnityEngine.TestTools;
[TestFixture]
public class SaveGameManagerTests
@@ -65,17 +64,18 @@ public void TestLoadGame()
Summary = summary,
Galaxy = new GalaxyMap(),
};
+ string serializedShit = SerializationHelper.Serialize(game);
SaveGameManager.Instance.SaveGameData(game, saveFileName);
// Load the game from file.
Game loadedGame = SaveGameManager.Instance.LoadGameData(saveFileName);
// Assert that the loaded game's summary matches the original summary.
- Assert.AreEqual(loadedGame.Summary.GalaxySize, summary.GalaxySize);
- Assert.AreEqual(loadedGame.Summary.Difficulty, summary.Difficulty);
- Assert.AreEqual(loadedGame.Summary.VictoryCondition, summary.VictoryCondition);
- Assert.AreEqual(loadedGame.Summary.ResourceAvailability, summary.ResourceAvailability);
- Assert.AreEqual(loadedGame.Summary.PlayerFactionID, summary.PlayerFactionID);
+ Assert.AreEqual(loadedGame.Summary.GalaxySize, summary.GalaxySize, "Galaxy size does not match.");
+ Assert.AreEqual(loadedGame.Summary.Difficulty, summary.Difficulty, "Difficulty does not match.");
+ Assert.AreEqual(loadedGame.Summary.VictoryCondition, summary.VictoryCondition, "Victory condition does not match.");
+ Assert.AreEqual(loadedGame.Summary.ResourceAvailability, summary.ResourceAvailability, "Resource availability does not match.");
+ Assert.AreEqual(loadedGame.Summary.PlayerFactionID, summary.PlayerFactionID, "Player faction ID does not match.");
}
[Test]
@@ -112,20 +112,20 @@ public void TestBasicSceneGraphLoaded()
};
// Create planets.
- Planet planet = new Planet { OwnerGameID = "FNALL1" };
+ Planet planet = new Planet { OwnerTypeID = "FNALL1" };
planetSystem.Planets.Add(planet);
game.AttachNode(planetSystem, planet);
// Create fleets.
- Fleet fleet = new Fleet { OwnerGameID = "FNALL1" };
+ Fleet fleet = new Fleet { OwnerTypeID = "FNALL1" };
game.AttachNode(planet, fleet);
// Create capital ships.
- CapitalShip capitalShip = new CapitalShip { OwnerGameID = "FNALL1" };
+ CapitalShip capitalShip = new CapitalShip { OwnerTypeID = "FNALL1" };
game.AttachNode(fleet, capitalShip);
// Create officers.
- Officer officer = new Officer { OwnerGameID = "FNALL1" };
+ Officer officer = new Officer { OwnerTypeID = "FNALL1" };
game.AttachNode(capitalShip, officer);
// Save the game to disk.
diff --git a/Assets/Tests/EditMode/Missions/DiplomacyMissionTests.cs b/Assets/Tests/EditMode/Missions/DiplomacyMissionTests.cs
deleted file mode 100644
index 73c1bc0..0000000
--- a/Assets/Tests/EditMode/Missions/DiplomacyMissionTests.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using NUnit.Framework;
-using System.Collections.Generic;
-
-[TestFixture]
-public class DiplomacyMissionTests
-{
- private Game game;
- private PlanetSystem planetSystem;
- private Planet planet;
-
- [SetUp]
- public void SetUp()
- {
- // Initialize the faction for the mission.
- Faction faction = new Faction()
- {
- GameID = "FNALL1"
- };
-
- // Initialize the planet for the mission.
- planet = new Planet()
- {
- OwnerGameID = "FNALL1"
- };
-
- // Initialize the planet system with the planet.
- planetSystem = new PlanetSystem()
- {
- Planets = new List()
- {
- planet
- }
- };
-
- // Initialize the game and embed the planet system.
- game = new Game()
- {
- Galaxy = new GalaxyMap()
- {
- PlanetSystems = new List()
- {
- planetSystem
- }
- },
- Factions = new List()
- {
- faction
- }
- };
- }
-
- [Test]
- public void TestMissionInitialization()
- {
- // Initialize participants.
- List mainParticipants = new List
- {
- new MissionParticipant
- {
- Skills = new SerializableDictionary()
- {
- { MissionParticipantSkill.Diplomacy, 0 },
- }
- }
- };
-
- List decoyParticipants = new List();
-
- // Initialize the DiplomacyMission and append it to the scene graph.
- DiplomacyMission diplomacyMission = new DiplomacyMission("FNALL1", mainParticipants, decoyParticipants);
- diplomacyMission.SetParent(planet);
-
- // Verify that the mission is initialized correctly
- Assert.AreEqual("Diplomacy", diplomacyMission.Name);
- Assert.AreEqual(diplomacyMission.ParticipantSkill, MissionParticipantSkill.Diplomacy);
- Assert.AreEqual(mainParticipants, diplomacyMission.GetChildren());
- }
-
- [Test]
- public void TestOnSuccess()
- {
- // Initialize participants.
- List mainParticipants = new List
- {
- new MissionParticipant
- {
- Skills = new SerializableDictionary()
- {
- { MissionParticipantSkill.Diplomacy, 1000 },
- }
- }
- };
-
- List decoyParticipants = new List();
-
- // Initialize the DiplomacyMission and append it to the scene graph.
- DiplomacyMission diplomacyMission = new DiplomacyMission("FNALL1", mainParticipants, decoyParticipants);
- diplomacyMission.SetParent(planet);
-
- // Create a MissionEvent and execute it.
- MissionEvent missionEvent = new MissionEvent(0, diplomacyMission);
- missionEvent.Execute(game);
-
- // Verify that planetary support has increased.
- Assert.Greater(planet.GetPopularSupport("FNALL1"), 0);
- }
-
- [Test]
- public void TestOnFailure()
- {
- // Initialize participants
- List mainParticipants = new List
- {
- new MissionParticipant
- {
- Skills = new SerializableDictionary()
- {
- { MissionParticipantSkill.Diplomacy, -1000 },
- }
- }
- };
-
- List decoyParticipants = new List();
-
- // Initialize the DiplomacyMission and append it to the scene graph.
- DiplomacyMission diplomacyMission = new DiplomacyMission("FNALL1", mainParticipants, decoyParticipants);
- diplomacyMission.SetParent(planet);
-
- // Create a MissionEvent and execute it.
- MissionEvent missionEvent = new MissionEvent(0, diplomacyMission);
- missionEvent.Execute(game);
-
- // @TODO: Verify failure.
- }
-}
diff --git a/Assets/Tests/EditMode/Missions/MissionTests.cs b/Assets/Tests/EditMode/Missions/MissionTests.cs
index 940d61e..01c6dc7 100644
--- a/Assets/Tests/EditMode/Missions/MissionTests.cs
+++ b/Assets/Tests/EditMode/Missions/MissionTests.cs
@@ -1,208 +1,206 @@
-using NUnit.Framework;
-using System.Collections.Generic;
-
-// Concrete class for testing abstract Mission
-public class MockMission : Mission
-{
- public bool WasSuccessful { get; private set; }
-
- // Constructor for MockMission with better readability.
- public MockMission(
- string name,
- string ownerGameID,
- List mainParticipants,
- List decoyParticipants,
- MissionParticipantSkill participantSkill,
- double quadraticCoefficient = 0.001,
- double linearCoefficient = 0.5,
- double constantTerm = 50,
- double minSuccessProbability = 1,
- double maxSuccessProbability = 100,
- int minTicks = 5,
- int maxTicks = 10)
- : base(
- name: name,
- ownerGameID: ownerGameID,
- mainParticipants: mainParticipants,
- decoyParticipants: decoyParticipants,
- participantSkill: participantSkill,
- quadraticCoefficient: quadraticCoefficient,
- linearCoefficient: linearCoefficient,
- constantTerm: constantTerm,
- minSuccessProbability: minSuccessProbability,
- maxSuccessProbability: maxSuccessProbability,
- minTicks: minTicks,
- maxTicks: maxTicks)
- {
- WasSuccessful = false; // Initialize success flag.
- }
-
- protected override void OnSuccess(Game game)
- {
- WasSuccessful = true; // Mark mission as successful.
- }
-}
-
-[TestFixture]
-public class MissionTests
-{
- private Officer successfulOfficer;
- private Officer failedOfficer;
- private MockMission mission;
- private Game game;
- private Planet testPlanet;
-
- [SetUp]
- public void Setup()
- {
- testPlanet = new Planet
- {
- DisplayName = "TestPlanet",
- Regiments = new List {
- new Regiment { DefenseRating = 50 },
- new Regiment { DefenseRating = 45 }
- }
- };
-
- successfulOfficer = new Officer
- {
- Diplomacy = 80,
- Espionage = 90,
- Combat = 75,
- Leadership = 85,
- Status = OfficerStatus.Available
- };
-
- failedOfficer = new Officer
- {
- Diplomacy = 10,
- Espionage = 15,
- Combat = 20,
- Leadership = 25,
- Status = OfficerStatus.Available
- };
- }
-
- [Test]
- public void TestMissionSuccess()
- {
- testPlanet = new Planet
- {
- DisplayName = "TestPlanet",
- Regiments = new List {
- new Regiment { DefenseRating = -1000 },
- }
- };
+// using NUnit.Framework;
+// using System.Collections.Generic;
+
+// // Concrete class for testing abstract Mission
+// class MockMission : Mission
+// {
+// public bool WasSuccessful { get; private set; }
+
+// // Constructor for MockMission with better readability.
+// public MockMission(
+// string name,
+// string ownerTypeID,
+// List mainParticipants,
+// List decoyParticipants,
+// MissionParticipantSkill participantSkill,
+// double quadraticCoefficient = 0.001,
+// double linearCoefficient = 0.5,
+// double constantTerm = 50,
+// double minSuccessProbability = 1,
+// double maxSuccessProbability = 100,
+// int minTicks = 5,
+// int maxTicks = 10)
+// : base(
+// name: name,
+// ownerTypeID: ownerTypeID,
+// mainParticipants: mainParticipants,
+// decoyParticipants: decoyParticipants,
+// participantSkill: participantSkill,
+// quadraticCoefficient: quadraticCoefficient,
+// linearCoefficient: linearCoefficient,
+// constantTerm: constantTerm,
+// minSuccessProbability: minSuccessProbability,
+// maxSuccessProbability: maxSuccessProbability,
+// minTicks: minTicks,
+// maxTicks: maxTicks)
+// {
+// WasSuccessful = false; // Initialize success flag.
+// }
+
+// protected override void OnSuccess(Game game)
+// {
+// WasSuccessful = true; // Mark mission as successful.
+// }
+// }
+
+// [TestFixture]
+// public class MissionTests
+// {
+// private Officer successfulOfficer;
+// private Officer failedOfficer;
+// private MockMission mission;
+// private Game game;
+// private Planet testPlanet;
+
+// [SetUp]
+// public void Setup()
+// {
+// testPlanet = new Planet
+// {
+// DisplayName = "TestPlanet",
+// Regiments = new List {
+// new Regiment { DefenseRating = 50 },
+// new Regiment { DefenseRating = 45 }
+// }
+// };
+
+// successfulOfficer = new Officer
+// {
+// Diplomacy = 80,
+// Espionage = 90,
+// Combat = 75,
+// Leadership = 85
+// };
+
+// failedOfficer = new Officer
+// {
+// Diplomacy = 10,
+// Espionage = 15,
+// Combat = 20,
+// Leadership = 25
+// };
+// }
+
+// [Test]
+// public void TestMissionSuccess()
+// {
+// testPlanet = new Planet
+// {
+// DisplayName = "TestPlanet",
+// Regiments = new List {
+// new Regiment { DefenseRating = -1000 },
+// }
+// };
- // Force mission to succeed by setting success probability to 100%
- mission = new MockMission(
- name: "Test Mission",
- ownerGameID: "FNEMP1",
- mainParticipants: new List { successfulOfficer },
- decoyParticipants: new List(),
- participantSkill: MissionParticipantSkill.Espionage,
- quadraticCoefficient: 0.001,
- linearCoefficient: 0.5,
- constantTerm: 5.0,
- minSuccessProbability: 100, // Guaranteed success
- maxSuccessProbability: 100,
- minTicks: 5,
- maxTicks: 10
- );
-
- mission.SetParent(testPlanet); // Set parent to avoid null references
-
- mission.Perform(game);
-
- Assert.IsTrue(mission.WasSuccessful, "The mission should have succeeded due to forced 100% success probability.");
- }
-
- [Test]
- public void TestMissionFailure()
- {
- testPlanet = new Planet
- {
- DisplayName = "TestPlanet",
- OwnerGameID = "FNALL1",
- Regiments = new List {
- new Regiment { DefenseRating = -1000 },
- }
- };
- // Force mission to fail by setting success probability to 0%
- mission = new MockMission(
- name: "Test Mission",
- ownerGameID: "FNEMP1",
- mainParticipants: new List { successfulOfficer },
- decoyParticipants: new List { },
- participantSkill: MissionParticipantSkill.Espionage,
- quadraticCoefficient: 0.001,
- linearCoefficient: 0.5,
- constantTerm: 5.0,
- minSuccessProbability: 0, // Guaranteed failure
- maxSuccessProbability: 0,
- minTicks: 5,
- maxTicks: 10
- );
-
- mission.SetParent(testPlanet);
-
- mission.Perform(game);
-
- Assert.IsFalse(mission.WasSuccessful, "The mission should have failed due to forced 0% success probability.");
- }
-
- [Test]
- public void TestDecoySuccess()
- {
- // Force decoy success by setting decoy success probability to 100%
- mission = new MockMission(
- name: "Decoy Test Mission",
- ownerGameID: "FNEMP1",
- mainParticipants: new List { failedOfficer },
- decoyParticipants: new List { successfulOfficer },
- participantSkill: MissionParticipantSkill.Espionage,
- quadraticCoefficient: 0.001,
- linearCoefficient: 0.5,
- constantTerm: 50,
- minSuccessProbability: 0, // Guaranteed decoy success
- maxSuccessProbability: 0,
- minTicks: 5,
- maxTicks: 10
- );
-
- mission.SetParent(testPlanet);
-
- mission.Perform(game);
-
- // Assuming decoy success logic will be implemented in the future
- Assert.Pass("Decoy success logic should be implemented.");
- }
-
- [Test]
- public void TestMissionFoiled()
- {
- // Force mission to be foiled by setting high defense score
- testPlanet.Regiments = new List { new Regiment { DefenseRating = 1000 } };
-
- mission = new MockMission(
- name: "Test Mission",
- ownerGameID: "FNEMP1",
- mainParticipants: new List { successfulOfficer },
- decoyParticipants: new List { failedOfficer },
- participantSkill: MissionParticipantSkill.Espionage,
- quadraticCoefficient: 0.001,
- linearCoefficient: 0.5,
- constantTerm: 50,
- minSuccessProbability: 0,
- maxSuccessProbability: 0,
- minTicks: 5,
- maxTicks: 10
- );
-
- mission.SetParent(testPlanet);
-
- mission.Perform(game);
-
- // @TODO: Implement logic for mission being foiled.
- }
-}
+// // Force mission to succeed by setting success probability to 100%
+// mission = new MockMission(
+// name: "Test Mission",
+// ownerTypeID: "FNEMP1",
+// mainParticipants: new List { successfulOfficer },
+// decoyParticipants: new List(),
+// participantSkill: MissionParticipantSkill.Espionage,
+// quadraticCoefficient: 0.001,
+// linearCoefficient: 0.5,
+// constantTerm: 5.0,
+// minSuccessProbability: 100, // Guaranteed success
+// maxSuccessProbability: 100,
+// minTicks: 5,
+// maxTicks: 10
+// );
+
+// mission.SetParent(testPlanet); // Set parent to avoid null references
+
+// mission.Perform(game);
+
+// Assert.IsTrue(mission.WasSuccessful, "The mission should have succeeded due to forced 100% success probability.");
+// }
+
+// [Test]
+// public void TestMissionFailure()
+// {
+// testPlanet = new Planet
+// {
+// DisplayName = "TestPlanet",
+// OwnerTypeID = "FNALL1",
+// Regiments = new List {
+// new Regiment { DefenseRating = -1000 },
+// }
+// };
+// // Force mission to fail by setting success probability to 0%
+// mission = new MockMission(
+// name: "Test Mission",
+// ownerTypeID: "FNEMP1",
+// mainParticipants: new List { successfulOfficer },
+// decoyParticipants: new List { },
+// participantSkill: MissionParticipantSkill.Espionage,
+// quadraticCoefficient: 0.001,
+// linearCoefficient: 0.5,
+// constantTerm: 5.0,
+// minSuccessProbability: 0, // Guaranteed failure
+// maxSuccessProbability: 0,
+// minTicks: 5,
+// maxTicks: 10
+// );
+
+// mission.SetParent(testPlanet);
+
+// mission.Perform(game);
+
+// Assert.IsFalse(mission.WasSuccessful, "The mission should have failed due to forced 0% success probability.");
+// }
+
+// [Test]
+// public void TestDecoySuccess()
+// {
+// // Force decoy success by setting decoy success probability to 100%
+// mission = new MockMission(
+// name: "Decoy Test Mission",
+// ownerTypeID: "FNEMP1",
+// mainParticipants: new List { failedOfficer },
+// decoyParticipants: new List { successfulOfficer },
+// participantSkill: MissionParticipantSkill.Espionage,
+// quadraticCoefficient: 0.001,
+// linearCoefficient: 0.5,
+// constantTerm: 50,
+// minSuccessProbability: 0, // Guaranteed decoy success
+// maxSuccessProbability: 0,
+// minTicks: 5,
+// maxTicks: 10
+// );
+
+// mission.SetParent(testPlanet);
+
+// mission.Perform(game);
+
+// // Assuming decoy success logic will be implemented in the future
+// Assert.Pass("Decoy success logic should be implemented.");
+// }
+
+// [Test]
+// public void TestMissionFoiled()
+// {
+// // Force mission to be foiled by setting high defense score
+// testPlanet.Regiments = new List { new Regiment { DefenseRating = 1000 } };
+
+// mission = new MockMission(
+// name: "Test Mission",
+// ownerTypeID: "FNEMP1",
+// mainParticipants: new List