TimBob12 Posted March 7, 2011 Share Posted March 7, 2011 Hi there, I wanted to have a go at writing my own function that would allow me to more easily populate a module with NPCs since it can get a bit annoying typing in all the info everytime in the .git file. So I had a go and came up with this: #include "k_inc_generic" #include "k_inc_utility" int Populate(int Amount, string Tag[], Location loc[]); int Populate(int Amount, string Tag[], Location loc[]) { int AutoInc = 0; while(AutoInc < Amount) { CreateObject(OBJECT_TYPE_CREATURE, Tag[AutoInc], Location(Vector(Location loc[AutoInc])); AssignCommand(Tag[AutoInc],ActionRandomWalk()); AutoInc++; } return 0; } int main() { string Tags[3]; location loca[3] float Orient[3]; Tags[0] = "npc_tag1"; Tags[1] = "npc_tag2"; Tags[2] = "npc_tag3"; loca[0] = Location(Vector(0.0, 0.0, 0.0), 0.0); loca[1] = Location(Vector(0.0, 0.0, 0.0), 0.0); loca[2] = Location(Vector(0.0, 0.0, 0.0), 0.0); Populate(3, Tags, loca); return 0; } I then found out that arrays aren't supported. So is there any other way of doing this? I have learnt about structs as an alternative but cannot find a way to apply it to the situation. Any help would be appreciated. Thanks TB12 Link to comment Share on other sites More sharing options...
Darth InSidious Posted March 7, 2011 Share Posted March 7, 2011 I think you're going to have to use a lot of repetition and some random number generation, I'm afraid. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 8, 2011 Author Share Posted March 8, 2011 Could you possibly post an example? Link to comment Share on other sites More sharing options...
Darth InSidious Posted March 8, 2011 Share Posted March 8, 2011 Since I'm not exactly sure what you're trying to do, no. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 8, 2011 Author Share Posted March 8, 2011 I meant could you post an example of how to imitate arrays with random number generation. Link to comment Share on other sites More sharing options...
Darth InSidious Posted March 8, 2011 Share Posted March 8, 2011 No. To make this script work, you're going to have to create a series of custom generic citizens, and assign to each one a particular value. Then, you need to have the script randomly select a value, and randomly generate its own co-ordinates. Since all NPCs snap to walkmesh, it doesn't matter if the Z co-ordinate is wrong. The only problem with this technique is that you're going to end up with a lot of NPCs outside of your area model. Link to comment Share on other sites More sharing options...
Qui-Gon Glenn Posted March 8, 2011 Share Posted March 8, 2011 Most interesting.... Random number generation is simple enough of course, but the array way of doing things would be so much better As far as NPCs outside of the area model, that would be problematic if you would see their tag bubbles through walls... I wonder if that would be the case; if not, not really a big deal. I was not aware of the "snapping" to walkmesh, that is a helpful bit of info... Nice to see ya on Holowan DI, been a while Link to comment Share on other sites More sharing options...
Darth InSidious Posted March 8, 2011 Share Posted March 8, 2011 Actually, the bigger problem is that more NPCs means more for the PC to process, meaning slowdown. Whether or not it also effects the engine, I couldn't say, but given KotOR II's somewhat delicate constitution, it's probably best not to risk it. And nice to see you, too. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 13, 2011 Author Share Posted March 13, 2011 Here is an idea that someone came up with. No idea if it is possible You always can use list. Your environment supports structures: typdef struct { NODEtype*Previous; NODEtype *Next; int Datatype; unsigned long int DabaBlockSize; void *DataBlock; }NODEtype; You an store any object in this node, and concatenate nodes to from a list. by marking the first and last elements, you can traverse the list ack and forth using pointer arithmetics. Pass the list to any funciton by passing a pointer to any element of the list.Preferable, use the first element... but it is not a must. Is this of any use? Link to comment Share on other sites More sharing options...
TimBob12 Posted March 15, 2011 Author Share Posted March 15, 2011 Another problem. Random number generation does not support negative numbers. Link to comment Share on other sites More sharing options...
bead-v Posted March 16, 2011 Share Posted March 16, 2011 int RandomNegative(int i){ return (Random(2*i)-i); } If you enter the int i, this will return you a random int between i and -i. int RandomInt(int iMax=1, int iMin=0){ int Malo = iMin; if(iMin>iMax) Malo=iMax; int iRandom = Malo + Random(abs(iMax-iMin)); return iRandom; } This will get you a random int between the two integers you enter, works with negative ints as well. Hope this helps ya. As for what you're trying to do, I don't think it's that practical. Compare: string Tags[3]; location loca[3] float Orient[3]; Tags[0] = "npc_tag1"; Tags[1] = "npc_tag2"; Tags[2] = "npc_tag3"; loca[0] = Location(Vector(0.0, 0.0, 0.0), 0.0); loca[1] = Location(Vector(0.0, 0.0, 0.0), 0.0); loca[2] = Location(Vector(0.0, 0.0, 0.0), 0.0); Populate(3, Tags, loca); CreateObject(1, "npc_tag1", Location(Vector(0.0, 0.0, 0.0), 0.0)); CreateObject(1, "npc_tag2", Location(Vector(0.0, 0.0, 0.0), 0.0)); CreateObject(1, "npc_tag3", Location(Vector(0.0, 0.0, 0.0), 0.0)); Which one is more typing? And if you want some other things to be executed on the spawned creatures you can just define a new function: void SpawnCreatur(string sResref, location lLoc){ object oCreature = CreateObject(1, sResref, lLoc); AssignCommand(oCreature, ActionRandomWalk()); } void main(){ SpawnCreatur("npc_tag1", Location(Vector(0.0, 0.0, 0.0), 0.0)); SpawnCreatur("npc_tag2", Location(Vector(0.0, 0.0, 0.0), 0.0)); SpawnCreatur("npc_tag3", Location(Vector(0.0, 0.0, 0.0), 0.0)); } As for populating the area without getting any coords, I don't think there's any practical way to do it, if you wanted them all to spawn inside an area model you would have to define where that is, or a little more simple would be defining squares in which they can spawn, but you need 2 coords for that (2 x and 2 y I mean). And that would only be practical if you're spawning more than 2 creatures in the same square. So this would only be useful in modules where there are big open areas where walking is possible everywhere. In closed areas with lots of small rooms and corridors it would prove not so useful. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 16, 2011 Author Share Posted March 16, 2011 Thanks for that, I am getting a script that I think might work. It is still based on random number generation so I can see how it turns out. Will try it later as just opened my new G500 mouse Link to comment Share on other sites More sharing options...
TimBob12 Posted March 16, 2011 Author Share Posted March 16, 2011 Ok, I have this code but its throwing up all sorts of type mismatches and missing arguements. Am stuck now as all seem to have correct arguements. #include "k_inc_generic" #include "k_inc_utility" int RandomInt(int iMax=1, int iMin=0) //Created by bead-v. Thank You { int Malo = iMin; if(iMin>iMax) Malo=iMax; int iRandom = Malo + Random(abs(iMax-iMin)); return iRandom; } void Populate(int Amount, string Tag1, string Tag2, string Tag3) { int Amount = 5; int AutoInc = 0; while(AutoInc < Amount) { object oPC=GetFirstPC(); int Select = Random(3); if(Select == 1) { int x = RandomInt(150); int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag1, Location(Vector(x,y,z),Orient)); AssignCommand(Tag1,ActionRandomWalk()); } if(Select == 2) { int x = RandomInt(150); int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag2, Location(Vector(x,y,z),Orient)); AssignCommand(Tag2,ActionRandomWalk()); } if(Select == 3) { int x = RandomInt(150); int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag3, Location(Vector(x,y,z),Orient)); AssignCommand(Tag3,ActionRandomWalk()); } else { string cmMessage = "Random Spawning Failed..."; SendMessageToPC(oPC, cmMessage); } AutoInc++; } } [HIDDEN] [/img] [/HIDDEN} Link to comment Share on other sites More sharing options...
bead-v Posted March 17, 2011 Share Posted March 17, 2011 #include "k_inc_generic" #include "k_inc_utility" int RandomInt(int iMax=1, int iMin=0) //Created by bead-v. Thank You { int Malo = iMin; if(iMin>iMax) Malo=iMax; int iRandom = Malo + Random(abs(iMax-iMin)); return iRandom; } void Populate(int Amount, string Tag1, string Tag2, string Tag3) { //int Amount = 5; you have already defined this as an argument of the function, you cannot define it again int AutoInc = 0; while(AutoInc < Amount) { object oPC=GetFirstPC(); int Select = Random(3); if(Select == 1) { int x = RandomInt(150); //I hope you know this is exactly the same as Random(150)... if you want it to return between -150 and 150 you have to use the first function I posted. int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag1, Location(Vector(x,y,z),Orient)); //problem here is that the Location() and Vector() functions need *floats* not ints as arugments, so you have to convert the ints to floats first using IntToFloat() AssignCommand(Tag1,ActionRandomWalk()); //Can't assign a command to a tag =P } if(Select == 2) { int x = RandomInt(150); int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag2, Location(Vector(x,y,z),Orient)); AssignCommand(Tag2,ActionRandomWalk()); } if(Select == 3) { int x = RandomInt(150); int y = RandomInt(150); int z = 0; int Orient = Random(360); object NPC1 = CreateObject(OBJECT_TYPE_CREATURE, Tag3, Location(Vector(x,y,z),Orient)); AssignCommand(Tag3,ActionRandomWalk()); } else { string cmMessage = "Random Spawning Failed..."; SendMessageToPC(oPC, cmMessage); } AutoInc++; } } I still don't think this is a good method though.. for example, you wouldn't be able to use this for 905 and 906 because most creatures would just end up outside the area model cuz the areas are either far to the right or far to the left... Link to comment Share on other sites More sharing options...
stoffe Posted March 17, 2011 Share Posted March 17, 2011 Here is an idea that someone came up with. No idea if it is possible (snip!) Is this of any use? NWScript is not a programming language, it's a very limited game engine scripting language with a C-like syntax of what little it is capable of doing. You have no control over memory, there's no such thing as pointers in it. You could probably fake array-like functionality by storing limited amounts of basic data as tokenized strings and have a Get and Set function to pack/unpack the data, but I doubt it would be worth the effort and overhead for most of what you'd usually have need of arrays for. I still don't think this is a good method though.. for example, you wouldn't be able to use this for 905 and 906 because most creatures would just end up outside the area model cuz the areas are either far to the right or far to the left... If you want to distribute NPCs semi-randomly throughout an area I'd just loop through all the waypoint and/or placeable objects in the area, pick out a few and spawn NPCs within a small radius around each. It would still be random-ish, though I think most of them would end up on the walkmesh that way. Link to comment Share on other sites More sharing options...
VarsityPuppet Posted March 19, 2011 Share Posted March 19, 2011 If you want to distribute NPCs semi-randomly throughout an area I'd just loop through all the waypoint and/or placeable objects in the area, pick out a few and spawn NPCs within a small radius around each. It would still be random-ish, though I think most of them would end up on the walkmesh that way. What if you made a function that generated a random vector (or the random coordinates for a vector) between the xmin, xmax and ymin and ymax values of the function? You would of course have to define the xmin/max and ymin/max values in the script. In my experience, if you spawn an npc outside of the walkmesh, the engine will correct its location to the nearest walkable area or sometimes some random places outside the walkmesh I like to call "sticky spots". So say we generate a random vector [7.8, 6.0, 4.0] but the game corrects the NPC's position so it actually spawns at [9.0, 6.0, 4.0]. Could you not then create a function that generates a random vector, tries to spawn an NPC at that vector, then checks to see the actual position of the NPC to sort of guess if the NPC spawned some place it shouldn't, then either delete it or jump it somewhere else. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 19, 2011 Author Share Posted March 19, 2011 That may work but my other idea was to use NPC Perception. e.g I spawn one NPC using either .GIT or script and then create a loop that takes that NPC, finds somewhere in its radius and spawns a new NPC. Then it continues BUT with the next NPC. The loop will stop once the required amount has been reached. They can all be assigned the RandomWalk function. Would this be a better method of random generation. Link to comment Share on other sites More sharing options...
bead-v Posted March 19, 2011 Share Posted March 19, 2011 Hmm, VP is right about the game correcting the positions, I've tested it. So his idea seems to be the best - getting a xmax, xmin, ymax, ymin, then just randomly spawning.. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 20, 2011 Author Share Posted March 20, 2011 Should the xMax etc. be declared in the function itself and how would you find out what to set them as. Sorry about this. I get everything else. Just not how to get the values. Link to comment Share on other sites More sharing options...
bead-v Posted March 20, 2011 Share Posted March 20, 2011 Nope, equip the whereami armband and hop into the module you want to populate... As I've said before, some models are far the left, some are positioned otherwise and so on.. if you want the creatures as evenly spread out as possible it's best you get the coords of the points farthest do the north/east/south/west, and spawn in that rectangle. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 20, 2011 Author Share Posted March 20, 2011 Ok then, thanks for that. Lets see what I can come up with. Link to comment Share on other sites More sharing options...
TimBob12 Posted March 30, 2011 Author Share Posted March 30, 2011 Ok, after lots of attempts and one hell of a lot of school work I finally managed to come up with this #include "k_inc_generic" #include "k_inc_utility" int RandomInt(int iMax=1, int iMin=0) //Created by bead-v. Thank You { int Malo = iMin; if(iMin>iMax) Malo=iMax; int iRandom = Malo + Random(abs(iMax-iMin)); return iRandom; } void Populate(int Amount, int xMin, int xMax, int yMin, int yMax, string Tag) { object oPC = GetFirstPC(); int AutoInc = 0; while(AutoInc<Amount) { AutoInc++; int x = RandomInt(xMax, xMin); int y = RandomInt(yMax, yMin); float z = 0.0; int Orient = Random(360); float x1 = IntToFloat(x); float y1 = IntToFloat(y); float Orient1 = IntToFloat(Orient); object AutoInc = CreateObject(OBJECT_TYPE_CREATURE, Tag, Location(Vector(x1,y1,z), Orient1)); AssignCommand(oPC, ActionRandomWalk()); } } And my main file #include "populate" void main() { string Tag = "ch_guard"; Populate(20, -28, 21, 69, 121, Tag); } But when I attach it to a dialogue nothing happens. It all compiles ok and I am definately attaching the main file not the function file. Im stumped and frankly quite tired. Any ideas? Link to comment Share on other sites More sharing options...
VarsityPuppet Posted March 31, 2011 Share Posted March 31, 2011 Ok, after lots of attempts and one hell of a lot of school work I finally managed to come up with this #include "k_inc_generic" #include "k_inc_utility" int RandomInt(int iMax=1, int iMin=0) //Created by bead-v. Thank You { int Malo = iMin; if(iMin>iMax) Malo=iMax; int iRandom = Malo + Random(abs(iMax-iMin)); return iRandom; } void Populate(int Amount, int xMin, int xMax, int yMin, int yMax, string Tag) { object oPC = GetFirstPC(); int AutoInc = 0; while(AutoInc<Amount) { AutoInc++; int x = RandomInt(xMax, xMin); int y = RandomInt(yMax, yMin); float z = 0.0; int Orient = Random(360); float x1 = IntToFloat(x); float y1 = IntToFloat(y); float Orient1 = IntToFloat(Orient); [b][color="DarkOrange"]object AutoInc = CreateObject(OBJECT_TYPE_CREATURE, Tag, [/color][/b] Location(Vector(x1,y1,z), Orient1)); AssignCommand(oPC, ActionRandomWalk()); } } Might have something to do with the code in orange. Link to comment Share on other sites More sharing options...
bead-v Posted April 1, 2011 Share Posted April 1, 2011 TB, I think you're not including the script correctly.. if your script name is "example.nss", you have to place it in the override folder, and then compile the script that makes a reference to it, which is supposed to look like this: #include "example.nss" I see no '.nss' in your reference.. It might still work though.. Also, the thing you call a "tag" is actually a reference that is set in the advanced tab in kt. Just make sure you wrote down the correct name. Oh, and by the way, why are you making the PC walk randomly? ... and I just noticed what VP was referring to... you declared the same variable two times, the Autoinc one. Link to comment Share on other sites More sharing options...
TimBob12 Posted April 1, 2011 Author Share Posted April 1, 2011 Wow it must have been late when I wrote this. Bead-v yes I have included it properly but you don't need the .nss extension. When I first wrote it a load of compiling errors came up through the main script referenced to populate.nss. The reason I had that as AutoInc was that I was wondering if I had to have an individual variable name for each NPC cos otherwise wouldn't it keep respawning the same NPC in several different places? Testing....... No it doesn't and they spawn randomly HURRAH! I have managed to get up to 200 spawned characters before the engine becomes Unplayable. Thank you everyone for help on this. I will post screenshots and code ASAP. Just noticed 300 posts Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.