Jump to content

Dubbelganger not removed after sceen ending


Recommended Posts

Hi!

 

I use Sex Attributs, Sexual Harassement, Devius Devices and meany more mods and the problem I have is not happening all the time, maby 1 in 10 times.

It's more of an iretation then a problem. But what happen is:

 

1. Harrasement event fires

2. Bla, bla, bla

3. Lose controle of movement

4. Wait for NPC to get here and add DD diveces

5. Black - for sceen selecetion and setup

6. Sex sceen

7. Dubbleganger si removed and NPC go back to do what he/she was doing. Movement are given back.

 

That is a normal event. My problem is that the dubbleganger is not removed but continue to be in the pose that was seleted. When my marker is over the dubbelganger the dubbleganger have my name and I can inteact with it as if it was my companion, but it will not move from that spot. If I do this the dubbleganger stand up, If I don't do it the dubblegange will sand up if I leve the settlement and come back. If a new harassment event is fired then the dubbleganger can be the NPC.

This dubbleganger will not beremoved at any time, I think that it is considerd a compantion that will not follow or talk to you. One can have multiple dubblegangers in a settlement and dispersed over several settlement. In my current game I have two dubblegangers in Sanctuary and one in Abernathy farm.

 

I have downloaded a bunch of new XML animation files that might have been the couse of the problem and I have allso updated some files with a new version.

In the event some XML files was missing. I don't get any error messages, I did get one in the start but that was beacuse I forgot to install a theme.

 

Have any one else stumbled on the same problem?

So can I use Fallrim tool to find the actor and remove it? Is there a name/string/value I should search for?

Or is there any other thing I can do to fix this?

Link to comment

Thank you for reminding me to study the script.

 

for reference I have AAF v117b intalled.

 

My guess is that the function "OnUnlockActor" is the one relasing the player and deleting the dubbelganger.

I find 3 instances of "OnUnlockActor", the first is for registration of external event, the second is a call to the function OnUnlockActor and the last is the function it self.

After looking through all the scripts for any call to "OnUnlockActor", finding none. Sexua Harassment only call "StartScene" in AFF_API.

The call comes from the function "resetActiveActors" and supply only actgor FromID.

Function OnUnlockActor(Int actorFormID, Bool isDoppelganger = False)

If we look att the function declaration we can see that we get actorFormID from the caller and isDoppelganger is allways false.

If (isDoppelganger == True)

	targetActor.SetAlpha(0.0)
	doppelganger = targetActor
	doppelganger.PlayIdle(LooseIdleStop)
	targetActor = PlayerRef
	actorFormID = targetActor.GetFormID()

EndIf

This make this part of the code unreachable, since we dont have an event call that can supply isDoppleganger with true.

 

In C++, C# and java when you declare an variable it's a good pracis to initiate the variable with a value. When we declare value we get a pointer to a memory address space, and in that address space we don't know what sort of data we have. So we initiate with a value, even if it's null, just so that we know that we have a valid value.

And I don't see papyrus should be any different.

Actor doppelganger		;what value do we have????

Actor doppelganger = none	;now we know

Since isDoppelganger is false we cant set doppelganger a value, and we don't know what we have for value for doppelganger since we have not initilized it with a value.

If doppelganger
	doppelganger.RemoveKeyword(AAF_API.AAF_ActorBusy)
	AAF_ActiveActors.RemoveAddedForm(doppelganger)
EndIf

If doppelganger have any value other then 0 then this code will be run. The if statement is seen as an boolean if and that only check if the value is zero (false) or non zero (true).

!= None should be added for security.

If(doppelganger != None)
			
	; Not needed when using true copy of clothes:
	;copyClothes(doppelganger, PlayerRef, True)
			
	UnregisterForHitEvent(doppelganger)
	doppelganger.Delete()
	currentDoppelganger = None
EndIf

The same will happen for this part. Maby we are extreamly lucky most of the time and we actualy have the address to doppleganger in the address space.

 

But what happen if the address space dont have a value that currespont to an actor, what will happen then?

Link to comment
23 hours ago, MichellChan said:

for reference I have AAF v117b intalled.

This is all happening because of the "gathering" bug which has been discussed in the main AAF thread.  When that bug happens, AAF's processing stops, so the doppelganger doesn't get cleaned up and other AAF variables are left in an unusable state.  This was fixed in AAF beta 118 (available on Discord or via dagobaking's Patreon) and will be fixed in the next public AAF release.

 

Quote

 

In C++, C# and java when you declare an variable it's a good pracis to initiate the variable with a value. When we declare value we get a pointer to a memory address space, and in that address space we don't know what sort of data we have. So we initiate with a value, even if it's null, just so that we know that we have a valid value.

And I don't see papyrus should be any different.

 

But in fact it is completely different.  Papyrus has its own types like Ints, Floats, Arrays, etc, that behave like those in C/C++.  But it also has object types like Actor, ObjectReference, Weapon, FormList, Quest, etc, that can only point to game forms.  When you declare one of those, it is always None unless you explicitly initialize it with an existing value.  It is not possible for an uninitialized Actor variable to point to anything other than None. 

 

Boolean expressions like If (akActor) are perfectly valid, because anything in Papyrus can be implicitly cast to a boolean, and in the case of an object the result is True if the object isn't None.

Link to comment
On 3/31/2020 at 2:57 PM, MichellChan said:

 


If (isDoppelganger == True)

	targetActor.SetAlpha(0.0)
	doppelganger = targetActor
	doppelganger.PlayIdle(LooseIdleStop)
	targetActor = PlayerRef
	actorFormID = targetActor.GetFormID()

EndIf

This make this part of the code unreachable, since we dont have an event call that can supply isDoppleganger with true.

?

 

As you point out, that function is registered for external events. So, the external event can call it with isDoppelganger as true.

On 3/31/2020 at 2:57 PM, MichellChan said:

 

In C++, C# and java when you declare an variable it's a good pracis to initiate the variable with a value. When we declare value we get a pointer to a memory address space, and in that address space we don't know what sort of data we have. So we initiate with a value, even if it's null, just so that we know that we have a valid value.

And I don't see papyrus should be any different.


Actor doppelganger		;what value do we have????

Actor doppelganger = none	;now we know

I prefer to keep the code cleaner and avoid needless declarations. The two lines you show have the exact same result. So, the shorter one is better, imo.

On 3/31/2020 at 2:57 PM, MichellChan said:

Since isDoppelganger is false we cant set doppelganger a value, and we don't know what we have for value for doppelganger since we have not initilized it with a value.

As noted above isDoppelganger is in fact not always false.

 

doppelganger will be either None or it will be populated with the new actor. Nothing about that is broken.

On 3/31/2020 at 2:57 PM, MichellChan said:

If doppelganger
	doppelganger.RemoveKeyword(AAF_API.AAF_ActorBusy)
	AAF_ActiveActors.RemoveAddedForm(doppelganger)
EndIf

If doppelganger have any value other then 0 then this code will be run. The if statement is seen as an boolean if and that only check if the value is zero (false) or non zero (true).

!= None should be added for security.

This part of the code works perfectly. "None" registers as False in the if statement. If there is no doppelganger, there is no need to remove keywords from a doppelganger.

On 3/31/2020 at 2:57 PM, MichellChan said:

If(doppelganger != None)
			
	; Not needed when using true copy of clothes:
	;copyClothes(doppelganger, PlayerRef, True)
			
	UnregisterForHitEvent(doppelganger)
	doppelganger.Delete()
	currentDoppelganger = None
EndIf

The same will happen for this part. Maby we are extreamly lucky most of the time and we actualy have the address to doppleganger in the address space.

 

But what happen if the address space dont have a value that currespont to an actor, what will happen then?

Luck has nothing to do with it. It works properly every time based on concrete logic. If there is no doppelganger defined it will return "None" every single time.

 

Any other questions?

Link to comment

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use