11using System . Collections . Generic ;
22using System . IO ;
3+ using System . Reflection ;
34using System . Reflection . Emit ;
45using HarmonyLib ;
56using ProjectGenesis . Utils ;
@@ -17,6 +18,9 @@ public static class AdvancedLaserPatches
1718
1819 private static RenderableObjectDesc _combatTurretAdvancedLaserContinuousDesc ;
1920
21+ private static readonly FieldInfo TurretComponent_projectileId_Field =
22+ AccessTools . Field ( typeof ( TurretComponent ) , nameof ( TurretComponent . projectileId ) ) ;
23+
2024 [ HarmonyPatch ( typeof ( SkillSystem ) , nameof ( SkillSystem . Init ) ) ]
2125 [ HarmonyPostfix ]
2226 public static void SkillSystem_Init ( )
@@ -53,13 +57,17 @@ public static IEnumerable<CodeInstruction> TurretComponent_StopContinuousSkill_T
5357 {
5458 var matcher = new CodeMatcher ( instructions , generator ) ;
5559
56- matcher . MatchForward ( false , new CodeMatch ( OpCodes . Ldarg_1 ) ,
57- new CodeMatch ( OpCodes . Ldfld , AccessTools . Field ( typeof ( SkillSystem ) , nameof ( SkillSystem . turretLaserContinuous ) ) ) ,
58- new CodeMatch ( OpCodes . Stloc_0 ) ) ;
60+ // change condition from projectileId>0 to projectileId!=0
61+ matcher . MatchForward ( true , new CodeMatch ( OpCodes . Ldarg_0 ) , new CodeMatch ( OpCodes . Ldfld , TurretComponent_projectileId_Field ) ,
62+ new CodeMatch ( OpCodes . Ldc_I4_0 ) ) ;
63+ matcher . Advance ( 1 ) . SetOpcodeAndAdvance ( OpCodes . Beq_S ) ;
64+
65+ matcher . MatchForward ( true , new CodeMatch ( OpCodes . Ldarg_1 ) ,
66+ new CodeMatch ( OpCodes . Ldfld , AccessTools . Field ( typeof ( SkillSystem ) , nameof ( SkillSystem . turretLaserContinuous ) ) ) ) ;
5967
60- matcher . Advance ( 1 ) . SetAndAdvance ( OpCodes . Ldarg_0 , null ) ;
61- matcher . InsertAndAdvance ( new CodeInstruction ( OpCodes . Call ,
62- AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( TurretComponent_StopContinuousSkill_Patch ) ) ) ) ;
68+ matcher . Advance ( 1 ) . InsertAndAdvance ( new CodeInstruction ( OpCodes . Ldarg_0 ) ,
69+ new CodeInstruction ( OpCodes . Call ,
70+ AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( StopContinuousSkill_Patch_Method ) ) ) ) ;
6371
6472 return matcher . InstructionEnumeration ( ) ;
6573 }
@@ -71,31 +79,97 @@ public static IEnumerable<CodeInstruction> TurretComponent_Shoot_Laser_Transpile
7179 {
7280 var matcher = new CodeMatcher ( instructions , generator ) ;
7381
74- matcher . MatchForward ( false , new CodeMatch ( OpCodes . Ldarg_1 ) ,
82+ // this part does:
83+ // turretLaserContinuous = IsAdvancedLaser ? _turretAdvancedLaserContinuous : SkillSystem.turretLaserContinuous;
84+ /*
85+ ldarg.1 // factory
86+ Ldarg_0
87+ Call IsAdvancedLaser
88+ Brtrue label2
89+ ldarg.1 // factory
90+ ldfld class SkillSystem PlanetFactory.killSystem
91+ stloc.s skillSystem
92+ ldloc.s skillSystem
93+ ldfld class DataPoolRenderer`1<valuetype LocalLaserContinuous> SkillSystem.turretLaserContinuous
94+ br label1
95+ Call Patch_Result_Method [label2]
96+ stloc.s turretLaserContinuous [label1]
97+ */
98+ matcher . MatchForward ( true , new CodeMatch ( OpCodes . Ldarg_1 ) ,
7599 new CodeMatch ( OpCodes . Ldfld , AccessTools . Field ( typeof ( PlanetFactory ) , nameof ( PlanetFactory . skillSystem ) ) ) ,
76- new CodeMatch ( OpCodes . Stloc_S ) , new CodeMatch ( OpCodes . Ldloc_S ) , new CodeMatch ( OpCodes . Ldfld ) ,
77- new CodeMatch ( OpCodes . Stloc_S ) ) ;
100+ new CodeMatch ( OpCodes . Stloc_S ) , new CodeMatch ( OpCodes . Ldloc_S ) , new CodeMatch ( OpCodes . Ldfld ) ) ;
101+
102+ matcher . Advance ( 1 ) . CreateLabel ( out Label label1 ) ;
103+
104+ matcher . InsertAndAdvance ( new CodeInstruction ( OpCodes . Br , label1 ) ) ;
105+ matcher . Insert ( new CodeInstruction ( OpCodes . Call ,
106+ AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( GetAdvancedLaserContinuous ) ) ) ) ;
107+ matcher . CreateLabel ( out Label label2 ) ;
108+
109+ matcher . Advance ( - 5 ) . InsertAndAdvance ( new CodeInstruction ( OpCodes . Ldarg_0 ) ,
110+ new CodeInstruction ( OpCodes . Call , AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( IsAdvancedLaser ) ) ) ,
111+ new CodeInstruction ( OpCodes . Brtrue , label2 ) , new CodeInstruction ( OpCodes . Ldarg_1 ) ) ;
112+
113+ // change condition from projectileId>0 to projectileId!=0
114+ matcher . MatchForward ( false , new CodeMatch ( OpCodes . Ldarg_0 ) , new CodeMatch ( OpCodes . Ldfld , TurretComponent_projectileId_Field ) ,
115+ new CodeMatch ( OpCodes . Brtrue ) , new CodeMatch ( OpCodes . Ldloc_S ) ) ;
116+
117+ matcher . Advance ( 2 ) . InsertAndAdvance ( new CodeInstruction ( OpCodes . Ldarg_1 ) , new CodeInstruction ( OpCodes . Ldarg_0 ) ,
118+ new CodeInstruction ( OpCodes . Call , AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( DecideProjectileId ) ) ) ) ;
78119
79- matcher . Advance ( 3 ) . SetAndAdvance ( OpCodes . Ldarg_1 , null ) . SetAndAdvance ( OpCodes . Ldarg_0 , null ) ;
80- matcher . InsertAndAdvance ( new CodeInstruction ( OpCodes . Call ,
81- AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( GetLaserContinuous ) ) ) ) ;
120+ // patch when shot if TurretComponent is advanced then set TurretComponent.ProjectileId = -TurretComponent.ProjectileId
121+ matcher . MatchForward ( true , new CodeMatch ( OpCodes . Ldarg_0 ) , new CodeMatch ( OpCodes . Ldfld , TurretComponent_projectileId_Field ) ,
122+ new CodeMatch ( OpCodes . Ldelema ) , new CodeMatch ( OpCodes . Dup ) ) ;
123+
124+ matcher . Advance ( 1 ) . InsertAndAdvance ( new CodeInstruction ( OpCodes . Ldarg_1 ) , new CodeInstruction ( OpCodes . Ldarg_0 ) ,
125+ new CodeInstruction ( OpCodes . Call , AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( RewriteProjectileIdIfAdvanced ) ) ) ) ;
126+
127+ // patch when get TurretComponent.ProjectileId back to -TurretComponent.ProjectileId if advanced
128+
129+ matcher . MatchForward ( false , new CodeMatch ( OpCodes . Ldarg_0 ) , new CodeMatch ( OpCodes . Ldfld , TurretComponent_projectileId_Field ) ,
130+ new CodeMatch ( OpCodes . Ldelema ) , new CodeMatch ( OpCodes . Dup ) ) ;
131+
132+ matcher . Advance ( 2 ) . InsertAndAdvance ( new CodeInstruction ( OpCodes . Ldarg_1 ) , new CodeInstruction ( OpCodes . Ldarg_0 ) ,
133+ new CodeInstruction ( OpCodes . Call , AccessTools . Method ( typeof ( AdvancedLaserPatches ) , nameof ( DecideProjectileId ) ) ) ) ;
82134
83135 return matcher . InstructionEnumeration ( ) ;
84136 }
85137
86- private static bool CheckAdvancedLaser ( PlanetFactory factory , ref TurretComponent component ) =>
138+ [ HarmonyPatch ( typeof ( TurretComponent ) , nameof ( TurretComponent . InternalUpdate ) ) ]
139+ [ HarmonyTranspiler ]
140+ public static IEnumerable < CodeInstruction > InternalUpdate_Transpiler ( IEnumerable < CodeInstruction > instructions )
141+ {
142+ var matcher = new CodeMatcher ( instructions ) ;
143+
144+ matcher . MatchForward ( true , new CodeMatch ( OpCodes . Ldarg_0 ) , new CodeMatch ( OpCodes . Ldfld , TurretComponent_projectileId_Field ) ,
145+ new CodeMatch ( OpCodes . Ldc_I4_0 ) ) ;
146+ matcher . Advance ( 1 ) . SetOpcodeAndAdvance ( OpCodes . Beq_S ) ;
147+
148+ return matcher . InstructionEnumeration ( ) ;
149+ }
150+
151+ private static bool IsAdvancedLaser ( PlanetFactory factory , ref TurretComponent component ) =>
87152 factory . entityPool [ component . entityId ] . modelIndex == ProtoID . M高频激光塔MK2 ;
88153
89- public static DataPoolRenderer < LocalLaserContinuous > GetLaserContinuous ( PlanetFactory factory , ref TurretComponent component ) =>
90- CheckAdvancedLaser ( factory , ref component ) ? _turretAdvancedLaserContinuous : factory . skillSystem . turretLaserContinuous ;
154+ public static int DecideProjectileId ( int index , PlanetFactory factory , ref TurretComponent component ) =>
155+ IsAdvancedLaser ( factory , ref component ) ? - index : index ;
156+
157+ public static void RewriteProjectileIdIfAdvanced ( PlanetFactory factory , ref TurretComponent component )
158+ {
159+ if ( IsAdvancedLaser ( factory , ref component ) ) component . projectileId = - component . projectileId ;
160+ }
91161
92- public static DataPoolRenderer < LocalLaserContinuous > TurretComponent_StopContinuousSkill_Patch ( SkillSystem skillSystem ,
162+ public static DataPoolRenderer < LocalLaserContinuous > StopContinuousSkill_Patch_Method ( DataPoolRenderer < LocalLaserContinuous > ori ,
93163 ref TurretComponent component )
94164 {
95- PlanetFactory factory = skillSystem . astroFactories [ component . target . astroId ] ;
96- return GetLaserContinuous ( factory , ref component ) ;
165+ if ( component . projectileId > 0 ) return ori ;
166+
167+ component . projectileId = - component . projectileId ;
168+ return _turretAdvancedLaserContinuous ;
97169 }
98170
171+ public static DataPoolRenderer < LocalLaserContinuous > GetAdvancedLaserContinuous ( ) => _turretAdvancedLaserContinuous ;
172+
99173 [ HarmonyPatch ( typeof ( SkillSystem ) , nameof ( SkillSystem . GameTick ) ) ]
100174 [ HarmonyPostfix ]
101175 public static void SkillSystem_GameTick ( SkillSystem __instance )
@@ -109,8 +183,7 @@ public static void SkillSystem_GameTick(SkillSystem __instance)
109183 if ( buffer [ id ] . id != id ) continue ;
110184
111185 buffer [ id ] . TickSkillLogic ( __instance , factories ) ;
112-
113- if ( buffer [ id ] . fade == 0.0 ) _turretAdvancedLaserContinuous . Remove ( id ) ;
186+ if ( buffer [ id ] . fade == 0.0f ) _turretAdvancedLaserContinuous . Remove ( id ) ;
114187 }
115188
116189 if ( _turretAdvancedLaserContinuous . count != 0 || _turretAdvancedLaserContinuous . capacity <= 256 ) return ;
@@ -131,9 +204,7 @@ public static void SkillSystem_RendererDraw(SkillSystem __instance)
131204 [ HarmonyPostfix ]
132205 public static void SkillSystem_Free ( )
133206 {
134- if ( _turretAdvancedLaserContinuous == null ) return ;
135-
136- _turretAdvancedLaserContinuous . FreeRenderer ( ) ;
207+ _turretAdvancedLaserContinuous ? . FreeRenderer ( ) ;
137208 }
138209
139210 [ HarmonyPatch ( typeof ( SkillSystem ) , nameof ( SkillSystem . SetForNewGame ) ) ]
0 commit comments