Хук с физикой DotA AllStars

Adam Smith

Друзья CG
4 Окт 2014
473
2
Код доработать надо, но тем не менее, работает не как в Dota Imba с беспонтовым Dummy. Поработать надо только над эффектом
Код:
"pudge_meat_hook_forward"
	{
		
		"BaseClass"						"ability_lua"
		"AbilityTextureName"			"pudge_meat_hook_lua"
		"FightRecapLevel"				"1"
		"ScriptFile"					"heroes/hero_butcher/pudge_meat_hook_forward.lua"	

		// Precache
		//-------------------------------------------------------------------------------------------------------------
		"precache"
		{
			"soundfile"			"soundevents/game_sounds_heroes/game_sounds_pudge.vsndevts"
			"particle"			"particles/units/heroes/hero_pudge/pudge_meathook_chain.vpcf"
			"particle"			"particles/units/heroes/hero_pudge/pudge_meathook_impact.vpcf"
			"particle"			"particles/units/heroes/hero_pudge/pudge_meathook.vpcf"
		}
	
		// Casting
		//-------------------------------------------------------------------------------------------------------------
		"AbilityCastRange"				"1000 1100 1200 1300"
		"AbilityCastPoint"				"0.3 0.3 0.3 0.3"

		// Time		
		//-------------------------------------------------------------------------------------------------------------
		"AbilityCooldown"				"14 13 12 11"


		// Cost
		//-------------------------------------------------------------------------------------------------------------
		"AbilityManaCost"				"110 120 130 140"

		// Special
		//-------------------------------------------------------------------------------------------------------------
		"AbilitySpecial"
		{
			"01"
			{
				"var_type"			"FIELD_FLOAT"
				"hook_speed"		"1600.0"
			}
			"02"
			{
				"var_type"			"FIELD_INTEGER"
				"hook_width"		"100"
			}
			"03"
			{
				"var_type"			"FIELD_INTEGER"
				"hook_distance"		"1000 1100 1200 1300"
			}
			"04"
			{
				"var_type"			"FIELD_INTEGER"
				"vision_radius"		"500 500 500 500"
			}
			"05"
			{
				"var_type"			"FIELD_FLOAT"
				"vision_duration"	"4.0 4.0 4.0 4.0"
			}
			"06"
			{
				"var_type"						"FIELD_FLOAT"
				"hook_followthrough_constant"	"0.65"
			}
			"07"
			{
				"var_type"					"FIELD_INTEGER"
				"hook_damage"				"90 180 270 360"
			}
			"08"
			{
				"var_type"					"FIELD_FLOAT"
				"hook_damage_based_dist"	"30 50 70 100"
			}
			"09"
			{
				"var_type"					"FIELD_INTEGER"
				"cast_range_scepter"		"2100"
			}
			"10"
			{
				"var_type"					"FIELD_INTEGER"
				"cooldown_scepter"			"6"
			}
		}
	}

Код:
pudge_meat_hook_forward = class ( {})

LinkLuaModifier ("modifier_pudge_meat_hook_forward", "heroes/hero_butcher/modifier_pudge_meat_hook_forward.lua", LUA_MODIFIER_MOTION_HORIZONTAL)


--[[Author: Valve
	Date: 26.09.2015.]]
--------------------------------------------------------------------------------

function pudge_meat_hook_forward:OnAbilityPhaseStart ()
  self:GetCaster ():StartGesture (ACT_DOTA_OVERRIDE_ABILITY_1)
  return true
end

function pudge_meat_hook_forward:IsRefreshable ()
  return false
end

function pudge_meat_hook_forward:GetBehavior()
  return DOTA_ABILITY_BEHAVIOR_POINT + DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING
end

function pudge_meat_hook_forward:GetCastRange (vLocation, hTarget)
  if self:GetCaster ():HasScepter () then
    return 2100
  end

  return self.BaseClass.GetCastRange (self, vLocation, hTarget)
end

function pudge_meat_hook_forward:IsStealable ()
  return true
end

function pudge_meat_hook_forward:GetCooldown (nLevel)
  if self:GetCaster ():HasScepter () then
    return 6
  end

  return self.BaseClass.GetCooldown (self, nLevel)
end
--------------------------------------------------------------------------------

function pudge_meat_hook_forward:OnAbilityPhaseInterrupted ()
  self:GetCaster ():RemoveGesture (ACT_DOTA_OVERRIDE_ABILITY_1)
end

--------------------------------------------------------------------------------

function pudge_meat_hook_forward:OnSpellStart ()
  self.bChainAttached = false
  
  self.hook_damage = self:GetSpecialValueFor ("hook_damage")
  self.hook_speed = self:GetSpecialValueFor ("hook_speed")
  self.hook_width = self:GetSpecialValueFor ("hook_width")
  self.hook_distance = self:GetSpecialValueFor ("hook_distance")
  if self:GetCaster ():HasScepter () then
    self.hook_distance = self:GetSpecialValueFor ("cast_range_scepter")
  end

  self.vision_radius = self:GetSpecialValueFor ("vision_radius")
  self.vision_duration = self:GetSpecialValueFor ("vision_duration")

  if self:GetCaster () and self:GetCaster ():IsHero () then
    local hHook = self:GetCaster ():GetTogglableWearable (DOTA_LOADOUT_TYPE_WEAPON)
    if hHook ~= nil then
      hHook:AddEffects (EF_NODRAW)
    end
  end

  self.vStartPosition = self:GetCaster ():GetOrigin ()
  self.vProjectileLocation = vStartPosition

  local vDirection = self:GetCursorPosition () - self.vStartPosition
  vDirection.z = 0.0

  local vDirection = (vDirection:Normalized () ) * self.hook_distance
  self.vTargetPosition = self.vStartPosition + vDirection

 
  self.vHookOffset = Vector (0, 0, 96)
  local vHookTarget = self.vTargetPosition + self.vHookOffset
  local vKillswitch = Vector ( ( (self.hook_distance / self.hook_speed) * 2), 0, 0)

  self.nChainParticleFXIndex = ParticleManager:CreateParticle ("particles/units/heroes/hero_pudge/pudge_meathook.vpcf", PATTACH_CUSTOMORIGIN, self:GetCaster () )
  ParticleManager:SetParticleAlwaysSimulate (self.nChainParticleFXIndex)
  ParticleManager:SetParticleControlEnt (self.nChainParticleFXIndex, 0, self:GetCaster (), PATTACH_POINT_FOLLOW, "attach_weapon_chain_rt", self:GetCaster ():GetOrigin () + self.vHookOffset, true)
  ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 1, vHookTarget)
  ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 2, Vector (self.hook_speed, self.hook_distance, self.hook_width) )
  ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 3, vKillswitch)
  ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 4, Vector (1, 0, 0) )
  ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 5, Vector (0, 0, 0) )
  ParticleManager:SetParticleControlEnt (self.nChainParticleFXIndex, 7, self:GetCaster (), PATTACH_CUSTOMORIGIN, nil, self:GetCaster ():GetOrigin (), true)

  EmitSoundOn ("Hero_Pudge.AttackHookExtend", self:GetCaster () )

  local info = {
    Ability = self,
    vSpawnOrigin = self:GetCaster ():GetOrigin (),
    vVelocity = vDirection:Normalized () * self.hook_speed,
    fDistance = self.hook_distance,
    fStartRadius = self.hook_width,
    fEndRadius = self.hook_width,
    Source = self:GetCaster (),
    iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_BOTH,
    iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
    iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_INVULNERABLE,
  }

  ProjectileManager:CreateLinearProjectile (info)

  self.bRetracting = false
  self.hVictim = nil
  self.bDiedInHook = false
end


--------------------------------------------------------------------------------

function pudge_meat_hook_forward:OnProjectileHit (hTarget, vLocation)
  if hTarget == self:GetCaster () then
    return false
  end

  if self.bRetracting == false then
    if hTarget ~= nil and ( not (hTarget:IsCreep () or hTarget:IsConsideredHero () ) ) then
      Msg ("Target was invalid")
      return false
    end

    local bTargetPulled = false
    if hTarget ~= nil then
      self.start_htarget_location = hTarget:GetAbsOrigin()
      ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 3, Vector(3000, 0, 0))     
      hTarget:AddNewModifier (self:GetCaster (), self, "modifier_pudge_meat_hook_forward", nil)

      if hTarget:GetTeamNumber () ~= self:GetCaster ():GetTeamNumber () then
        local damage = {
          victim = hTarget,
          attacker = self:GetCaster (),
          damage = self.hook_damage,
          damage_type = DAMAGE_TYPE_PURE,
          ability = this
        }

        ApplyDamage (damage)

        if not hTarget:IsAlive () then
          self.bDiedInHook = true
        end

        if not hTarget:IsMagicImmune () then
          hTarget:Interrupt ()
        end

        local nFXIndex = ParticleManager:CreateParticle ("particles/units/heroes/hero_pudge/pudge_meathook_impact.vpcf", PATTACH_CUSTOMORIGIN, hTarget)
        ParticleManager:SetParticleControlEnt (nFXIndex, 0, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", self:GetCaster ():GetOrigin (), true)
        ParticleManager:ReleaseParticleIndex (nFXIndex)
      end



      AddFOWViewer (self:GetCaster ():GetTeamNumber (), hTarget:GetOrigin (), self.vision_radius, self.vision_duration, false)
      self.hVictim = hTarget
      bTargetPulled = true
    end

    local vHookPos = self.vTargetPosition
    local flPad = self:GetCaster ():GetPaddedCollisionRadius ()
    if hTarget ~= nil then
      vHookPos = hTarget:GetOrigin ()
      flPad = flPad + hTarget:GetPaddedCollisionRadius ()
    end

    --Missing: Setting target facing angle
    local vVelocity = self.vStartPosition - vHookPos
    vVelocity.z = 0.0

    local flDistance = vVelocity:Length2D () - flPad
    vVelocity = vVelocity:Normalized () * self.hook_speed

    local info = {
      Ability = self,
      vSpawnOrigin = vHookPos,
      vVelocity = vVelocity,
      fDistance = flDistance,
      Source = self:GetCaster (),
    }

    ProjectileManager:CreateLinearProjectile (info)
    self.vProjectileLocation = vHookPos

    if hTarget ~= nil and ( not hTarget:IsInvisible () ) and bTargetPulled then
      ParticleManager:SetParticleControlEnt (self.nChainParticleFXIndex, 1, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetOrigin () + self.vHookOffset, true)
      ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 4, Vector (0, 0, 0) )
      ParticleManager:SetParticleControl (self.nChainParticleFXIndex, 5, Vector (1, 0, 0) )
    else
      ParticleManager:SetParticleControlEnt (self.nChainParticleFXIndex, 1, self:GetCaster (), PATTACH_POINT_FOLLOW, "attach_weapon_chain_rt", self:GetCaster ():GetOrigin () + self.vHookOffset, true);
    end

    EmitSoundOn ("Hero_Pudge.AttackHookRetract", hTarget)

    if self:GetCaster ():IsAlive () then
      self:GetCaster ():RemoveGesture (ACT_DOTA_OVERRIDE_ABILITY_1);
      self:GetCaster ():StartGesture (ACT_DOTA_CHANNEL_ABILITY_1);
    end

    self.bRetracting = true
  else
    if self:GetCaster () and self:GetCaster ():IsHero () then
      local hHook = self:GetCaster ():GetTogglableWearable (DOTA_LOADOUT_TYPE_WEAPON)
      if hHook ~= nil then
        hHook:RemoveEffects (EF_NODRAW)
      end
    end
    EmitSoundOn ("Hero_Pudge.AttackHookRetractStop", self:GetCaster () )
  end

  return true
end


function pudge_meat_hook_forward:OnOwnerDied ()
  self:GetCaster ():RemoveGesture (ACT_DOTA_OVERRIDE_ABILITY_1);
  self:GetCaster ():RemoveGesture (ACT_DOTA_CHANNEL_ABILITY_1);
  local hHook = self:GetCaster ():GetTogglableWearable (DOTA_LOADOUT_TYPE_WEAPON)
  if hHook ~= nil then
    hHook:RemoveEffects (EF_NODRAW)
  end
end

--------------------------------------------------------------------------------
Код:
modifier_pudge_meat_hook_forward = class ( {})


function modifier_pudge_meat_hook_forward:IsDebuff ()
  return true
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:IsStunDebuff ()
  return true
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:RemoveOnDeath ()
  return false
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:OnCreated (kv)
  if IsServer () then
    self:StartIntervalThink(0.03)
    self:GetAbility():SetActivated(false)   
  end
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:DeclareFunctions ()
  local funcs = {
    MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
  }

  return funcs
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:GetOverrideAnimation (params)
  return ACT_DOTA_FLAIL
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:CheckState ()
  if IsServer () then
    if self:GetCaster () ~= nil and self:GetParent () ~= nil then
      if self:GetCaster ():GetTeamNumber () ~= self:GetParent ():GetTeamNumber () and ( not self:GetParent ():IsMagicImmune () ) then
        local state = {
          [MODIFIER_STATE_STUNNED] = true,
        }

        return state
      end
    end
  end

  local state = {}

  return state
end

--------------------------------------------------------------------------------

function modifier_pudge_meat_hook_forward:OnIntervalThink()
  if IsServer() then
    local caster = self:GetCaster()
    local hTarget = self:GetParent()
    local hHook = self:GetAbility():GetCaster ():GetTogglableWearable (DOTA_LOADOUT_TYPE_WEAPON)
    if hHook ~= nil then
      hHook:AddEffects (EF_NODRAW)
    end
    if hTarget ~= nil and ( not hTarget:IsInvisible() ) and self:GetAbility().bTargetPulled then
      ParticleManager:SetParticleControlEnt( self:GetAbility().nChainParticleFXIndex, 1, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetOrigin() + self:GetAbility().vHookOffset, true )
      ParticleManager:SetParticleControl( self:GetAbility().nChainParticleFXIndex, 4, Vector( 0, 0, 0 ) )      
      ParticleManager:SetParticleControl (self:GetAbility().nChainParticleFXIndex, 3, Vector(1, 0, 0))
    else
      ParticleManager:SetParticleControlEnt( self:GetAbility().nChainParticleFXIndex, 1, self:GetCaster(), PATTACH_POINT_FOLLOW, "attach_weapon_chain_rt", self:GetCaster():GetOrigin() + self:GetAbility().vHookOffset, true);
    end
    if hTarget ~= nil then    
      local ability = self:GetAbility()
      local speed = ability:GetSpecialValueFor("hook_speed")
      ability.hook_traveled_distance = 0    
      local target_point = hTarget:GetAbsOrigin()
      local caster_location = caster:GetAbsOrigin()
      local distance = (caster_location - target_point):Length2D()
      local direction = (caster_location - target_point):Normalized()
      local duration = distance/speed
      local iTime = 1
     
     
      -- Saving the data in the ability
      ability.time_walk_distance = distance
      ability.hook_speed = speed * 1/30 -- 1/30 is how often the motion controller ticks
      ability.hook_direction = direction
      if ability.time_walk_distance > 150 then
        hTarget:SetAbsOrigin(hTarget:GetAbsOrigin() + ability.hook_direction * ability.hook_speed)
        ability.hook_traveled_distance = ability.hook_traveled_distance + ability.hook_speed      
      else
        self:Destroy()
      end
    end
  end
end


function modifier_pudge_meat_hook_forward:OnDestroy()
  if IsServer () then
    self:GetAbility():SetActivated(true) 
    FindClearSpaceForUnit( self.hVictim, self:GetAbility():GetCaster():GetAbsOrigin(), false )
    ParticleManager:DestroyParticle(self:GetAbility ().nChainParticleFXIndex, true)
    local hTarget = self:GetParent()
    if hTarget:GetTeamNumber() ~= self:GetCaster():GetTeamNumber() then
      local distance_damage = (hTarget:GetAbsOrigin() - self:GetAbility().start_htarget_location):Length2D()
      local mult = self:GetAbility():GetSpecialValueFor("hook_damage_based_dist")/100
      local damage = {
        victim = hTarget,
        attacker = self:GetCaster(),
        damage = distance_damage*mult,
        damage_type = DAMAGE_TYPE_PHYSICAL,
        ability = self:GetAbility()
      }

      ApplyDamage (damage)    
      local particle_kill = "particles/units/heroes/hero_axe/axe_culling_blade_kill.vpcf"
      local sound_success = "Hero_Axe.Culling_Blade_Success"
      hTarget:EmitSound(sound_success)
      local culling_kill_particle = ParticleManager:CreateParticle(particle_kill, PATTACH_CUSTOMORIGIN, hTarget)
      ParticleManager:SetParticleControlEnt(culling_kill_particle, 0, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetAbsOrigin(), true)
      ParticleManager:SetParticleControlEnt(culling_kill_particle, 1, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetAbsOrigin(), true)
      ParticleManager:SetParticleControlEnt(culling_kill_particle, 2, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetAbsOrigin(), true)
      ParticleManager:SetParticleControlEnt(culling_kill_particle, 4, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetAbsOrigin(), true)
      ParticleManager:SetParticleControlEnt(culling_kill_particle, 8, hTarget, PATTACH_POINT_FOLLOW, "attach_hitloc", hTarget:GetAbsOrigin(), true)
      ParticleManager:ReleaseParticleIndex(culling_kill_particle)
    end
    local hHook = self:GetAbility():GetCaster ():GetTogglableWearable (DOTA_LOADOUT_TYPE_WEAPON)
    if hHook ~= nil then
      hHook:RemoveEffects (EF_NODRAW)
    end
  end
end
 
Последнее редактирование модератором:

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Код доработать надо, но тем не менее, работает не как в Dota Imba с беспонтовым Dummy. Поработать надо только над эффектом
Лолшто.
А ты не знал что в доте тоже хук это думмик? Как и луч феникса например и прочие штуки. Просто они называются валвами не думмики а thinker'ы.
 
Последнее редактирование модератором:

Adam Smith

Друзья CG
4 Окт 2014
473
2
Лолшто.
А ты не знал что в доте тоже хук это думмик? Как и луч феникса например и прочие штуки. Просто они называются валвами не думмики а thinker'ы.
Хук проджектайл, не? К тому же, тинкер вроде не юнит
 
Последнее редактирование модератором:

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Хук проджектайл, не? К тому же, тинкер вроде не юнит
Код:
"npc_dota_thinker"
	{
		// General
		//
		"BaseClass"					"npc_dota_thinker"	// Class of entity of link to.
		"Model"						"models/development/invisiblebox.vmdl"	// Model.
		"SoundSet"					"0"					// Name of sound set.
		"MovementCapabilities"		"DOTA_UNIT_CAP_MOVE_NONE"
		"AttackCapabilities"		"DOTA_UNIT_CAP_NO_ATTACK"
		"BoundsHullName"			"DOTA_HULL_SIZE_HERO"
		"VisionDaytimeRange"		"0"		// Range of vision during day light.
		"VisionNighttimeRange"		"0"		// Range of vision at night time.
	}
 
Последнее редактирование модератором:

Adam Smith

Друзья CG
4 Окт 2014
473
2
Понял, ошибся)Странно что это юнит, могли бы нормально сделать
Хук ведь проджектайл?Валвы пример хука в луа запилили через проджектайл
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Понял, ошибся)Странно что это юнит, могли бы нормально сделать
Хук ведь проджектайл?Валвы пример хука в луа запилили через проджектайл
Как вариант можно сделать и через проджектайл, но я заметил что если часто без кд долбить по хуку ты хукнешь сам хук D:
 
Последнее редактирование модератором:
Реклама: