Jump to content

Player.GetAttacked sticks on 1


Athelbras

Recommended Posts

According to the GECK's write-up for GetAttacked in FNV:

 

"Returns 1 if the calling actor has been attacked. This value is cleared when the actor drops out of combat."

 

But in my tests it never clears for Player.GetAttacked. It begins with 0 when a player character is initially created, but as soon as that character is attacked during its first combat situation, it remains stuck at 1 forever. This is true whether the function is invoked within GameMode of a follower script, or within OnCombatEnd, or within any other ON condition, or in any quest script, etc.

 

Note though that GetAttacked *does* work correctly when used for an NPC, such as in the script for any of my companion mods; e.g. MBRipperREF.GetAttacked is properly reset to 0 when combat ends for that NPC.

 

So the question is this: does Player.GetAttacked really work and something is wrong with my environment? Or is this a known bug?

 

If a known bug, is there a known way to clear that status flag within OnCombatEnd (or elsewhere) so that calls to GetAttack for Player work correctly? Alternatively, I'll just use some workaround, but am wondering if there is a way to use the function as originally intended.

Edited by Athelbras
Link to comment
Share on other sites

From Oblivion:

Differs from IsInCombat in that it is treated retroactively, in that once attacked, an actor will continue to return 1 until they have yielded or left combat.
When called on the player, will return 1 from any point shortly after the tutorial starts, or as soon as the player is targeted by anything.
Unlike IsInCombat, this will return 1 if an actor is attacked, but that attack does not trigger combat, such as the case might be with friendly hits, but may prove unreliable.

 

I always use IsInCombat, it usually works pretty fine.

Link to comment
Share on other sites

I need much finer (more detailed) control than what IsInCombat offers ...

 

What I need to know for scripting is whether the Player was personally attacked. Not just whether an overall combat situation exists.

 

It can be done for NPCs by using GetAttacked, which becomes 1 when the NPC is directly attacked, and then cleared to 0 by OnCombatEnd. A practical use is for preventing an NPC from joining in a fight until that NPC has personally been attacked. In other words "passive until you are attacked". For example, IsInCombat can be True/1 while a fight rages between you and enemies, and the NPC companion can be kept out of that fight until he/she/it is personally attacked (as indicated by GetAttacked becoming 1); at which point the NPC can be allowed to fight as well. All under perfect scripted control. That approach works very well, and quite reliably.

 

But if you also want to script an NPC to not join in fighting until the Player's character is personally attacked ... it doesn't work correctly (except the first time), because Player.GetAttacked is never reset to 0. It stays 1 forever. The idea was to allow the player character to do long range sniping at enemies without companions charging forward too soon. In other words "passive until I am attacked". So the approach that works perfectly for NPCs does not work for the Player character being the trigger event.

 

And, unfortunately, OnHit is not a substitute for a properly functioning Player.GetAttacked function call, since OnHit is *only* processed for an NPC, even though a "Player" qualifier can seemingly be supplied (OnHit Player) because that qualifier is ignored; the active reference is always the NPC for that script. If it *did* work, it could potentially solve my problem - I'd set my own player-was-attacked flag.

 

- * -

 

And, unfortunately, IsInCombat is too generalized for my needs. It isn't really an "active combat" indicator. Instead it is an umbrella status that covers a kind of "you're in trouble" situation.

 

It certainly has a value of 1 during a fight. But is also 1 if "enemies are actively searching for the player" but have not actually found you, and so haven't even started attacking yet. It can also be 1 if enemies are attacking one of your companions while you are being totally ignored.

 

Which means if I use IsInCombat, and my NPC is set for "passive until I am attacked", it goes charging off before I am directly attacked or fighting even begins.

 

In actuality, IsInCombat can remain set to 1 across *multiple* instances of actual fighting (as demarcated by OnCombatEnd), with long intervals of nothing much happening in-between, and not reset to 0 until minutes after the last OnCombatEnd occurred.

 

- * -

 

My current conjecture is that Player.GetAttacked is never reset to 0 because there is *no* processing for OnCombatEnd using the Player's reference, which is where/how it would be reset (as per NPCs). And although you can script a separate "OnCombatEnd Player" block, the "Player" qualifier is ignored and the NPC reference is passed along instead.

 

I had thought the Player.GetAttack issue might be a bug. But I am now thinking it is a "feature"; as in the Devs didn't see the need to have block processing for the Player reference; which includes OnHit, OnStartCombat, and OnCombatEnd. Which caused Player.GetAttack to be a broken function, which they either did not notice or did not care to fix.

 

- * -

 

So ... anyone have a suggestion or idea?

 

[simply monitoring Player health feels like it would be crude and error-prone/unreliable]

Edited by Athelbras
Link to comment
Share on other sites

If a function doesn't work exactly as you expect, not always it means it's broken, some functions work correctly only on NPCs. If a function doesn't do exactly what you need, in a single command, then it's all in finding a workaround, it's all mixing functions and try in game. For example, if IsInCombat is 1 + enemy is in LOS and on an adeguate range then it's probable it's attacking, GetCombatTarget could tell who the target is.

Alternatively, what about an OnHit block and GetOwnerLastTarget to get the Player REF, or an OnHit event handler filtered by Player as target, I think both work fine for your case. Monitoring health isn't a bad idea also

Edited by Fallout2AM
Link to comment
Share on other sites

Thanks! I appreciate the fact that you took the time to offer suggestions. But I am not sure those are workable. Here is the detailed reasoning ...

 

- GetOwnerLastTarget does not have an entry in geck.bethsoft.com under the Functions category, so I wasn't aware of it. After reading your reply, I experimented with it a bit, but haven't figured out what the function really does or how it works. I had hoped that "GetOwnerLastTarget Player" would return a reference to an NPC if an NPC attacked the player ... but it always returns 0.

 

- OnHit can't be filtered by "Player". It is strictly NPC-reference oriented; the NPC to whom the script belongs. This is so for BEGIN OnHit as well as BEGIN OnHit Player (the Player qualifier is ignored).

 

- There appears to be no means of getting NPC actor references for those in the current cell, so I can't invoke GetLOS for NPC-to-Player or Player-to-NPC. Meaning, there is no function to simply get a REF to an NPC actor that is currently in the cell, and then get the next one, and so on. Hence I can't construct a proper GetLOS call. But perhaps you know of a way to get references for NPC actors within a cell?

 

- I am familiar with GetLastTarget GetCombatTarget; I use it to evaluate the nature of a companion's opponent. But, since I can't get NPC references, I have no actor reference to use for invoking GetLastTarget to see if the result is "Player"; i.e. the same problem as for GetLOS.

 

- I could not invoke IsInCombat and GetLOS (if useable) and have "true" be an assumption that the Player is attacked. Because it is very common for nearby enemies to be only attacking one of my NPC companions while my Player character is totally ignored. So that assumption could be incorrect quite often; which (for my purposes) makes it not useful.

 

But even so, I'd be happy to receive any further thoughts or suggestions that you might have.

Edited by Athelbras
Link to comment
Share on other sites

- I tried GetOwnerLastTarget but it seems breaking my script, in GameMode and inside an OnHit event. Unrelated note, you can find the list of all the functions here.

 

- OnHIt can be filtered by player. I just tried it.

 

- The way you get a reference is about your taste, me for example I often use GetCombatTarget or scanners.

 

- I never heard of GetLastTarget sorry

 

- If you are afraid that they are attacking a companion you just need to introduce a condition that excludes companions references

Link to comment
Share on other sites

I was testing some other things, I took the occasion to test this too and maybe you could appreciate these extra infos. When you snipe someone, and they don't see you, you are sneaking, they are just alerted but not fighting you, they are looking for you, you see caution or danger on top, but not danger blinking (which means they found you), you will have this result:

 

IsInCombat == 1

GetAttacked == 1

GetCombatTarget == PlayerREF

 

While the blocktype or the event OnStartCombat will trigger only if they find you (so I guess GetLOS must be verified)

Edited by Fallout2AM
Link to comment
Share on other sites

There must be some basic difference between what you did for the video versus what I am doing.

 

Where do you have that OnHit block that you used for your video? By "where" I mean: in what script? And to what actor/object/whatever is that script attached? That may be the crucial information.

 

Could you please show the scripting that you used?

 

My OnHit blocks are in a companion NPC's script or in a companion Creature's script. Here are simple test examples. msgPlayerHit is never displayed. It is only msgOtherHit that is displayed (when the NPC/Creature is hit), because the actor reference is never Player.

 

BEGIN OnHit

 

if this == Player

ShowMessage msgPlayerHit

elseif GetSelf == Player

ShowMessage msgPlayerHit

elseif GetIsReference Player == 1

ShowMessage msgPlayerHit

else

ShowMessage msgOtherHit

endif

 

END

 

BEGIN OnHit Player

 

if this == Player

ShowMessage msgPlayerHit

elseif GetSelf == Player

ShowMessage msgPlayerHit

elseif GetIsReference Player == 1

ShowMessage msgPlayerHit

else

ShowMessage msgOtherHit

endif

 

END

 

So perhaps your OnHit was not in a companion's script - if not, where is it located instead?

 

Are you maybe using NVSE? I am not.

 

In my other reply, I did not mean GetLastTarget - that should have been written as GetCombatTarget. Apologies for the confusion.

Edited by Athelbras
Link to comment
Share on other sites

or an OnHit event handler filtered by Player as target

 

yes I'm using NVSE.

Doing it with vanilla functions isn't simple (and probably accurate) in the same way. However, if what you want is only gain more time to snipe, without that the companions rush in attacking the enemy, I'm sure that a mix of all the previous said things will make the trick, some smart way to mix IsInCombat, GetLos, the player's health etc.

Link to comment
Share on other sites

Please ... your script with the OnHit block ... what is it linked to? What actor / object / whatever uses the script? Or is it somehow an unlinked script that runs all by itself?

 

My companion has a script which is specified in its SCRI - Script field, and it is that script that has my OnHit. How is yours setup?

Edited by Athelbras
Link to comment
Share on other sites

  • Recently Browsing   0 members

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