Jump to content
The Dark Mod Forums

Querying entities in script - alternatives ?


motorsep

Recommended Posts

Currently the only way to query an entity in script is by name. So if you don't know the name, you can't do anything. And even if I have a name and suffix, so I could put it into a loop, it's a major slow down.

 

I recall someone saying there are active entities and inactive ones, and C++ code only works with active entities, which is efficient.

 

Is it possible to pull something like that in script (exposing a new function to script) ? I'd really like to have a small pool of entities to go through and reference them by index instead of their name.

Link to comment
Share on other sites

Have a look at http://bugs.thedarkmod.com/view.php?id=3802

 

That was a pretty simple patch i added for 2.03. You could use it too (the commit number is in the tracker). It lets you efficiently get a list of entities by any key/value criteria, including prefix match on name or class, and it communicates by entity pointers not strings.

Link to comment
Share on other sites

@SteveL: Ported, adopting it to Doom 3 code base (compiled successfully). However I have a question.

 

Since Doom 3 has no EventArgs(), I needed to convert this:

 

 

const idEventDef EV_GetNextEntity( "getNextEntity",
EventArgs(
's', "key", "Optional string: prefix for spawnarg key match. E.g. \"target\" will match \"target\", \"target1\" etc.",
's', "value", "Optional string: spawnarg value to match. Can be used independently of ''key''. If ''key'' is not set, all spawnargs will be checked for the value.",
'E', "lastMatch", "Last match: search will start after this entity. Use $null_entity or pass an uninitialized entity variable to start a new search." ),
'e',
"Discover all entities in the map. Returns $null_entity when no more found.");

 

into Doom 3 format, and this is what I got:

 

const idEventDef EV_GetNextEntity( "getNextEntity", "ssE", 'e' );

 

Is it correct ?

 

Also, how does it look like in events.script ?

 

Like this: scriptEvent void getNextEntity( string key, string value, entity lastMatch ); ?

Edited by motorsep
Link to comment
Share on other sites

Hmm. I never used doom3 so I can't say whether it's correct. It doesn't look wrong :) Since you've gone so far you can just test it of course. I put both a test script and the output for events.script on that tracker entry, a bit further down. Yes the script bit you posted looks right too.

Link to comment
Share on other sites

Sort of loosely related -- well not really but this reminded me of it -- was there ever a fix where, when a button or similarly triggered thing calls a script, it passes the button entity to the script (the activated) rather than the player (the activator), as it does currently, even if it were with a new kind of button or entity. If not, I hope someone comes up with something. (Tels tried once.) Sort of in the same ballpark as letting a script know an entity that it otherwise couldn't.

What do you see when you turn out the light? I can't tell you but I know that it's mine.

Link to comment
Share on other sites

Tels has put that in a recent patch for triggers, one that I have in my queue. I don't know whether it ever for fixed for buttons.

 

Edit: googling a bit I see a post from you a while back mentioning the fix broke an fm puzzle. That sounds fixable I'd hope. The spawnarg presumably does nothing in the puzzle?

Link to comment
Share on other sites

Sort of loosely related -- well not really but this reminded me of it -- was there ever a fix where, when a button or similarly triggered thing calls a script, it passes the button entity to the script (the activated) rather than the player (the activator), as it does currently, even if it were with a new kind of button or entity. If not, I hope someone comes up with something. (Tels tried once.) Sort of in the same ballpark as letting a script know an entity that it otherwise couldn't.

Instead of using frob_action_script you can use change_state_callback, which will pass the button, too. You can see this in my FM The Builder Roads.

FM's: Builder Roads, Old Habits, Old Habits Rebuild

Mapping and Scripting: Apples and Peaches

Sculptris Models and Tutorials: Obsttortes Models

My wiki articles: Obstipedia

Texture Blending in DR: DR ASE Blend Exporter

Link to comment
Share on other sites

@SteveL: I am quite new to scripting in DoomScript, so I have a question about the usage of this script function :) I need to run a loop until $null_entity is returned. And inside that loop I need to check for "inline" spawn arg on each entity getNextEntity gets and then if it's "1", I need to remove it.

 

would it be something like:

 

entity e;

while ( e != $null_entity  ) {
          e = sys.getNextEntity("inline","1", e);
          e.remove();
}

 

And I need to call it after level is loaded, to remove inlined entities. What am I missing?

 

Also, is there a way to see entity count on the map? I'd like to spawn as usual, check entities count, then trigger the script and see if it did remove inlined entities.

 

Thanks.

Link to comment
Share on other sites

Not tested because I'm away from home all week but I'll have a go.

 

In TDM (not sure if it's the same in doom3) to run a script at map start after entities have spawned, you call it from main() in your <mymapname>.script file which goes in your maps folder next to your <mymapname>.map file.

 

Your script looks like it'll probably work. Only I'm not sure whether it's safe/reliable to test whether e is null after you just remove()d it. So I'd reorder the script to collect the first e in the while() test itself, and remove it if you found you got a valid entity.

 

A shorthand way to do that is to say

 

while ( e = sys.getNextEntity( blah blah ) )

 

That both assigns the next entity to e and tests whether it's null in a single step. If e becomes null, the while test fails and the loop ends. You don't need to mention $null_entity explicitly. Saying "if (e)" or "while (e)" is the same as saying "if (e) != $null_entity". But by all means put the test in explicitly if you want. It's clearer and easier to read.

 

Anyway, my attempt. I'll stick in an extra test to check the entity is a func static,in case anything else has an "inline" spawnarg.

void removeInlines()
{
  entity e;
  while( e = sys.getNextEntity("inline", "1", e) )
  {
     if ( e.getKey( "classname" ) == "func_static" )
     {
        e.remove();
     }
  }
}


void main()
{
  removeInlines();

  // add any other initialisation stuff
}

Link to comment
Share on other sites

Also, is there a way to see entity count on the map? I'd like to spawn as usual, check entities count, then trigger the script and see if it did remove inlined entities.

 

I missed this bit. Expanded version. You'd save this script as a text file "mymapname.script" matching your actual map name and then it should just work if it works like TDM by the way:

void printEntityCount
{
  float num_ents = 0;
  entity e;
  while( e = sys.getNextEntity("", "", e) )
  {
  num_ents += 1;
  }
  sys.println("Entity count: " + num_ents);
}


void removeInlines()
{
  entity e;
  while( e = sys.getNextEntity("inline", "1", e) )
  {
     if ( e.getKey( "classname" ) == "func_static" )
     {
        e.remove();
     }
  }
}


void main()
{
  printEntityCount();
  removeInlines();
  printEntityCount();
  // add any other initialisation stuff
}

Link to comment
Share on other sites

Thanks SteveL!

 

Afaik the only entity that can have inline key is func_static, that's why I didn't bother with the check. So just to summarize, this script would only roll through the entities with inline key, not through all available entities on the map ?

 

As for entity count, I though there is a cmd in the engine that prints entity count like fps, on the HUD. But script will do for testing purposes :)

Link to comment
Share on other sites

So just to summarize, this script would only roll through the entities with inline key, not through all available entities on the map ?

That's right. The count code is doing them all, but the remover will only touch entities with inline=1.

 

The counting function is obviously inefficient, but like you say that doesn't matter when testing, or when a script will only get run once at map start.

 

Ps. I see I missed the brackets off the first line of the script. Should have been

void printEntityCount()

Link to comment
Share on other sites

Not tested because I'm away from home all week but I'll have a go.

 

In TDM (not sure if it's the same in doom3) to run a script at map start after entities have spawned, you call it from main() in your <mymapname>.script file which goes in your maps folder next to your <mymapname>.map file.

 

Just one quick hint: Insert:

 

sys.waitFrame();

 

or even sys.wait(0.16) which waits roughly 10 frames, before you do any stuff in your main routine.

 

Some entities have scriptobjects with init() routines, and I found that if you spawn a thread in main and/or do other stuff with entities, some of the init() routines have not yet been run. This means some scriptobjects have uninitialized variables and are not in a stable state.

 

For your entity count, it could also mean that some entities are not yet spawned, if they are spawned by init() routines during the first few frames.

 

In this case it is probably not important, but it can bite you later and is very hard to debug why suddenly your map script does some very strange things.

Edited by Tels
  • Like 1

"The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man." -- George Bernard Shaw (1856 - 1950)

 

"Remember: If the game lets you do it, it's not cheating." -- Xarax

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • OrbWeaver

      Does anyone actually use the Normalise button in the Surface inspector? Even after looking at the code I'm not quite sure what it's for.
      · 4 replies
    • Ansome

      Turns out my 15th anniversary mission idea has already been done once or twice before! I've been beaten to the punch once again, but I suppose that's to be expected when there's over 170 FMs out there, eh? I'm not complaining though, I love learning new tricks and taking inspiration from past FMs. Best of luck on your own fan missions!
      · 4 replies
    • The Black Arrow

      I wanna play Doom 3, but fhDoom has much better features than dhewm3, yet fhDoom is old, outdated and probably not supported. Damn!
      Makes me think that TDM engine for Doom 3 itself would actually be perfect.
      · 6 replies
    • Petike the Taffer

      Maybe a bit of advice ? In the FM series I'm preparing, the two main characters have the given names Toby and Agnes (it's the protagonist and deuteragonist, respectively), I've been toying with the idea of giving them family names as well, since many of the FM series have named protagonists who have surnames. Toby's from a family who were usually farriers, though he eventually wound up working as a cobbler (this serves as a daylight "front" for his night time thieving). Would it make sense if the man's popularly accepted family name was Farrier ? It's an existing, though less common English surname, and it directly refers to the profession practiced by his relatives. Your suggestions ?
      · 9 replies
    • nbohr1more

      Looks like the "Reverse April Fools" releases were too well hidden. Darkfate still hasn't acknowledge all the new releases. Did you play any of the new April Fools missions?
      · 5 replies
×
×
  • Create New...