Modifié par Vermain, 12 septembre 2013 - 10:32 .
Get*ObjectInShape - Half-Circles
#1
Posté 12 septembre 2013 - 10:32
#2
Posté 12 septembre 2013 - 11:02
Easy way:
// Get the first object in nShape
// - nShape: SHAPE_*
// - fSize:
// -> If nShape == SHAPE_SPHERE, this is the radius of the sphere
// -> If nShape == SHAPE_SPELLCYLINDER, this is the length of the cylinder
// Spell Cylinder's always have a radius of 1.5m.
// -> If nShape == SHAPE_CONE, this is the widest radius of the cone
// -> If nShape == SHAPE_SPELLCONE, this is the length of the cone in the
// direction of lTarget. Spell cones are always 60 degrees with the origin
// at OBJECT_SELF.
// -> If nShape == SHAPE_CUBE, this is half the length of one of the sides of
// the cube
// - lTarget: This is the centre of the effect, usually GetSpellTargetLocation(),
// or the end of a cylinder or cone.
// - bLineOfSight: This controls whether to do a line-of-sight check on the
// object returned. Line of sight check is done from origin to target object
// at a height 1m above the ground
// (This can be used to ensure that spell effects do not go through walls.)
// - nObjectFilter: This allows you to filter out undesired object types, using
// bitwise "or".
// For example, to return only creatures and doors, the value for this
// parameter would be OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR
// - vOrigin: This is only used for cylinders and cones, and specifies the
// origin of the effect(normally the spell-caster's position).
// Return value on error: OBJECT_INVALID
object GetFirstObjectInShape(int nShape, float fSize, location lTarget, int bLineOfSight=FALSE, int nObjectFilter=OBJECT_TYPE_CREATURE, vector vOrigin=[0.0,0.0,0.0])
Use a SHAPE_CONE or SHAPE_SPELLCONE.
More complex answer:
Look at goaneng's Pentagrams and Summoning Circles. He has a hemisphere, which you can rotate in any direction on any axis (x, y, or z). While that code is only for vfx, the inc_draw include has all the vector math already done for you, and very elegantly. You should be able to adapt it pretty easily. As an added plus, he includes a demo module. When I was coding special effects for some of HG's portals, I simply added certain areas from HG to the demo mod and tinkered with the effects until I got exactly what I wanted. In any event, the testing room he provides should help you figure out rotation etc.
[Edit] Doh, just read the latter half of your post, where you do what I usually ask people to do: say what they're going to use it for. This recent thread was extremely helpful when it came to vector math, and had a very similar problem, though he wanted a deflection area in FRONT of the target in that case.
Funky
Modifié par FunkySwerve, 12 septembre 2013 - 11:04 .
#3
Posté 13 septembre 2013 - 12:20
#4
Posté 13 septembre 2013 - 01:16
// Returns TRUE if object oBehind is located behind object oInFront as
// determined by the direction oInFront is facing.
int GetIsLocatedBehind( object oInFront, object oBehind){
if( !GetIsObjectValid(oInFront) || !GetIsObjectValid( oBehind))
return FALSE;
int nFrontType = GetObjectType(oInFront), nRearType = GetObjectType(oBehind));
if ((nFrontType != OBJECT_TYPE_PLACEABLE &&
nFrontType != OBJECT_TYPE_CREATURE) ||
(nRearType != OBJECT_TYPE_PLACEABLE &&
nRearType != OBJECT_TYPE_CREATURE)
return FALSE;
float fFacing = GetFacing(oInFront);
float fBehind = VectorToAngle(GetPositionFromLocation(GetLocation(oBehind)) -GetPositionFromLocation(GetLocation( oInFront)));
while(fFacing > 360.0)
fFacing -= 360.0;
while(fFacing <= 0.0)
fFacing += 360.0;
while(fBehind > 360.0)
fBehind -= 360.0;
while(fBehind <= 0.0)
fBehind += 360.0;
// "Behind" here is defined as 45 degrees left or right of directly 180
// degrees from oInFront's facing direction. To narrow the "cone", change
// the 45.0 to something smaller. Make it larger to widen it. It should
// not be more than 90.0 or else your getting in front of the guy. 90.0
// is directly off his left or right shoulder, 0.0 is directly behind him.
return (fabs( fBehind -fFacing) >= (180.0 -45.0));
}
Funky
#5
Posté 13 septembre 2013 - 01:25
Funky
#6
Posté 13 septembre 2013 - 01:28
#7
Posté 13 septembre 2013 - 03:01
#8
Posté 13 septembre 2013 - 03:14
Also I think Axe's has some unnecessary checks, as GetFacing only returns between 0 and 360, according to the Lexicon, but hey.
Funky
#9
Posté 13 septembre 2013 - 03:29
Lightfoot8 wrote...
Why not just get the angle between your (attacker and target) and compare it to the angle between your (attacker and ally) if your ally is farther away then your target.
I think I might do something like this, yeah. Is it basically just:
-Get angles for myself/ally in comparison to target.
-Add 180 to ally's result.
-Subtract/add 45 degrees (or however large/small I want the flanking area to be) and see if I'm outside of that arc. (As well as making sure to apply sanity checks so I'm not at 480 degrees or something weird!)
-If so, and in range (distance check), I must be flanking.
Along those lines, anyways? I'm still working on streamlining my code, but I think I have the basic jist of it.
#10
Posté 14 septembre 2013 - 02:40
{
vector posAttaker = GetPosition(oAttaker);
vector posTarget = GetPosition(oTarget);
vector posAlly = GetPosition(oAlly);
vector VectorToTargetFromAttacker = posTarget- posAttaker ;
float AngleToTargetFromAttacker = VectorToAngle( VectorToTargetFromAttacker);
vector VectorToAllyFromTarget = posAlly - posTarget;
float AngleToAllyFromTarget = VectorToAngle( VectorToAllyFromTarget);
float DifferanceBetweenAngles = AngleToTargetFromAttacker - AngleToAllyFromTarget;
//Adjust the angle so our results to compair will always be positive by adding
//Half the the test range. This just allows us to be able to do a single
//compairsion check instead of two.
//EDIT: I Need AdjustedAngle to be an int so I can do my sanity check the way
//I like to.
int AdjustedAngle = FloatToInt(DifferanceBetweenAngles) + 45;
// Sainty check. make sure the angle is in the 0 - 360 range.
AdjustedAngle %= 360;
if (AdjustedAngle < 0) AdjustedAngle += 360;
// Check and return if the n adjusted Angle is +/- 45 deg
// since we have already added 45 degrees we only need to check if it is less
// then 90
return AdjustedAngle <= 90;
}
Will hopefully be able to post more information reguarding the code later tonight.
EDIT: Pasting with Chrome is a pain.
Modifié par Lightfoot8, 14 septembre 2013 - 02:43 .
#11
Posté 14 septembre 2013 - 06:37
I'd appreciate it, but thanks for posting what you did.Lightfoot8 wrote...
Will hopefully be able to post more information reguarding the code later tonight.
Funky
#12
Posté 15 septembre 2013 - 09:59

In NWN if point A, B and C where the locations of objects, we could get the position of that object by using the GetPosition function. GetPosition returns it's data in the vector data type. Now many would say that is position is not a vector it is just a single point, since it is not defined in the traditional way, that being a direction and a magnitude. Or lets just say a distance in a direction, the magnitude being the distance.
For that matter, the NWN data type for the vector, does not even store it in the traditional way. Instead of storing them in a structure that contains a distance and a direction element. they are stored in a structure that contains the Change in the x direction and change in the y direction. It is basically the same thing just stored in a different format. Given a direction and distance the change in x and y can be calculated and vice versa.
Stored in this format our position can be considered as a vector from the position (0,0). drawing the vectors for my positions would look like this.
so our positions are fundamentally vectors from the (0,0) position. It is important to note that vectors in themselves do not have a fixed starting location. they only represent a distance and direction that one thing is from another.
To find a vector between two points, subtract the position of your source point from the position of your destination point.

as shown above, the order of the subtraction does not effect the magnitude of the vector. both A-B and B-A have the same magnitude, the only difference in the vectors is that they go in oppsit directions.
For Vermain's problem, if we consider point A to the the position of the attacker and Point B to be the position of the target it is easy to see that angle of vector B-A will give us an angle that we can compare against.

All we need to do for Vermin's problem is compare the differance between the angles for the B-A vector and the angle of the C-B vector.
pA = GetPosition(A)
pB = GetPosition(
pC = GetPosition©
fAngle= VectorToAngle(pB-pA)- VectortoAngle ( pC-pB)
Modifié par Lightfoot8, 22 septembre 2013 - 04:08 .
#13
Posté 15 septembre 2013 - 11:00
vector VectorToTargetFromAttacker = posTarget- posAttaker ;
float AngleToTargetFromAttacker = VectorToAngle( VectorToTargetFromAttacker);
vector VectorToAllyFromTarget = posAlly - posTarget;
float AngleToAllyFromTarget = VectorToAngle( VectorToAllyFromTarget);
float DifferanceBetweenAngles = AngleToTargetFromAttacker - AngleToAllyFromTarget;
Something doesn't look right about this. The AngleToTargetFromAttacker is supplementary to the AngleToAttackerFromTarget (new term). Thus the DifferenceBetweenAngles is supplementary to (AngleToAttackerFromTarget + AngleToAllyFromTarget) which can vary based on orientation (e.g. If both the attacker and ally are due east of the target the difference calculated would be 180. If both the attacker and ally are due north of the target the difference calculated would be 0).
Also fabs (float absolute value) can be used without having to impose a sanity check (or go through the steps of adding half the total angle).
Modifié par WhiZard, 15 septembre 2013 - 11:11 .
#14
Posté 15 septembre 2013 - 11:52
WhiZard wrote...
vector VectorToTargetFromAttacker = posTarget- posAttaker ;
float AngleToTargetFromAttacker = VectorToAngle( VectorToTargetFromAttacker);
vector VectorToAllyFromTarget = posAlly - posTarget;
float AngleToAllyFromTarget = VectorToAngle( VectorToAllyFromTarget);
float DifferanceBetweenAngles = AngleToTargetFromAttacker - AngleToAllyFromTarget;
Thus the DifferenceBetweenAngles is supplementary
No the angles should not be supplementary They would be if I used VectorToAttackerfrom target. but I did not It is the vector to the target from the attacker. Hmm, perhaps I am missing what you are saying. Yes is both are the same direction from the target the difference in the angles will be 180 that is by design, since we want the difference to be 0 when they are directly opposing.
Also fabs (float absolute value) can be used without having to impose a sanity check (or go through the steps of adding half the total angle).
I have gotten burned to many times going that rout. the sanity checks are more for keeping the angles in the 360 range. Even the last script I posted for Shadow was flawed at certain angles due to omitting the sanity checks. As for the + 45, that is just the way I like to do it.
Edit:

The code is using the B-A vector not the A-B vector.
e.g. If both the attacker and ally are due east of the target the difference calculated would be 180. If both the attacker and ally are due north of the target the difference calculated would be 0).
No the difference would still be 180 in both cases, Or should be, I will double check my code later. Given I have not tested it at all.
Modifié par Lightfoot8, 16 septembre 2013 - 04:38 .
#15
Posté 16 septembre 2013 - 03:39
In this case fabs would work as there is no possibility of exceeding 360, but I understand your general dislike of it.
#16
Posté 17 septembre 2013 - 03:26
int GetIsFlanked(object oAttacker, object oTarget, float fAngle = 90.0, object oAlly = OBJECT_INVALID)
{
float fToAttacker = VectorToAngle(GetPosition(oAttacker)- GetPosition(oTarget));
float fToFacing;
if(GetIsObjectValid(oAlly))
fToFacing = VectorToAngle(GetPosition(oAlly) - GetPosition(oTarget));
else
fToFacing = GetFacing(oTarget);
float fBackArc = fabs(fabs(fToAttacker - fToFacing) - 180.0);
return (fBackArc <= fAngle/2);
}
Modifié par WhiZard, 17 septembre 2013 - 03:29 .
#17
Posté 22 septembre 2013 - 04:15
#18
Posté 22 septembre 2013 - 05:34
Thanks,
Funky
#19
Posté 22 septembre 2013 - 06:12
Or in the gray shaded area below.

The facing of the target does not matter. the only check I am doing is to see if they are opposing.
In WiZards version. He accounted for just a single attacker with no ally comming in from behind the target,
note: both scripts would fail to return a TRUE result if both attacker and ally where coming in from behind the target. They are checking more for opposition then flanking.
Modifié par Lightfoot8, 22 septembre 2013 - 06:20 .
#20
Posté 23 septembre 2013 - 12:02
Thanks,
Funky
#22
Posté 23 septembre 2013 - 02:45
FunkySwerve wrote...
Ah, ok, I thought that's what I was reading. I guess in my mind, for a get is flanking function you would just want to know the facing of the target and the position of the attacker - not what the OP specifically requested, I know, but not all that different in the end.
Thanks,
Funky
There are two approaches generally.
1) Backstab: give the target damage/penalties when attacked from behind. For this approach the direction the target is facing is important.
2) Volleying: give the target incrementing damage/penalties as long as it remains between two creatures pushing it back and forth with their blows. For this approach the position of the ally is important.
While my function can be used for both approaches (neglect the ally parameter if you are backstabbing), the OP seemed to describe a backstab model while asking for a function factoring in the position of the ally. So I am not 100% sure if this addresses his concern.
#23
Posté 23 septembre 2013 - 11:04





Retour en haut






