Jesus4Lyf
Good Idea™
- Reaction score
- 397
Agent Stats
Version 1.2.0
Requirements:
- Jass NewGen
Code:
JASS:
//
// _ ___ ___ __ _ _____ ___ _____ _ _____ ___
// /_\ / __| __| \| |_ _| / __|_ _/_\_ _/ __|
// / _ \ (_ | _|| \ \ | | | \__ \ | |/ _ \| | \__ \
// /_/ \_\___|___|_|\__| |_| |___/ |_/_/ \_\_| |___/
// By Jesus4Lyf. v1.2.0.
//
// What is AgentStats?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// AgentStats is a handle count debugging tool for monitoring the number of
// handles in game, in debug mode.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Create a new trigger object called AgentStats, go to 'Edit -> Convert
// to Custom Text', and replace everything that's there with this script.
//
// Then, import the "trackagents.j" file to "war3mapImported\trackagents.j".
//
// Commands Provided:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Type the following commands in game:
//
// -count Displays the number of agents in the game.
// -count <handle> Displays the number of <handle>s in the game.
// -stats Displays agent stats.
// -stats <handle> Displays <handle> stats.
//
// Examples:
// -stats timer
// -count triggerevent
// -stats
// -count widget
// -count
//
library AgentStats initializer OnInit
globals
private constant integer SEARCH_DEGREE=20
private constant string COMMAND_CHAR="-"
private constant integer COMMAND_CHAR_LENGTH=StringLength(COMMAND_CHAR)
private constant string TRACKER_PATH="war3mapImported\\trackagents.j"
endglobals
globals
private string array TypeName
private hashtable NameToType=InitHashtable()
private constant integer TYPE_UNKNOWN =0
private constant integer TYPE_WIDGET =1
private constant integer TYPE_TRIGGER =2
private constant integer TYPE_DESTRUCTABLE =3
private constant integer TYPE_ITEM =4
private constant integer TYPE_UNIT =5
private constant integer TYPE_TIMER =6
private constant integer TYPE_HASHTABLE =7
private constant integer TYPE_TRIGGEREVENT =8
private constant integer TYPE_TRIGGERCONDITION =9
private constant integer TYPE_TRIGGERACTION =10
private constant integer TYPE_PLAYER =11
private constant integer TYPE_GROUP =12
private constant integer TYPE_EFFECT =13
private constant integer TYPE_LOCATION =14
private constant integer TYPE_RECT =15
private constant integer TYPE_BOOLEXPR =16
private constant integer TYPE_SOUND =17
private constant integer TYPE_FORCE =18
private constant integer TYPE_UNITPOOL =19
private constant integer TYPE_ITEMPOOL =20
private constant integer TYPE_QUEST =21
private constant integer TYPE_QUESTITEM =22
private constant integer TYPE_DEFEATCONDITION =23
private constant integer TYPE_TIMERDIALOG =24
private constant integer TYPE_LEADERBOARD =25
private constant integer TYPE_MULTIBOARDITEM =26
private constant integer TYPE_MULTIBOARD =27
private constant integer TYPE_TRACKABLE =28
private constant integer TYPE_DIALOG =29
private constant integer TYPE_BUTTON =30
private constant integer TYPE_TEXTTAG =31
private constant integer TYPE_LIGHTNING =32
private constant integer TYPE_IMAGE =33
private constant integer TYPE_UBERSPLAT =34
private constant integer TYPE_REGION =35
private constant integer TYPE_FOGSTATE =36
private constant integer TYPE_FOGMODIFIER =37
private constant integer TYPE_ABILITY =38
private constant integer MAX_TYPE =38
endglobals
private function InitTypeNames takes nothing returns nothing
local integer i=MAX_TYPE
set TypeName[TYPE_UNKNOWN] ="UNKNOWN"
set TypeName[TYPE_WIDGET] ="Widget"
set TypeName[TYPE_TRIGGER] ="Trigger"
set TypeName[TYPE_DESTRUCTABLE] ="Destructable"
set TypeName[TYPE_ITEM] ="Item"
set TypeName[TYPE_UNIT] ="Unit"
set TypeName[TYPE_TIMER] ="Timer"
set TypeName[TYPE_HASHTABLE] ="Hashtable"
set TypeName[TYPE_TRIGGEREVENT] ="TriggerEvent"
set TypeName[TYPE_TRIGGERCONDITION] ="TriggerCondition"
set TypeName[TYPE_TRIGGERACTION] ="TriggerAction"
set TypeName[TYPE_PLAYER] ="Player"
set TypeName[TYPE_GROUP] ="Group"
set TypeName[TYPE_EFFECT] ="Effect"
set TypeName[TYPE_LOCATION] ="Location"
set TypeName[TYPE_RECT] ="Rect"
set TypeName[TYPE_BOOLEXPR] ="BoolExpr"
set TypeName[TYPE_SOUND] ="Sound"
set TypeName[TYPE_FORCE] ="Force"
set TypeName[TYPE_UNITPOOL] ="UnitPool"
set TypeName[TYPE_ITEMPOOL] ="ItemPool"
set TypeName[TYPE_QUEST] ="Quest"
set TypeName[TYPE_QUESTITEM] ="QuestItem"
set TypeName[TYPE_DEFEATCONDITION] ="DefeatCondition"
set TypeName[TYPE_TIMERDIALOG] ="TimerDialog"
set TypeName[TYPE_LEADERBOARD] ="Leaderboard"
set TypeName[TYPE_MULTIBOARDITEM] ="MultiboardItem"
set TypeName[TYPE_MULTIBOARD] ="Multiboard"
set TypeName[TYPE_TRACKABLE] ="Trackable"
set TypeName[TYPE_DIALOG] ="Dialog"
set TypeName[TYPE_BUTTON] ="Button"
set TypeName[TYPE_TEXTTAG] ="TextTag"
set TypeName[TYPE_LIGHTNING] ="Lightning"
set TypeName[TYPE_IMAGE] ="Image"
set TypeName[TYPE_UBERSPLAT] ="Ubersplat"
set TypeName[TYPE_REGION] ="Region"
set TypeName[TYPE_FOGSTATE] ="FogState"
set TypeName[TYPE_FOGMODIFIER] ="FogModifier"
set TypeName[TYPE_ABILITY] ="Ability"
loop
call SaveInteger(NameToType,0,StringHash(StringCase(TypeName<i>,false)),i)
exitwhen i==0
set i=i-1
endloop
endfunction
globals
private hashtable Read=InitHashtable()
private hashtable Count=InitHashtable()
private integer CountInstance=-1
private integer Sum=0
endglobals
//! textmacro AgentStats__Count takes TYPECAPS
call SaveInteger(Count,CountInstance,TYPE_$TYPECAPS$,LoadInteger(Count,CountInstance,TYPE_$TYPECAPS$)+1)
set Sum=Sum+1
//! endtextmacro
private function CreateInstance takes nothing returns nothing
local integer i=SEARCH_DEGREE
local group g
loop
exitwhen i==0
set i=i-1
call DestroyGroup(CreateGroup())
endloop
set g=CreateGroup()
set i=GetHandleId(g)
call DestroyGroup(g)
set g=null
set CountInstance=CountInstance+1
loop
exitwhen i==0x100000
set i=i-1
call SaveFogStateHandle(Read,0,i,ConvertFogState(i))
if LoadWidgetHandle(Read,0,i)!=null then
call SaveInteger(Count,CountInstance,TYPE_WIDGET,LoadInteger(Count,CountInstance,TYPE_WIDGET)+1)
if LoadUnitHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UNIT")
elseif LoadDestructableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DESTRUCTABLE")
elseif LoadItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ITEM")
endif
elseif LoadTriggerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGER")
elseif LoadTimerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TIMER")
elseif LoadHashtableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("HASHTABLE")
elseif LoadTriggerEventHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGEREVENT")
elseif LoadTriggerConditionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGERCONDITION")
elseif LoadTriggerActionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGERACTION")
elseif LoadPlayerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("PLAYER")
elseif LoadGroupHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("GROUP")
elseif LoadEffectHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("EFFECT")
elseif LoadLocationHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LOCATION")
elseif LoadRectHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("RECT")
elseif LoadBooleanExprHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("BOOLEXPR")
elseif LoadSoundHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("SOUND")
elseif LoadForceHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FORCE")
elseif LoadUnitPoolHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UNITPOOL")
elseif LoadItemPoolHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ITEMPOOL")
elseif LoadQuestHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("QUEST")
elseif LoadQuestItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("QUESTITEM")
elseif LoadDefeatConditionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DEFEATCONDITION")
elseif LoadTimerDialogHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DIALOG")
elseif LoadLeaderboardHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LEADERBOARD")
elseif LoadMultiboardItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("MULTIBOARDITEM")
elseif LoadMultiboardHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("MULTIBOARD")
elseif LoadTrackableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRACKABLE")
elseif LoadDialogHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DIALOG")
elseif LoadButtonHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("BUTTON")
elseif LoadTextTagHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TEXTTAG")
elseif LoadLightningHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LIGHTNING")
elseif LoadImageHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("IMAGE")
elseif LoadUbersplatHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UBERSPLAT")
elseif LoadRegionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("REGION")
elseif LoadFogStateHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FOGSTATE")
elseif LoadFogModifierHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FOGMODIFIER")
elseif LoadAbilityHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ABILITY")
elseif HaveSavedHandle(Read,0,i) then
//! runtextmacro AgentStats__Count("UNKNOWN")
endif
endloop
call SaveInteger(Count,CountInstance,-1,Sum)
set Sum=0
endfunction
// Abstraction
private function GetLastInstance takes nothing returns integer
return CountInstance
endfunction
private function GetTypeCount takes integer whichInstance, integer whichType returns integer
return LoadInteger(Count,whichInstance,whichType)
endfunction
private function GetType takes string typeNameLowerCase returns integer
return LoadInteger(NameToType,0,StringHash(typeNameLowerCase))
endfunction
private function GetTypeName takes integer whichType returns string
return TypeName[whichType]
endfunction
private function GetTotalCount takes integer whichInstance returns integer
return LoadInteger(Count,whichInstance,-1)
endfunction
globals
private integer array Sorted
endglobals
private function InitSort takes nothing returns nothing
local integer i=MAX_TYPE
loop
set Sorted<i>=i
exitwhen i==0
set i=i-1
endloop
endfunction
private function Sort takes integer whichInstance returns nothing
local integer i=1
local integer j
local integer val
loop
set val=Sorted<i>
set j=i-1
loop
exitwhen j<0 or GetTypeCount(whichInstance,Sorted[j])>GetTypeCount(whichInstance,val)
set Sorted[j+1]=Sorted[j]
set j=j-1
endloop
set Sorted[j+1]=val
exitwhen i==MAX_TYPE
set i=i+1
endloop
endfunction
private function CommandCount takes string subject returns nothing
local integer t=GetType(subject)
if t!=0 or subject=="unknown" then
call BJDebugMsg("Number of "+GetTypeName(t)+"s: "+I2S(GetTypeCount(GetLastInstance(),t)))
else
call BJDebugMsg("Number of agents: "+I2S(GetTotalCount(GetLastInstance())))
endif
endfunction
private function CommandStats takes string subject returns nothing
local integer t=GetType(subject)
if t!=0 or subject=="unknown" then
call BJDebugMsg(" ")
call BJDebugMsg(" == "+GetTypeName(t)+" Stats ==")
call BJDebugMsg("Currently: "+I2S(GetTypeCount(GetLastInstance(),t))+" exist.")
call BJDebugMsg("Last Scan: "+I2S(GetTypeCount(GetLastInstance()-1,t))+" existed.")
call BJDebugMsg("Post Init: "+I2S(GetTypeCount(0,t))+" existed.")
call BJDebugMsg("Currently, "+GetTypeName(t)+"s make up "+/*
*/R2S(GetTypeCount(GetLastInstance(),t)*100./GetTotalCount(GetLastInstance()))/*
*/+"% of all agents.")
call BJDebugMsg("Since last scan, "+GetTypeName(t)+"s have increased by "+/*
*/I2S(GetTypeCount(GetLastInstance(),t)-GetTypeCount(GetLastInstance()-1,t))/*
*/+".")
else
call Sort(GetLastInstance())
call BJDebugMsg(" ")
call BJDebugMsg(" == Agent Stats ==")
call BJDebugMsg("Currently: "+I2S(GetTotalCount(GetLastInstance()))+" exist.")
call BJDebugMsg("Last Scan: "+I2S(GetTotalCount(GetLastInstance()-1))+" existed.")
call BJDebugMsg("Post Init: "+I2S(GetTotalCount(0))+" existed.")
call BJDebugMsg("Since last scan, Agents have increased by "+/*
*/I2S(GetTotalCount(GetLastInstance())-GetTotalCount(GetLastInstance()-1))/*
*/+".")
call Sort(GetLastInstance())
call BJDebugMsg("Most common agents:")
call BJDebugMsg("1. "+GetTypeName(Sorted[0])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[0]))+" in existance.")
call BJDebugMsg("2. "+GetTypeName(Sorted[1])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[1]))+" in existance.")
call BJDebugMsg("3. "+GetTypeName(Sorted[2])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[2]))+" in existance.")
endif
endfunction
private function OnChat takes nothing returns boolean
local string s=GetEventPlayerChatString()
set s=StringCase(SubString(s,COMMAND_CHAR_LENGTH,StringLength(s)),false)
if SubString(s,0,5)=="count" then
call CreateInstance.evaluate()
call CommandCount(SubString(s,6,StringLength(s)))
elseif SubString(s,0,5)=="stats" then
call CreateInstance.evaluate()
call CommandStats(SubString(s,6,StringLength(s)))
endif
return false
endfunction
private function PostInit takes nothing returns nothing
call CreateInstance() // Creates instance #0
if GetTotalCount(GetLastInstance())==0 then
call BJDebugMsg("AgentStats Error: Blizzard may have fixed the return bug, or else you are missing "+TRACKER_PATH+".")
endif
call DestroyTimer(GetExpiredTimer())
endfunction
private function OnInit takes nothing returns nothing
debug local integer i=11
debug local trigger t=CreateTrigger()
debug call StoreInteger(InitGameCache("Preloader.w3v"),"globals","hashtable",GetHandleId(Read))
debug call InitTypeNames()
debug call InitSort()
debug call TimerStart(CreateTimer(),0,false,function PostInit)
debug loop
debug call TriggerRegisterPlayerChatEvent(t,Player(i),COMMAND_CHAR,false)
debug exitwhen i==0
debug set i=i-1
debug endloop
debug call TriggerAddCondition(t,Filter(function OnChat))
debug set t=null
endfunction
endlibrary
</i></i></i>
This is an overpowered handle counter. It scans the game and detects all handles of all types, and sorts them and counts them. It is only useful for debugging, leak monitoring and curiosity. It is set up to only work in debug mode.
Updates:
- Version 1.2.0: Fixed compatability for Warcraft III patch 1.24c. Removed Preloader use.
- Version 1.1.0: Just provides simple text commands now (rework).
- Version 1.0.0 (ALPHA): Release.