The order filter and other filters

edited June 2016 in Tutorials

Filters in general

This tutorial explains the use of the different filter functions currentlly in the API, and illustrates this using a small example in the order filter.

There are currently 9 filters available in the lua API, namely:

  • AbilityTuningFilter - Filters abilities and all values they use on cast.
  • BountyRunePickupFilter - Filters bounty rune pickups.
  • DamageFilter - Filters damage events.
  • ExecuteOrderFilter - Filters orders (usually given by players).
  • ModifierGainedFilter - Filters modifiers events when they are first applied to a unit.
  • ModifyExperienceFilter - Filters modifications of experience.
  • ModifyGoldFilter - Filters modifications of gold.
  • RuneSpawnFilter - Filters rune spawns.
  • TrackingProjectileFilter - Filters tracking projectile launches.

These filters are set using functions like CDOTABaseGameMode:SetExecuteOrderFilter(function, context), check the API wiki for the exact function name for each function. The filters can then be cleared again using functions like CDOTABaseGameMode:ClearExecuteOrderFilter() and similar functions - again, see the API wiki.

The general idea

(This is the most important section of this entire tutorial)

The Source 2 engine listens for events, either generated by players or units in the game. The engine has a lot of handlers that determine what to do when a certain event is received. Filters get to look at these events before they reach the engine and have the opportunity to decide not to deliver the event, or maybe to deliver a modified version of the event.

An analogy to explain this is that of a company receiving mail. The regular situation would be the company(the engine) receiving mail (events) and reading them as usual. Now imagine a new secretary is hired(the filter) that reads every letter received and decides if the letter is important enough to be handled or not. This sytem is illustrated in the following picture:

http://i.imgur.com/Op4u0Oa.png

Filters in lua

So now we know how filters work, how do we use them. This explanation will use the ExecuteOrderFilter, keep in mind that all filters use the same basic idea.

The first step is to set the filter using the CDOTABaseGameMode:SetExecuteOrderFilter(function, context) API call. Let's analyze what this function expects. There are two parameters:

Parameter: function - The filter function. This function is your actual filter. It is called every time the event you are filtering is called (in this case when an order arrives). The filter function receives two parameters: self and event. The self parameter is just the context of the function (and is hidden if you use Dynamic_Wrap and the : operator). The really interesting parameter is the event parameter. This parameter contains all the data of the event. Your filter function should look at this function and make a decision. There are three possible outcomes:

  1. You want to do nothing and accept the event, you return true.
  2. You want to reject the event, it will be like this event never happened, return false.
  3. You want to accept the event with some changes, all you have to do modify the event table and return true.

Parameter: context - This parameter is what is passed into the filter function as self.

Example 1: Disabling glyph

Time to put into practice what we just used. We know the glyph is an order given by a player, so we should use the order filter to disable it. All we have to do is find any glyph orders and return false. Ofcourse you can add any restriction you want based on the contents of the event parameter. Just DeepPrintTable( event ) to see what data is available to you.

To check which order types there are, look at the wiki.

Note that in this example the : operator on GameMode:OrderFilter hides the first (self) parameter.

--First set the filter to start catching events, usually this is in your init
GameRules:GetGameModeEntity():SetExecuteOrderFilter(Dynamic_Wrap(GameMode, "OrderFilter"), self)

--......................

--Add the order filter to your game mode entity
function GameMode:OrderFilter(event)
    --Check if the order is the glyph type
    if event.order_type == DOTA_UNIT_ORDER_GLYPH then
        return false
    end

    --Return true by default to keep all other orders the same
    return true
end

Example 2: Order modification

This example mimics a sort of 'drunk' state of a unit by adding a random offset to any movement orders. The code is pretty easy, all you have to do is modify the incoming order and return true.

--First set the filter to start catching events, usually this is in your init
GameRules:GetGameModeEntity():SetExecuteOrderFilter(Dynamic_Wrap(GameMode, "OrderFilter"), self)

--......................

--Add the order filter to your game mode entity
function GameMode:OrderFilter(event)
    --Check if the order is the glyph type
    if event.order_type == DOTA_UNIT_ORDER_MOVE_TO_POSITION then
        local offsetVector = RandomVector(100)
        event.position_x = event.position_x + offsetVector.x
        event.position_y = event.position_y + offsetVector.y
        return true
    end

    --Return true by default to keep all other orders the same
    return true
end

Comments

  • Nice guide!

    It might be an idea to add some examples from mods. I've learned the orderfilter from dotacraft and farmingsimulator. Right now I want to use the modifiergainedfilter, but I have no idea where to start or how it should look

  • Worth noting on this one is that Scan can be disabled the same way as glyph, replacing DOTA_UNIT_ORDER_GLYPH with DOTA_UNIT_ORDER_RADAR. This was not in the API last time I checked for some reason, but important because even if you disable the minimap, players can still activate it with the hotkey if this isn't specified. If vision is an important part of your game mode but you don't want normal Dota rules, that's kind of important. The button will still be present when disabled if the minimap is visible, but I believe it can be removed visually with some hacky Panorama JS. Forgot exactly what the command was.

  • Worth noting that you shouldn't remove the button with hacky panorama JS because it most likely isn't gonna get magically restored in other games after yours is played.

  • Posts: 57

    Regarding the potential problems of hacky JS, I used:

     $.GetContextPanel().GetParent().GetParent().GetParent()
     .FindChildTraverse('GlyphScanContainer').style.visibility = 'collapse';
    

    Which hides that pair of icons. Published a map, played it. They were gone. Then I went to play a practice match of regular dota, and it had reappeared successfully.

  • yes valve fixed it properly after 7.00