View Single Post
  #4  
Old 10-15-2012, 01:40 PM
image
Demi-God
 
Join Date: Jan 2002
Posts: 1,290
Default

This is a bit cleaner.. The performance seems about the same, it may matter if the zones have 1000+ npc's.

Code:
Index: common/ruletypes.h
===================================================================
--- common/ruletypes.h	(revision 2231)
+++ common/ruletypes.h	(working copy)
@@ -480,6 +480,14 @@
 RULE_REAL ( EQStream, RetransmitTimeoutMult, 3.0 ) // multiplier applied to rtt stats to generate a retransmit timeout value
 RULE_BOOL ( EQStream, RetransmitAckedPackets, true ) // should we restransmit packets that were already acked?
 RULE_CATEGORY_END()
+
+// Image: Features that are not required but may help improve performance
+RULE_CATEGORY ( Performance )
+RULE_BOOL ( Performance, LOSCacheEnabled, false )
+// The millisecond value is important to be above the time it would take for AI process or something else to trigger CheckLOS.
+// If you have too low of value, say 250ms, the cached entry will most likely be expired before it can be re-used.
+RULE_INT ( Performance, LOSCacheEntryMS, 3000 )
+RULE_CATEGORY_END()
 
 #undef RULE_CATEGORY
 #undef RULE_INT
Index: zone/aggro.cpp
===================================================================
--- zone/aggro.cpp	(revision 2231)
+++ zone/aggro.cpp	(working copy)
@@ -1002,12 +1002,71 @@
 }
 
 
+// Image (10/14/2012): Added LOSEntry as a cache to slow down the attempts against los on the same mob in a short time frame
+bool Mob::FindLosCacheEntry(Mob* other, bool& inLOS, int32& hits)
+{
+	if ( other == NULL || !RuleB(Performance,LOSCacheEnabled) )
+		return false;
+
+	std::map<int16, LOSEntry>::iterator iter = m_LOSCache.find(other->GetID());
+	if ( iter != m_LOSCache.end() )
+	{
+		if ( iter->second.entry == other ) // this means the entry is valid and we have the right mob
+		{
+			if ( Timer::GetCurrentTime() < iter->second.lastChecked )
+			{
+				// Update the entry with the new hits, here we could essentially 'increase' the cache too
+				iter->second.hits += 1;
+				// if this is true then we already have an entry that is at the same location, save it for another period of time
+				if ( iter->second.lastX == other->GetX() &&
+					iter->second.lastY == other->GetY() &&
+					iter->second.ourLastX == GetX() &&
+					iter->second.ourLastY == GetY() )
+					iter->second.lastChecked = Timer::GetCurrentTime() + RuleI(Performance, LOSCacheEntryMS);
+
+				inLOS = iter->second.isLOS;
+				hits = iter->second.hits;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 //Father Nitwit's LOS code
 bool Mob::CheckLosFN(Mob* other) {
 	bool Result = false;
 
+	if ( other == this )
+		return true;
+	
+	int32 hits = 0;
+
+	// Image (10/14/2012): Added LOSEntry as a cache to slow down the attempts against los on the same mob in a short time frame
+	if ( FindLosCacheEntry( other, Result, hits) )
+		return Result;
+
 	if(other)
+	{
 		Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize());
+		
+		if ( RuleB(Performance,LOSCacheEnabled) )
+		{
+			LOSEntry newEnt;
+			newEnt.entry = other;
+			newEnt.isLOS = Result;
+			newEnt.lastChecked = Timer::GetCurrentTime() + RuleI(Performance, LOSCacheEntryMS);
+			newEnt.hits = 1;
+			newEnt.lastX = other->GetX();
+			newEnt.lastY = other->GetY();
+			newEnt.lastZ = other->GetZ();
+			newEnt.ourLastX = GetX();
+			newEnt.ourLastY = GetY();
+			newEnt.ourLastZ = GetZ();
+			m_LOSCache[other->GetID()] = newEnt;
+		}
+	}
 
 	return Result;
 }
Index: zone/command.cpp
===================================================================
--- zone/command.cpp	(revision 2231)
+++ zone/command.cpp	(working copy)
@@ -6723,7 +6723,13 @@
 {
 	if(c->GetTarget())
 	{
-//		if(c->CheckLos(c->GetTarget()))
+		bool los = false;
+		int32 hits = 0;
+		if ( c->FindLosCacheEntry(c->GetTarget(), los, hits) )
+			c->Message(12,"(Client->Mob) Cached entry exists with mob. LOSVisibleStatus: %i.  CacheEntryHits: %i.", los, hits);
+		if ( c->GetTarget()->FindLosCacheEntry(c, los, hits) )
+			c->Message(12,"(Mob->Client) Cached entry exists ON mob. LOSVisibleStatus: %i.  CacheEntryHits: %i.", los, hits);
+
 		if(c->CheckLosFN(c->GetTarget()))
 			c->Message(0, "You have LOS to %s", c->GetTarget()->GetName());
 		else
Index: zone/mob.h
===================================================================
--- zone/mob.h	(revision 2231)
+++ zone/mob.h	(working copy)
@@ -466,6 +466,23 @@
 class EGNode;
 class MobFearState;
 
+// Image (10/14/2012): Added LOSEntry as a cache to slow down the attempts against los on the same mob in a short time frame
+struct LOSEntry {
+	Mob* entry;
+	bool isLOS;
+	int32 lastChecked; // Timer::GetCurrentTime entry to compare
+	int32 hits; // times the entry was hit in the timeframe of the cache
+	// target last location
+	float lastX;
+	float lastY;
+	float lastZ;
+
+	// our last location when we got this entry
+	float ourLastX;
+	float ourLastY;
+	float ourLastZ;
+};
+
 class Mob : public Entity {
 public:
 bool logpos;
@@ -646,6 +663,9 @@
 	inline bool SeeInvisibleUndead() const { return see_invis_undead; } 
 	inline bool SeeHide() const { return see_hide; }
 	inline bool SeeImprovedHide() const { return see_improved_hide; }
+	
+	// Image (10/14/2012): Added LOSEntry as a cache to slow down the attempts against los on the same mob in a short time frame
+	bool FindLosCacheEntry(Mob* other, bool& inLOS, int32& hits);
 
 	bool CheckLos(Mob* other);
 	bool CheckLosFN(Mob* other);
@@ -1256,6 +1276,9 @@
 
 	std::vector<std::string> RampageArray;
 	std::map<std::string, std::string> m_EntityVariables;
+	
+	// Image (10/14/2012): Added LOSEntry as a cache to slow down the attempts against los on the same mob in a short time frame
+	std::map<int16, LOSEntry> m_LOSCache;
 
 	sint16 SkillDmgTaken_Mod[HIGHEST_SKILL+2];
 	sint16 Vulnerability_Mod[HIGHEST_RESIST+2];
__________________
www.eq2emu.com
EQ2Emu Developer
Former EQEMu Developer / GuildWars / Zek Seasons Servers
Member of the "I hate devn00b" club.
Reply With Quote