Skip to content

Commit 3997bee

Browse files
authored
Merge pull request #128 from reubene/master
Save improvements
2 parents bd955ac + 031f866 commit 3997bee

23 files changed

+608
-123
lines changed

Civ2/Dialogs/FileDialogs/LoadMap.cs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
using Civ2.Dialogs.NewGame;
2+
using Civ2.Dialogs.NewGame.PremadeWorld;
3+
using Civ2.Rules;
14
using Civ2engine;
5+
using Civ2engine.IO;
26
using Model;
37
using Model.InterfaceActions;
48

@@ -18,8 +22,46 @@ public override ICivDialogHandler UpdatePopupData(Dictionary<string, PopupBox?>
1822
return this;
1923
}
2024

21-
protected override IInterfaceAction HandleFileSelection(string fileName, Dictionary<string, ICivDialogHandler> civDialogHandlers, Civ2Interface active)
25+
protected override IInterfaceAction HandleFileSelection(string fileName, Dictionary<string, ICivDialogHandler> civDialogHandlers, Civ2Interface civ2Interface)
2226
{
23-
throw new NotImplementedException();
27+
28+
var mapDirectory = Path.GetDirectoryName(fileName);
29+
var root = Settings.SearchPaths.FirstOrDefault(p => mapDirectory.StartsWith(p)) ?? Settings.SearchPaths[0];
30+
31+
civ2Interface.MainApp.SetActiveRulesetFromFile(root, mapDirectory, new Dictionary<string, string>());
32+
33+
var config = Initialization.ConfigObject;
34+
try
35+
{
36+
var mapData = MapReader.Read(fileName);
37+
config.ResourceSeed = mapData.ResourceSeed;
38+
config.FlatWorld = mapData.FlatWorld;
39+
config.WorldSize = [mapData.Width /2, mapData.Height];
40+
config.TerrainData = mapData.TerrainData;
41+
if (mapData.StartPositions is { Length: > 0 } && mapData.StartPositions.Any(p=> p.First != -1 && p.Second != -1))
42+
{
43+
config.StartPositions = mapData.StartPositions.Select(p => new int[] { p.First, p.Second }).ToArray();
44+
}
45+
46+
config.ResourceSeed = mapData.ResourceSeed % 64;
47+
}
48+
catch
49+
{
50+
return civDialogHandlers[Failed.Title].Show(civ2Interface);
51+
}
52+
53+
Initialization.LoadGraphicsAssets(civ2Interface);
54+
55+
if (config.ResourceSeed > 0)
56+
{
57+
return civDialogHandlers[RandomiseResourceSeed.Title].Show(civ2Interface);
58+
}
59+
60+
if (config.StartPositions is { Length: > 0 })
61+
{
62+
return civDialogHandlers[StartLoc.StartLocKey].Show(civ2Interface);
63+
}
64+
65+
return civDialogHandlers[DifficultyHandler.Title].Show(civ2Interface);
2466
}
2567
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Civ2engine;
2+
using Model.Dialog;
3+
4+
namespace Civ2.Dialogs.NewGame.PremadeWorld;
5+
6+
public class Failed : SimpleSettingsDialog
7+
{
8+
public const string Title = "FAILEDTOLOAD";
9+
10+
public Failed() : base(Title){}
11+
protected override string SetConfigValue(DialogResult result, PopupBox? popupBox)
12+
{
13+
return MainMenu.Title;
14+
}
15+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Civ2.Rules;
2+
using Civ2engine;
3+
using Model.Dialog;
4+
5+
namespace Civ2.Dialogs.NewGame.PremadeWorld;
6+
7+
public class RandomiseResourceSeed : SimpleSettingsDialog
8+
{
9+
public const string Title = "USESEED";
10+
public RandomiseResourceSeed() : base(Title)
11+
{
12+
}
13+
14+
protected override string SetConfigValue(DialogResult result, PopupBox? popupBox)
15+
{
16+
if (result.SelectedIndex == 0)
17+
{
18+
Initialization.ConfigObject.ResourceSeed = 0;
19+
}
20+
21+
return Initialization.ConfigObject.StartPositions is { Length: > 0 }
22+
? StartLoc.StartLocKey
23+
: DifficultyHandler.Title;
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Civ2.Rules;
2+
using Civ2engine;
3+
using Model.Dialog;
4+
5+
namespace Civ2.Dialogs.NewGame.PremadeWorld;
6+
7+
public class StartLoc : SimpleSettingsDialog
8+
{
9+
public const string StartLocKey = "USESTARTLOC";
10+
11+
public StartLoc() : base(StartLocKey)
12+
{
13+
}
14+
15+
protected override string SetConfigValue(DialogResult result, PopupBox? popupBox)
16+
{
17+
if (result.SelectedIndex == 0)
18+
{
19+
Initialization.ConfigObject.StartPositions = [];
20+
}
21+
22+
return DifficultyHandler.Title;
23+
}
24+
}

Engine/src/AdvanceFunctions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ private static void ApplyCivAdvance(Game game, int advanceIndex, Civilization ci
149149
.Select(loc =>
150150
{
151151
loc.tile.AddImprovement(improvement, loc.terrain, level,
152-
game.Rules.Terrains[loc.tile.Z]);
152+
game.Rules.Terrains[loc.tile.Z], loc.tile.GetCivsVisibleTo(game));
153153
return loc.tile;
154154
}).ToList();
155155
game.TriggerMapEvent(MapEventType.UpdateMap, improvement.HasMultiTile ? locations.Concat(locations.SelectMany(l=> l.Neighbours())).ToList() : locations );

Engine/src/GameExtensions.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@ public static void SetImprovementsForCities(this IGame game,Civilization civiliz
4141
{
4242
tile.Improvements.Clear();
4343
tile.EffectsList.Clear();
44+
var visibleTo = tile.PlayerKnowledge.Select(((playerTile, civId) => new { playerTile, civId } ))
45+
.Where(arg => arg != null).Select(arg => arg.civId).ToList();
4446
foreach (var can in improvements)
4547
{
4648
var terrain = can.improvement.AllowedTerrains[tile.Z]
4749
.FirstOrDefault(t => t.TerrainType == (int)tile.Type);
4850
if (terrain is not null)
4951
{
50-
tile.AddImprovement(can.improvement, terrain, can.level, game.Rules.Terrains[tile.Z]);
52+
tile.AddImprovement(can.improvement, terrain, can.level, game.Rules.Terrains[tile.Z], visibleTo);
5153
}
5254
}
5355
}
@@ -112,13 +114,14 @@ public static List<Unit> CheckConstruction(this IGame game, Tile tile, TerrainIm
112114
return new List<Unit>();
113115
}
114116

117+
var visibleTo = tile.GetCivsVisibleTo(game);
115118
if (improvement.Negative)
116119
{
117-
tile.RemoveImprovement(improvement, levelToBuild);
120+
tile.RemoveImprovement(improvement, levelToBuild, visibleTo);
118121
}
119122
else
120123
{
121-
tile.AddImprovement(improvement, terrain, levelToBuild, game.Rules.Terrains[tile.Z]);
124+
tile.AddImprovement(improvement, terrain, levelToBuild, game.Rules.Terrains[tile.Z], visibleTo);
122125
}
123126

124127
units.ForEach(u =>

Engine/src/IO/MapReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace Civ2engine.IO
66
{
77
public static class MapReader
88
{
9-
public static MapData Read(Ruleset ruleset, string mapFileName)
9+
public static MapData Read(string mapPath)
1010
{
1111
var data = new MapData();
1212
using var reader =
13-
new BinaryReader(File.Open(ruleset.FolderPath + Path.DirectorySeparatorChar + mapFileName,
13+
new BinaryReader(File.Open(mapPath,
1414
FileMode.Open));
1515

1616
data.Width = reader.ReadInt16(); //bytes[0x00000000]; // Width x 2 (e.g. 100 for a 50 x 80 map)

Engine/src/MapGeneration/MapGenerator.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ public static Task<Map[]> GenerateMap(GameInitializationConfig config)
4343
{
4444
var terra = config.TerrainData[index++];
4545
var tile = new Tile(2 * x + odd, y, terrains[0][terra & 0xF], mainMap.ResourceSeed, mainMap, x,
46-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
47-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
48-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
49-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
50-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
5146
new bool[config.NumberOfCivs + 1])
5247
{
5348
River = terra > 100
@@ -124,11 +119,6 @@ private static Map GenerateMap(GameInitializationConfig config, int width, int h
124119
for (int x = 0; x < mainMap.Tile.GetLength(0); x++)
125120
{
126121
var tile = new Tile(2 * x + odd, y, defaultTerrain, mainMap.ResourceSeed, mainMap, x,
127-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
128-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
129-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
130-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
131-
new bool[config.NumberOfCivs + 1], new bool[config.NumberOfCivs + 1],
132122
new bool[config.NumberOfCivs + 1])
133123
{
134124
Island = -1

Engine/src/MapObjects/MapNavigationFunctions.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,33 @@ public static IEnumerable<Tile> Neighbours(this Map map, Tile candidate, bool tw
9898
return TilesAround(map, candidate, offsets, nullForInvalid);
9999
}
100100

101+
public static IEnumerable<Tile> SecondRing(this Map map, Tile candidate, bool nullForInvalid = false)
102+
{
103+
104+
var odd = candidate.Odd;
105+
var offsets = new List<int[]>
106+
{
107+
new[] { odd, -3 },
108+
new[] { 1, -2 },
109+
new[] { 1 + odd, -1 },
110+
new[] { 2, 0 },
111+
new[] { 1 + odd, 1 },
112+
new[] { 1, 2 },
113+
new[] { odd, 3 },
114+
new[] { 0, 4 },
115+
new[] { odd - 1, 3 },
116+
new[] { -1, 2 },
117+
new[] { -2 + odd, 1 },
118+
new[] { -2, 0 },
119+
new[] { -2 + odd, -1 },
120+
new[] { -1, -2 },
121+
new[] { odd - 1, -3 },
122+
new[] { 0, -4 },
123+
};
124+
125+
return TilesAround(map, candidate, offsets, nullForInvalid);
126+
}
127+
101128
private static IEnumerable<Tile> TilesAround(Map map, Tile centre, IEnumerable<int[]> offsets,
102129
bool nullForInvalid = false)
103130
{

Engine/src/MapObjects/TileExtensions.cs

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,63 @@ namespace Civ2engine.MapObjects
1111
{
1212
public static class TileExtensions
1313
{
14-
public static void RemoveImprovement(this Tile tile, TerrainImprovement improvement, int levelToRemove)
14+
public static void RemoveImprovement(this Tile tile, TerrainImprovement improvement, int levelToRemove,
15+
List<int> visibleTo)
1516
{
1617
var built = tile.Improvements.FirstOrDefault(i => i.Improvement == improvement.Id);
17-
18+
1819
if (built == null || built.Level < levelToRemove) return;
19-
20+
2021
tile.EffectsList.RemoveAll(i => i.Source == improvement.Id && i.Level >= levelToRemove);
2122
if (levelToRemove == 0)
2223
{
2324
tile.Improvements.Remove(built);
25+
foreach (var civId in visibleTo)
26+
{
27+
tile.PlayerKnowledge?[civId]?.Improvements.RemoveAll(i => i.Improvement == improvement.Id);
28+
}
2429
}
2530
else
2631
{
2732
built.Level = levelToRemove - 1;
33+
foreach (var civId in visibleTo)
34+
{
35+
var existing = tile.PlayerKnowledge?[civId]?.Improvements
36+
.FirstOrDefault(i => i.Improvement == improvement.Id);
37+
if (existing != null)
38+
{
39+
existing.Level = levelToRemove - 1;
40+
}
41+
}
42+
}
43+
}
44+
45+
public static List<int> GetCivsVisibleTo(this Tile tile, IGame game)
46+
{
47+
if (tile.Map.MapRevealed)
48+
{
49+
return game.AllCivilizations.Where(c=>c.Alive).Select(c=>c.Id).ToList();
50+
}
51+
52+
var civs = new List<int>();
53+
if (tile.CityHere != null)
54+
{
55+
civs.Add(tile.CityHere.OwnerId);
2856
}
57+
else
58+
{
59+
civs.AddRange(tile.UnitsHere.Select(u=>u.Owner.Id).Distinct());
60+
}
61+
civs.AddRange(tile.Neighbours().SelectMany(neighbourTile=>neighbourTile.UnitsHere).Where(unit=>!civs.Contains(unit.Owner.Id)).Select(unit => unit.Owner.Id).Distinct());
62+
civs.AddRange(tile.CityRadius().Where(radiusTile=> radiusTile.CityHere != null && !civs.Contains(radiusTile.CityHere.Owner.Id)).Select(radiusTile => radiusTile.CityHere.Owner.Id).Distinct());
63+
civs.AddRange(tile.SecondRing().SelectMany(outerTile => outerTile.UnitsHere.Where(unit=>unit.TwoSpaceVisibility && !civs.Contains(unit.Owner.Id)).Select(u=>u.Owner.Id)).Distinct());
64+
65+
return civs;
2966
}
3067

31-
public static void AddImprovement(this Tile tile, TerrainImprovement improvement, AllowedTerrain terrain, int levelToBuild,
32-
Terrain[] terrains)
68+
public static void AddImprovement(this Tile tile, TerrainImprovement improvement, AllowedTerrain terrain,
69+
int levelToBuild,
70+
Terrain[] terrains, IList<int> civsVisibleTo)
3371
{
3472
var improvements = tile.Improvements;
3573
if (improvement.ExclusiveGroup > 0)
@@ -42,6 +80,14 @@ public static void AddImprovement(this Tile tile, TerrainImprovement improvement
4280
tile.EffectsList.RemoveAll(e => e.Source == i.Improvement);
4381
improvements.Remove(i);
4482
});
83+
foreach (var civId in civsVisibleTo)
84+
{
85+
var seenImprovement = tile.PlayerKnowledge![civId]!.Improvements;
86+
foreach (var imp in previous)
87+
{
88+
seenImprovement.Remove(imp);
89+
}
90+
}
4591
}
4692

4793
var transformEffect = terrain.Effects?.FirstOrDefault(e => e.Target == ImprovementConstants.Transform);
@@ -63,6 +109,21 @@ public static void AddImprovement(this Tile tile, TerrainImprovement improvement
63109
improvements.Add(new ConstructedImprovement
64110
{ Group = improvement.ExclusiveGroup, Improvement = improvement.Id, Level = levelToBuild });
65111
}
112+
113+
foreach (var civId in civsVisibleTo)
114+
{
115+
var seenImprovement = tile.PlayerKnowledge![civId]!.Improvements;
116+
var ex = seenImprovement.FirstOrDefault(i => i.Improvement == improvement.Id);
117+
if (ex is not null)
118+
{
119+
ex.Level = levelToBuild;
120+
}
121+
else
122+
{
123+
seenImprovement.Add(new ConstructedImprovement
124+
{ Group = improvement.ExclusiveGroup, Improvement = improvement.Id, Level = levelToBuild });
125+
}
126+
}
66127
}
67128

68129
public static void BuildEffects(this Tile tile, TerrainImprovement improvement, AllowedTerrain terrain, int levelToBuild)
@@ -85,6 +146,11 @@ public static IEnumerable<Tile> CityRadius(this Tile tile, bool nullForInvalid =
85146
return tile.Map.CityRadius(tile, nullForInvalid);
86147
}
87148

149+
public static IEnumerable<Tile> SecondRing(this Tile tile, bool nullForInvalid = false)
150+
{
151+
return tile.Map.SecondRing(tile, nullForInvalid);
152+
}
153+
88154
public static IEnumerable<Tile> Neighbours(this Tile tile)
89155
{
90156
return tile.Map.Neighbours(tile);
@@ -115,7 +181,25 @@ public static void UpdatePlayer(this Tile tile,int civilizationId)
115181
public static void UpdateAllPlayers(this Tile tile)
116182
{
117183
var visibility = tile.Visibility;
118-
var playerKnowledge = new PlayerTile[visibility.Length];
184+
185+
PlayerTile?[] playerKnowledge;
186+
if (tile.PlayerKnowledge is not null)
187+
{
188+
if (tile.PlayerKnowledge.Length < visibility.Length)
189+
{
190+
playerKnowledge = new PlayerTile?[visibility.Length];
191+
Array.Copy(tile.PlayerKnowledge, playerKnowledge, tile.PlayerKnowledge.Length);
192+
}
193+
else
194+
{
195+
playerKnowledge = tile.PlayerKnowledge;
196+
}
197+
}
198+
else
199+
{
200+
playerKnowledge = new PlayerTile?[visibility.Length];
201+
}
202+
119203
for (var i = 0; i < visibility.Length; i++)
120204
{
121205
if(tile.Map.IsCurrentlyVisible(tile, i))

0 commit comments

Comments
 (0)