Go Back   EQEmulator Home > EQEmulator Forums > Archives > Archive::Development > Archive::Development

Archive::Development Archive area for Development's posts that were moved here after an inactivity period of 90 days.

Reply
 
Thread Tools Display Modes
  #1  
Old 02-05-2004, 12:13 AM
smogo
Discordant
 
Join Date: Jan 2004
Location: 47
Posts: 339
Default

here is a piece of code that might help.

Basically, pre-computes neighborhood for all mobs in zone every x seconds. This is quite fast, and --linear--
in Entity::AggroCheckClose, instead of parsing all mob_list and checking for neighbors, use that cache

Below are two snippets



i used DoorProcess to update neighborhood, as this is called in most zones (if not all) whatever the players in it. Thus, every 5 secs, an update of the terrain (a static singleton of Terrain class) if performed. After this has been called, terrain hopefully has a list (hastable) of all mobs within a given range, for each mob. i know this is not the right place to do it, but for the moment i didn't want to get too intrusive and add pieces of code in net.cpp or wherever.

Code:
--- ../../cvs/eqemu/eqemu/Source/zone/entity.cpp  2004-02-02 13:55:07.000000000 +0000
+++ entity.cpp  2004-02-05 11:18:55.000000000 +0000
@@ -52,6 +52,10 @@
 #define strcasecmp _stricmp
 #endif

+#ifdef KD
+#include "../extra/Vector.h"
+#include "../extra/Terrain.h"
+#endif
 extern Zone* zone;
 extern volatile bool ZoneLoaded;
 extern WorldServer worldserver;
@@ -216,6 +220,24 @@
    else
      iterator.Advance();
  }
+#ifdef KD
+ printf("in EntityList::DoorProcess, time is %4.1f: \n",Timer::GetCurrentTime()*0.001f);
+ LinkedListIterator<Mob*> miter(mob_list);
+ Vector *vmob=new Vector();
+ miter.Reset();
+ while(miter.MoreElements()) {
+   //printf("Yet another mob in the list...\n");
+   vmob->add(miter.GetData());
+   miter.Advance();
+ }
+ printf("got %d entities from mob_list\n",vmob->size());
+ Mob* mobs[vmob->size()];
+ vmob->copyInto(mobs);
+ // aggregate on a max 200.0 distance
+ // this should be dynamically set to the max aggro range of all mobs
+ terrain.update(vmob->size(),mobs,200.0f);
+ delete vmob;
+#endif
  if(count==0)
in MobAI
when checking for a AgrroRadius match, get the vector of mobs that were matched as neighbors. Use this list insted if the full mob_list to check for aggro.
Code:
--- ../../cvs/eqemu/eqemu/Source/zone/MobAI.cpp 2004-02-02 13:54:59.000000000 +0000
+++ MobAI.cpp 2004-02-05 10:41:31.000000000 +0000
@@ -20,6 +20,11 @@
  extern SPDat_Spell_Struct spells[SPDAT_RECORDS];
 #endif

+#ifdef KD
+#include "../extra/LL.h"
+#include "../extra/Terrain.h"
+#endif
+
 extern EntityList entity_list;
 extern Database database;
 extern Zone *zone;
@@ -222,7 +227,34 @@
 Mob* EntityList::AICheckCloseArrgo(Mob* sender, float iArrgoRange, float iAssistRange) {
  if (!sender || !sender->IsNPC())
    return 0;
+#ifdef KD
+ Vector *ngh=terrain.neighbors(sender->GetID());
+ if(ngh==NULL){
+   //printf("Mob::AICheckCloseArrgo , %d has no neighbors\n",sender->GetID());
+   return 0;
+ }
+ int ncount= ngh->size();
+ //printf("Mob::AICheckCloseArrgo , got %d neighbors for %d ",ncount, sender->GetID());
+ Mob* neighbors[ncount];
+ ngh->copyInto(neighbors);
+ //for(int i=0;i<ncount;i++) {
+ //  printf("%d:[%4.1f,%4.1f]", ((Mob*)ngh->get(i))->GetID(),
+ //                          ((Mob*)ngh->get(i))->GetX(), ((Mob*)ngh->get(i))->GetY());
+ //}
+ KDIterator<Mob*> iterator(neighbors,ncount,FORWARD);
+#ifdef KDSTAT
+ printf("%d :",sender->GetID());
+ iterator.Reset();
+ while(iterator.MoreElements()) {
+   Mob* mob = iterator.GetData();
+   printf("<%d>",mob->GetID());
+   iterator.Advance();
+ }
+ printf("\n"); fflush(stdout);
+#endif //KDSTAT
+#else
  LinkedListIterator<Mob*> iterator(mob_list);
+#endif
  iterator.Reset();
  float dist;
  //float distZ;
the other code (Terrain and Hashtable and Vector ... )are a available here
http://perso.wanadoo.fr/afou/khalzed...ighbors.tar.gz
you need to add -DKD and -DKDSTAT to you COPTS in the zone makefile
tune verbosity by editing the VERBOSE define in Terrain.cpp

Tpical output
Code:
...
Request for neighborhood before initializing
Request for neighborhood before initializing
...
Code:
in EntityList::DoorProcess, time is  5.0:
got 55 entities from mob_list
updating terrain, 55 mobs
enter collide with 55 elements
 Terrain::collide for distance 100.0 found :
   54 groups of average size 9.9 (max group : 18 + self),   and 1 lonely
 linear parse : 532 instead of 3025 (17.6%)
leavin collide
nieghbours set
llnear : parse checks wil be made using cache, and thus estimates the amount of cpu used (17,6% means you cut down cpu for check of 82%)

Drawbacks :
* you must select a big-enough value for the cache range checking. on a 'typical' DB :
Code:
mysql> select aggroradius, count(id) from npc_types group by aggroradius;
+-------------+-----------+
| aggroradius | count(id) |
+-------------+-----------+
|           0 |        63 |
|          45 |       152 |
|          65 |     26669 |
|          85 |        37 |
|         200 |     44854 |
+-------------+-----------+
set distance to 200.0f + 20.f (estimated distance moved between two cache updates). The lower, the smaller the groups, thus the less CPU used. But some zones might only have 65.0 agrroradius mobs.

* Use a better timer. Once every second should be fine.

* Nothing ensures that the first call to cache is valid. Thus the first checkings may abort. It does not seem to have any impact, as process goes up normally after the cache has been set.

* the code was written from scratch, or translated from java. It has memory leaks (at least freeing the old hashtable before update, but most probably more). However interfaces are small, so one could easily subst Hashtable and Vector classes for more reliable ones.
As of this code, it gets Sig segv after a few minutes. =(

* some comments are out of date, and irrelevant


Besides this (little) unpleansant effect, results are good. Very good.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 09:18 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3