Locational Damage Script Available?

Post » Sun May 27, 2012 2:06 pm

It shouldn't be too difficult to simply "give" actors collision boxes. Make a script concentration aimed spell like this:

Ok, you're hired! :-D
It's just too bad I don't have any money to pay you yet :-P

Writing that off the top of your head? The modding community never fails to amaze me with the talent here!


It does some comparison math, and then spits out which node was hit.

After this I think the easiest thing to do would be to set yet another float global as the damage multiplier for the given node. Then you can simply call the damaging script, which just reads this global into the damage formulation.

In other words, you can just use that script to determine what area the actor got hit, then use another script to actually cause damage/effects to it? So I could use that script along with a version of my script to have locational armor values and damages? Not simply damage multipliers, I mean.
User avatar
Mimi BC
 
Posts: 3282
Joined: Sat Oct 07, 2006 10:30 pm

Post » Sun May 27, 2012 1:51 pm

Well, it's nice but I'm not sure if it will actually work. The idea to actually "bind" collision boxes to an actor's body parts is genius, but I don't know how to implement it. Since these are collision boxes created at run time, I don't know how you would determine their size, and from what I know, all the primitives start out with no sizes at all. The only one that I can think of which starts out with a defined size and shape would be the weapon rack activators.

Also, http://www.creationkit.com/GetEquippedWeapon_-_Actor doesn't actually return an object reference to an actor's currently equipped weapon (I don't know of any way to do that), but rather tells you the base object of whatever the equipped weapon is. So you can't use that to figure out the coordinates of the equipped weapon (I'm not even sure that the equipped weapon is considered a separate object from the player).

I also haven't been able to get akProjectile for arrows. I've only been able to get a value from akProjectile when the hit resulted from a spell.
User avatar
Tom Flanagan
 
Posts: 3522
Joined: Sat Jul 21, 2007 1:51 am

Post » Sun May 27, 2012 10:23 am

Insects are activators with defined shape and size. They don't have to be collision boxes at all, as they are used as mathematical reference points rather than direct detectors. In any case, maybe they just default to a scale of 0 and can be scaled up, who knows. Worth trying. Also, you could make a very small invisible copy of the weapon rack activators with the scripts attached that I set out I think.

As for the GetEquippedWeapon, I think I thought of a really wonky crazy work around. The trick is, we don't NEED where the weapon is, as long as we know where the hand, wrist, and forearm are. OnHit generates an activator which flies to a finger node, then the forearm node and then it retrieves their locations at each of these sites, saving them as variables. Then it plots a line of these two points and extends it by akAggressor.GetEquippedWeapon().GetSize(). Now that it has this function it can travel along the imaginary length of the blade and at a given number of points along it the invisible bee will report its location into a small linked list of globals.
EDIT: Come to think of it, to save processing power you wouldn't even need to move this activator once it had computed the line. You can just get the remainder of the values through some math.

Flash back to the spell that is keeping track of the activators:
It can now use this linked list to do comparisons of how close each part of the weapon was to each bound chaser node. It finds the minimum distance, and also where along the weapon you hit. This would enable for a combat system that has multiple "hit boxes" along the length of a weapon, like in Smash.
User avatar
Nomee
 
Posts: 3382
Joined: Thu May 24, 2007 5:18 pm

Post » Sun May 27, 2012 6:36 am

Yep, my head is now officially hurting again ;-P

I've already got cuirass and shield values set on (un)euip. I may just add functions that do the same for helmets, gauntlets, and boots also. Shouldn't take much effort. Then at least the values will be set for any future locational applications :-)

Since it USUALLY only happens on cell load (save for the player), I don't believe it causes any lag in combat. That's one benefit I got by attaching the script to an actor instead of a magic effect :-)
User avatar
Sophie Payne
 
Posts: 3377
Joined: Thu Dec 07, 2006 6:49 am

Post » Sun May 27, 2012 4:34 pm

@Ducey

Sorry, I guess I didn't read your suggestion clearly enough. I see what you're doing now. You're using the activators to keep track of the positions of the attacker's weapon and the target's body parts.

I thought what you meant was to put actual trigger zones around the target's body parts, then use OnTriggerEnter or something to detect where exactly the target gets hit.
User avatar
Dale Johnson
 
Posts: 3352
Joined: Fri Aug 10, 2007 5:24 am

Post » Sun May 27, 2012 2:52 am

Looks like the hardest part of this whole ordeal is determining what the coordinates are that the player is aiming at
User avatar
Neliel Kudoh
 
Posts: 3348
Joined: Thu Oct 26, 2006 2:39 am

Post » Sun May 27, 2012 8:01 am

If Game.GetPlayer().GetCombatTarget!=NONE

get combat target only works if the player is directly looking at their combat target, so if it returns something, its the combat target.
User avatar
Add Meeh
 
Posts: 3326
Joined: Sat Jan 06, 2007 8:09 am

Post » Sun May 27, 2012 1:39 am

But that just returns an objectref, not coordinates in the game world
User avatar
Monique Cameron
 
Posts: 3430
Joined: Fri Jun 23, 2006 6:30 am

Post » Sun May 27, 2012 5:43 am

I don't understand why we need the game co-ordinates where the player is aiming...
User avatar
C.L.U.T.C.H
 
Posts: 3385
Joined: Tue Aug 14, 2007 6:23 pm

Post » Sun May 27, 2012 4:41 am

Is where the player aiming what we want... or where the weapons swing/hit?

Oh well, on a side note, I updated my script to add values to an actor's equipped helmets, gauntlets, and boots for future locational functions. The cuirass is still the default defensive value for armor. The shield also has value in case the attack is blocked.

My goodness, I have a LOT of logic to clean up! :-P
User avatar
Terry
 
Posts: 3368
Joined: Mon Jul 09, 2007 1:21 am

Post » Sun May 27, 2012 9:22 am

Because if you do not know where the player is aiming, then how do you know if the player is aiming at a head/arm/leg/chest?


For example, we have two bumper cars in an arena. We have GPS coordinates for car A, but have no idea where car B is. How can we know, without looking at the cars, if car A has come close enough to car B or vica versa at any time to hit each other?

Finding the locations of the different body parts on the target shortly after the moment they are hit is pretty easy, but finding where the player was aiming is a much different story. It likely wouldn't be a problem if there was some GetHeadingAngle equivalent for vertical angles. GetHeadingAngle is great for determining the player's rotation around the Z axis, but gives us no information on where an object is relative to the player's rotation around the Y axis (which is the axis that you "rotate" around when you look up and down.)

Otherwise, we could just move an activator to a node, then do getheadingangle between the node and the attacker, then get the elevationangle and determine easily if those angles are below some absolute value, then we know the player or attacker was looking pretty close to where the node is and thus should achieve a headshot/armshot or whatever.

I guess you could do GetAngleY() on the player and GetPositionX, GetPositionY, GetPositionZ, and GetHeadingAngle(), then also get the positions of the activator at the node and do a little trig, but all of those are time sensitive as it is important that that specific information be gathered at the moment or as close to the moment that you strike the enemy as possible. With that many functions, you start reducing the accuracy of the calculations simply because you give the player more time to move before the "measurements" are taken.

I will try some different methods and see what I can come up with, but bottom line, I and many others are overlooking some efficient method of doing this (with melee attacks) that a few modders have discovered, and it would be really nice if those modders would contribute this information to the community.
User avatar
Cartoon
 
Posts: 3350
Joined: Mon Jun 25, 2007 4:31 pm

Post » Sun May 27, 2012 5:15 am

Well, this is the very rough script I used to determine where the attacker is staring at on a victim's body. It only works for when the victim happens to be standing up straight and not down on the ground paralyzed. If I wanted to figure that out, I would need to do some more math to figure out the relative coords of the victims feet and head node.

Spoiler
Scriptname fg109TestMEScript extends ActiveMagicEffectActor VictimActor PlayerEvent OnEffectStart(Actor akTarget, Actor akCaster)	Victim = akTarget	Player = Game.GetPlayer()EndEventEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)	if (akAggressor == Player) == (Victim == Player)		Return	;we only care if either Victim or akAggressor is the player	endif	Actor Attacker = akAggressor as Actor	Float DistanceTotal = Attacker.GetDistance(Victim)	Float OffsetZ = DistanceTotal * Math.Sin(Attacker.GetAngleX() * -1)	;this is the offset from attacker's eye height due to head tilt angle	Float TargetZ = Attacker.Z + Attacker.GetHeight() + OffsetZ	;this is the Z coordinate that the attacker was looking at	Float VictimZ = TargetZ - Victim.Z		;this is the Z offset from the victim's feet that the attacker was looking at	VictimZ = VictimZ * 100 / Victim.GetHeight()	;this would be a percentage dependent on the victim's height	if (VictimZ > 80)	;the attacker was looking at a point above 80% of the victim's body		Debug.Notification("Attacker was staring at victim's head area.")	elseif (VictimZ < 25)	;the attacker was looking at a point below 25% of the victim's body		Debug.Notification("Attacker was staring at victim's feet area.")	elseif (VictimZ < 50)	;the attacker was looking at a point between 25% and 50% of the victim's body		Debug.Notification("Attacker was staring at victim's legs area.")	else	;the attacker was looking at a point between 50% and 80% of the victim's body		Debug.Notification("Attacker was staring at victim's torso area.")	endif	Float AngleZ = Victim.GetHeadingAngle(Attacker)	;how far victim would have to turn to see the attacker	if (AngleZ >= -45.0 && AngleZ <= 45.0)		Debug.Notification("Attacker was staring at the victim's front.")	elseif (AngleZ > 45.0 && AngleZ < 135.0)		Debug.Notification("Attacker was staring at the victim's right.")	elseif (AngleZ < -45.0 && AngleZ > -135.0)		Debug.Notification("Attacker was staring at the victim's left.")	else		Debug.Notification("Attacker was staring at the victim's back.")	endifEndEvent

But as I said in my other post, just because the attacker is looking at the area doesn't mean that they are attacking it.

GetHeadingAngle is great for determining the player's rotation around the Z axis, but gives us no information on where an object is relative to the player's rotation around the Y axis (which is the axis that you "rotate" around when you look up and down.)

Actually, you're talking about the X axis rotation. I wrote a http://www.gamesas.com/topic/1358532-question-about-translateto/page__p__20487469__hl__getheadinganglex__fromsearch__1#entry20487469 a while back for figuring out "GetHeadingAngleX".
User avatar
Melanie
 
Posts: 3448
Joined: Tue Dec 26, 2006 4:54 pm

Post » Sun May 27, 2012 4:04 pm

http://www.creationkit.com/GetAngleX_-_ObjectReference

This states that actors cannot rotate around the X axis (which makes since to me, if the X axis is pointing straight foreward/back.)



During melee combat when would you be aiming at a point other than where you are hitting? With arrows this isn't true because of the parabolic arc that they travel in, but for melee combat I cannot think of how this would not be true.
User avatar
Silencio
 
Posts: 3442
Joined: Sun Mar 18, 2007 11:30 pm

Post » Sun May 27, 2012 5:50 am

This states that actors cannot rotate around the X axis (which makes since to me, if the X axis is pointing straight foreward/back.)

I believe that when it says actors cannot rotate about the X axis, it means that you can't rotate them so that they're lying on their back or on their face. However, calling SetAngle or GetAngle retrieves the X axis rotation of the camera view, or NPC's head. You can try using "Player.SetAngle X -50" in the console and find yourself staring at the sky.

During melee combat when would you be aiming at a point other than where you are hitting? With arrows this isn't true because of the parabolic arc that they travel in, but for melee combat I cannot think of how this would not be true.

Well, when I'm in melee combat, when my target reticle is on an NPC's head, swinging my weapon has me hitting their chest. Maybe there's something wrong with my game if that doesn't happen to you.
User avatar
Ymani Hood
 
Posts: 3514
Joined: Fri Oct 26, 2007 3:22 am

Post » Sun May 27, 2012 2:21 am

Well, this is the very rough script I used to determine where the attacker is staring at on a victim's body.

-----------------------------------------------------------------------

if (akAggressor == Player) == (Victim == Player)
Return ;we only care if either Victim or akAggressor is the player
endif

Hmm, that makes me think for a moment. Would there be any way to tell the AI to look/aim at a certain part of the target in order to take advantage of locational damage? And can it also be used for NPC vs. NPC combat?

Yes, I know that's an issue for AFTER locational damage is implemented. I'm just curious :-P
User avatar
(G-yen)
 
Posts: 3385
Joined: Thu Oct 11, 2007 11:10 pm

Post » Sun May 27, 2012 7:36 am

You can call SetAngle on the NPC to force it to face in a certain direction. I am not sure if an NPC needs to look at something in order to hit it, although it normally does so.

You can just get rid of the check if you want it to be applied in NPC vs NPC combat. I just didn't feel the need to do that.
User avatar
ashleigh bryden
 
Posts: 3446
Joined: Thu Jun 29, 2006 5:43 am

Post » Sun May 27, 2012 2:48 pm

I still don't see why we need to know where the player is aiming. As I said, we could easily find out the locations of the hand and forearm, and taken together those two points will yield a line. That line can be used to determine where the player's weapon is aiming, without needing any information on where the reticle is.
Also, I'm not sure about this, but I think that when a player equips a weapon it actually adds a node to them that is the weapon node. I'd need to confirm that though.
User avatar
carley moss
 
Posts: 3331
Joined: Tue Jun 20, 2006 5:05 pm

Post » Sun May 27, 2012 3:51 pm

Well, the way I see it, extending the line taken from those two points would only work properly if you know that the attacker is doing a thrusting attack. A slashing attack would have the weapon more perpendicular to the line than on it. And then you would need to figure out if the attacker is doing a swing from right to left or from left to right. This also doesn't account for dual-wielding.
User avatar
DeeD
 
Posts: 3439
Joined: Sat Jul 14, 2007 6:50 pm

Post » Sun May 27, 2012 12:30 pm

You're assuming that we only use as a third point the tip of the weapon. If we take several mathematical reference points along the length of the blade and reference all of them to the target's nodes, we should come up with a node on body/node on sword match that has the least distance.

Also, if you're worried about the angle being wrong, we could always use a finger node and a wrist node as our reference points, as that alignment would always match the angle of the sword. I don't see why it would matter whether they were dual-wielding, or what direction the attack was coming from. The script's workflow basically just makes it such that every time an actor is hit, the game fills a linked list of globals (well, probably 3, each with an X, Y, or Z coordinate) with several points along a projected length of the blade. Then these linked lists are systematically compared with the coordinates of all the nodes we have attached to the victim's body. Once it finds a smallest distance it will know where the weapon hit approximately.
User avatar
Enie van Bied
 
Posts: 3350
Joined: Sun Apr 22, 2007 11:47 pm

Post » Sun May 27, 2012 8:02 am

Sorry, I did not consider using finger nodes and wrist nodes; I know barely anything about modeling and haven't taken a close look at the skeletons. If it's true that the alignment between the two points will always match the angle of the sword, then what you're suggesting is possible.

It'll still have some limitations, but it should probably work for figuring out where a player hits in melee combat. I guess it'll all come down to how quickly you can find the coordinates of the two points after a hit is registered. I think I'll try it out and see what happens.
User avatar
Elizabeth Davis
 
Posts: 3406
Joined: Sat Aug 18, 2007 10:30 am

Post » Sun May 27, 2012 3:08 am

Let me know how it goes. I'm obviously interested in this, but I can't really understand a lot of the linked list documentation.
User avatar
KRistina Karlsson
 
Posts: 3383
Joined: Tue Jun 20, 2006 9:22 pm

Post » Sun May 27, 2012 10:06 am

I tried with a couple different finger nodes, but the end results were all something like this: http://youtu.be/d8_-zr4hOso

I tested with this script on the dummy:

Spoiler
Scriptname fg109TestObjScript extends ObjectReferenceActivator Property DummyObject AutoActivator Property fg109TestObject AutoEvent OnCellAttach()	WeaponTipNode = PlaceAtMe(fg109TestObject)EndEventEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)	Actor Attacker = akAggressor as Actor	ObjectReference WristNodeR = Attacker.PlaceAtMe(DummyObject, 1, False, True)	ObjectReference FingerNodeR = Attacker.PlaceAtMe(DummyObject, 1, False, True)	WristNodeR.MoveToNode(Attacker, "NPC R Hand [RHnd]")	FingerNodeR.MoveToNode(Attacker, "NPC R Finger01 [RF01]")	Float Reach = Attacker.GetEquippedWeapon().GetReach()	Float Multi = Reach / WristNodeR.GetDistance(FingerNodeR)	Float DeltaX = (FingerNodeR.X - WristNodeR.X) * Multi	Float DeltaY = (FingerNodeR.Y - WristNodeR.Y) * Multi	Float DeltaZ = (FingerNodeR.Z - WristNodeR.Z) * Multi	WeaponTipNode.MoveTo(WristNodeR, DeltaX, DeltaY, DeltaZ)	WristNodeR.Delete()	FingerNodeR.Delete()EndEvent
User avatar
Ice Fire
 
Posts: 3394
Joined: Fri Nov 16, 2007 3:27 am

Post » Sun May 27, 2012 2:33 am

It seems from the video that the node is at the beginning of the animation. Like, somehow during the animation it stops registering where the nodes actually are. Unfortunate.
User avatar
Marine x
 
Posts: 3327
Joined: Thu Mar 29, 2007 4:54 am

Post » Sun May 27, 2012 1:52 am

HAHA! I think I figured out the problem. I'm pretty sure you need to be doing WristNodeX - FingerNodeX instead of the other way around. Right now I think the script is functioning properly, but extending the sword in the wrong direction.
User avatar
Joey Avelar
 
Posts: 3370
Joined: Sat Aug 11, 2007 11:11 am

Post » Sun May 27, 2012 4:24 pm

I'm pretty sure it's supposed to be FingerNode - WristNode, but I tried it both ways.

EDIT: Looked through the creation kit, and the problem is because I was using the weapon's reach. I thought the reach is counted in units but apparently not. I changed to using 128.0 and it looks like it works for regular attacks, although not power attacks.
User avatar
meg knight
 
Posts: 3463
Joined: Wed Nov 29, 2006 4:20 am

PreviousNext

Return to V - Skyrim