Author Topic: What's the point?  (Read 1495 times)

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
What's the point?
« Reply #45 on: February 08, 2013, 10:41:07 pm »


               Shadoow: Yes but isn't DCR called in different places?
I know what you mean about those silent shouts: shouting I was attacked to everyone in the same faction. Thus all hostile if you have a PW with a couple hundred members belonging to hostile faction. What a drag. Of course Nwn was not designed for PW, and that was pointed out ad nauseum everytime someone would question something like that. Got rid of that stuff long ago. Mostly I just use perception and hardly any of my npc's have hb's.
Anyway not to knock the game.  Since the difference between early Nwn and the final patch and later even with Shadoow's 1.70 and others work, for instance, made it so much better.  Purely from scripting functionality with the addition of many new functions.  Not to mention all the great haks and such, and custom content.  Really what I am trying to get at is that it is a much superior game. (Preaching to the Choir)!
I tip my cap to all. 
               
               

               


                     Modifié par ffbj, 08 février 2013 - 10:52 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
What's the point?
« Reply #46 on: February 08, 2013, 10:42:31 pm »


               Fair enough. I almost didn't post, for fear of flogging a zombie horse.

If you want to get to the bottom of the 40 heartbeat mystery, post the code and we can have at it. I'll admit it's hard to make sense of, the way you described it. '<img'>

Funky
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
What's the point?
« Reply #47 on: February 08, 2013, 10:44:26 pm »


               

ffbj wrote...

Shadoow: Yes but isn't DCR called in different places?
I know what you mean about those silent shouts: shouting I was attacked to everyone in the same faction.  Thus all hostile if you have a PW with a couple hundred members belonging to hostile faction.  What a drag.  Of course Nwn was not designed for PW, and that was pointed out ad nauseum everytime someone would question something like that.  Got rid of that stuff long ago.  Mostly I just use perception and hardly any of my npc's have hb's.


This is actually one of the reasons that the first suggestion in my delagging tutorial is custom factions. They help even if you've pared out a lot of the excess silent shouting in your ai, as we have.

Funky
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
What's the point?
« Reply #48 on: February 08, 2013, 10:52:02 pm »


               @FFBJ

(spoken on the side of the conversation)
responding to shouts and heartbeats are very useful in AI. In order to reduce their overhead, I do my best to only spawn NPCs when players are able to interact with them. And then I try to get rid of the NPCs as soon as they are unneeded.
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
What's the point?
« Reply #49 on: February 08, 2013, 11:07:27 pm »


               I think that is a valid approach, and I do have a few compact factions still using shouts, and many of my functional npc's do have hb's. But mainly it's stuff like if it's raining get out of the rain.
I think one thing I did was limit the call to a range, because isn't the normal call server wide?
Of course if you have most of your monsters despawning that would not be a problem. Mostly I think lag is incurred with spawning and I have pretty much effectively reduced that cause of lag. For color I usually have things like animals on the perception diet, and then Pc's go away the animal just goes dormant, as you get a bit of lag from destroying/despawning. Still I am no lag expert as a friend says to me..Well you could never run a dozen people in your world cause it would lag out. Mostly related to, imo complex hb pc related and monster and active npc ai of specialized npc's: bounties, masterscouts.etc.. So worst case scenario a large area ,npc's, monsters, pc's all fighting. Problem is I like large areas with mixed melee's.
Funky: Could you like that anit-lag tutorial. I could use a brush up.
Thanks.
You should have said: Flogging an undead horse. But I suppose that a horse of a different color.
               
               

               


                     Modifié par ffbj, 08 février 2013 - 11:10 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
What's the point?
« Reply #50 on: February 08, 2013, 11:13:40 pm »


               Here's the link to the webpage:
Lexicon Lyceum, Lagbusting

Funky
               
               

               
            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
What's the point?
« Reply #51 on: February 08, 2013, 11:19:24 pm »


               Funky's Lag Busting Tutorial

One of the things he suggests to lower problems with silent shouts is to make your hostile creatures members of custom factions rather than the standard Hostile one, so they're not all spamming each other with shouts.

Edit: Too slow!
               
               

               


                     Modifié par Squatting Monk, 08 février 2013 - 11:19 .
                     
                  


            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
What's the point?
« Reply #52 on: February 08, 2013, 11:24:49 pm »


               Prediction: HP's problem with many NPCs in one area is not a TMI error but an AI Update Time Overflow error.

From the Omnibus:

OldMansBeard wrote...

It means, roughly, that you have a script somewhere that is using up too much processor time and locking out some other scripts that are trying to run. Many objects in the game will have heartbeat scripts that are automatically run every 6 seconds. But if it takes more than 6 seconds to run through them all once, the system has a problem and this is what it is trying to tell you.

<snip>

You might have an area with too many placeables and NPCs, each with a reasonable heartbeat script that takes only a little time to run but in total they are too much. But the engine will degrade gracefully in this situation and you would have seen the game get very laggy as you added more and more objects, before you started to get the error message.


               
               

               


                     Modifié par Squatting Monk, 08 février 2013 - 11:33 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
What's the point?
« Reply #53 on: February 09, 2013, 12:14:46 am »


               

ffbj wrote...

I think one thing I did was limit the call to a range, because isn't the normal call server wide?

area-wide

what I did to solve this issue was to create a custom AI that uses only 4 events for monsters that dont have to be smart and that are being butchered by hordes such as spiderlings and other tiny vermins. They dont shout, they dont receive shouts and have no spellcast at script and these four scripts consist of few instructions to attack nearest seen enemy.

Still it doesnt solve much when player uses AOE spells agains them. Druid spamming SoVs, entangle, grease, stonehold still lock up CPU usage over 90% and causes module-wide lags. In fact just spawning around 100 these vermins increased CPU usage over 50%.

Due to this i believe there must be some hardcoded stuff like try to call the onspellcastat script even the creature has no assigned. Or players perception list being updated... dont know exactly, I can only recommend not to spawn so many creatures at once. If anyone interested I can release my low AI for situations like this, but like I said it doesnt help much.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
What's the point?
« Reply #54 on: February 09, 2013, 12:22:38 am »


               I'm interested. One of my upcoming projects is a revamping of my ai, which is still basically a dressed-up x2 ai with some performance tweaks (other than onspawn, where we run a seperate script to apply all sorts of item props and effects based on local vars). I want to add more complex target selection, in part so I can add new item props ala Dragon Age which draw aggro. We already do a little more targeting than the bioware default, which is just plain silly (they REALLY hate druids, for no particular reason), but nothing to write home about.

I figure while I'm doing that I might as well optimize DetermineCombatRound, which is a disaster, to put it kindly. '<img'>

Funky
               
               

               


                     Modifié par FunkySwerve, 09 février 2013 - 12:24 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
What's the point?
« Reply #55 on: February 09, 2013, 12:42:35 am »


               ok here it is: LINK

seems I have forgotten however, I was 4scripts in the beginning but later I had to add other events including heatbeat because creatures in certain situations weren't active

Keep in mind this is specifically designed for stupid creatures with no special abilities. Its not a generic low CPU AI. And due to the missing scripts it might misfunction (creature will not do anything) in certain cases such as casting spells onto target from corner where he cannot see you. This AI also wont call other creatures nearby to fight so creatures in group can be lured away.

There is a few lines of module specific code in OnSpawn such as variable based stealth spawn and despawn, and OnDeath is executing my 2DA xp system so you have to replace it with your own.

BTW: to optimize DetermineCombatRound is definitely good idea. I wanted to do it in my unofficial patch as well, but so far trying to keep the original code as close to default as possible for comparing reasons. Maybe later...
               
               

               


                     Modifié par ShaDoOoW, 09 février 2013 - 12:50 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
What's the point?
« Reply #56 on: February 09, 2013, 06:53:16 am »


               

pope_leo wrote...

Lightfoot8 wrote...
The recursion level level is 0x100 or 256,   It applies to all recersive function calls not just scripts.    Extending it is a little more difficult then increasing the instruction count counter because its limit is based on the size of the buffer originally allocated for the storage of the return pointers.    


I went back and double checked... there is a separate script execution recursion level that has a hard coded limit of 8.

Script a:

void main()
{
    object mod = GetModule();
    int recurse_lvl = GetLocalInt(mod, "RECURSION_LEVEL");
    SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
    SetLocalInt(mod, "RECURSION_LEVEL", ++recurse_lvl);
    ExecuteScript("b", mod);
}

Script b:

void main()
{
    object mod = GetModule();
    int recurse_lvl = GetLocalInt(mod, "RECURSION_LEVEL");
    SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
    SetLocalInt(mod, "RECURSION_LEVEL", ++recurse_lvl);
    ExecuteScript("a", mod);
}

The final print would be "Recursion Level: 7". There will be no feedback if it throws an error.


I found this interesting indeed,  Though I do hate being the one proven wrong.   I was planning on tracing the script through to learn a little more about how this is handled in the VM.  I just have not found the time yet and do not know when I will, So I setteled for a different test for the moment.    Unlike the TMI error that just stops every thing from running,  This limit still allows the scripts that where ran to finish running, It just blocks the 9 script from running.   I modified your script just a tad for the test.  


 void main()
{
    object mod = GetModule();
    int recurse_lvl = GetLocalInt(mod, "RECURSION_LEVEL");
    SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
    SetLocalInt(mod, "RECURSION_LEVEL", ++recurse_lvl);
    ExecuteScript("b", mod);
    SetLocalInt(mod, "RECURSION_LEVEL", --recurse_lvl);
    SpeakString("Recursion Level: " + IntToString(recurse_lvl), TALKVOLUME_SHOUT);
}


The final print was  "Recursion Level: 0".

EDIT:  Due to request, here is the full Log Report. 
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 0
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 1
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 2
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 3
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 4
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 5
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 6
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 7
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 7
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 6
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 5
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 4
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 3
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 2
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 1
[CHAT WINDOW TEXT] [Sat Feb 09 01:44:46] SERVER : [Shout] Recursion Level: 0
               
               

               


                     Modifié par Lightfoot8, 09 février 2013 - 02:59 .
                     
                  


            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
What's the point?
« Reply #57 on: February 13, 2013, 05:01:29 pm »


               Informative thread. Thanks all.
               
               

               


                     Modifié par ffbj, 13 février 2013 - 05:06 .
                     
                  


            

Legacy_Highv Priest

  • Full Member
  • ***
  • Posts: 170
  • Karma: +0/-0
What's the point?
« Reply #58 on: February 18, 2013, 04:58:23 am »


               void main()
{
object oSelf = OBJECT_SELF;
object oKill = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oSelf);
object oCheat = GetNearestObjectByTag("ZombieScan", oKill, 2);
if(!GetLocalInt(oSelf, "bash") && GetAttackTarget() == OBJECT_INVALID)
{
     if(GetObjectSeen(oKill))
     {
      ActionAttack(oKill, FALSE);
     }
      else if(GetLocalInt(oSelf, "RUSH") == FALSE)
      {
       DelayCommand(60.0, SetLocalInt(oSelf, "RUSH", TRUE));
       ActionAttack(oKill, FALSE);
      }
      else if(GetLocalInt(oSelf, "RUSH") == TRUE)
      {
       JumpToObject(oCheat);
       DelayCommand(0.5, ActionAttack(oKill, TRUE));
       SetLocalInt(oSelf, "RUSH", FALSE);
      }
}
}

A few important notes, bash is used to make the zombies attack barriers when blocked by them(they are triggered to hit the barrier by a trigger on the barriers location which sets bash to true, upon the barriers destruction it sets bash to false and they continue, if the barrier doesn't exist then it won't set bash to true[I typed this out in case some players get any ideas from my server >.>]). The majority of the time only the very first parts of the code are -ever- used.
               
               

               


                     Modifié par Highv Priest, 18 février 2013 - 04:59 .
                     
                  


            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
What's the point?
« Reply #59 on: February 18, 2013, 02:59:57 pm »


               This seems a bit non-sequitor, but anyway I like idea of zombies smashing through barriers.  I always got annoyed when flyers would be stopped by gates in the open, why not just fly over them, or cliffs, or tower etc... So I have mine do that.  So the above seems  to say if you can see the enemy attack them.  If not and rush is not set it, wait for 60 seconds then attack. Finally if rush is set then jump to an object "Zombie Scan" I have no idea where that is, and attack the PC.
The general gist seems to be that zoombies don't care if the see you or not, which I do something similar to that.  Sort of the detect life idea, so they will come at you regardless if you are in stealth invisible, etc..
As long as we are sharing zombie scripts here is one of mine:
 redundant conditional checks.
 zombie hb wander around attack chickens if available. ffbj
*/
//:://////////////////////////////////////////////////
//:: Copyright © 2002 Floodgate Entertainment
//:: Created By: Naomi Novik
//:: Created On: 12/22/2002
//:://////////////////////////////////////////////////
#include "nw_i0_generic"
void main()
{
   if (GetIsInCombat()) return;
   //group with others and attack pc
   object oEnemy = GetNearestSeenEnemy();
   object oPC = GetLastPerceived();
   int  iTalentHR = TalentSpellAttack(oEnemy);
     string sWPTag1 = "wp_random";//seed tag of wp. wp's must be placed.
     string sRan = IntToString(d6()); //change dsize for more wp
     string sWPTag = sWPTag1 + sRan; //selects wp_random1-6
     location lWP = GetLocation(GetNearestObjectByTag(sWPTag));
     float fWait = StringToFloat(sRan);
    if (GetAlignmentGoodEvil(oEnemy) != ALIGNMENT_EVIL)
     {
     TalentBuffSelf();
    DelayCommand (fWait,ActionAttack (oEnemy, iTalentHR));
    DelayCommand (6.0, ActionAttack (oEnemy));//slow, methodical, thoughtful, zombies
     }
    else
    DelayCommand (1.0,ActionMoveToLocation(lWP,TRUE));
   object oTarget;
   oTarget = GetNearestObjectByTag("Chicken");
   location lWP1 = GetLocation(oTarget);
   location lWP2 = GetLocation(oEnemy);
    if (GetIsObjectValid(oTarget))
    {
   ActionMoveToLocation(lWP1,TRUE);
   ActionAttack (oTarget);
   return;
    }
     else if ((GetIsObjectValid(oEnemy) && GetDistanceToObject(oEnemy) < 15.0) && !(GetIsInCombat()))
       {
           ActionMoveToLocation(lWP2,TRUE);
           ActionAttack (oEnemy, iTalentHR);
       }
 else if (GetTag(oPC) == ("Zombie"))
 ActionMoveToObject(oPC,FALSE);//group with other zombies
}