Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by rlranft

  1. rlranft

    AI tutorial

    "Exactly?" I would say that you could diff my documentation in GitHub against the official to find out what exactly is different, but beyond that any time the engine changes or new features are added my personal copy gets farther and farther out of date. I think http://roostertailgames.com/TorqueRef/content/documentation/Scripting/Advanced/RTSPrototype.html and http://roostertailgames.com/TorqueRef/content/documentation/Scripting/Advanced/RTSPrototype2.html will still work but I haven't tried to get these scripts functioning in anything after 3.8 so they may have broken due to engine-side changes.
  2. You know, I just remembered that by default the TS functions getRecords()/getFields() are actually for dealing with exactly this in script. Check the comments in Engine\source\console\consoleFunctions.cpp for details.
  3. Theoretically you could set the GuiToolTipProfile.opaque field to false to "turn tool tips off" - it should just make them invisible, they'd still technically be there. I don't recall when the profiles are refreshed exactly so it might not function as expected on a hot-key but it would be okay to use in the preferences file as I'm pretty sure the profile is applied any time a UI element is shown/unhidden. By default GuiToolTipProfile is defined in \modules\Sandbox\1\gui\guiProfiles.cs.
  4. FRAPS used to work, it's what we used to make a few of the demo videos back at GG.
  5. Any particular number used would be if the developer intended to allow the system to handle it in the default manner after that size was reached. For many cases it is irrelevant, as you point out. so using 16 would mean that the developer assumes that the end user would leave the settings such that this LOD would be reached, and also that this would be sufficient between this LOD range and default cull. From my perspective you can use whatever number you want.
  6. That is the size in rendered pixels at which the LOD system switches to that mesh. So, when the object is far enough away that it is 16 pixels across or less, that detail mesh LOD will be used for rendering. Use whatever sizes work for you, but at 1 that mesh will not be displayed until the object is quite distant indeed....
  7. I second this and have done it on several occasions. Also, any time I have used any sort of SQL back-end this is essentially how I have done it. Works like a charm and would result in neater script-side code than my following suggestion: SimGroups are also handy (and can already be created engine-side and passed to script), since they can contain other groups - lists of lists, or "multidimensional arrays", with the added benefit that each object is unique and so can stand in as multimaps (dictionaries that allow multiple "same key" entries) since each SimGroup is a unique object but can have the same internalName (where I'd store the "key" if I wanted this functionality). If you're using SimGroups like this, keep in mind that adding a group to another group removes it from any group it is already a member of - a SimGroup can only belong to one parent. I used this (and dynamic code generation script-side using exec()) when working on the Tower Defense template used in the original 3 Step Studio project for the wave editor tool to allow users to create waves of arbitrary unit count and composition to track and update the GUI elements for displaying current wave contents. So - Create top parent group. Create "array 0 level" group entry 0. Set "array 0 level" entry 0 internalName field to "key" name/value. Create groups (or SimObjects) to add to "array 0 level" group 0 and set internalName to "value" value and add to "array 0 level" group entry 0 until satisfied. Create "array 0 level" group entry 1. Set "array 0 level" entry 1 internalName field to "key" name/value. Create groups (or SimObjects) to add to "array 0 level" group 1 and set internalName to "value" value and add to "array 0 level" group entry 1 until satisfied. Wash, rinse, repeat. Push back to script side via trampoline (using existing examples in engine for guidance). Loop through and populate script-side array from groups. I suppose you could add some syntactic sugar to SimGroup/SimObject to allow script-side access to sub-elements by internalName using array notation if you wanted that - it would sure neaten up the script-side access of these structures and completely eliminate the need to convert the result to an array script-side (as both methods above would require).
  8. rlranft

    AI tutorial

    This is a complex topic. I highly recommend working through all of the World Editor and Scripting documents : http://www.roostertailgames.com/TorqueRef/index.html (this is my personal copy - there are others available that may be more up-to-date). Much of the documentation is outdated but if you're willing to work through the initial learning curve it shouldn't be too hard to adapt the older examples to the newer engine. AI isn't built in, you have to script it yourself. AIPlayer objects exist, but without some scripting they will just stand there.
  9. You can already define a 2d array in torquescript. Why are you fixated on thunking back and forth to C++? http://www.roostertailgames.com/TorqueRef/index.html
  10. Okay, can we get the actual use-case? You can't find any examples of this because there is no need to do this. TorqueScript has multi-dimensional arrays. Why are you not just using them? What is the perceived bottleneck?
  11. Do you need it to do exactly that? Because it'd be pretty simple to create a SimGroup in your engine function, populate it, and return that. SimGroups can be indexed and iterated over in TS. Easier still would be to just make a quick "SimGroup manager" class script-side. What's the exact use-case?
  12. Excellent - now we're getting somewhere! Or, maybe nowhere, because it looks like the code that generates the callback isn't actually passing our object reference to script. Congratulations! Sounds like a bug, buddy! Perhaps wander over to the GitHub repo and log an issue?
  13. If you don't name every rock and tree in your level how do you know the getName() methods don't work? Same for getInternalName() - if it's not set it is an empty string. Of course, getClassName() may or may not work - could just try %obj.class and see what's in that, along with %obj.name. Some objects don't have the getters defined and simply use an exposed field. You can always look in the source (Engine/source/T3D/tsStatic.h and Engine/source/T3D/tsStatic.cpp) to see what is implemented (looking at that dump getClassName() should work, and getName() should work if the object has a name).
  14. I'm just gonna chime in here and say that when the engine was written people were happy just to have decals working - most didn't bother doing anything besides let the decals fade (like T3D does). Old code is old, bro.
  15. On the client functions exist for adding/removing decals, but you have to have the decal's id: decalManagerRemoveDecal(%unit.decal); decalManagerAddDecal(%position, %norm, 0, 1, "destDecal", true);http://www.roostertailgames.com/TorqueRef/content/documentation/Scripting/Advanced/RTSPrototype.html#Spawning_the_Marker
  16. Hmm, that's a good question - I thought these decals were handled client-side, but in source it references gDecalManager so perhaps these are server-side and replicated....
  17. Well, getting stuck more is probably a result of having the higher horizontal resolution while keeping the same vertical size - so more polygons that exceed the "max walkable" slope. So one would have to ensure that the source heightmap was relatively free of noise.
  18. Yeah, that should do the trick - the "downside" is the increase in the terrain data size. So unless you're running the 64 bit build you'll hit the memory cap earlier.
  19. Can we change the versioning scheme? I'd like to offer this: Major version: Dr. Seuss book titles, in alphabetical order ascending. Minor version: Genus/species names of rodents, in alphabetical order by genus first then species ascending. Build/update version: Pastry names from around the world, in alphabetical order ascending. I feel this would make it almost instinctive to understand for even the bloodiest of raw newcomers. As you can see, it follows the natural order of the Universe and therefore is the most natural way to organize such things.
  20. Hey, next time contact me if you need an ugly soundtrack for your video.
  21. No doubt! I use vi much more often than vim. And I voted for .torquescript because I'm perverse that way (I'm a father, after all). And it won't clash.
  22. I use this to keep the side-bar in the docs in sync with the documents - so that the right bit rolls out and stuff is all lined up right: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace tocUpdate { class Program { static void Main(string[] args) { if(args.Length < 1) return; String path = args[0]; List lines = new List(); StreamReader sr = new StreamReader(path + "\\toc.html"); while (!sr.EndOfStream) { lines.Add(sr.ReadLine()); } sr.Close(); int docLine = 0; for(int i = 0; i < lines.Count; ++i) { if(lines.Contains("id = \"doc")) { // this has a doc id int start = 0; int end = 0; int count = 0; int index = 0; while(count <= 3) { if(lines[index] == '\"') { count++; } else if(count == 3) { start = index; count++; break; } index++; } while(count <= 4) { if (lines[index] == '\"') { end = index; count++; break; } index++; } String sub = lines.Substring(start, (end - start)); lines = lines.Replace(sub, "doc" + docLine); // now find the referenced page and update the document id in the script section int hrefStart = lines.IndexOf("href ="); int hrefEnd = hrefStart + 1; char quote = lines[hrefStart]; while (quote != '\"') { ++hrefStart; quote = lines[hrefStart]; hrefEnd = hrefStart + 1; } // should now have index of starting quote for doc path quote = lines[hrefEnd]; while (quote != '\"') { ++hrefEnd; quote = lines[hrefEnd]; } // and the end of the doc path List docLines = new List(); String targetDoc = lines.Substring(hrefStart + 1, (hrefEnd - hrefStart) - 1); targetDoc = targetDoc.Replace('/', '\\'); using (StreamReader docReader = new StreamReader(path + "\\" + targetDoc)) { bool inScript = false; while(!docReader.EndOfStream) { String line = docReader.ReadLine(); if (line.Contains(" inScript = true; if (line.Contains("")) inScript = false; if (!inScript) docLines.Add(line); else { // look for our doc id and update to new id if(line.Contains("pageID")) { String substr = line.Substring(line.IndexOf("pageID")); line = line.Replace(substr, "pageID = " + docLine + ";"); } if(line.Contains("'doc")) { String substr = line.Substring(line.IndexOf("'doc")); line = line.Replace(substr, "'doc" + docLine + "');"); } docLines.Add(line); } } } using (StreamWriter docWriter = new StreamWriter(path + "\\" + targetDoc)) { foreach(String line in docLines) { docWriter.WriteLine(line); } } ++docLine; } StreamWriter sw = new StreamWriter(path + "\\toc.html"); foreach (String line in lines) sw.WriteLine(line); sw.Flush(); sw.Close(); } } } } In case anyone is planning to add stuff to https://github.com/dottools/Torque3D-Documentation.
  23. I've pushed my changes into my fork of the Torque3D-Documentation repository - https://github.com/RichardRanft/Torque3D-Documentation. Note - as I've said before, I only update the stuff I'm interested in. There is still a ton of outdated info there....
  24. Yeah, as the code that damik posted says, it's the player object that the damage originated from. When the weapon is fired the player id is set on the projectile. When the target takes damage it asks the projectile who it belongs to so the right person gets credit for the kill (if it kills them).
  • Create New...