Welcome to the AFK Mods bug tracker. In order to report an issue, you need to have a VALIDATED account to post one. Once you have followed the link the registration email sent you, please select a project from the drop down menu below. Select “Open New Issue” and fill out the form with as many details as possible.

Issue Data
Status: New
Issue Type: Bug Report
Project: Unofficial Fallout 4 Patch
Component: Fallout 4: Vanilla
Category: Perks & Stats
Assigned To: Nobody
Platform: All
Severity: Medium
Votes: 0
Watching: N/A
Opened By ov2k on May 2, 2023 4:20 pm

Issue #32903: intimidation command effect reapplies and prevents pacifying twice

 
gameplay
With 3 ranks of Intimidation, PACIFY and then COMMAND an NPC (while hidden to avoid hostility). Assuming the PACIFY was successful, the NPC can now be commanded. Holster the weapon (again while hidden to avoid hostility), and the NPC can no longer be commanded. After 60 seconds, without doing anything, the COMMAND dialogue (e.g., "You're going to do what I say."‚Äč) will play again, and the NPC can be commanded again. However, holstering the weapon does not deactivate command mode. Command mode will deactivate in the course of normal gameplay (e.g., by unloading the NPC). However, the NPC can never be pacified again.

summary
I'm pretty sure this is a bug. The COMMAND dialogue isn't supposed to play a second time unprompted. It occurs because HoldupCommandEffect only gets temporarily disabled instead of dispelled, so it reactivates. In doing so, it sets a flag variable, HoldupCommandAV, that blocks the PACIFY ability. Since HoldupPacifyEffect unsets HoldupCommandAV and since HoldupCommandEffect isn't supposed to reactivate, I think it was intended to be able to PACIFY after COMMAND.

detail
In more detail, the COMMAND ability enabled by Intimidation 3 casts HoldupCommandSpell, which applies HoldupCommandEffect. However, HoldupCommandEffect doesn't actually get dispelled. When HoldupPacifyEffect finishes (e.g., when holstering the weapon), HoldupPacifyEffect adds HoldupDispelSpell, which applies HoldupDispelEffect. HoldupCommandSpell has a condition on HoldupCommandEffect that requires HoldupDispelEffect not be applied. As a result, applying HoldupDispelEffect temporarily disables HoldupCommandEffect (OnEffectFinish() gets called). Once HoldupDispelEffect gets dispelled, HoldupCommandEffect gets re-applied (OnEffectStart() gets called again). HoldupCommandEffect's OnEffectStart() sets HoldupCommandAV to 1, which blocks the PACIFY ability.

solution
I'm not sure how to have HoldupDispelSpell or HoldupPacifyEffect dispel HoldupCommandEffect, so I think the next best thing is to have HoldupCommandEffect dispel itself similarly to how HoldupPacifyEffect dispels itself. I've included a replacement HoldupCommandEffectScript.psc that does this. It only registers for things that would break pacification of a commanded NPC.

Scriptname holdupCommandEffectScript extends ActiveMagicEffect


actor victimActor 
actorValue property HoldupCommandAV auto mandatory
actorValue property morality auto mandatory
actorValue Property IgnorePlayerWhileFrenzied auto mandatory
message property holdupMessageCommandSuccess auto mandatory
message property holdupMessageCommandFailure auto mandatory
scene property holdupCommandScene auto mandatory
ReferenceAlias property CommandVictimAlias auto mandatory
float property CommandChance auto mandatory
keyword property ActorTypeNPC auto mandatory
perk property blackwidow02 auto mandatory
perk property blackwidow03 auto mandatory
perk property ladykiller02 auto mandatory
perk property ladykiller03 auto mandatory
spell property holdupDispelSpell auto mandatory
float perkBonus = 0.0
globalvariable property blackWidow02HoldupBonus auto mandatory
globalvariable property blackWidow03HoldupBonus auto mandatory
int startingMorality
keyword property TeammateDontUseAmmoKeyword auto mandatory


Event OnEffectStart(Actor akTarget, Actor akCaster)
    if CommandVictimAlias.getReference().getValue(HoldupCommandAV) == 1 && CommandVictimAlias.getReference() != None
         CommandVictimAlias.getActorReference().AddSpell(holdupDispelSpell, false)
         CommandVictimAlias.Clear()
    endif
	CommandVictimAlias.ForceRefto(akTarget)
    ;***Play player line and victim response***
    holdupCommandScene.stop()
	holdupCommandScene.start()
	getperkBonus()
	if utility.randomFloat(0.0, 100.0) + perkBonus < CommandChance
		victimActor = akTarget
	    victimActor.setcandocommand()
	    victimActor.SetCommandState(true)
		victimActor.changeAnimFlavor()
		victimActor.setplayerTeammate(true)
		victimActor.AddKeyword(TeammateDontUseAmmoKeyword)
		startingMorality = akTarget.GetValue(Morality) as int
		akTarget.SetValue(Morality, 0)
		victimActor.SetValue(HoldupCommandAV, 1 )
		victimActor.EvaluatePackage()
		;***Registering for all events that can break the holdup command state
		RegisterForAnimationEvent(Game.GetPlayer(), "weaponSheathe";)
		RegisterForHitEvent(akTarget, game.getPlayer(), abMatch = true)
		RegisterForPlayerTeleport()
	else
		self.dispel()
		akTarget.AddSpell(holdupDispelSpell, false)
		holdupMessageCommandFailure.show()
	endif
EndEvent

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
	;dispel effect if the player sheathes their weapon
	if (akSource == game.getPlayer()) && (asEventName == "weaponSheathe";)
		self.dispel()
	 debug.trace("dispelling due to weapon sheathe";)
	endif
EndEvent

Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
	;***Combat with the player will dispel effect
	if aeCombatState == 1 && victimActor.GetValue(HoldupCommandAV) == 1 && akTarget == game.getPlayer()
		debug.trace("dispelling due to player attack in command mode";)
		self.dispel()
	endif
EndEvent

Event onHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial)
	;Dispel if the player hits the target actor, unless they are frenzied
	if akAggressor == game.getPlayer()
		debug.trace("dispelling due to player hit";)
		self.dispel()
	endif
EndEvent

Event onPickpocketFailed()
	;If the player gets caught pickpocketing the victim actor, dispel the effect.
	self.dispel()
EndEvent

Event onPlayerTeleport()
	;If the player goes through a load door, fast travels, or is moved; dispel the effect.
	self.dispel()
EndEvent

Event onEffectFinish(Actor akTarget, Actor akCaster)
		akTarget.SetValue(Morality, startingMorality)
		akTarget.SetCanDoCommand(false)
		victimActor.SetCommandState(false)
		victimActor.setplayerTeammate(false)
		victimActor.RemoveKeyword(TeammateDontUseAmmoKeyword)
endEvent

function getperkBonus()
	;***Check to see if player has Black Widow or Lady Killer at the appropriate rank and check gender of the target to determine if there is a bonus to the pacify chance
	if victimActor.hasKeyword(ActorTypeNPC)
		if game.getplayer().hasperk(blackwidow02) && victimActor.getActorBase().getSex() ==0 
			if game.getplayer().hasperk(blackwidow03)
				perkBonus == blackWidow03HoldupBonus.getValue()
			else
				perkBonus == blackWidow02HoldupBonus.getValue()
			endif
		endif
		if game.getplayer().hasperk(ladykiller02) && victimActor.getActorBase().getSex() == 1
			if game.getplayer().hasperk(blackwidow03)
				perkBonus == blackWidow03HoldupBonus.getValue()
			else
				perkBonus == blackWidow02HoldupBonus.getValue()
			endif
		endif
	endif
endFunction

Comments

1 comment(s)
ov2k said:
 
Until a fix is applied, a workaround is to deactivate the COMMAND and PACIFY modes (e.g., by holstering the weapon) and then unload the actor in under 60 seconds.

Showing Comments 1 - 1 of 1