Random number generator inside While loop
#1
Posté 28 juillet 2010 - 03:28
void main()
{
object oCenter = GetObjectByTag("guardbeacon");
string sWay = "Guard";
string sGuard;
object oArea = GetArea(GetEnteringObject());
string sArea = GetTag(oArea);
string sTarget;
int nCount = 1;
object oTarget;
location lTarget;
int iRand = Random(4);
string sRand;
if (sArea == "AmaristanCoastwood")
{
if (GetLocalString(oArea, "Guards") != "yes")
{
SetLocalString(oArea, "Guards", "yes");
sGuard = "amarioutcast001";
oTarget = GetNearestObjectByTag(sWay, oCenter, nCount);
lTarget = GetLocation(oTarget);
while (GetIsObjectValid(oTarget))
{
CreateObject(OBJECT_TYPE_CREATURE, sGuard, lTarget, FALSE);
nCount = nCount + 1;
oTarget = GetNearestObjectByTag(sWay, oCenter, nCount);
lTarget = GetLocation(oTarget);
iRand = Random(4);
if (iRand = 0)
{
sGuard = "amarioutcast001";
}
if (iRand = 1)
{
sGuard = "amarioutcast";
}
if (iRand = 2)
{
sGuard = "arakirirebel";
}
if (iRand = 3)
{
sGuard = "dhazaarioutcast";
}
sRand = IntToString(iRand);
SendMessageToPC(GetEnteringObject(), "iRand is " + sRand);
}
}
}
}
#2
Posté 28 juillet 2010 - 04:28
Modifié par ShaDoOoW, 28 juillet 2010 - 04:29 .
#3
Posté 28 juillet 2010 - 04:29
Try putting a line like this in the OnClientEnter event of the Module Properties:
Random(GetTimeMillisecond());
The other problem is that you are using a while statement but you aren't cycling through any objects using GetFirst and GetNext functions. An if statement would be more appropriate than the while.
Lastly, instead of doing a bunch of if statements you may want to use a switch/case:
iRand = Random(4);
switch(iRand);
{
case 0:
sGuard = "amarioutcast001";
break;
case 1:
sGuard = "amarioutcast";
break;
case 2:
sGuard = "arakirirebel";
break;
case 3:
sGuard = "dhazaarioutcast";
break;
}
-420
#4
Posté 28 juillet 2010 - 06:32
if (iRand = 0)
should be:
if (iRand == 0)
If you want to see the randomness this is how I tested it. I took a part of what you had there and stuck it in a while loop to run 100 times. You will see that you get a pretty even mix. Here's the script:
void main()
{
int iLoops = 100;
int iGuard1;
int iGuard2;
int iGuard3;
int iGuard4;
string sGuard;
while (iLoops >0)
{
int iRand = Random(4);
if (iRand == 0)
{
sGuard = "amarioutcast001";
iGuard1++;
}
if (iRand == 1)
{
sGuard = "amarioutcast";
iGuard2++;
}
if (iRand == 2)
{
sGuard = "arakirirebel";
iGuard3++;
}
if (iRand == 3)
{
sGuard = "dhazaarioutcast";
iGuard4++;
}
iLoops--;
}
string sGuard1 = IntToString(iGuard1);
string sGuard2 = IntToString(iGuard2);
string sGuard3 = IntToString(iGuard3);
string sGuard4 = IntToString(iGuard4);
//sRand = IntToString(iRand);
//SendMessageToPC(GetEnteringObject(), "iRand is " + sRand);
SendMessageToPC(GetEnteringObject(), "Guard1 =" + sGuard1 +
"\\\\\\\\nGuard2 =" + sGuard2 +
"\\\\\\\\nGuard3 =" + sGuard3 +
"\\\\\\\\nGuard4 =" + sGuard4);
}
Hope this helps. Good luck.
EDIT: Please note that for some reason when you put a "\\" in a post here it adds three more to it. There should only be one in front of the "n"s where it says "nGuard2", "nGuard3" and "nGuard4". Not sure why this happens but it can be very problematic to some scripts if people don't catch it.
Modifié par GhostOfGod, 28 juillet 2010 - 06:44 .
#5
Posté 28 juillet 2010 - 06:46
#6
Posté 28 juillet 2010 - 07:49
The NWN compilier should have thrown a total fit over that logic issue, Ivanovich. Not that I just did that myself earlier this week to know that. Nope, not me. Uh uh. *whistles innocently*
#7
Posté 28 juillet 2010 - 09:19
Modifié par Lightfoot8, 28 juillet 2010 - 09:24 .
#8
Posté 30 juillet 2010 - 07:52
All I'm trying to do is - when a PC enters an area - have guards spawn on waypoints already layed out in the module. I've tried the PersistentObject function, to no avail (it did not like the area as the persistent object.
if the creature is "creature001" and the waypoint is "guard" and there are 3 waypoints (but the number could vary in different zones), how on God's green Earth can I simply get the guards to spawn on variable number of waypoints named "Guard" as the PC enters the zone?
This really shouldn't be that difficult, yet I seem to hit a wall each time.
#9
Posté 30 juillet 2010 - 08:09
I've read the response from "420" above, but I cannot figure how else to create the loop without a "while".
#10
Posté 30 juillet 2010 - 08:09
{
object oPC = GetEnteringObject();
object oCenter = GetNearestObjectByTag("x3_plc_evlaltar", oPC);
string sWay = "Guard";
string sGuard;
object oArea = OBJECT_SELF;
string sArea = GetTag(oArea);
string sTarget;
int nCount = 1;
object oTarget;
location lTarget;
int iRand = Random(4);
string sRand;
if (sArea == "AmaristanTownofAbbala")
{
sGuard = "arakhirisoldier1";
oTarget = GetNearestObjectByTag(sWay, oCenter, nCount);
lTarget = GetLocation(oTarget);
if (GetLocalString(oArea, "Guards") != "yes")
{
while (GetIsObjectValid(oTarget))
{
SendMessageToPC(oPC, "Pass");
//CreateObject(OBJECT_TYPE_CREATURE, sGuard, lTarget, FALSE);
nCount = nCount + 1;
oTarget = GetNearestObjectByTag(sWay, oCenter, nCount);
lTarget = GetLocation(oTarget);
}
}
SetLocalString(oArea, "Guards", "Yes");
}
}
#11
Posté 30 juillet 2010 - 08:29
To fix put a check at the top of the script to exit the script if the Entering object is not a PC.
object oPC = GetEnteringObject();
If (!GetIsPC(oPC)) return;
Modifié par Lightfoot8, 30 juillet 2010 - 08:29 .
#12
Posté 30 juillet 2010 - 08:36
string sMan = "The Man"
object oHelper = LastForumHelper();
SendMessageToForumHelper(oHelper, "You = " + sMan + "!! Thanks!");
#13
Posté 30 juillet 2010 - 10:18
What I meant was that if you want to use a while loop the format should look something like this:Ivanovich wrote...
I've read the response from "420" above, but I cannot figure how else to create the loop without a "while".
void main()
{
object oTarget = GetFirstObjectInArea(OBJECT_SELF);
while(GetIsObjectValid(oTarget))
{
if(GetTag(oTarget) == "TargetTag")
{
//Do something to the target then break out of the loop
break;
}
oTarget = GetNextObjectInArea(OBJECT_SELF);
}
}
There are a bunch of helpful GetFirst/GetNext related functions:
GetFirstEffect() GetFirstFactionMember() [Used to cycle through party members] GetFirstInPersistentObject() [Used to cycle through objects in a trigger or an AoE] GetFirstItemInInventory() GetFirstItemProperty() GetFirstObjectInArea() GetFirstObjectInShape() [Also used for auras] GetFirstPC()
In addition you can always use the iLoops method posted by GhostOfGod if you are working with a static number of objects.
-420
Modifié par 420, 30 juillet 2010 - 10:19 .
#14
Posté 31 juillet 2010 - 12:44
#15
Posté 31 juillet 2010 - 12:51
object oPC = GetExitingObject();
object oCenter = GetNearestObjectByTag("guardbeacon", oPC);
but oCenter is always blank, as if it's not picked up. The item "guardbeacon" is in the area the PC just exited. But it seems that if I put this script in the OnExit part of the area, it never finds the "guardbeacon" with this function. Thoughts?
I also tried it with
object oCenter = GetNearestObjectByTag("guardbeacon", OBJECT_SELF);
But the area doesn't get it either.
Modifié par Ivanovich, 31 juillet 2010 - 12:52 .
#16
Posté 31 juillet 2010 - 01:43
Ivanovich wrote...
I stayed away from the GetFirstObjectInArea because of the amount of objects in the area. It might be a cumbersome script on the server.
*************
Here's an additional question. On Exiting the area, I've got this:
object oPC = GetExitingObject();
object oCenter = GetNearestObjectByTag("guardbeacon", oPC);
but oCenter is always blank, as if it's not picked up. The item "guardbeacon" is in the area the PC just exited. But it seems that if I put this script in the OnExit part of the area, it never finds the "guardbeacon" with this function. Thoughts?
I also tried it with
object oCenter = GetNearestObjectByTag("guardbeacon", OBJECT_SELF);
But the area doesn't get it either.
The responce to bout of your last posts are linked.
Once the PC leaves the Area he is no longer in an area. His location in Invalid therefore you can not find any objects that are close to him. Or even get a location for him. You would be best to use GetFirstObjectInArea/GetNextObject in area.
420 is also correct. If you only have 4 waypoints and you are wanting a loop to get all of them you are better off with the GetFirst/GetLast functions. These functions have the advantage if being iterators. This means that every time you call the GetNext function it does not have to start over from scratch and can just start the search back up where the previous function lest off.
The Get Nearest functions are not iterators so every time the function is called it has no ground work laid for it. It will search through every object in the area. then have to calculate which one is closer. There is a lot more over head to this function, It probable even calls the GetFirstObjectInArea/Next functions every tine you use it. unless you actually need the closest x number of objects, you are better off looping through the Objects one time as opposed to x times. without all the distance calculations also.
Modifié par Lightfoot8, 31 juillet 2010 - 01:44 .
#17
Posté 01 août 2010 - 09:28
Your help was sincerely appreciated. Cheers.
Modifié par Ivanovich, 01 août 2010 - 09:33 .
#18
Posté 01 août 2010 - 09:34
Thanks for all your help.
#19
Posté 02 août 2010 - 04:58
Would it be to cycle through all objects with the GetFirst/NextInArea function again? Or is there a simpler way?
#20
Posté 02 août 2010 - 08:11
Just place this function at top of your script and then in your script use:int GetNumPCsInArea(object oArea)
{
if(!GetIsObjectValid(oArea) || GetArea(oArea) != oArea)
{
return 0;
}
object oPC = GetFirstPC();
int nCount;
while(GetIsObjectValid(oPC))
{
if(GetArea(oPC) == oArea)
{
nCount++;
}
oPC = GetNextPC();
}
return nCount;
}
Another method using GetNearestCreature, and that method is more efficient, but when we are speaking about such small codes, it don't matter really.if(GetNumPCsInArea(oArea) == 0)
BTW you might consider to postphone the cleaning area to 2minutes after last PC exit area. Quite often, some player enters area again until that, so cleaning could be quite ineffective. (If you delay cleaning, just must then re-check PC count in area!)
Also, good idea is to reset all encounters when you clean monsters, to ensure players won't exploit cleaning area in order to get safely through area to lower floor.
Modifié par ShaDoOoW, 02 août 2010 - 08:14 .
#21
Posté 02 août 2010 - 08:32
#22
Posté 02 août 2010 - 08:41
void CleanArea()
{
object oArea = OBJECT_SELF;
if(GetNumPCsInArea(oArea) > 0)
{
return;
}
SetLocalInt(oArea,"CLEANED",1);//im checking this when someone enter area to know if I should spawn npcs
object oFirst = GetFirstObjectInArea(oArea);
int nTh = 1;
object oNPC = GetObjectType(oFirst) == OBJECT_TYPE_CREATURE ? oFirst : GetNearestObject(OBJECT_TYPE_CREATURE,oFirst,nTh++);
while(GetIsObjectValid(oNPC))
{
if(GetLocalInt(oNPC,"CLEANME") != -1)
{
DestroyObject(oNPC);
}
oNPC = GetNearestObject(OBJECT_TYPE_CREATURE,oFirst,nTh++);
}
}
void main()
{
object oArea = OBJECT_SELF;
if(GetNumPCsInArea(oArea) > 0)
{
return;
}
DelayCommand(120.0,CleanArea());
}
Modifié par ShaDoOoW, 02 août 2010 - 08:43 .
#23
Posté 03 août 2010 - 11:32
#24
Posté 04 août 2010 - 12:07
When you script the "GetItemActivatedTargetLocation" function, and you've created an item to use a unique power with the same name as used in the script, the process goes as such:
1. You use the item.
2. You target something.
3. If the "something" is greater than a pre-defined distance away, you first MOVE towards that something before your next action.
Is there a way to change that predefined distance to longer? Ie, if I target something on the other side of the screen, can I make it accept the target without moving half the way there? Or is that hardcoded into the engine?
Thx!
Modifié par Ivanovich, 04 août 2010 - 12:07 .
#25
Posté 05 août 2010 - 08:51
2DA V2.0
Label Range Name TargetType
386 ACTIVATE_ITEM S 6802 0x7f
413 ACTIVATE_ITEM_SELF S 6802 0x01
428 ACTIVATE_ITEM_SELF2 S 6802 0x09
697 ACTIVATE_ITEM_L L 83622 0x7f
795 ACTIVATE_ITEM_T T 86781 0x7f
The range collunm can have values of:
Range of spell
P = personal
T = touch
S = short
M = medium
L = long
Target types are as follows.
self = 0x01
creature = 0x02
area = 0x04
items = 0x08
door = 0x10
placeable = 0x20
trigger = 0x40
Modifié par Lightfoot8, 05 août 2010 - 08:56 .





Retour en haut






