@@ -16,7 +16,13 @@ public static class Main
1616 internal static readonly Stopwatch stopwatch = new ( ) ;
1717 internal static bool fullyInitialized ;
1818 internal static bool dependencyCycle ;
19-
19+ internal static Dictionary < string , string > embarkNames = new ( ) ;
20+ internal static Dictionary < UnitData . Type , UnitData . Type > embarkOverrides = new ( ) ;
21+ internal static bool currentlyEmbarking = false ;
22+ internal static Dictionary < string , string > attractsResourceNames = new ( ) ;
23+ internal static Dictionary < string , string > attractsTerrainNames = new ( ) ;
24+ internal static Dictionary < ImprovementData . Type , ResourceData . Type > attractsResourceOverrides = new ( ) ;
25+ internal static Dictionary < ImprovementData . Type , Polytopia . Data . TerrainData . Type > attractsTerrainOverrides = new ( ) ;
2026
2127 [ HarmonyPrefix ]
2228 [ HarmonyPatch ( typeof ( GameLogicData ) , nameof ( GameLogicData . AddGameLogicPlaceholders ) ) ]
@@ -30,6 +36,48 @@ private static void GameLogicData_Parse(GameLogicData __instance, JObject rootOb
3036 if ( skin . skinData != null )
3137 __instance . skinData [ ( SkinType ) skin . idx ] = skin . skinData ;
3238 }
39+ foreach ( KeyValuePair < string , string > entry in embarkNames )
40+ {
41+ try
42+ {
43+ UnitData . Type unit = EnumCache < UnitData . Type > . GetType ( entry . Key ) ;
44+ UnitData . Type newUnit = EnumCache < UnitData . Type > . GetType ( entry . Value ) ;
45+ embarkOverrides [ unit ] = newUnit ;
46+ Plugin . logger . LogInfo ( $ "Embark unit type for { entry . Key } is now { entry . Value } ") ;
47+ }
48+ catch
49+ {
50+ Plugin . logger . LogError ( $ "Embark unit type for { entry . Key } is not valid: { entry . Value } ") ;
51+ }
52+ }
53+ foreach ( KeyValuePair < string , string > entry in attractsResourceNames )
54+ {
55+ try
56+ {
57+ ImprovementData . Type improvement = EnumCache < ImprovementData . Type > . GetType ( entry . Key ) ;
58+ ResourceData . Type resource = EnumCache < ResourceData . Type > . GetType ( entry . Value ) ;
59+ attractsResourceOverrides [ improvement ] = resource ;
60+ Plugin . logger . LogInfo ( $ "Improvement { entry . Key } now attracts { entry . Value } ") ;
61+ }
62+ catch
63+ {
64+ Plugin . logger . LogError ( $ "Improvement { entry . Key } resource type is not valid: { entry . Value } ") ;
65+ }
66+ }
67+ foreach ( KeyValuePair < string , string > entry in attractsTerrainNames )
68+ {
69+ try
70+ {
71+ ImprovementData . Type improvement = EnumCache < ImprovementData . Type > . GetType ( entry . Key ) ;
72+ Polytopia . Data . TerrainData . Type terrain = EnumCache < Polytopia . Data . TerrainData . Type > . GetType ( entry . Value ) ;
73+ attractsTerrainOverrides [ improvement ] = terrain ;
74+ Plugin . logger . LogInfo ( $ "Improvement { entry . Key } now attracts on { entry . Value } ") ;
75+ }
76+ catch
77+ {
78+ Plugin . logger . LogError ( $ "Improvement { entry . Key } terrain type is not valid: { entry . Value } ") ;
79+ }
80+ }
3381 fullyInitialized = true ;
3482 }
3583 }
@@ -160,6 +208,83 @@ public static bool TechView_CreateNode(TechView __instance, TechData data, TechI
160208 return false ;
161209 }
162210
211+ [ HarmonyPrefix ]
212+ [ HarmonyPatch ( typeof ( EmbarkAction ) , nameof ( EmbarkAction . Execute ) ) ]
213+ private static bool EmbarkAction_Execute_Prefix ( EmbarkAction __instance , GameState gameState )
214+ {
215+ currentlyEmbarking = true ;
216+ return true ;
217+ }
218+
219+ [ HarmonyPrefix ]
220+ [ HarmonyPatch ( typeof ( ActionUtils ) , nameof ( ActionUtils . TrainUnit ) ) ]
221+ private static bool ActionUtils_TrainUnit ( ref UnitState __result , GameState gameState , PlayerState playerState , TileData tile , ref UnitData unitData )
222+ {
223+ if ( tile == null )
224+ {
225+ return true ;
226+ }
227+ if ( tile . unit == null )
228+ {
229+ return true ;
230+ }
231+ if ( currentlyEmbarking )
232+ {
233+ if ( embarkOverrides . TryGetValue ( tile . unit . type , out UnitData . Type newType ) )
234+ {
235+ gameState . GameLogicData . TryGetData ( newType , out unitData ) ;
236+ }
237+ currentlyEmbarking = false ;
238+ }
239+ return true ;
240+ }
241+
242+ [ HarmonyPostfix ]
243+ [ HarmonyPatch ( typeof ( StartTurnAction ) , nameof ( StartTurnAction . Execute ) ) ]
244+ private static void StartTurnAction_Execute ( StartTurnAction __instance , GameState state )
245+ {
246+ for ( int i = state . ActionStack . Count - 1 ; i >= 0 ; i -- )
247+ {
248+ if ( state . ActionStack [ i ] . GetActionType ( ) == ActionType . CreateResource )
249+ {
250+ state . ActionStack . RemoveAt ( i ) ;
251+ }
252+ }
253+ for ( int i = 0 ; i < state . Map . Tiles . Length ; i ++ )
254+ {
255+ TileData tileData = state . Map . Tiles [ i ] ;
256+ if ( tileData . owner == __instance . PlayerId && tileData . improvement != null && state . CurrentTurn > 0U )
257+ {
258+ ImprovementData improvementData ;
259+ state . GameLogicData . TryGetData ( tileData . improvement . type , out improvementData ) ;
260+ if ( improvementData != null )
261+ {
262+ if ( improvementData . HasAbility ( ImprovementAbility . Type . Attract ) && tileData . improvement . GetAge ( state ) % improvementData . growthRate == 0 )
263+ {
264+ ResourceData . Type resourceType = ResourceData . Type . Game ;
265+ if ( attractsResourceOverrides . TryGetValue ( tileData . improvement . type , out ResourceData . Type newType ) )
266+ {
267+ resourceType = newType ;
268+ }
269+ Polytopia . Data . TerrainData . Type targetTerrain = Polytopia . Data . TerrainData . Type . Forest ;
270+ if ( attractsTerrainOverrides . TryGetValue ( tileData . improvement . type , out Polytopia . Data . TerrainData . Type newTerrain ) )
271+ {
272+ targetTerrain = newTerrain ;
273+ }
274+ foreach ( TileData tileData2 in state . Map . GetArea ( tileData . coordinates , 1 , true , false ) )
275+ {
276+ if ( tileData2 . owner == __instance . PlayerId && tileData2 . improvement == null && tileData2 . resource == null && tileData2 . terrain == targetTerrain )
277+ {
278+ state . ActionStack . Add ( new CreateResourceAction ( __instance . PlayerId , resourceType , tileData2 . coordinates , CreateResourceAction . CreateReason . Attract ) ) ;
279+ break ;
280+ }
281+ }
282+ }
283+ }
284+ }
285+ }
286+ }
287+
163288 internal static void Init ( )
164289 {
165290 stopwatch . Start ( ) ;
0 commit comments