User:ArthurAutomaton/sandbox: Difference between revisions
(added a rambling account of a trigger problem) |
|||
Line 24: | Line 24: | ||
These tools have been created by members of the modding community and are not supported by Valve. | These tools have been created by members of the modding community and are not supported by Valve. | ||
== | == Triggers and shared mutable state == | ||
=== Problem === | |||
I have two triggers, <code>trigger_get</code> and <code>trigger_set</code>. When <code>trigger_set</code> is triggered, I want to save some information in a certain variable. When <code>trigger_get</code> is triggered, I should be able to access that information. | |||
== | === An approach that doesn't work === | ||
{{warning|Here is a common approach that '''''DOES NOT WORK'''''}} | |||
1. Create <code>scripts/vscripts/trigger.lua</code> with the following content: | |||
* [ | <source lang="lua"> | ||
FOO = 0 | |||
function SetSharedVar () | |||
FOO = 1 | |||
print("SetSharedVar called; FOO = " .. FOO) | |||
end | |||
function GetSharedVar () | |||
print("GetSharedVar called; FOO = " .. FOO) | |||
end | |||
</source> | |||
2. In Hammer, edit the properties of <code>trigger_get</code> as follows: | |||
* Set ''Entity Scripts = trigger.lua''. | |||
* Add an output like this: | |||
::{| class=standard-table | |||
! || My Output || Target Entity || Target Input || Parameter || Delay || Only Once | |||
|- | |||
| [[Image:Io11.png]] || OnStartTouch || trigger_get || CallScriptFunction || GetSharedVar || 0.00 || No | |||
|} | |||
3. In Hammer, edit the properties of <code>trigger_set</code> as follows: | |||
* Set ''Entity Scripts = trigger.lua''. | |||
* Add an output like this: | |||
::{| class=standard-table | |||
! || My Output || Target Entity || Target Input || Parameter || Delay || Only Once | |||
|- | |||
| [[Image:Io11.png]] || OnStartTouch || trigger_set || CallScriptFunction || SetSharedVar || 0.00 || No | |||
|} | |||
'''The expected outcome:''' When a unit steps on <code>trigger_set</code> and then afterwards steps on <code>trigger_get</code>, we expect to see the following output in the console: | |||
SetSharedVar called; FOO = 1 | |||
GetSharedVar called; FOO = 1 | |||
'''What really happens:''' What we actually see in the console is this: | |||
SetSharedVar called; FOO = 1 | |||
GetSharedVar called; FOO = 0 | |||
This shows that the assignment <code>FOO = 1</code> made by <code>SetSharedVar</code> is NOT visible to <code>trigger_get</code>. | |||
'''My guess about why this happens''': When you "bind" some Lua code to an entity by setting its ''Entity Scripts'' property, that code is "private" to the entity: The entity initially has ITS OWN "blank" Lua environment (with only the library functions and the game API visible), which no other entity can access. When the map is loaded, the game engine populates this environment by running the Lua file specified by the ''Entity Scripts'' property. In our case, we set ''Entity Scripts = trigger.lua'' on both triggers, but they both get THEIR OWN COPIES of the global variables in <code>trigger.lua</code>. So the assignment <code>FOO = 1</code> made by <code>trigger_set</code> is not visible to <code>trigger_get</code> since it just changes <code>trigger_set</code>'s copy of <code>FOO</code>. | |||
=== An approach that works === | |||
Follow steps 1-3 above but replace Step 2 with this: | |||
2'. In Hammer, edit the properties of <code>trigger_get</code> as follows: | |||
* DO NOT SET THE ''Entity Scripts'' PROPERTY | |||
* Add an output like this '''(note that we now use <code>trigger_set</code> as the target)''': | |||
::{| class=standard-table | |||
! || My Output || Target Entity || Target Input || Parameter || Delay || Only Once | |||
|- | |||
| [[Image:Io11.png]] || OnStartTouch || trigger_set || CallScriptFunction || GetSharedVar || 0.00 || No | |||
|} | |||
With this solution we get the expected output in the console. Why? If the guess above is correct, it's because we're now using <code>trigger_set</code> as the target, hence <code>GetSharedVar</code> now accesses <code>trigger_set</code>'s copy of <code>FOO</code>. |
Revision as of 01:19, 24 August 2014
Sandbox
Some notes to myself about modding DotA 2.
Creating a unit that's controllable by a specific player
This code creates a mud golem at (0, 0, 0) on the Radiant team and makes it controllable by player 0:
unit_team = DOTA_TEAM_GOODGUYS unit_name = "npc_dota_neutral_mud_golem" player = PlayerResource:GetPlayer(0) point = Vector(0, 0, 0) unit = CreateUnitByName(unit_name, point, true, nil, nil, unit_team) unit:SetControllableByPlayer(player:GetPlayerID(), true)
Relevant links:
Unofficial Dota 2 Modding Tools
These tools have been created by members of the modding community and are not supported by Valve.
Problem
I have two triggers, trigger_get
and trigger_set
. When trigger_set
is triggered, I want to save some information in a certain variable. When trigger_get
is triggered, I should be able to access that information.
An approach that doesn't work

1. Create scripts/vscripts/trigger.lua
with the following content:
FOO = 0
function SetSharedVar ()
FOO = 1
print("SetSharedVar called; FOO = " .. FOO)
end
function GetSharedVar ()
print("GetSharedVar called; FOO = " .. FOO)
end
2. In Hammer, edit the properties of trigger_get
as follows:
- Set Entity Scripts = trigger.lua.
- Add an output like this:
3. In Hammer, edit the properties of trigger_set
as follows:
- Set Entity Scripts = trigger.lua.
- Add an output like this:
The expected outcome: When a unit steps on trigger_set
and then afterwards steps on trigger_get
, we expect to see the following output in the console:
SetSharedVar called; FOO = 1 GetSharedVar called; FOO = 1
What really happens: What we actually see in the console is this:
SetSharedVar called; FOO = 1 GetSharedVar called; FOO = 0
This shows that the assignment FOO = 1
made by SetSharedVar
is NOT visible to trigger_get
.
My guess about why this happens: When you "bind" some Lua code to an entity by setting its Entity Scripts property, that code is "private" to the entity: The entity initially has ITS OWN "blank" Lua environment (with only the library functions and the game API visible), which no other entity can access. When the map is loaded, the game engine populates this environment by running the Lua file specified by the Entity Scripts property. In our case, we set Entity Scripts = trigger.lua on both triggers, but they both get THEIR OWN COPIES of the global variables in trigger.lua
. So the assignment FOO = 1
made by trigger_set
is not visible to trigger_get
since it just changes trigger_set
's copy of FOO
.
An approach that works
Follow steps 1-3 above but replace Step 2 with this:
2'. In Hammer, edit the properties of trigger_get
as follows:
- DO NOT SET THE Entity Scripts PROPERTY
- Add an output like this (note that we now use
trigger_set
as the target):
With this solution we get the expected output in the console. Why? If the guess above is correct, it's because we're now using trigger_set
as the target, hence GetSharedVar
now accesses trigger_set
's copy of FOO
.