Skip to content

Commit 7fabe42

Browse files
authored
Merge pull request KaBooMa#29 from HazDS/haz-pickpocket
Fixes pick pocketing and vehicle cleanup issues
2 parents b20d375 + b1dd18e commit 7fabe42

File tree

4 files changed

+73
-35
lines changed

4 files changed

+73
-35
lines changed

S1API/Entities/NPC.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,32 @@ private void InitializeBehaviourComponents()
22422242
S1NPC.Behaviour.ConsumeProductBehaviour = existing;
22432243
}
22442244

2245+
// UnconsciousBehaviour and DeadBehaviour are required by NPC.IsConscious
2246+
// which is checked during pickpocketing and other interactions
2247+
if (S1NPC.Behaviour.UnconsciousBehaviour == null)
2248+
{
2249+
var existing = S1NPC.Behaviour.GetComponentInChildren<S1Behaviour.UnconsciousBehaviour>(true);
2250+
if (existing == null)
2251+
{
2252+
GameObject go = new GameObject("UnconsciousBehaviour");
2253+
go.transform.SetParent(S1NPC.Behaviour.transform, false);
2254+
existing = go.AddComponent<S1Behaviour.UnconsciousBehaviour>();
2255+
}
2256+
S1NPC.Behaviour.UnconsciousBehaviour = existing;
2257+
}
2258+
2259+
if (S1NPC.Behaviour.DeadBehaviour == null)
2260+
{
2261+
var existing = S1NPC.Behaviour.GetComponentInChildren<S1Behaviour.DeadBehaviour>(true);
2262+
if (existing == null)
2263+
{
2264+
GameObject go = new GameObject("DeadBehaviour");
2265+
go.transform.SetParent(S1NPC.Behaviour.transform, false);
2266+
existing = go.AddComponent<S1Behaviour.DeadBehaviour>();
2267+
}
2268+
S1NPC.Behaviour.DeadBehaviour = existing;
2269+
}
2270+
22452271
TryRegisterBehaviourEventLinks();
22462272
}
22472273

S1API/Entities/NPCInventory.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -223,21 +223,9 @@ public void EnsureInitialized()
223223
{
224224
ReflectionUtils.TrySetFieldOrProperty(inv, "npc", NPC.S1NPC);
225225

226-
if (inv.PickpocketIntObj != null)
227-
{
228-
MethodInfo hoveredMi = typeof(S1NPCs.NPCInventory).GetMethod("Hovered", BindingFlags.Public | BindingFlags.Instance);
229-
MethodInfo interactedMi = typeof(S1NPCs.NPCInventory).GetMethod("Interacted", BindingFlags.Public | BindingFlags.Instance);
230-
if (hoveredMi != null)
231-
{
232-
UnityAction hovered = (UnityAction)Delegate.CreateDelegate(typeof(UnityAction), inv, hoveredMi);
233-
inv.PickpocketIntObj.onHovered?.AddListener(hovered);
234-
}
235-
if (interactedMi != null)
236-
{
237-
UnityAction interacted = (UnityAction)Delegate.CreateDelegate(typeof(UnityAction), inv, interactedMi);
238-
inv.PickpocketIntObj.onInteractStart?.AddListener(interacted);
239-
}
240-
}
226+
// NOTE: Do NOT add listeners here - the game's NPCInventory.Awake() already adds
227+
// onHovered and onInteractStart listeners. Adding them again causes duplicate
228+
// event firing which breaks the pickpocket screen.
241229
}
242230
catch { }
243231

S1API/Internal/Patches/LandVehiclePatches.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ internal class LandVehiclePatches
1515
[HarmonyPatch("OnDestroy")]
1616
[HarmonyPostfix]
1717
public static void OnDestroy(S1Vehicles.LandVehicle __instance) {
18-
VehicleRegistry.RemoveVehicle(__instance.GUID.ToString());
18+
try
19+
{
20+
if (__instance != null)
21+
VehicleRegistry.RemoveVehicle(__instance.GUID.ToString());
22+
}
23+
catch
24+
{
25+
// Ignore errors during cleanup - VehicleManager may be destroyed during scene unload
26+
}
1927
}
2028

2129
}

S1API/Vehicles/VehicleRegistry.cs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -154,39 +154,55 @@ public static LandVehicle CreateVehicle(string vehicleCode)
154154
}
155155

156156
/// <summary>
157-
/// Removes a vehicle from the game's lists, for permenently destroying a vehicle. This will be called automatically in OnDestroy, so there's likely no need to call this manually
157+
/// Removes a vehicle from the game's lists, for permanently destroying a vehicle. This will be called automatically in OnDestroy, so there's likely no need to call this manually.
158158
/// </summary>
159-
/// <param name="guidString"></param>
159+
/// <param name="guidString">The GUID string of the vehicle to remove.</param>
160160
public static void RemoveVehicle(string guidString) {
161-
S1Guid guid = new S1Guid(guidString);
161+
if (string.IsNullOrEmpty(guidString))
162+
return;
163+
162164
var registry = S1Vehicles.VehicleManager.Instance;
165+
if (registry == null)
166+
return;
167+
168+
S1Guid guid = new S1Guid(guidString);
163169

164170
int? allIndex = null;
165171
S1Vehicles.LandVehicle? gameVehicle = null;
166-
for (int i = 0; i < registry.AllVehicles.Count; ++i) {
167-
if (registry.AllVehicles[i]?.GUID.Equals(guid) ?? false) {
168-
allIndex = i;
169-
gameVehicle = registry.AllVehicles[i];
170-
break;
172+
173+
var allVehicles = registry.AllVehicles;
174+
if (allVehicles != null)
175+
{
176+
for (int i = 0; i < allVehicles.Count; ++i) {
177+
if (allVehicles[i]?.GUID.Equals(guid) ?? false) {
178+
allIndex = i;
179+
gameVehicle = allVehicles[i];
180+
break;
181+
}
171182
}
172183
}
184+
173185
int? playerIndex = null;
174-
for (int i = 0; i < registry.PlayerOwnedVehicles.Count; ++i) {
175-
if (registry.PlayerOwnedVehicles[i]?.GUID.Equals(guid) ?? false) {
176-
playerIndex = i;
177-
break;
186+
var playerVehicles = registry.PlayerOwnedVehicles;
187+
if (playerVehicles != null)
188+
{
189+
for (int i = 0; i < playerVehicles.Count; ++i) {
190+
if (playerVehicles[i]?.GUID.Equals(guid) ?? false) {
191+
playerIndex = i;
192+
break;
193+
}
178194
}
179195
}
180-
if (allIndex != null) {
181-
registry.AllVehicles.RemoveAt((int)allIndex);
196+
197+
if (allIndex != null && allVehicles != null) {
198+
allVehicles.RemoveAt((int)allIndex);
182199
}
183-
if (playerIndex != null) {
184-
registry.PlayerOwnedVehicles.RemoveAt((int)playerIndex);
200+
if (playerIndex != null && playerVehicles != null) {
201+
playerVehicles.RemoveAt((int)playerIndex);
185202
}
186-
187-
if(gameVehicle != null && _cache.ContainsKey(gameVehicle))
188-
_cache.Remove(gameVehicle);
189203

204+
if (gameVehicle != null && _cache.ContainsKey(gameVehicle))
205+
_cache.Remove(gameVehicle);
190206
}
191207

192208
private static LandVehicle Wrap(S1Vehicles.LandVehicle veh)

0 commit comments

Comments
 (0)