Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / debug_client.cpp
blobcbceca4ef3340829b9034f1ccbc3d1987fac212d
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /////////////
25 // INCLUDE //
26 /////////////
27 #include "stdpch.h" // First include for pre-compiled headers.
29 // Misc
30 #include "nel/misc/file.h"
31 #include "nel/misc/async_file_manager.h"
32 // 3d
33 #include "nel/3d/u_text_context.h"
35 // Client
36 #include "debug_client.h"
37 #include "graph.h"
38 #include "client_cfg.h"
39 #include "net_manager.h"
40 #include "user_entity.h"
41 #include "view.h"
42 #include "login.h"
43 #include "user_agent.h"
44 #include "interface_v3/interface_manager.h"
45 #include "interface_v3/sphrase_manager.h"
46 #include "entities.h"
47 #include "nel/gui/lua_helper.h"
48 using namespace NLGUI;
49 #include "character_cl.h"
50 #include "r2/editor.h"
51 #include "r2/dmc/client_edition_module.h"
52 #include "nel/gui/lua_manager.h"
54 ///////////
55 // USING //
56 ///////////
57 using namespace NL3D;
58 using namespace NLMISC;
59 using namespace std;
60 using namespace R2;
63 ////////////
64 // GLOBAL //
65 ////////////
66 #if defined(NL_OS_WINDOWS)
67 MEMORYSTATUS MemoryStatus;
68 #endif
69 bool FreezeGraph = false;
71 //the NEL 3d textcontext
72 extern NL3D::UTextContext *TextContext;
73 extern uint8 ShowInfos; // 0=no info 1=text info 2=graph info 3=streaming info 4=fps only
74 extern UDriver *Driver;
76 /// domain server version for patch
77 extern string R2ServerVersion;
79 #define DIV 1024
80 #define WIDTH 7
81 static const char *divisor = "K";
83 // Check if the stack is empty (of debug str not infos).
84 uint DebugStackEmpty = true;
85 // vector that contains debug strings.
86 std::vector<std::string> DebugStack;
88 COFile DebugFile;
89 bool IsDebugFile = false;
90 // Verbose mode about the animation of the selection.
91 bool VerboseAnimSelection = false;
92 // Verbose mode about the animation of the user.
93 bool VerboseAnimUser = false;
94 // Verbose Mode about visual properties.
95 bool VerboseVP = false;
96 // Slot of the entity to display with the debug page.
97 CLFECOMMON::TCLEntityId WatchedEntitySlot = CLFECOMMON::INVALID_SLOT;
100 // To Display some Debug information
101 uint32 Verbose = 0;
103 // Time in main loop
104 uint64 IngameEnterTime = 0;
106 ///////////////
107 // FUNCTIONS //
108 ///////////////
109 //-----------------------------------------------
110 // pushInfoStr :
111 // Push a string in a debug stack but will display only if there is a debug string in the stack when flush.
112 //-----------------------------------------------
113 void pushInfoStr(const std::string &str)
115 // Add the string to the debug stack.
116 if (!ClientCfg.Light)
117 DebugStack.push_back(str);
118 }// pushInfoStr //
120 //-----------------------------------------------
121 // pushDebugStr :
122 // Push a string in a debug stack.
123 //-----------------------------------------------
124 void pushDebugStr(const std::string &str)
126 if (!ClientCfg.Light)
128 // Add the string to the debug stack.
129 DebugStack.push_back("=> " + str);
131 // Stack is no more empty.
132 DebugStackEmpty = false;
134 }// pushDebugStr //
136 //-----------------------------------------------
137 // flushDebugStack :
138 // Display 'title' and a warning for each element in the Debug Stack.
139 //-----------------------------------------------
140 void flushDebugStack(const std::string &title)
142 // If debug stack is not empty
143 if(!DebugStackEmpty)
145 if(IsDebugFile)
147 // Log Title.
148 string strTmp = toString(" %s\n", title.c_str());
149 DebugFile.serialBuffer((uint8*)strTmp.c_str(), (uint)strTmp.size());
151 for(uint i=0; i<DebugStack.size(); ++i)
153 strTmp = toString(" %s\n", DebugStack[i].c_str());
154 DebugFile.serialBuffer((uint8*)strTmp.c_str(), (uint)strTmp.size());
157 // Empty line separator
158 strTmp = toString("\n");
159 DebugFile.serialBuffer((uint8*)strTmp.c_str(), (uint)strTmp.size());
161 // No Output File -> nldebug only if DisableNLDebug not set to true
162 else if (!DisableNLDebug)
164 nldebug("%s", title.c_str());
165 for(uint i=0; i<DebugStack.size(); ++i)
166 nldebug(" %s", DebugStack[i].c_str());
168 // Empty line separator
169 nldebug("");
173 // Clean the stack (infos could remain in the stack so clean here).
174 DebugStack.clear();
175 // Stack is empty now.
176 DebugStackEmpty = true;
177 }// flushDebugStack //
179 //-----------------------------------------------
180 // setDebugOutput :
181 // Set an output file to log debugs.
182 //-----------------------------------------------
183 void setDebugOutput(const std::string &filename)
185 // Remove output
186 if(filename.empty())
188 DebugFile.close();
189 IsDebugFile = false;
190 return;
193 // Open The Item Association File
194 if(!DebugFile.open(filename, false, true))
196 nlwarning("setDebugOutput: Cannot Open the '%s'.", filename.c_str());
197 IsDebugFile = false;
199 else
200 IsDebugFile = true;
201 }// setDebugOutput //
205 //-----------------------------------------------
206 // initDebugMemory :
207 // ...
208 //-----------------------------------------------
209 void initDebugMemory()
211 #if defined(NL_OS_WINDOWS)
212 GlobalMemoryStatus(&MemoryStatus);
215 nlwarning("The MemoryStatus structure is %ld bytes long.", stat.dwLength);
216 nlwarning("It should be %d.", sizeof (stat));
217 nlwarning("%ld percent of memory is in use.", stat.dwMemoryLoad);
218 nlwarning("There are %*ld total %sbytes of physical memory.", WIDTH, stat.dwTotalPhys/DIV, divisor);
219 nlwarning("There are %*ld free %sbytes of physical memory.", WIDTH, stat.dwAvailPhys/DIV, divisor);
220 nlwarning("There are %*ld total %sbytes of paging file.", WIDTH, stat.dwTotalPageFile/DIV, divisor);
221 nlwarning("There are %*ld free %sbytes of paging file.", WIDTH, stat.dwAvailPageFile/DIV, divisor);
222 nlwarning("There are %*lx total %sbytes of virtual memory.", WIDTH, stat.dwTotalVirtual/DIV, divisor);
223 nlwarning("There are %*lx free %sbytes of virtual memory.\n", WIDTH, stat.dwAvailVirtual/DIV, divisor);
225 #endif
228 //-----------------------------------------------
229 // memoryUsedSinceLastCall :
230 // ...
231 //-----------------------------------------------
232 double memoryUsedSinceLastCall()
234 #if defined(NL_OS_WINDOWS)
235 MEMORYSTATUS stat;
236 GlobalMemoryStatus(&stat);
238 double mem = (double)MemoryStatus.dwAvailPhys-(double)stat.dwAvailPhys;
240 MemoryStatus = stat;
242 return mem;
245 nlwarning("%ld percent of memory is in use.", stat.dwMemoryLoad);
246 nlwarning("There are %*ld free %sbytes of physical memory.", WIDTH, stat.dwAvailPhys/DIV, divisor);
247 nlwarning("There are %*ld free %sbytes of paging file.", WIDTH, stat.dwAvailPageFile/DIV, divisor);
248 nlwarning("There are %*lx free %sbytes of virtual memory.\n", WIDTH, stat.dwAvailVirtual/DIV, divisor);
250 #endif
251 return std::numeric_limits<double>::quiet_NaN();
256 * Constructor
258 CDebugClient::CDebugClient()
263 #define INFO if (info_is_active(ANIM_INFO)) nlinfo
264 #define INFO (info_is_active(ANIM_INFO)?nlinfo:)
267 INFO("fjkljf %gf %fhgf", dg, dsf);
270 // ***************************************************************************
272 CGraph SpfGraph ("time per frame (100 ms)", 10.0f, 10.0f, 250.0f, 100.0f, CRGBA(0,128,0,255), 0, 100.0f, 3);
273 CGraph CurrentTaskGraph ("current task", 10.0f, 120.0f, 250.0f, 50.0f, CRGBA(0,0,128,255), 0, 1.0f, 3);
274 CGraph VRAMDownGraph ("vram download (1Mo)", 10.0f, 180.0f, 250.0f, 50.0f, CRGBA(128,0,0,255), 0, 1.f, 3);
275 CGraph VRAMUpGraph ("vram upload (1Mo)", 10.0f, 240.0f, 250.0f, 50.0f, CRGBA(128,0,0,255), 0, 1.f, 3);
276 CGraph OpenedFileGraph ("fopen (10)", 10.0f, 300.0f, 250.0f, 50.0f, CRGBA(128,128,0,255), 0, 10.f, 3);
277 CGraph ByteReadGraph ("byte read (500 ko)", 10.0f, 360.0f, 250.0f, 100.0f, CRGBA(0,128,128,255), 0, 500, 3);
278 CGraph ByteReadGraphInstant ("instant byte read (500 ko)", 10.0f, 470.0f, 250.0f, 100.0f, CRGBA(64,0,128,255), 0, 500, 3);
279 CGraph FileReadGraph ("fread (10)", 10.0f, 580.0f, 250.0f, 50.0f, CRGBA(128,0,128,255), 0, 10, 3);
280 CGraph LuaMemGraph ("Lua memory (mb)", 290.0f, 10.0f, 250.0f, 100.0f, CRGBA(0,128,64,255), 0, 64.0f, 3);
282 void displayStreamingDebug ()
284 // Yoyo: display with getPerformanceTime() for better precision.
285 static TTicks oldTick = CTime::getPerformanceTime();
286 TTicks newTick = CTime::getPerformanceTime();
287 double deltaTime = CTime::ticksToSecond (newTick-oldTick);
288 oldTick = newTick;
289 static NLMISC::CValueSmoother smooth;
290 smooth.addValue((float)deltaTime);
291 deltaTime = deltaTime * 5.0f / 6.0f;
292 float deltaTimeSmooth = smooth.getSmoothValue () * 5.0f / 6.0f;
294 if (!FreezeGraph)
296 // Vram delta
297 static uint32 lastVRAMUsed = Driver->profileAllocatedTextureMemory();
298 uint32 VRAMUsed = Driver->profileAllocatedTextureMemory();
299 sint value = (sint)VRAMUsed-(sint)lastVRAMUsed;
300 if (value>=0)
302 VRAMUpGraph.addOneValue ((float)value/(1024.f*1024.f));
303 VRAMDownGraph.addOneValue (0);
305 else
307 VRAMDownGraph.addOneValue ((float)(-value)/(1024.f*1024.f));
308 VRAMUpGraph.addOneValue (0);
310 lastVRAMUsed = VRAMUsed;
312 // File opened delta
313 static uint32 lastFileOpened = CIFile::getNumFileOpen();
314 uint32 fileOpened = CIFile::getNumFileOpen();
315 OpenedFileGraph.addOneValue((float)(fileOpened-lastFileOpened));
316 lastFileOpened=fileOpened;
318 // Byte read delta
319 static uint32 lastByteRead = CIFile::getReadFromFile();
320 uint32 byteRead = CIFile::getReadFromFile();
321 ByteReadGraph.addOneValue((float)CIFile::getReadingFromFile()/1024.f);
322 ByteReadGraphInstant.addOneValue((float)(byteRead-lastByteRead)/1024.f);
323 lastByteRead=byteRead;
325 // Byte read delta
326 static uint32 lastFileRead = CIFile::getNumFileRead();
327 uint32 fileRead = CIFile::getNumFileRead();
328 FileReadGraph.addOneValue((float)(fileRead-lastFileRead));
329 lastFileRead=fileRead;
331 // MS per frame
332 SpfGraph.addOneValue (1000.f*(float)deltaTime);
334 // lua memory
335 LuaMemGraph.addOneValue(CLuaManager::getInstance().getLuaState()->getGCCount() / 1024.f);
337 // Count of waitinf instance
338 CurrentTaskGraph.addOneValue (CAsyncFileManager::getInstance().isTaskRunning()?1.f:0.f);
341 // Add graph value
343 if(ShowInfos == 3)
345 float lineStep = ClientCfg.DebugLineStep;
346 float line;
348 // Initialize Pen //
349 //----------------//
350 // Create a shadow when displaying a text.
351 TextContext->setShaded(true);
352 TextContext->setShadeOutline(false);
353 // Set the font size.
354 TextContext->setFontSize(ClientCfg.DebugFontSize);
355 // Set the text color
356 TextContext->setColor(ClientCfg.DebugFontColor);
358 // TOP LEFT //
359 //----------//
360 TextContext->setHotSpot(UTextContext::TopLeft);
362 // FPS and Ms per frame
363 line = 0.99f;
364 TextContext->printfAt(0.01f, line, "STREAMING INFORMATION");
365 if(deltaTimeSmooth != 0.f)
366 TextContext->printfAt(0.8f, line,"%.1f fps", 1.f/deltaTimeSmooth);
367 else
368 TextContext->printfAt(0.8f, line,"%.1f fps", 0.f);
369 TextContext->printfAt(0.9f, line, "%d ms", (uint)(deltaTimeSmooth*1000));
372 // Dump the task array
373 line = 0.90f;
374 TextContext->printfAt(0.3f, line,"Task manager:");
375 line -= lineStep;
376 static vector<string> names;
377 CAsyncFileManager::getInstance().dump(names);
378 uint i;
379 for (i=0; i<names.size (); i++)
381 TextContext->printfAt(0.3f, line, " %s", names[i].c_str());
382 line -= lineStep;
385 // Dump the opened file array
386 line = 0.90f;
387 TextContext->printfAt(0.65f, line,"Files opened:");
388 line -= lineStep;
389 CIFile::dump(names);
390 for (i=0; i<names.size (); i++)
392 TextContext->printfAt(0.65f, line, " %s", names[i].c_str());
393 line -= lineStep;
396 // No more shadow when displaying a text.
397 TextContext->setShaded(false);
398 TextContext->setShadeOutline(false);
402 // ***************************************************************************
404 Display short debug information of FartTP / reselectperso events
406 class CDebugConnectionHistory
408 public:
409 enum TEvent
411 ServerHopEvent= 0,
412 FarTPEvent,
413 ReselectPersoEvent,
414 NumDebugConnectionEvent
417 public:
418 CDebugConnectionHistory()
420 MaxQueueSize= 8;
421 for(uint i=0;i<NumDebugConnectionEvent;i++)
422 EventCounters[i]= 0;
425 // Add a connection event
426 void debugAddConnectionEvent(TEvent ev)
428 nlassert(ev<NumDebugConnectionEvent);
429 EventCounters[ev]++;
430 EventQueue.push_back(ev);
431 if(EventQueue.size()>MaxQueueSize)
432 EventQueue.pop_front();
435 // display debug information in a string
436 void debugDisplayConnectionEvent(string &str)
438 // display counters
439 for(uint i=0;i<NumDebugConnectionEvent;i++)
441 str+= toString("%s: %d\n", CounterNames[i], EventCounters[i]);
443 // display queue of last events:
444 str+= "Connection Events: ";
445 for(uint i=0;i<EventQueue.size();i++)
447 if(i>0)
448 str+= ", ";
449 // Avoid crash in the crash log: in the improbable case where EventQueue has been crashed, at least don't crash here
450 uint index= EventQueue[i];
451 clamp(index,0U,uint(NumDebugConnectionEvent-1));
452 str+= EventNames[index];
454 str+= "\n";
457 private:
458 static const char *EventNames[NumDebugConnectionEvent];
459 static const char *CounterNames[NumDebugConnectionEvent];
461 uint EventCounters[NumDebugConnectionEvent];
462 deque<TEvent> EventQueue;
463 uint MaxQueueSize;
466 static CDebugConnectionHistory DebugConnectionHistory;
467 const char *CDebugConnectionHistory::EventNames[CDebugConnectionHistory::NumDebugConnectionEvent]=
468 {"HOP", "FTP", "RSL"};
469 const char *CDebugConnectionHistory::CounterNames[CDebugConnectionHistory::NumDebugConnectionEvent]=
470 {"NumServerHOP", "NumFarTP", "NumReselectPerso"};
473 // extern methods
474 void crashLogAddServerHopEvent()
476 DebugConnectionHistory.debugAddConnectionEvent(CDebugConnectionHistory::ServerHopEvent);
478 void crashLogAddFarTpEvent()
480 DebugConnectionHistory.debugAddConnectionEvent(CDebugConnectionHistory::FarTPEvent);
482 void crashLogAddReselectPersoEvent()
484 DebugConnectionHistory.debugAddConnectionEvent(CDebugConnectionHistory::ReselectPersoEvent);
488 // ***************************************************************************
489 string getDebugInformation()
491 string str;
493 str += toString("UserId: %u\n", NetMngr.getUserId());
494 str += toString("HomeId: %u\n", CharacterHomeSessionId.asInt());
495 extern TSessionId HighestMainlandSessionId;
496 str += toString("ShardId: %u\n", HighestMainlandSessionId.asInt());
497 extern bool IsInRingSession;
498 if (IsInRingSession)
500 if (getEditor().isInitialized())
501 str += toString("SessionId: %u\n", getEditor().getDMC().getEditionModule().getCurrentAdventureId().asInt());
502 extern R2::TUserRole UserRoleInSession;
503 str += toString("Role: %s\n", UserRoleInSession.toString().c_str());
505 else
507 str += toString("On a Mainland Shard\n");
509 CConfigFile::CVar *varPtr= ClientCfg.ConfigFile.getVarPtr("Application");
510 if(varPtr)
511 str += toString("Application: %s\n", varPtr->asString(0).c_str());
512 else
513 str += toString("Application: NotFound\n");
515 if(UserEntity)
517 str += toString("Player Name: '%s'\n", UserEntity->getEntityName().c_str());
518 str += toString("UserPosition: %.2f %.2f %.2f\n", UserEntity->pos().x, UserEntity->pos().y, UserEntity->pos().z);
520 else
522 str += "No user entity information\n";
525 str += toString("ViewPosition: %.2f %.2f %.2f\n", View.viewPos().x, View.viewPos().y, View.viewPos().z);
526 uint64 timeInGame = ingameTime1 ();
527 str += toString("Time in game: %dh %dmin %dsec\n", (uint)(timeInGame/(60*60*1000)), (uint)(timeInGame/(60*1000))%60, (uint)(timeInGame/1000)%60);
528 str += toString("LocalTime: %s\n", NLMISC::IDisplayer::dateToHumanString(time(NULL)));
529 str += toString("ServerTick: %u\n", NetMngr.getCurrentServerTick());
530 str += toString("ConnectState: %s\n", NetMngr.getConnectionStateCStr());
531 str += toString("LocalAddress: %s\n", NetMngr.getAddress().asString().c_str());
532 str += toString("Language: %s\n", CI18N::getCurrentLanguageName().c_str());
533 str += toString("ClientVersion: %s\n", getDebugVersion().c_str());
534 if (ClientCfg.R2Mode)
536 str += toString("PatchVersion: %s\n", R2ServerVersion.c_str());
538 else if ((ShardSelected >= 0) && (ShardSelected < (sint32)Shards.size()))
540 str += toString("PatchVersion: %s\n", Shards[ShardSelected].Version.c_str());
542 str += string("Client is ") + string((ClientCfg.Local?"off":"on")) + string("line\n");
543 // FarTP/ReselectPerso
544 DebugConnectionHistory.debugDisplayConnectionEvent(str);
546 return str;
549 void resetIngameTime ()
551 IngameEnterTime = T1;
554 uint64 ingameTime0 ()
556 return T0 - IngameEnterTime;
559 uint64 ingameTime1 ()
561 return T1 - IngameEnterTime;
564 // ***************************************************************************
566 void displayNetDebug ()
568 CInterfaceManager *pIM= CInterfaceManager::getInstance();
569 float lineStep = ClientCfg.DebugLineStep;
570 float line;
572 // Initialize Pen //
573 //----------------//
574 // Create a shadow when displaying a text.
575 TextContext->setShaded(true);
576 TextContext->setShadeOutline(false);
577 // Set the font size.
578 TextContext->setFontSize(ClientCfg.DebugFontSize);
579 // Set the text color
580 TextContext->setColor(ClientCfg.DebugFontColor);
583 // BOTTOM RIGHT //
584 //--------------//
585 TextContext->setHotSpot(UTextContext::BottomRight);
586 line = 0.f;
587 // Database Synchronisation counter
588 // Local Counter
589 uint val= pIM->getLocalSyncActionCounter() ;
590 val&= pIM->getLocalSyncActionCounterMask();
591 TextContext->printfAt(1.f, line, "Local Counter: %d", val);
592 line += lineStep;
593 // Inventory Counter
594 val= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:COUNTER")->getValue32();
595 val&= pIM->getLocalSyncActionCounterMask();
596 TextContext->printfAt(1.f, line, "INVENTORY:COUNTER: %d", val);
597 line += lineStep;
598 // Exchange Counter
599 val= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:EXCHANGE:COUNTER")->getValue32();
600 val&= pIM->getLocalSyncActionCounterMask();
601 TextContext->printfAt(1.f, line, "EXCHANGE:COUNTER: %d", val);
602 line += lineStep;
603 // Programme Counter
604 val= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:TARGET:CONTEXT_MENU:COUNTER")->getValue32();
605 val&= pIM->getLocalSyncActionCounterMask();
606 TextContext->printfAt(1.f, line, "TARGET:CONTEXT_MENU:COUNTER: %d", val);
607 line += lineStep;
608 // User Counter
609 val= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:COUNTER")->getValue32();
610 val&= pIM->getLocalSyncActionCounterMask();
611 TextContext->printfAt(1.f, line, "USER:COUNTER: %d", val);
612 line += lineStep;
613 line += lineStep;
615 // SPhrase Execution Synchronisation Counter
616 CSPhraseManager *pPM= CSPhraseManager::getInstance();
617 // Next action
618 uint srvVal= NLGUI::CDBManager::getInstance()->getDbProp(PHRASE_DB_COUNTER_NEXT)->getValue32();
619 uint locVal= pPM->getPhraseNextExecuteCounter() ;
620 srvVal&= PHRASE_EXECUTE_COUNTER_MASK;
621 locVal&= PHRASE_EXECUTE_COUNTER_MASK;
622 TextContext->printfAt(1.f, line, "NextAction (loc/srv): %d/%d", locVal, srvVal);
623 line += lineStep;
624 // CycleAction
625 srvVal= NLGUI::CDBManager::getInstance()->getDbProp(PHRASE_DB_COUNTER_CYCLE)->getValue32();
626 locVal= pPM->getPhraseCycleExecuteCounter();
627 srvVal&= PHRASE_EXECUTE_COUNTER_MASK;
628 locVal&= PHRASE_EXECUTE_COUNTER_MASK;
629 TextContext->printfAt(1.f, line, "CycleAction (loc/srv): %d/%d", locVal, srvVal);
630 line += lineStep;
633 // BOTTOM MIDDLE //
634 //--------------//
635 TextContext->setHotSpot(UTextContext::BottomLeft);
636 float xUser= 0.3f;
637 float xWatched= 0.5f;
638 // Display information about the debug entity slot.
639 if(WatchedEntitySlot != CLFECOMMON::INVALID_SLOT)
641 line = 0.f;
642 TextContext->printfAt(xWatched, line, "Watched");
643 line += lineStep;
644 // Get a pointer on the target.
645 CEntityCL *watchedEntity = EntitiesMngr.entity(WatchedEntitySlot);
646 if(watchedEntity)
647 watchedEntity->displayDebugPropertyStages(xWatched, line, lineStep);
649 // Display information about the user
650 if(UserEntity)
652 line = 0.f;
653 TextContext->printfAt(xUser, line, "User");
654 line += lineStep;
655 UserEntity->displayDebugPropertyStages(xUser, line, lineStep);
660 // ***************************************************************************
661 bool verboseVPAdvanceTest(CEntityCL *en, uint32 form)
663 // TestYoyo: Use this method to test only a part of the entities
664 // was used initialy to debug mektoub mounts bugs.
666 if(!VerboseVP)
667 return false;
669 if( NetMngr.getUserId()!=1507 )
670 return false;
672 // creation test (by form to create)
673 if(form!=0)
675 CSheetId sheetId(form);
676 CSheetId playerSheetId("matis.race_stats");
677 CSheetId mektoubSheetId("chilb2.creature");
678 return (sheetId==playerSheetId || sheetId==mektoubSheetId);
680 // update vp or remove test
681 else
683 CCharacterCL *e= dynamic_cast<CCharacterCL*>(en);
684 if(!e)
685 return false;
686 if( e->isPlayer() || e->getSheet()->Id== CSheetId("chilb2.creature") )
688 return true;
690 return false;