User:ArthurAutomaton/sandbox

From Valve Developer Community
Jump to navigation Jump to search

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! (My triggers are setup like this.)

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