This article relates to the game "Dota 2". Click here for more information.
This article relates to the SDK/Workshop Tools for "Dota 2 Workshop Tools". Click here for more information.
This article's documentation is for Source 2. Click here for more information.

Dota 2 Workshop Tools/Scripting/ThinkerFunctions: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
mNo edit summary
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{otherlang2
{{lang|Dota 2 Workshop Tools/Scripting/ThinkerFunctions}}
|zh-cn = Dota_2_Workshop_Tools:zh-cn/Scripting:zh-cn/ThinkerFunctions:zh-cn
}}
[[Think|Thinking]] functions can be registered at any time using <code>SetThink</code> with a function. It is possible to have multiple think functions running on an entity at the same time, but does require the think functions to be named so as not to overlap.


== Usage ==
{{Dota 2Tools topicons}}
<source lang="lua">SetThink( "ThinkerFunction", self, "thinkerNameString", 1 )</source>
The <code>SetThink</code> function can be used to


* run a function every ''x'' seconds,
* schedule a function to be run ''x'' seconds from now.


* <code>ThinkerFunction</code> - This can be a string of the name of the function to call, or a function object.
Passing a function to <code>SetThink</code> is called "registering a [[Think|think]] function". It is possible to have multiple think functions running on an entity at the same time, but this does require the think functions to be named so as not to overlap.
The following arguments are optional:
 
* <code>ThinkerFunctionScope</code> - This can be a table, to cause ThinkerFunction will be indexed on this object. Use this to get member functions as think callbacks.
{{warning|<code>SetThink</code> does not respect game pauses. You can use the [https://github.com/bmddota/barebones/blob/source2/game/dota_addons/barebones/scripts/vscripts/libraries/timers.lua Timer library by BMD] to create think functions that respect game pauses.}}
* <code>thinkerNameString</code> - The name of the think slot. Use this when handling multiple thinkers.
 
* <code>1</code> - Number specifying a delay in seconds before the thinker starts to think.
== Signature ==
<code>SetThink</code> is a method on the [[Dota_2_Workshop_Tools/Scripting/API#CBaseEntity|<code>CBaseEntity</code>]] class. It can be used in two ways:
 
<span style="color:green">void</span> <span style="color:blue">SetThink</span>(<span style="color:green">function</span> thinkFn, <span style="color:green">string</span> thinkName, <span style="color:green">float</span> initialDelay)
 
; <code>thinkFn</code>
: The function that you want to run.
 
The other two arguments are optional:
 
; <code>thinkName</code>
: The name of the think slot. Use this if you want to register multiple thinkers on the same entity.
; <code>initialDelay</code>
: Delay in seconds before the thinker should start.
 
<span style="color:green">void</span> <span style="color:blue">SetThink</span>(<span style="color:green">string</span> thinkFnName, <span style="color:green">table</span> context, <span style="color:green">string</span> thinkName, <span style="color:green">float</span> initialDelay)
 
; <code>thinkFnName</code>
: The '''name''' of the function you want to run.
; <code>context</code>
: A table/object. The function that will be registered is <code>context[thinkFnName]</code>. In other words, <code>SetThink</code> uses the first argument as an index into the second argument.
; <code>thinkName</code>, <code>initialDelay</code>
: These are optional. Their descriptions are as above.
 
Your function should return a number or <code>nil</code>:
 
* Returning a number sets the next think time.  
* Returning <code>nil</code> will unregister the thinker and stop it.
 
== Examples ==
 
=== Example 1 ===
 
Print a message to the console every 5 seconds:
 
<table>
<tr><th>Class method</th><th>Ordinary function</th></tr>
<tr>
<td valign="top">
<source lang="lua">
  -- scripts/vscripts/addon_game_mode.lua
if CustomGameMode == nil then
  CustomGameMode = class({})
end
function CustomGameMode:PrintHello ()
  print("Hello world!")
  return 5
end
function CustomGameMode:InitGameMode ()
  GameRules:GetGameModeEntity():SetThink("PrintHello", self)
end
function Activate ()
  GameRules.CustomAddon = CustomGameMode()
  GameRules.CustomAddon:InitGameMode()
end
</source>
</td>
<td valign="top">
<source lang="lua">
-- scripts/vscripts/addon_game_mode.lua
 
function PrintHello ()
  print("Hello world!")
  return 5
end
 
function Activate ()
  GameRules:GetGameModeEntity():SetThink(PrintHello)
end
</source>
</td>
</tr>
</table>
 
=== Example 2 ===
 
Print a message to the console 15 seconds after <code>Activate</code> is called:
 
<table>
<tr><th>Class method</th><th>Ordinary function</th></tr>
<tr>
<td valign="top">
<source lang="lua">
-- scripts/vscripts/addon_game_mode.lua
if CustomGameMode == nil then
  CustomGameMode = class({})
end
function CustomGameMode:PrintHello ()
  print("Hello world!")
  return nil
end
function CustomGameMode:InitGameMode ()
  GameRules:GetGameModeEntity():SetThink("PrintHello", self, 15)
end
function Activate ()
  GameRules.CustomAddon = CustomGameMode()
  GameRules.CustomAddon:InitGameMode()
end
</source>
</td>
<td valign="top">
<source lang="lua">
-- scripts/vscripts/addon_game_mode.lua
function PrintHello ()
  print("Hello world!")
  return nil
end
function Activate ()
  GameRules:GetGameModeEntity():SetThink(PrintHello, 15)
end
</source>
</td>
</tr>
</table>
 
=== Example 3 ===
 
Count down from 25 when <code>Activate</code> is called while respecting pauses:
 
<source lang="lua">
-- scripts/vscripts/addon_game_mode.lua
 
local COUNT_DOWN_FROM = 25
 
function round (num)
  return math.floor(num + 0.5)
end
 
 
function Activate ()
  local endTime = round(GameRules:GetGameTime() + COUNT_DOWN_FROM)
  GameRules:GetGameModeEntity():SetThink(function ()
    local delta = round(endTime - GameRules:GetGameTime())
    if delta > 0 then
      print(tostring(delta))
      return 1
    end
  end)
end
</source>
 
=== Example 4 ===
 
Force player 0 to pick a random hero when the game starts:
 
<source lang="lua">
-- scripts/vscripts/addon_game_mode.lua
function RandomHeroThink ()
  local player0 = PlayerResource:GetPlayer(0)
  if player0 then
    PlayerResource:SetHasRepicked(0)
    player0:MakeRandomHeroSelection()
  else
    return 0.5
  end
end
function Activate ()
  GameRules:GetGameModeEntity():SetThink(RandomHeroThink, "RAND")
end
</source>


Returning a nil will unregister the thinker and stop it. Returning a number sets the next think time.


{{shortpagetitle}}
{{shortpagetitle}}
[[Category:Dota 2 Workshop Tools]]
[[Category:Dota 2 Workshop Tools]]

Latest revision as of 09:24, 25 November 2022

English (en)中文 (zh)Translate (Translate)

The SetThink function can be used to

  • run a function every x seconds,
  • schedule a function to be run x seconds from now.

Passing a function to SetThink is called "registering a think function". It is possible to have multiple think functions running on an entity at the same time, but this does require the think functions to be named so as not to overlap.

Warning.pngWarning:SetThink does not respect game pauses. You can use the Timer library by BMD to create think functions that respect game pauses.

Signature

SetThink is a method on the CBaseEntity class. It can be used in two ways:

void SetThink(function thinkFn, string thinkName, float initialDelay)
thinkFn
The function that you want to run.

The other two arguments are optional:

thinkName
The name of the think slot. Use this if you want to register multiple thinkers on the same entity.
initialDelay
Delay in seconds before the thinker should start.
void SetThink(string thinkFnName, table context, string thinkName, float initialDelay)
thinkFnName
The name of the function you want to run.
context
A table/object. The function that will be registered is context[thinkFnName]. In other words, SetThink uses the first argument as an index into the second argument.
thinkName, initialDelay
These are optional. Their descriptions are as above.

Your function should return a number or nil:

  • Returning a number sets the next think time.
  • Returning nil will unregister the thinker and stop it.

Examples

Example 1

Print a message to the console every 5 seconds:

Class methodOrdinary function
  -- scripts/vscripts/addon_game_mode.lua
 
 if CustomGameMode == nil then
   CustomGameMode = class({})
 end
 
 function CustomGameMode:PrintHello ()
   print("Hello world!")
   return 5
 end
 
 function CustomGameMode:InitGameMode ()
   GameRules:GetGameModeEntity():SetThink("PrintHello", self)
 end
 
 function Activate ()
   GameRules.CustomAddon = CustomGameMode()
   GameRules.CustomAddon:InitGameMode()
 end
 -- scripts/vscripts/addon_game_mode.lua

 function PrintHello ()
   print("Hello world!")
   return 5
 end

 function Activate ()
   GameRules:GetGameModeEntity():SetThink(PrintHello)
 end

Example 2

Print a message to the console 15 seconds after Activate is called:

Class methodOrdinary function
 -- scripts/vscripts/addon_game_mode.lua
 
 if CustomGameMode == nil then
   CustomGameMode = class({})
 end
 
 function CustomGameMode:PrintHello ()
   print("Hello world!")
   return nil
 end
 
 function CustomGameMode:InitGameMode ()
   GameRules:GetGameModeEntity():SetThink("PrintHello", self, 15)
 end
 
 function Activate ()
   GameRules.CustomAddon = CustomGameMode()
   GameRules.CustomAddon:InitGameMode()
 end
 -- scripts/vscripts/addon_game_mode.lua
 
 function PrintHello ()
   print("Hello world!")
   return nil
 end
 
 function Activate ()
   GameRules:GetGameModeEntity():SetThink(PrintHello, 15)
 end

Example 3

Count down from 25 when Activate is called while respecting pauses:

 -- scripts/vscripts/addon_game_mode.lua

 local COUNT_DOWN_FROM = 25

 function round (num)
   return math.floor(num + 0.5)
 end


 function Activate ()
   local endTime = round(GameRules:GetGameTime() + COUNT_DOWN_FROM)
   GameRules:GetGameModeEntity():SetThink(function ()
     local delta = round(endTime - GameRules:GetGameTime())
     if delta > 0 then
       print(tostring(delta))
       return 1
     end
   end)
 end

Example 4

Force player 0 to pick a random hero when the game starts:

 -- scripts/vscripts/addon_game_mode.lua
 
 function RandomHeroThink ()
   local player0 = PlayerResource:GetPlayer(0)
   if player0 then
     PlayerResource:SetHasRepicked(0)
     player0:MakeRandomHeroSelection()
   else
     return 0.5
   end
 end
 
 function Activate ()
   GameRules:GetGameModeEntity():SetThink(RandomHeroThink, "RAND")
 end