Author Topic: is GetNextObjectInShape() buggy?  (Read 881 times)

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« on: August 18, 2010, 09:53:15 am »


               So, I have been playing with some custom spells, thanks largely to the custom content creation tutorials and the Lexicon. The spell I have most wanted to make is a variation on Firebrand, at least in that there are a number of missiles based on a fraction of caster level, up to the number of available enemies. To make it, I modified DoMissileStorm() to better suit my purpose and that seems to work quite nicely.

However, I noticed that fairly frequently not all the missiles were appearing. The enemies were there, they were visible, there was line of sight, etc., but only one missile would show up despite multiple enemies in range. So, I added some debug code to the spell that sent a note to nwclientLog1.txt after the calls to GetFirstObjectInShape() and GetNextObjectInShape(). I haven't noticed anything unusual with GetFirstObjectInShape() and GetNextObjectInShape() often seems to work fine. But, when I notice too few missiles, I pause and check the log and see that GetNextObjectInShape() has returned 0x7f000000, which is the invalid object that fails the GetIsObjectValid() test and stops the loop. The problem is that there are valid objects there, often right next to the initial target (which can be a creature or a location).

My call to the function was initially
location lTarget = GetSpellTargetLocation(); // outside the loop
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE);
and then I thought maybe something funky was going on with the vOrigin variable, so I changed the call to
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE, vFirstTarget);
where vFirstTarget is defined (also outside the loop as
vector vFirstTarget = GetPositionFromLocation(lTarget);
though I have also tested it with the location of the caster; neither is helpful.

Anyway, the issue is that sometimes GetNextObjectInShape() is saying there are no targets left when there are clearly some left. Initially, I was assuming that I had mucked up something else in my code. But, paying closer attention, I can see the same problem with (unmodified) Firebrand, where sometimes it just ignores all but one of the obvious targets.

Am I doing something wrong? Is this a known issue? Is there a fix. Any hints much appreciated.
               
               

               


                     Modifié par MrZork, 18 août 2010 - 08:55 .
                     
                  


            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #1 on: August 18, 2010, 10:01:08 am »


               BTW, sorry for the lack of nice formatting for the script snippets. I tried using
code tags
but that just seems to use a monospaced font. Is there a
[script]script tag[/script] ?

EDIT: Apparently not...
               
               

               


                     Modifié par MrZork, 18 août 2010 - 09:02 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #2 on: August 18, 2010, 10:58:32 am »


               send whole script, btw for code im using quote, it suit me very well
               
               

               
            

Legacy_C Writer

  • Jr. Member
  • **
  • Posts: 73
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #3 on: August 18, 2010, 01:29:46 pm »


               Are you saying that there are some targets that are never getting hit who are supposed to, or that there are supposed to be more missiles than targets but extra missiles are not recognising NPCs as being eligible targets? Because I believe that the scripting would be quite different in both cases.



What gets me is that I've used GetNextObjectInShape() in order to get everything around the PC and it worked. But are you using the SHAPE_CONE parameter? Becasue according to NWN lexicon, that one is probably buggy due to its single usage in the OC and reports about the shape being incorrect.
               
               

               
            

Legacy_Khuzadrepa

  • Sr. Member
  • ****
  • Posts: 347
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #4 on: August 18, 2010, 02:11:24 pm »


               Are you using GetFirstObjectInShape() to get your first target?  It doesn't look that way from your snippet.  GetFirstObjectInShape MUST be used in conjunction with GetNextObjectInShape().  Details are in the Lexicon. '<img'>
Hope that helps! '<img'>
               
               

               


                     Modifié par Khuzadrepa, 18 août 2010 - 01:17 .
                     
                  


            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #5 on: August 18, 2010, 03:19:13 pm »


               Thanks for the replies. To answer a few things:

Are you saying that there are some targets that are never getting hit who are supposed to, or that there are supposed to be more missiles than targets but extra missiles are not recognising NPCs as being eligible targets? Because I believe that the scripting would be quite different in both cases.

There aren't particular targets who aren't getting hit. In other words, it doesn't seem to be the same one's left out each time, but there are times when one guy gets hit and another right near him does not, though there doesn't seem to be anything different about them.

There are supposed to be as many missiles as enemies in range, up to a limit (caster level/4). This isn't supposed to be like Isaac's where there is any decision to be made about distributing extra missiles. For purposes of the description, it's like Firebrand in that regard (but with fewer missiles). For reference, the spell description is in the code below.

What gets me is that I've used GetNextObjectInShape() in order to get everything around the PC and it worked. But are you using the SHAPE_CONE parameter? Becasue according to NWN lexicon, that one is probably buggy due to its single usage in the OC and reports about the shape being incorrect.

As per the snippet I posted, I am using SHAPE_SPHERE.

Are you using GetFirstObjectInShape() to get your first target?  It doesn't look that way from your snippet.  GetFirstObjectInShape MUST be used in conjunction with GetNextObjectInShape().  Details are in the Lexicon. '<img'>

Yup, I am calling GetFirstObjectInShape() the first time outside my while loop, then doing the remaining calls with GetNextObjectInShape() inside the loop.

I avoided posting the code earlier because it's a bit mucky with comments and debug print statements, but here it is:

[EDIT] I'm sorry, but the code formatted with the quote tags was unreadable. It lost the indentation, lines were wrapping several times, etc. Until I figure out how to post properly here, I guess I will post remotely and give a link.
[EDIT 2] Okay, here's the link (assuming that works like I'm expecting): http://www.stumpyank...-20100818a.html.

As I noted above, I have tried the

vector vFirstTarget = GetPositionFromLocation(lTarget);

with the location of the spell target and with the spellcaster (which is supposed to 1) be the default and 2) not matter for SHAPE_SPHERE), but it doesn't seem to fix the problem.

BTW, as I mentioned, I had never noticed that Firebrand does the same thing at times, but it does. It uses the DoMissileStorm() function (just like the Isaac's spells). I think the issue may be with targeting enemies who aren't close to the caster. That's why I started playing with the vOrigin parameter, suspecting that it was centering the sphere around the caster instead of around the target. But, my attempted fix of specifying that the center is at the target didn't pan out, so that may not be the issue.
               
               

               


                     Modifié par MrZork, 18 août 2010 - 02:39 .
                     
                  


            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #6 on: August 18, 2010, 06:24:56 pm »


               Buggy? (That depends on who wrote it or how good it's written)

Laggy? (Probably, unless it is carefully coded)

It is however a necessary code, because many spells & scripts use it..
               
               

               


                     Modifié par Genisys, 18 août 2010 - 05:25 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #7 on: August 18, 2010, 06:44:23 pm »


               Here is What I think you are running into.  Or at least what I have noticed with spells like fireball.  



The Creatures In The spells affected area has changed between the time the Inpact script ran and the time when the Visual Effects are playing.  



ex.   mage casts the spell while the targets are rushing at him.     Creature A Is 10 feet behind Creature B When the inpact script goes off.  When the Visuals of the Spell are seen Creature A and B are standing right next to each other attacking the caster.  However Creature A get hit by the spell but creature B does not because he was not in the spells range at the thime the inpact script ran.
               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #8 on: August 18, 2010, 08:33:53 pm »


               Lightfoot8, I wish it were something like that, but, if I am reading that correctly, this isn't that kind of situation. I can see a scenario where a spell caster targets one creature for a Fireball, hoping to hit nearby enemies as well. If the target creature runs toward the caster while the others stand still, by the time the Fireball gets to him, he is far enough away from the others that they are no longer in its blast radius.



However, this spell is having the trouble described even when the target and the other enemies are still pretty near one another (sometimes not moving from the time the spell was cast) when the projectiles get to them.



Moreover, the spell is more like Firebrand than Fireball. Individual missiles go after each enemy (instead of one ball that has a blast radius) and all of the decision about whether the enemies are in the area of effect are made at the same time. So, an enemy running away after that will still be hit (kind of the way ducking behind a way doesn't keep a Magic Missile from hitting a target after the first missile leaves the caster).



I have noticed that targeting a location instead of a creature may be working better, though there is no reason for that to be the case. Targeting a creature or a spot right next to the creature should be the same thing. Though the missile will follow the creature if he moves, the code looks at that position and decides which creatures to hit as soon as the script fires, even if there is a delay between then and when the missiles fire. (Of course, it might matter if the delay between the player choosing to cast the spell and the spell actually firing is large. But, the problem persists even if the targets aren't moving substantially.
               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #9 on: August 18, 2010, 08:36:10 pm »


               

MrZork wrote...

Lightfoot8, I wish it were something like that, but, if I am reading that correctly, this isn't that kind of situation. I can see a scenario where a spell caster targets one creature for a Fireball, hoping to hit nearby enemies as well. If the target creature runs toward the caster while the others stand still, by the time the Fireball gets to him, he is far enough away from the others that they are no longer in its blast radius.

However, this spell is having the trouble described even when the target and the other enemies are still pretty near one another (sometimes not moving from the time the spell was cast) when the projectiles get to them.

Moreover, the spell is more like Firebrand than Fireball. Individual missiles go after each enemy (instead of one ball that has a blast radius) and all of the decision about whether the enemies are in the area of effect are made at the same time. So, an enemy running away after that will still be hit (kind of the way ducking behind a wall doesn't keep a Magic Missile from hitting a target after the first missile leaves the caster).

I have noticed that targeting a location instead of a creature may be working better, though there is no reason for that to be the case. Targeting a creature or a spot right next to the creature should be the same thing. Though the missile will follow the creature if he moves, the code looks at that position and decides which creatures to hit as soon as the script fires, even if there is a delay between then and when the missiles fire. (Of course, it might matter if the delay between the player choosing to cast the spell and the spell actually firing is large. But, the problem persists even if the targets aren't moving substantially.


               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #10 on: August 18, 2010, 08:56:15 pm »


               I can't see any obvious mistake in your script. I would try to use NWN debugger, this will show you exactly what are the targets from GetInShape and also shows you where the script ended.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #11 on: August 18, 2010, 08:57:28 pm »


               I see one thing that could be messing things up. Not sure though. In your GetFirstObjectInShape line(100) you are using SHAPE_SPHERE and you are putting a value in for vOrigin. However that vector should only be used when using cylinder or cone shape.
Same gos for line 168.
               
               

               


                     Modifié par GhostOfGod, 18 août 2010 - 07:58 .
                     
                  


            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #12 on: August 19, 2010, 03:43:06 am »


               ShaDoOoW, Good suggestion. I haven't used the debugger yet. I really need to learn that; it must be much easier than what I am doing now.

GhostOfGod, as noted in the first post, initially I called the function without specifying a vOrigin parameter. I added the last parameter after I noticed the problem. As best I can tell, removing it doesn't help. You are right: I may as well it out, since it is only supposed to be used by the function for the other shapes.
               
               

               


                     Modifié par MrZork, 19 août 2010 - 02:57 .
                     
                  


            

Legacy_ent.devil

  • Newbie
  • *
  • Posts: 24
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #13 on: August 19, 2010, 02:36:58 pm »


               Couple of questions about the uploaded script which have probably crept in during debugging and not going to cause the issue but would help remove them for clarity:



Line 55, nDamage = nDamage; Why?



Line 58, is there a chance the value could be 0 (depending on how rounding is done with the division)?



Line 108, GetObjectType(OBJECT_SELF) so if you're a placeable? Also the OBJECT_TYPE_CREATURE criteria is used in the GetFirst/NextObjectInShape();



Line 158, should that be DURATION_TYPE_INSTANT? (Only mentioned if you are missing the visuals)



What do you get from your debugging PrintStrings?

               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
is GetNextObjectInShape() buggy?
« Reply #14 on: August 20, 2010, 08:23:58 am »


               Good catches ent.devil. :-)

Line 55 looks like a copy-paste blunder.

Line 58 is okay. The spell is level 7, so no casters below 4th level should be casting it. I don't know if there would be an issue if cast from an item, but I'll cross that when I come to it. The spell levels available for item properties are 13 and 24 in IPRP_SPELLS.2DA. My assumption is that the game would not try to have an item cast a level 7 spell with lower than a level 13 caster, but I will at least hope for now that any oddness there isn't at issue for actual spell casters.

Line 108 is leftover from the DoMissileStorm() code. I think it's there with line 109 to check that the targets are visible to the caster (OBJECT_SELF), unless (I am guessing) the caster isn't a person. But it looks like something there may be bugged. I may just take out that part of the check (the parts on lines 108 and 109) to see if it makes a difference. I don't really want to be able to hit enemies invisible to the caster, but those lines of code may not be doing just that anyway.

Line 158 looks like an error. I took that straight from DoMissileStorm(). Since it's there, I assume that it works, but you are right that it should probably be DURATION_TYPE_INSTANT.

An updated version with just those edits is at http://www.stumpyank...-20100819b.html. (And, it looks like I overwrote the previous version linked in earlier post with this new one. Sorry.)

A typical snippet from the debug printstrings is

calling DoMagicMissileStorm(nD8Dice=19, nMissiles=7)
DoMagicMissileStorm: first target=95c (Luskan Frost Giant)
DoMagicMissileStorm: target=95c (Luskan Frost Giant) not resisted, base nDam=90
DoMagicMissileStorm: (empowered) target=95c (Luskan Frost Giant) nDam=135
DoMagicMissileStorm: new target=958 (Luskan Captain)
DoMagicMissileStorm: target=958 (Luskan Captain) not resisted, base nDam=66
DoMagicMissileStorm: (empowered) target=958 (Luskan Captain) nDam=99
DoMagicMissileStorm: new target=7fffffff (Alissra Xandross)
DoMagicMissileStorm: new target=963 (Summoned Elder Air Elemental)
DoMagicMissileStorm: target=963 (Summoned Elder Air Elemental) not resisted, base nDam=71
DoMagicMissileStorm: (empowered) target=963 (Summoned Elder Air Elemental) nDam=106
DoMagicMissileStorm: new target=532 (Siege Golem)
DoMagicMissileStorm: target=532 (Siege Golem) not resisted, base nDam=76
DoMagicMissileStorm: (empowered) target=532 (Siege Golem) nDam=114
DoMagicMissileStorm: new target=52d (Gate Guard)
DoMagicMissileStorm: new target=7f000000 ()
Event added while paused:  EventId: 8   CallerId: 2f    ObjectId: 2f
Event added while paused:  EventId: 8   CallerId: 2f    ObjectId: 2f
Event added while paused:  EventId: 8   CallerId: 2f    ObjectId: 2f
Event added while paused:  EventId: 8   CallerId: 2f    ObjectId: 2f
calling DoMagicMissileStorm(nD8Dice=19, nMissiles=7)
DoMagicMissileStorm: first target=96c (Luskan Archer)
DoMagicMissileStorm: target=96c (Luskan Archer) not resisted, base nDam=94
DoMagicMissileStorm: new target=968 (Luskan Captain)
DoMagicMissileStorm: target=968 (Luskan Captain) not resisted, base nDam=75
DoMagicMissileStorm: new target=970 (Luskan Soldier)
DoMagicMissileStorm: target=970 (Luskan Soldier) not resisted, base nDam=73
DoMagicMissileStorm: new target=7f000000 ()
calling DoMagicMissileStorm(nD8Dice=19, nMissiles=7)
DoMagicMissileStorm: first target=950 (Luskan Frost Giant)
DoMagicMissileStorm: target=950 (Luskan Frost Giant) not resisted, base nDam=92
DoMagicMissileStorm: (empowered) target=950 (Luskan Frost Giant) nDam=138
DoMagicMissileStorm: new target=7f000000 ()


The last run (final 5 lines) is a case where only one enemy was hit, though more were present.

Thanks for those notes. I won't be able to play with this for a couple days, but I hope to get back to it after the weekend.
               
               

               


                     Modifié par MrZork, 20 août 2010 - 07:28 .