User:ArthurAutomaton/sandbox: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
mNo edit summary
(added a section on a jail system for dota 2)
Line 40: Line 40:
| If true, <code>amount</code> will be added to the player's current gold; if false, the player's current gold will be set to <code>amount</code>.
| If true, <code>amount</code> will be added to the player's current gold; if false, the player's current gold will be set to <code>amount</code>.
|}
|}
== Jail System ==
=== Hammer Setup ===
In Hammer, create a trigger_hero with the name <i>radiant_prison</i>. Create another trigger_hero with the name <i>dire_prison</i>.
{{warning|The two triggers should not overlap physically!}}
Set the Entity Scripts property of both triggers to <code>jail_trigger.lua</code>. Finally, add an output on both triggers as follows:
::{| class=standard-table
!  || My Output || Target Entity || Target Input || Parameter || Delay || Only Once
|-
| [[Image:Io11.png]] || OnStartTouch || trigger_name|| CallScriptFunction || ReleasePrisonersConditionally || 0.00 || No
|}
=== VScripts ===
<code>jail_trigger.lua</code>:
function ReleasePrisonersConditionally(trigger)
    print("!!! ReleasePrisonersConditionally CALLED !!!")
    local jailSystem = GameRules.MyAddon.jailSystem
    local thisPrison = trigger.caller
    local vInmates = jailSystem:GetPrisoners(thisPrison)
   
    if #vInmates == 0 then
      print("no inmates found in " .. thisPrison:GetName())
      return
    end
   
    local nTeamID = vInmates[1]:GetTeam()
    if (not jailSystem:IsImprisoned(trigger.activator, thisPrison) and
        trigger.activator:GetTeam() == nTeamID) then
      print("releasing prisoners")
      for _,npc in pairs(vInmates) do
          jailSystem:Release(npc, thisPrison)
      end
    end
end
<code>addon_game_mode.lua</code>:
RAZOR = "npc_dota_hero_razor"
RADIANT_PRISON = "radiant_prison"
DIRE_PRISON = "dire_prison"
if CMyGameMode == nil then
    CMyGameMode = class({})
end
function Precache (context)
    PrecacheUnitByNameSync(RAZOR, context) -- XXX
end
-- Create the game mode when we activate
function Activate ()
    GameRules.MyAddon = CMyGameMode()
    GameRules.MyAddon:InitGameMode()
end
function CMyGameMode:InitGameMode ()
    print( "Addon is loaded." )
    GameRules:SetHeroRespawnEnabled(false)
   
    -- XXX: For testing; remember to remove this!
    self:PopulateWorldForTesting()
   
    -- Initialize the jail system
    self.jailSystem = CJailSystem({
          [DOTA_TEAM_GOODGUYS] = Entities:FindByName(nil, DIRE_PRISON),
          [DOTA_TEAM_BADGUYS] = Entities:FindByName(nil, RADIANT_PRISON)
    })
    self.jailSystem:Init()
end
function CMyGameMode:PopulateWorldForTesting ()
    local razor = CreateUnitByName(RAZOR, Vector(0, 512, 0), true,
                                  nil, nil, DOTA_TEAM_BADGUYS)
    razor:SetControllableByPlayer(0, true)
end
 
----------
if CJailSystem == nil then
    CJailSystem = class({ team2prison = {};
                          prisoners = {};
 
                          constructor = function (self, tbl)
                            self.team2prison = tbl or self.team2prison
   
                            for _,v in pairs(self.team2prison) do
                                v.JAIL_prisoners = {} -- XXX: Use DoUniqueString
                            end
                          end
                      })
end
function CJailSystem:Init ()
    ListenToGameEvent("entity_killed", Dynamic_Wrap(CJailSystem, "OnEntityKilled" ), self)
end
function CJailSystem:GetPrisoners (prison)
    local vInmates = {}
    for k,_ in pairs(prison.JAIL_prisoners) do
      table.insert(vInmates, k)
    end
    return vInmates
end
function CJailSystem:IsImprisoned (npc, prison)
    return prison.JAIL_prisoners[npc]
end
function CJailSystem:OnEntityKilled (keys)
    local killedEntity = EntIndexToHScript(keys.entindex_killed)
    local prison = self.team2prison[killedEntity:GetTeam()]
    if killedEntity:UnitCanRespawn() and prison then
      self:Imprison(killedEntity, prison)
    end
end
function CJailSystem:Imprison (npc, prison)
    prison.JAIL_prisoners[npc] = true
    npc:RespawnUnit()
    FindClearSpaceForUnit(npc, prison:GetCenter(), false)
    -- XXX: If we apply modifiers now, nothing happens (API bug?);
    --      so we wait a bit and then apply them.
    GameRules:GetGameModeEntity():SetThink(
      function()
          npc:AddNewModifier(npc, nil, "modifier_stunned", nil)
          npc:AddNewModifier(npc, nil, "modifier_invulnerable", nil)
      end, nil, 0.5)
end
function CJailSystem:Release (npc, prison)
    prison.JAIL_prisoners[npc] = false
    npc:RemoveModifierByName("modifier_stunned")
    npc:RemoveModifierByName("modifier_invulnerable")
    -- Add teleport stuff here!
end

Revision as of 06:46, 14 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:

CDOTA_BaseNPC_Hero.SetGold

void SetGold(int amount, bool addToCurrentGold)

Sets the gold amount for the player owning this hero

Parameters

Type Name Description
int amount An amount of gold
bool addToCurrentGold If true, amount will be added to the player's current gold; if false, the player's current gold will be set to amount.

Jail System

Hammer Setup

In Hammer, create a trigger_hero with the name radiant_prison. Create another trigger_hero with the name dire_prison.

Warning.pngWarning:The two triggers should not overlap physically!

Set the Entity Scripts property of both triggers to jail_trigger.lua. Finally, add an output on both triggers as follows:

My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnStartTouch trigger_name CallScriptFunction ReleasePrisonersConditionally 0.00 No

VScripts

jail_trigger.lua:

function ReleasePrisonersConditionally(trigger)
   print("!!! ReleasePrisonersConditionally CALLED !!!")
   local jailSystem = GameRules.MyAddon.jailSystem
   local thisPrison = trigger.caller
   local vInmates = jailSystem:GetPrisoners(thisPrison)
   
   if #vInmates == 0 then
      print("no inmates found in " .. thisPrison:GetName())
      return
   end
   
   local nTeamID = vInmates[1]:GetTeam()
   if (not jailSystem:IsImprisoned(trigger.activator, thisPrison) and
       trigger.activator:GetTeam() == nTeamID) then
      print("releasing prisoners")
      for _,npc in pairs(vInmates) do
         jailSystem:Release(npc, thisPrison)
      end
   end
end


addon_game_mode.lua:

RAZOR = "npc_dota_hero_razor"
RADIANT_PRISON = "radiant_prison"
DIRE_PRISON = "dire_prison"

if CMyGameMode == nil then
   CMyGameMode = class({})
end

function Precache (context)
   PrecacheUnitByNameSync(RAZOR, context) -- XXX
end

-- Create the game mode when we activate
function Activate ()
   GameRules.MyAddon = CMyGameMode()
   GameRules.MyAddon:InitGameMode()
end

function CMyGameMode:InitGameMode ()
   print( "Addon is loaded." )
   GameRules:SetHeroRespawnEnabled(false)
   
   -- XXX: For testing; remember to remove this!
   self:PopulateWorldForTesting()
   
   -- Initialize the jail system
   self.jailSystem = CJailSystem({
         [DOTA_TEAM_GOODGUYS] = Entities:FindByName(nil, DIRE_PRISON),
         [DOTA_TEAM_BADGUYS] = Entities:FindByName(nil, RADIANT_PRISON)
   })
   self.jailSystem:Init()
end

function CMyGameMode:PopulateWorldForTesting ()
   local razor = CreateUnitByName(RAZOR, Vector(0, 512, 0), true,
                                  nil, nil, DOTA_TEAM_BADGUYS)
   razor:SetControllableByPlayer(0, true)
end
 
----------

if CJailSystem == nil then
   CJailSystem = class({ team2prison = {};
                         prisoners = {};
  
                         constructor = function (self, tbl)
                            self.team2prison = tbl or self.team2prison
   
                            for _,v in pairs(self.team2prison) do
                               v.JAIL_prisoners = {} -- XXX: Use DoUniqueString
                            end
                         end
                      })
end

function CJailSystem:Init ()
   ListenToGameEvent("entity_killed", Dynamic_Wrap(CJailSystem, "OnEntityKilled" ), self)
end

function CJailSystem:GetPrisoners (prison)
   local vInmates = {}
   for k,_ in pairs(prison.JAIL_prisoners) do
      table.insert(vInmates, k)
   end
   return vInmates
end

function CJailSystem:IsImprisoned (npc, prison)
   return prison.JAIL_prisoners[npc]
end

function CJailSystem:OnEntityKilled (keys)
   local killedEntity = EntIndexToHScript(keys.entindex_killed)
   local prison = self.team2prison[killedEntity:GetTeam()]
   if killedEntity:UnitCanRespawn() and prison then
      self:Imprison(killedEntity, prison)
   end
end

function CJailSystem:Imprison (npc, prison)
   prison.JAIL_prisoners[npc] = true
   npc:RespawnUnit()
   FindClearSpaceForUnit(npc, prison:GetCenter(), false)
   -- XXX: If we apply modifiers now, nothing happens (API bug?);
   --      so we wait a bit and then apply them.
   GameRules:GetGameModeEntity():SetThink(
      function()
         npc:AddNewModifier(npc, nil, "modifier_stunned", nil)
         npc:AddNewModifier(npc, nil, "modifier_invulnerable", nil)
      end, nil, 0.5)
end

function CJailSystem:Release (npc, prison)
   prison.JAIL_prisoners[npc] = false
   npc:RemoveModifierByName("modifier_stunned")
   npc:RemoveModifierByName("modifier_invulnerable")
   -- Add teleport stuff here!
end