mod help - fist fight flag? determining state is impossible?

+
looking for a programmatic way of determining fist fight 'state'.

currently, the game simply sets current weapon to PW_Fists, and prevents the player from swapping weapons until the fight is over.

that's fine, and works as long as you don't try to change the weapon auto-switch code to allow automatic switching FROM fists (during a monster fight).

however, the game prevents auto-swapping from fists specifically because it doesn't want the game/player to swap weapons during a fist fight.

it works fine (returns PW_Fists), as long as opponent you attack is using fists (!hasPhysicalWeapon; see playerWeaponHolster.ws, GetMostConvenientMeleeWeapon) otherwise (like in BnW gwent brawl) where they're holding clubs, it fails.

Of course, it only fails if you attempt to implement a feature to automatically switch from fists to a sword in actual combat... which doesn't exist in the base game... specifically prevents auto-swap from fists during ANY fights, because of this oversight...

if... i could find the code which starts/ends a fist fight sequence, could add a variable... but, it's probably coded into each quest separately (not as a variable, just sets playerWeapon to PW_Fists on a quest by quest basis)...
Code:
if ( targetToDrawAgainst.IsHuman() && ( !hasPhysicalWeapon || ( targetToDrawAgainst.GetAttitude( thePlayer ) != AIA_Hostile ) ) )
{
    ret = PW_Fists;
}
it's literally that one line that is the problem. it was originally meant to check for fist fights, until they started giving them weapons...

if only there were some way to check for a condition at this juncture and determine fist fight 'state'... or go back to not giving them weapons...

targetToDrawAgainst is a dwarf in the BnW gwent brawl, which classifies as 'human' since it isn't a 'monster'. it then fails the !hasPhysicalWeapon check, since it's holding a club, and also the hostile check.
Code:
if ( this.GetCurrentMeleeWeaponType() != PW_Fists && weapon != this.GetCurrentMeleeWeaponType() )
then this line in r4Player.ws seems to later have been implemented as a 'fix', which just prevents the player from ever auto-switching from PW_Fists during combat... evident in the use of 'this.' object, which is redundant and unnecessary.
Code:
(CNewNPC)targetToDrawAgainst.fistFightForcedFromQuest
returns false for the dwarves, maybe since they're holding clubs.
Code:
npcs[i].fistFightForcedFromQuest = true;
this is indeed simply set per quest, per npc, with an action block elsewhere, ie: (quest_function.ws).
Code:
latent quest function BlockGamePlayFunctionality
quest function CombatStateChange
latent quest function EnableFistFightMiniGame
However, as noted above, the npcs.fistFightForcedFromQuest variable is not always set, which means preferedCombatStyle == EBG_Combat_Fists will also return false for those NPCs, and i can't find any actual functions which begin/end a fist fight sequence. these simply set a property (sometimes) on quest NPCs, and if none are set to 'EBG_Combat_Fists', then there's no way of even determining that.

SOLVED:

Ah, I suppose I can just use IsActionAllowed( EIAB_DrawWeapon ), which should and does return false during that sequence, but curiously isn't even a condition in GetMostConvenientMeleeWeapon (playerWeaponHolster.ws) or DoAttack (r4Player.ws)... only ProcessCombatActionBuffer (r4Player.ws), which is bypassed in some cases via GetMostConvenientMeleeWeapon.

There actually is a variable called 'fistFightMiniGameEnabled' and function 'IsFistFightMinigameEnabled()' in r4Players.ws, which i didn't even realize i used previously (4 year old code haha), and 2 functions called OnStartFistfightMinigame and OnEndFistfightMinigame.


I suppose either solution is fine: IsActionAllowed( EIAB_DrawWeapon ) or IsFistFightMinigameEnabled()... oddly, checks are in the wrong places though.
 
Last edited:
Not solved - It turns out the IsInFistFightMiniGame(), IsFistFightMiniGameEnabled() functions return false for the Toussaint Gwent Tourney Dwarves... because it's not an 'actual' fist fight. The IsInFistFight(), fistFightCheck() functions simply return whether or not the enemy is holding a weapon... and the Dwarves are, so it's not a 'fistfight' lmao. So there's really no way to determine the state for some sequences, which is why the entire GetMostConvenientWeapon() chain is completely butchered... to prevent auto-swapping from fists; horrible.

You can check for IsActionAllowed(EIAB_DrawWeapon), which returns false for the Dwarves sequence (the quest manually blocks it), but it also returns false during many other sequences and animations, and often is not reliable for these purposes.

Code is also duplicated all over the place. Double checks for if the same weapon is equipped across multiple functions, several ways to check for fist fights, neither of which actually do? 2 ways of checking whether NPC has a weapon... etc... redundant... someone was clearly in a rush to fix/finish this code.

Each NPC should have had a flag called 'IsFistFightEnabled'... if you want to arm then with clubs, otherwise your functions only half-work... :\ ie: all those scared soldiers in the courtyard with Regis/Dettlaff? Geralt actually thinks they're fist fights... because they're not holding weapons, so if you don't pull out a weapon, and have made a mod to auto-switch from fists, he still won't because of all the checks for if the enemy is holding a weapon... so ridiculous... instead of a flag, or lack of one, even if armed/unarmed.

Probably an easier alternative would have been to give them some other 'life' source instead of ESS/VIT, called FIST power! :\ Which is basically just enemy type, instead of monster/human, or non-hostile NPCs, etc... called 'fistfighter', brawler, etc...

Or simply... Stop arming the bloody Dwarves!

So I took a look at (EnumBehaviorGraph, npcTypes.ws) EBG_Combat_Fists again and Behaviour functions in quest_function.ws, and no behaviour is set for those NPCs (entities), as I already stated the Toussaint Dwarves return false for that behaviour, and are holding clubs.

IsWeaponActionAllowed simply checks either (EnumInputActionBlock) IsActionAllowed( EIAB_Fists ) or EIAB_DrawWeapon, and GetBIsCombatActionAllowed has little to do with Behaviours (except that they're animations also processed on combat buffer), but returns whether the player is currently in a 'combat action' animation. B probably stands for Combat Buffer, as a check to see if the combat buffer has been processed (empty), ready for action.

I'm out of ideas... since you can't use those in GetMostConvenientMeleeWeapon, the action is already blocked, and there's no way to determine if the action is blocked due to a quest or combat action.

Bloody Dwarves, always gotta ruin your day.

Instead of breaking up a Gwent tournament, they broke a bunch of Witcher code...
 
Last edited:
Top Bottom