forked from RimWorldMod/Tech-Advancing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Main.cs
254 lines (222 loc) · 11.9 KB
/
Main.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TechAdvancing;
using UnityEngine;
using Verse;
using RimWorld;
using System.Reflection;
using System.IO;
namespace TechAdvancing
{
[StaticConstructorOnStartup]
public class Injector_GHXXTechAdvancing
{
static Injector_GHXXTechAdvancing() //Detour the method that gets run when a research gets finished. Old school detour. Could be replaced with harmony
{
MethodInfo source = typeof(ResearchManager).GetMethod("ReapplyAllMods", BindingFlags.Instance | BindingFlags.Public);
MethodInfo destination = typeof(_ResearchManager).GetMethod("_ReapplyAllMods", BindingFlags.Static | BindingFlags.NonPublic);
//Log.Message("Source method = " + source.Name + "Target = " + destination.Name);
Detour.DoDetour(source, destination);
GameObject initializer = new GameObject("GHXXTAMapComponentInjector");
initializer.AddComponent<MapComponentInjector>();
UnityEngine.Object.DontDestroyOnLoad(initializer);
HarmonyDetours.Setup();
}
}
/// <summary>
/// Class storing the new ReapplyAllMods method to perform the old-school detour with.
/// </summary>
internal static class _ResearchManager // TODO use Harmony for this.
{
public static TechLevel factionDefault = TechLevel.Undefined;
public static bool isTribe = true;
private static bool firstNotificationHidden = false;
private static int[][] researchProjectsArray = new int[][] { new int[2], new int[2], new int[2],
new int[2], new int[2], new int[2], new int[2], new int[2]}; // Techlevel --> Researched | Total
// .. .... . . .. . . . .. .. .
public static DateTime startedAt = DateTime.Now;
public static string facName = "";
public static bool firstpass = true;
internal static void _ReapplyAllMods(this ResearchManager _this) //new ReapplyAllMods Method
{
if (Faction.OfPlayerSilentFail?.def?.techLevel == null || Faction.OfPlayer.def.techLevel == TechLevel.Undefined) // if some mod does something funky again....
return;
if (firstpass || facName != Faction.OfPlayer.def.defName)
{
startedAt = DateTime.Now;
facName = Faction.OfPlayer.def.defName;
try
{
GetAndReloadTL(); //store the default value for the techlevel because we will modify it later and we need the one from right now
isTribe = factionDefault == TechLevel.Neolithic;
LoadCfgValues();
firstpass = false;
//Debug
LogOutput.WriteLogMessage(Errorlevel.Debug, "Con A val= " + TechAdvancing_Config_Tab.Conditionvalue_A + "|||Con B Val= " + TechAdvancing_Config_Tab.Conditionvalue_B);
}
catch (Exception ex)
{
LogOutput.WriteLogMessage(Errorlevel.Error, "Caught error in Reapply All Mods: " + ex.ToString());
}
}
var researchProjectStoreTotal = new Dictionary<TechLevel, int>();
var researchProjectStoreFinished = new Dictionary<TechLevel, int>();
for (int i = 0; i < Enum.GetValues(typeof(TechLevel)).Length; i++)
{
researchProjectStoreTotal.Add((TechLevel)i, 0);
researchProjectStoreFinished.Add((TechLevel)i, 0);
}
foreach (var researchProjectDef in DefDatabase<ResearchProjectDef>.AllDefs)
{
//skip the research if it contains the disabled-tag:
#region tagDesc
/*
<ResearchProjectDef>
<defName>Firefoam</defName>
<label>firefoam</label>
<description>Allows the construction of firefoam poppers; fire-safety buildings which spread fire-retardant foam in response to encroaching flames.</description>
<baseCost>800</baseCost>
<techLevel>Industrial</techLevel>
<prerequisites>
<li>MicroelectronicsBasics</li>
</prerequisites>
! <tags>
Important ! <li>ta-ignore</li>
! </tags>
<requiredResearchBuilding>HiTechResearchBench</requiredResearchBuilding>
<researchViewX>7</researchViewX>
<researchViewY>4</researchViewY>
</ResearchProjectDef>
*/
#endregion
if (researchProjectDef.tags?.Any(x => x.defName == "ta-ignore") != true)
{
researchProjectStoreTotal[researchProjectDef.techLevel]++; //total projects for techlevel
if (researchProjectDef.IsFinished)
{ // TODO filter out undefined later
researchProjectStoreFinished[researchProjectDef.techLevel]++; //finished projects for techlevel
researchProjectDef.ReapplyAllMods(); // TODO always run it?
}
}
else
{
LogOutput.WriteLogMessage(Errorlevel.Debug, "Found ta-ignore tag in:" + researchProjectDef.defName);
}
}
TechAdvancing.Rules.researchProjectStoreTotal = researchProjectStoreTotal;
TechAdvancing.Rules.researchProjectStoreFinished = researchProjectStoreFinished;
TechLevel newLevel = TechAdvancing.Rules.GetNewTechLevel();
if (newLevel != TechLevel.Undefined)
{
if (firstNotificationHidden && DateTime.Now.Subtract(TimeSpan.FromSeconds(5)) > startedAt) //hiding the notification on world start
{
if (Faction.OfPlayer.def.techLevel < newLevel)
Find.LetterStack.ReceiveLetter("newTechLevelLetterTitle".Translate(), "newTechLevelLetterContents".Translate(isTribe ? "configTribe".Translate() : "configColony".Translate()) + " " + newLevel.ToString() + ".", LetterDefOf.PositiveEvent);
}
else
{
firstNotificationHidden = true;
}
Faction.OfPlayer.def.techLevel = newLevel;
}
/***
how techlevel increases:
player researched all techs of techlevel X and below. the techlevel rises to X+1
player researched more than 50% of the techlevel Y then the techlevel rises to Y
**/
RecalculateTechlevel(false);
}
private static void LoadCfgValues() //could be improved using just vanilla loading // TODO obsolete?
{
Scribe_Deep.Look(ref TechAdvancing_Config_Tab.Conditionvalue_A, "Conditionvalue_A");
Scribe_Deep.Look(ref TechAdvancing_Config_Tab.Conditionvalue_B, "Conditionvalue_B");
Scribe_Deep.Look(ref TechAdvancing_Config_Tab.baseTechlvlCfg, "baseTechlvlCfg");
Scribe_Deep.Look(ref TechAdvancing_Config_Tab.configCheckboxNeedTechColonists, "configCheckboxNeedTechColonists");
if (TechAdvancing_Config_Tab.baseTechlvlCfg != 1)
{
TechAdvancing_Config_Tab.baseFactionTechLevel = (TechAdvancing_Config_Tab.baseTechlvlCfg == 0) ? TechLevel.Neolithic : TechLevel.Industrial;
}
}
internal static TechLevel GetAndReloadTL()
{
if (Faction.OfPlayer.def.techLevel > TechLevel.Undefined && _ResearchManager.factionDefault == TechLevel.Undefined)
{
_ResearchManager.factionDefault = Faction.OfPlayer.def.techLevel;
TechAdvancing_Config_Tab.baseFactionTechLevel = Faction.OfPlayer.def.techLevel;
}
if (Faction.OfPlayer.def.techLevel == TechLevel.Undefined)
{
LogOutput.WriteLogMessage(Errorlevel.Warning, "Called without valid TL");
#if DEBUG
throw new InvalidOperationException("If you see this message please report it immediately. Thanks! (0x1)");
#endif
}
return Faction.OfPlayer.def.techLevel;
}
internal static void RecalculateTechlevel(bool showIncreaseMsg = true)
{
if (Faction.OfPlayerSilentFail?.def?.techLevel == null || Faction.OfPlayer.def.techLevel == TechLevel.Undefined) // if some mod does something funky again....
return;
GetAndReloadTL();
TechLevel baseNewTL = Rules.GetNewTechLevel();
if (TechAdvancing_Config_Tab.configCheckboxNeedTechColonists == 1 && !Util.ColonyHasHiTechPeople())
{
Faction.OfPlayer.def.techLevel = (TechLevel)Util.Clamp((int)TechLevel.Undefined, (int)baseNewTL, (int)TechAdvancing_Config_Tab.maxTechLevelForTribals);
}
else
{
Faction.OfPlayer.def.techLevel = baseNewTL;
}
if (showIncreaseMsg) //used to supress the first update message| Treat as always false
{
Messages.Message("ConfigEditTechlevelChange".Translate() + " " + (TechLevel)Faction.OfPlayer.def.techLevel + ".", MessageTypeDefOf.PositiveEvent);
}
}
}
public static class Event
{
public static void OnKill(Pawn oldPawn) //event for when a pawn dies
{
//namespace prefix is required
if (TechAdvancing.MapCompSaveHandler.ColonyPeople.ContainsKey(oldPawn))
{
TechAdvancing.MapCompSaveHandler.ColonyPeople.Remove(oldPawn);
if (TechAdvancing.MapCompSaveHandler.ColonyPeople.Count == 0 && // that means there was something in there before -> now the techlvl is locked
TechAdvancing_Config_Tab.configCheckboxNeedTechColonists == 1 // and the limit is enabled
)
{
Find.LetterStack.ReceiveLetter("newTechLevelMedievalCapRemLetterTitleRev".Translate(), "newTechLevelMedievalCapRemLetterContentsRev".Translate(), LetterDefOf.NegativeEvent);
}
}
TechAdvancing._ResearchManager.RecalculateTechlevel(false);
}
public static void OnNewPawn(Pawn oldPawn) //event for new pawn in the colony
{
if (((int?)oldPawn?.Faction?.def?.techLevel ?? -1) >= (int)TechLevel.Industrial)
{
if (!TechAdvancing.MapCompSaveHandler.ColonyPeople.ContainsKey(oldPawn))
{
TechAdvancing.MapCompSaveHandler.ColonyPeople.Add(oldPawn, oldPawn.Faction);
if (TechAdvancing.MapCompSaveHandler.ColonyPeople.Count == 1 && // that means there was nothing in there before -> now the techlvl is unlocked
TechAdvancing_Config_Tab.configCheckboxNeedTechColonists == 1 // and the limit is enabled
)
{
Find.LetterStack.ReceiveLetter("newTechLevelMedievalCapRemLetterTitle".Translate(), "newTechLevelMedievalCapRemLetterContents".Translate(_ResearchManager.isTribe ? "configTribe".Translate() : "configColony".Translate()), LetterDefOf.PositiveEvent);
TechAdvancing._ResearchManager.RecalculateTechlevel(false);
}
}
else
{
TechAdvancing.MapCompSaveHandler.ColonyPeople[oldPawn] = oldPawn.Faction;
}
}
}
public static void PostOnNewPawn() //post version of onNewPawn (after the pawn joined)
{
TechAdvancing._ResearchManager.RecalculateTechlevel(false);
}
}
}