PDA

View Full Version : Fix the Line of Sight bug for Force Powers Force Scream / Master Battle Meditation


WRFan
07-15-2009, 08:05 AM
There's a hardcoded bug in TSL that will affect enemies through walls even if force powers are explicitly set to "affect only if line of sight == TRUE"). E.g., all Force Screams and 2nd and 3rd tiers of Battle Meditation should only affect enemies if there's a line of sight between the caster and the target:

object oTarget = GetFirstObjectInShape(nShape, fShapeSize, lTargetLoc, TRUE, OBJECT_TYPE_CREATURE );

But it doesn't work properly. Similarly, the function GetObjectSeen doesn't work properly, returns TRUE even if enemies are behind walls/closed doors.

I finally managed to find a function that is checking for the line of sight properly, it's called HasLineOfSight. So to fix the problem, modify the Force Scream script like this:


vector vSource = GetPosition( OBJECT_SELF );
vector vTarget = GetPosition( oTarget );
int SeeMe = HasLineOfSight( vSource, vTarget, OBJECT_SELF, oTarget );

if( ( GetRacialType(oTarget) != RACIAL_TYPE_DROID ) &&
GetIsEnemy(oTarget) && SeeMe )
{



Do the same check for Improved/Master Battle Meditation.

Otherwise enemies damaged through walls enter combat state and start determining combat rounds based on the OnDamaged event and then they will run towards your location and attack you. Very annoying if you are already dealing with some other enemies. Happens very often at the Trayus academy on Malachor at the end of the game

Trench
07-15-2009, 12:54 PM
That is sweet! Do you think you could release this fix as a mod to those of us who fail at scripting?:D

N**
07-15-2009, 05:09 PM
This problem exists in KotOR as well, most notably for the Wave and Storm powers.

A quick check showed that neither power does LoS validation. I don't know if the check performed in KotOR's GetFirstObjectInShape() and GetNextObjectInShape() is bugged like you say it is in TSL.

WRFan
07-19-2009, 08:10 AM
It seems to be more complicated than I assumed. There seems to be some problem with the Z coordinate of the vector. If either the source (caster) of the target (enemy) is elevated above ground (standing on some elevated position like a hill or something), the HasLineOfSight function will return FALSE for LOS. It's best to take the Z coordinate out of equation completely by setting a fixed Z value both for source and target vectors:


vector vSource = GetPosition( OBJECT_SELF );
vector vTarget = GetPosition( oTarget );

vector fSource = Vector(vSource.x, vSource.y, 3.0f);
vector fTarget = Vector(vTarget.x, vTarget.y, 3.0f);

int SeeMe = HasLineOfSight( fSource, fTarget, OBJECT_SELF, oTarget );

if( ( GetRacialType(oTarget) != RACIAL_TYPE_DROID ) &&
GetIsEnemy(oTarget) && SeeMe )
{


besides, this function still gets confused from time to time and returns LOS==TRUE even if it's false. It will always determine LOS properly if enemies are behind closed doors, but if enemies are just behind shelves or some other placeable, the function may return LOS== TRUE, even if it's false. Can't be fixed through scripts, it's a hardcoded bug.

Btw, here's an excerpt from k_inc_generic script, which is at the core of all scripting in Kotor 2:


I added this support to make it so that
// ranged-only users will try to chase down the characters.
// But the problem is that the HasLineOfSight function is
// returning vectors that don't actually give line of
// sight -sometimes-. It works about 60%, but the percentage
// goes down the further the player is from the attacker.
// I would like to fix this up in the future if I have time
// to get back to it.


well, I think that says it all. Obviously, Obsidian never found the time to fix the function, because LucasArts were rushing them to finish the game by Christmas. Same old story.

Still, this function works better than the other LOS checking functions, so it's better than nothing.

I also tried to re-write the Force Scream script completely, using a GetNearestCreature loop instead of the GetFirstObjectInShape function. No go though, doesn't determine LOS properly either and slows the computer like hell, eats away the entire CPU. Was supposed to work like this:


int nCnt = 1;
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, nCnt, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);

while (GetObjectIsValid(oTarget))
float fDist = GetDistanceBetween(OBJECT_SELF, oTarget);

if( ( GetRacialType(oTarget) != RACIAL_TYPE_DROID ) &&
GetIsEnemy(oTarget) && fDist < 12.0f)

//do Force Scream

nCnt++;
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, nCnt, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);

// while loop end


But it doesn't work! Enemies get hit by Force scream through closed doors, walls etc. Now I don't know how the game understands the attribute "PERCEPTION_SEEN", maybe it simply means that the creature had been perceived before, without checking for actual LOS. Or maybe it's simply broken.

N**
07-19-2009, 10:59 PM
int SeeMe = HasLineOfSight( fSource, fTarget, OBJECT_SELF, oTarget );
What are the 3rd and 4th parameters being used for in this function? You may be able to specify a normalized point used as the raycasting angle between objects for vSource. It's unlikely, but I don't have TSL installed to try so I thought I'd mention it.

[QUOTE=WRFan;2651971]
It will always determine LOS properly if enemies are behind closed doors, but if enemies are just behind shelves or some other placeable, the function may return LOS== TRUE, even if it's false.
This is probably a stupid question, but are you sure this isn't caused from the increased Z axis?


Btw, here's an excerpt from k_inc_generic script, which is at the core of all scripting in Kotor 2:
Maybe I misread what that employee wrote, but it sounds like he's saying that HasLineOfSight() is occasionally returning true when it shouldn't. His wording is almost too vague to make a guess, but that might happen while chasing enemies down or if the ray distance is longer than the targetting distance.