Зацикливание

  • Автор темы Автор темы den4iccc
  • Дата начала Дата начала

den4iccc

Друзья CG
20 Сен 2014
440
1
Проект
Survival in Taiga XE
Хоть и тупой вопрос, но я не понимаю почему у меня идёт зацикливание у меня есть проверка for i = 0,1 do еcли FindAbilityByName значит RemoveAbility, пробовал через break и GetAbilityByIndex(i) всё равно цикл не заканчивается, без цикла у меня просто не заносится ничего в панель абилок, (как мне сделать проверку без зацикливания ?) + это у меня не способность где нужно прожать кастер
 
Я вписал это в систему постройки то есть когда постройка возведена он делает проверку если есть абилка то он её удаляет, но получается так что он проверяет это с бесконечностью
Код:
	local player = event.caster:GetPlayerOwner()
	local pID = player:GetPlayerID()
  	local hero = player:GetAssignedHero()
	local caster = event.caster
	local ability = event.ability

 for i=0,1 do 
	 if hero:FindAbilityByName("ability_2") then
	 caster:RemoveAbility("ability_1")		
	end
end
я бы не назвал это кодом) это скорее всего быдлокод
 
Последнее редактирование модератором:
Ты уверен, что зацикливание именно в этом куске?
Проверь принтами, где происходит зацикливание:

Код:
print("one")
 for i=0,1 do 
    print("second") 
	 if hero:FindAbilityByName("ability_2") then
	 caster:RemoveAbility("ability_1")		
	end
end
 
Последнее редактирование модератором:
Мне нужно прописать время для обработки запроса как я понял ? консоль выдает [Developer]: RemoveAbility - Unit does not have ability ability_1.
Сам процесс с принтом [ VScript ]: one
[ VScript ]: second
[ Developer ]: RemoveAbility - Unit does not have ability ability_1.
[ VScript ]: second
[ Developer ]: RemoveAbility - Unit does not have ability ability_1.
[ VScript ]: one
[ VScript ]: second
[ Developer ]: RemoveAbility - Unit does not have ability ability_1.
[ VScript ]: second
[ Developer ]: RemoveAbility - Unit does not have ability ability_1.
[ VScript ]: one
[ VScript ]: second
 
У тебя зацикливание происходит не в цикле for.
А в том коде, в котором этот for лежит.

Скинь полный кусок.
 
Код:
	local player = event.caster:GetPlayerOwner()
	local pID = player:GetPlayerID()
  local hero = player:GetAssignedHero()
	local caster = event.caster
	local ability = event.ability
			 
	if not IsChanneling( caster ) then
		-- Remake
		ability.queue = {}

		for itemSlot=0,5 do
			local item = caster:GetItemInSlot(itemSlot)
			if item ~= nil then

				table.insert(ability.queue, item:GetEntityIndex())

				local item_name = tostring(item:GetAbilityName())
				if not IsChanneling( caster ) and string.find(item_name, "train") then

					local train_ability_name = string.gsub(item_name, "item_", "")

					local ability_to_channel = caster:FindAbilityByName(train_ability_name)

					ability_to_channel:SetChanneling(true)
					if Debug_Queue then
						print(ability_to_channel:GetAbilityName()," started channel")
					end

					Timers:CreateTimer(ability_to_channel:GetChannelTime(), 
					function()
						if Debug_Queue then
							print("table")
							DeepPrintTable(ability_to_channel.queue)
						end
						if IsValidEntity(item) then
							ability_to_channel:EndChannel(false)
							ReorderItems(caster, ability_to_channel.queue)
							if Debug_Queue then
								print("finis building")
							end
						else
							if Debug_Queue then
								print("aborted")
							end
						end
					end)
				end
			end
		end
	end		
	-- print("one")
	-- for i=0,1 do 
	-- print("second") 
	-- if hero:FindAbilityByName("ability_2") then
	-- caster:RemoveAbility(""ability_1")		
	-- end
 -- end
 
Последнее редактирование модератором:
Это весь кусок? Чет я не вижу его начала, не вижу слов "function".
 
Последнее редактирование модератором:
да это вся функция Система билдинга от Noya, function AdvanceQueue( event ) .... end
 
Я без понятия, какая там у него система. Скинь код целиком. Скорее всего, у тебя вся эта функция где-то вызывается в бесконечном цикле, а не сама функция устраивает зацикливание.

Можешь прям это проверить, написав принт сразу после слов function().
 
Код:
Debug_Queue = false
function EnqueueUnit( event, food )
	local player = event.caster:GetPlayerOwner()
	local pID = player:GetPlayerID()
  local hero = player:GetAssignedHero()
	local caster = event.caster
	local ability = event.ability
	local player = caster:GetPlayerOwner():GetPlayerID()
	local gold_cost = ability:GetGoldCost( ability:GetLevel() - 1 )

	if CheckFood(caster:GetPlayerOwner(), tonumber(event.food),true)== false then 
		PlayerResource:ModifyGold(caster:GetPlayerOwnerID(), gold_cost, false, 0)
		return 
	else
		SpendFood(caster:GetPlayerOwner(), tonumber(event.food))
	end

	-- Initialize queue
	if not ability.queue then
		ability.queue = {}
	end

	
	
	-- Queue up to 6 units max
	if #ability.queue < 6 then

		local ability_name = ability:GetAbilityName()
		local item_name = "item_"..ability_name
		local item = CreateItem(item_name, caster, caster)
		caster:AddItem(item)

		-- RemakeQueue
		ability.queue = {}
		for itemSlot = 0, 5, 1 do
			local item = caster:GetItemInSlot( itemSlot )
			if item ~= nil then
				table.insert(ability.queue, item:GetEntityIndex())
			end
		end
	else
		-- Refund with message
 		PlayerResource:ModifyGold(player, gold_cost, false, 0)
		FireGameEvent( 'custom_error_show', { player_ID = player, _error = "Queue is full" } )		
	end
end

function SetOwner( event )
	local caster = event.caster
	local target = event.target

	print(tonumber(event.food))

	target.foodSpent = tonumber(event.food)
	target:SetOwner(caster:GetOwner())
end

-- Destroys an item on the buildings inventory, refunding full cost of purchasing and reordering the queue
-- If its the first slot, the channeling ability is also set to not channel, refunding the full price.
function DequeueUnit( event )
	local caster = event.caster
	local item = event.ability
	local player = caster:GetPlayerOwner():GetPlayerID()

	local item_ability = EntIndexToHScript(item:GetEntityIndex())
	local item_ability_name = item_ability:GetAbilityName()

	-- Get tied ability
	local train_ability_name = string.gsub(item_ability_name, "item_", "")
	local train_ability = caster:FindAbilityByName(train_ability_name)
	local gold_cost = train_ability:GetGoldCost( train_ability:GetLevel() - 1 )

	if Debug_Queue then
		print("Start dequeue")
	end

	for itemSlot = 0, 5, 1 do
    	local item = caster:GetItemInSlot( itemSlot )
    if item ~= nil then
    	local current_item = EntIndexToHScript(item:GetEntityIndex())

    	if current_item == item_ability then
    		if Debug_Queue then
	    		print("Q")
	    		DeepPrintTable(train_ability.queue)
    		end
    		local queue_element = getIndex(train_ability.queue, item:GetEntityIndex())
    		if Debug_Queue then
    			print(item:GetEntityIndex().." in queue at "..queue_element)
    		end
	      table.remove(train_ability.queue, queue_element)

	      caster:RemoveItem(item)
	      
	      -- Refund ability cost
	      PlayerResource:ModifyGold(player, gold_cost, false, 0)

	      local foodToReturn = train_ability:GetLevelSpecialValueFor("food_cost", 1)
	      caster:GetPlayerOwner().food = caster:GetPlayerOwner().food - foodToReturn

	      if Debug_Queue then
					print("Refund ",gold_cost)
				end

				-- Set not channeling if the cancelled item was the first **current** slot
				if itemSlot == 0 then
					train_ability:SetChanneling(false)
					train_ability:EndChannel(true)
					if Debug_Queue then
						print("Cancel current channel")
					end
					ReorderItems(caster,train_ability.queue)
				else
					if Debug_Queue then
						print("Removed unit in queue slot",itemSlot)	
					end				
				end
				break
			end
    end
  end
end

-- Auxiliar function, takes all items and puts them 1 slot back
function ReorderItems( caster, queue )
	queue = {}
	for itemSlot = 0, 5, 1 do
		local item = caster:GetItemInSlot( itemSlot )
    	if item ~= nil then
    		if Debug_Queue then
    			print("========>REMOVING",item:GetEntityIndex())  		
    		end
  		local new_item = CreateItem(item:GetName(), caster, caster)
    		caster:RemoveItem(item)
			table.insert(queue, new_item:GetEntityIndex())
			if Debug_Queue then
				print("========>ADDED",new_item:GetEntityIndex())  	
			end	
    		caster:AddItem(new_item)
    	end
  end
end


-- Moves on to the next element of the queue
function NextQueue( event )
	local caster = event.caster
	local ability = event.ability
	ability:SetChanneling(false)
	--print("Move next!")

	-- Dequeue
	--DeepPrintTable(event)
	local hAbility = EntIndexToHScript(ability:GetEntityIndex())

	for itemSlot = 0, 5, 1 do
    	local item = caster:GetItemInSlot( itemSlot )
    if item ~= nil then
    	local item_name = tostring(item:GetAbilityName())

    	-- Remove the "item_" to compare
    	local train_ability_name = string.gsub(item_name, "item_", "")

    	if train_ability_name == hAbility:GetAbilityName() then

    		local train_ability = caster:FindAbilityByName(train_ability_name)

    		if Debug_Queue then
	    		print("Q")
	    		DeepPrintTable(train_ability.queue)
    		end
    		local queue_element = getIndex(train_ability.queue, item:GetEntityIndex())
    		if IsValidEntity(item) then
    			if Debug_Queue then
	    			print(item:GetEntityIndex().." in queue at "..queue_element)
	    		end
		      table.remove(train_ability.queue, queue_element)
	      	caster:RemoveItem(item)
	      end

      	break
      elseif item then
    		--print(item_name,hAbility:GetAbilityName())
    	end
    end
  end
end

function AdvanceQueue( event )
	local player = event.caster:GetPlayerOwner()
	local pID = player:GetPlayerID()
  local hero = player:GetAssignedHero()
	local caster = event.caster
	local ability = event.ability
			 
	if not IsChanneling( caster ) then
		-- Remake
		ability.queue = {}

		for itemSlot=0,5 do
			local item = caster:GetItemInSlot(itemSlot)
			if item ~= nil then

				table.insert(ability.queue, item:GetEntityIndex())

				local item_name = tostring(item:GetAbilityName())
				if not IsChanneling( caster ) and string.find(item_name, "train") then

					local train_ability_name = string.gsub(item_name, "item_", "")

					local ability_to_channel = caster:FindAbilityByName(train_ability_name)

					ability_to_channel:SetChanneling(true)
					if Debug_Queue then
						print(ability_to_channel:GetAbilityName()," started channel")
					end

					Timers:CreateTimer(ability_to_channel:GetChannelTime(), 
					function()
						if Debug_Queue then
							print("table")
							DeepPrintTable(ability_to_channel.queue)
						end
						if IsValidEntity(item) then
							ability_to_channel:EndChannel(false)
							ReorderItems(caster, ability_to_channel.queue)
							if Debug_Queue then
								print("finis building")
							end
						else
							if Debug_Queue then
								print("aborted")
							end
						end
					end)
				end
			end
		end
	end		
	-- print("one")
	-- for i=0,1 do 
	-- print("second") 
	-- if hero:FindAbilityByName("ability_2") then
	-- caster:RemoveAbility(""ability_1")		
	-- end
 -- end
end


-- Auxiliar table function
function tableContains(list, element)
  if list == nil then return false end
  for i=1,#list do
    if list[i] == element then
      return true
    end
  end
  return false
end

function getIndex(list, element)
  if list == nil then return false end
  for i=1,#list do
    if list[i] == element then
      return i
    end
  end
  return -1
end

function getUnitIndex(list, unitName)
  --print("Given Table")
  --DeepPrintTable(list)
  if list == nil then return false end
  for k,v in pairs(list) do
    for key,value in pairs(list[k]) do
    	if Debug_Queue then
     	 print(key,value)
     	end
      if value == unitName then 
        return key
      end
    end    
  end
  return -1
end

-- Auxiliar function that goes through every ability and item, checking for any ability being channelled
function IsChanneling ( unit )
	
	for abilitySlot=0,15 do
		local ability = unit:GetAbilityByIndex(abilitySlot)
		if ability ~= nil and ability:IsChanneling() then 
			return true
		end
	end

	for itemSlot=0,5 do
		local item = unit:GetItemInSlot(itemSlot)
		if item ~= nil and item:IsChanneling() then
			return true
		end
	end

	return false
end

function BuildHero( event )
	local caster = event.caster
	local player = caster:GetPlayerOwner()
	local hero = player:GetAssignedHero()
	local playerID = player:GetPlayerID()
	local unit_name = event.Hero
	local origin = event.caster:GetAbsOrigin() + RandomVector(250)

	-- Get a random position to create the illusion in
	local origin = caster:GetAbsOrigin() + RandomVector(150)

	-- handle_UnitOwner needs to be nil, else it will crash the game.
	local illusion = CreateUnitByName(unit_name, origin, true, hero, nil, hero:GetTeamNumber())
	illusion:SetPlayerID(playerID)
	illusion:SetControllableByPlayer(playerID, true)
	
end
 
Последнее редактирование модератором:
Посел function AdvanceQueue( event ) пропиши print("ok").

Если будет в консоли постоянно писаться ok, то ищи место, где ты вызываешь эту функцию AdvanceQueue().
 
Последнее редактирование модератором:
Ахахах дичь у меня OnIntervalThink стоит пассивка которая и вызывает функцию AdvanceQueue я вчера с этим геморойничел прописал для npc OnIntervalThink который бы чекал с опред таймером, можно ли как нибудь записать если это действие произошло иначе типо прерывает интервал
 
Кароч я перенёс это в другой файл там сделал эту проверку и прописал новую абилку, и вопрос можно ли как то работать из lua с ThinkInterval или придётся прописывать
типо вот этого local cooldown = ability:GetLevelSpecialValueFor( "cooldown" , ability:GetLevel() - 1 ) и занести "cooldown" в AbilitySpecial
Код:
	"chek"
	{
	 "BaseClass"      "ability_datadriven"
	 "MaxLevel"      "1"
	 "AbilityBehavior"    "DOTA_ABILITY_BEHAVIOR_PASSIVE"
	
	 "Modifiers"
	 {
	  "modifier_cheking"
	  {
	   "Passive"   "1"
	   "IsHidden"   "1"
	 
	   "ThinkInterval" "0.03"
	   "OnIntervalThink"
	   {
	    "RunScript"
	    {
	     "ScriptFile" "chek.lua"
	     "Function"  "cheking"
	    }
	   }
	  }
	
	  "modifier_cheking_passive"
	  {
	   "Passive"   "1"
	   "IsHidden"   "1"
	 
	   "States"
	   {
	    "MODIFIER_STATE_ROOTED"  "MODIFIER_STATE_VALUE_ENABLED"
	   }
	  }
	 }
	}

lua
Код:
function cheking(keys)
	local player = keys.caster:GetPlayerOwner()
  local pID = player:GetPlayerID()
  local hero = player:GetAssignedHero()
  local caster = keys.caster
	
	 local target = keys.target
	 local ability = keys.ability
	

			for i=0,1 do 
				if hero:FindAbilityByName("ability_2") then
				caster:RemoveAbility("ability_1")		
				end
			end

end
 
Последнее редактирование модератором:
В смысле, работать из lua с thinkerom, который ты описал в datadriven? Я думаю нет, по крайней мере, не видел такого. Сделай просто thinker в lua, а не в dd.
 
Блин я думаю что если сделаю таймер то будет в принципе тоже самое, хочу сделать проверку так чтобы она сама срабатывала один раз а не n-ое кол-во раз или сделать авто каст
Код:
local ability = event.ability 
  ability:ToggleAutoCast()
и поставить таймер
Код:
 local time = 1 
 Timers:CreateTimer(1, function() 
  if (time == 1) then 
 .....
return nil
end)
 
Я без понятия, о чем ты говоришь, так как не знаю твоей идеи и твоей реализации механики.
 
Хочу сделать так если у героя есть абилка значит npc(постройка удаляет свой собственный скил) всё работает но с циклом
 
А тебе нужно без цикла?

Ну в момент добавления герою этой абилки и производи удаление. Если через lua добавляешь.
 
Реклама: