Results 1 to 9 of 9

Thread: It seems that many action didn't work when called too often?

  1. #1
    Basic Member
    Join Date
    Dec 2016
    Posts
    123

    It seems that many action didn't work when called too often?

    My bot stuck at Action:Pickrune....and before Feb 10th update it stay idle when calling Action:MoveToLocation. Is there other Action that return idle when called every frame?

  2. #2
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    There are all kinds of issues with the Action*_*() since the Feb 8 & 10th update for me as well. The issues are that I used to issue an Action_*() command every frame for every hero and it was working (no idea what checks they were doing on the backend server to allow me to call Action_AttackUnit() every frame and allow the attack to get through even though I was issuing the same Action_AttackUnit() every frame, but they were doing it since I was not "break" my attack animations when seeing it work in game). Now it seems like I cannot do that and expect it to work.

    Now, technically, this is not a Valve issue but a bot-creator's issue. Stop spamming the system with stuff every frame... and have some sort of memory of what command you issued last and how long it will take to execute... and have some sort of logic to determine when you should interrupt the current command versus allow it to complete before doing something else versus pre-empting it and then letting it complete. That's on us really to do as bot-creators/writers. Now Valve can add some sanity checks on the backend to allow our 'badly implemented' code to work, but really, I feel like it is on us.

    Yes, this means I have to fix/re-write large chunks of my code. But once I do this, I will have a much better understanding of the decision making happening in my bot rather than just assuming that the last-frame's decision making was correct.

  3. #3
    Basic Member
    Join Date
    Dec 2016
    Posts
    123
    Quote Originally Posted by nostrademous View Post
    There are all kinds of issues with the Action*_*() since the Feb 8 & 10th update for me as well. The issues are that I used to issue an Action_*() command every frame for every hero and it was working (no idea what checks they were doing on the backend server to allow me to call Action_AttackUnit() every frame and allow the attack to get through even though I was issuing the same Action_AttackUnit() every frame, but they were doing it since I was not "break" my attack animations when seeing it work in game). Now it seems like I cannot do that and expect it to work.

    Now, technically, this is not a Valve issue but a bot-creator's issue. Stop spamming the system with stuff every frame... and have some sort of memory of what command you issued last and how long it will take to execute... and have some sort of logic to determine when you should interrupt the current command versus allow it to complete before doing something else versus pre-empting it and then letting it complete. That's on us really to do as bot-creators/writers. Now Valve can add some sanity checks on the backend to allow our 'badly implemented' code to work, but really, I feel like it is on us.

    Yes, this means I have to fix/re-write large chunks of my code. But once I do this, I will have a much better understanding of the decision making happening in my bot rather than just assuming that the last-frame's decision making was correct.
    You command your bot to move to current lanefront point 0.50, a movetolocation action is called, then you stop spamming that action since your bot are already on its way to lanefront 0.50, but when your bot is on his way to lanefront 0.50, the current lane front value change, it's now 0.33 and that's where your bot want to go now, how do your bot know your target location changed and a new movetolocation action should be called then? Do you create a variable to store bot's current target location, and call move action when that location change?

    For pickrune I use GetCurrentActionType( ) to check if the current action is already pickrune then stop spammin, because there is only one rune in one place. But for other action like attackunit or movetolocation I can't just do a simple check. If bot is about to attack a creep when an enemy hero with very low hp showed up, of course he should stop attack creep and go for the hero. What should I do to tell bot that there is a target change and you may stop current attack and call Action:AttackUnit again with the new target returned?
    Last edited by lunarbreez; 02-13-2017 at 09:50 AM.

  4. #4
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    Quote Originally Posted by lunarbreez View Post
    You command your bot to move to current lanefront point 0.50, a movetolocation action is called, then you stop spamming that action since your bot are already on its way to lanefront 0.50, but when your bot is on his way to lanefront 0.50, the current lane front value change, it's now 0.33 and that's where your bot want to go now, how do your bot know your target location changed and a new movetolocation action should be called then? Do you create a variable to store bot's current target location, and call move action when that location change?
    I check my bot's position and the lanefront position every frame. I only issue/send a new MoveToLocation() when it changed from the last MoveToLocation() I sent previously. Note... I didn't use to do this, I just recently started. In addition to that, I also check that the location I want to move to is at least 5.0 units of distance away from where I am currently, otherwise I ignore it. This prevents my bot from "orbiting" the location that it wants to be at.

    Quote Originally Posted by lunarbreez View Post
    For pickrune I use GetCurrentActionType( ) to check if the current action is already pickrune then stop spammin, because there is only one rune in one place. But for other action like attackunit or movetolocation I can't just do a simple check. If bot is about to attack a creep when an enemy hero with very low hp showed up, of course he should stop attack creep and go for the hero. What should I do to tell bot that there is a target change and you may stop current attack and call Action:AttackUnit again with the new target returned?
    Up to you here. It is easier for me since I did a full-bot over-write rather than mode-based over-writes and hence I can control the decision tree of my bots. Basically I evaluate decisions in a certain priority with a fall-through method if the current priority tier is not something I want to act on. It goes like this: "if I need to and can use shrine" > "retreat" > "fight" > "get rune" > "go to side/secret shop" > "help allies if needed" > "roshan if appropriate" > "defend lane if necessary" > "go ganking if appropriate" > "go roaming if appropriate" > "jungle" > "ward" > "change lane if appropriate" > "push lane if appropriate" > "normal laning"

  5. #5
    Basic Member
    Join Date
    Dec 2016
    Posts
    123
    Quote Originally Posted by nostrademous View Post
    I only issue/send a new MoveToLocation() when it changed from the last MoveToLocation()
    So you have a variable to store the information from last MoveToLocation() and compare, so you know when it's a new MoveToLocation() and should be send again?

    I'm also doing a complete take over, running a priority check made by myself to decide which action should be taken and use none of the mode exist. I found this "doing the same type action but change to another target" may cause some problem.

    Take my lasthit code as example, lasthit() will return a high priority for lasthit and the weakest creep around bot. If lasthit got the highest priority among all action then the golasthit() function start to work, I use "if (npcBot:GetCurrentActionType( ) == BOT_ACTION_TYPE_ATTACK) then return;" to stop spamming so the Action:AttackUnit can be successfully performed. But if the target get healed, maybe by an omni knight, and it is no longer the weakest creep around, bot won't attack new weakest creep because its action type is already BOT_ACTION_TYPE_ATTACK and new Action:AttackUnit is not issued.

    the
    Code:
    function lasthit()
    	local npcBot = GetBot();
    	local EnemyCreeps = npcBot:GetNearbyLaneCreeps(1000,true);--get nearby enemy creeps
    	local lowest_hp = 10000;
    	local weakest_creep = nil;
    	local creep_pos = Fountain;
    	local itemdamage = 0;
    	local extradamage =0;
    	local lasthit_p =0;	
    	
    	if(CheckItemByName("item_quelling_blade")) then
    		itemdamage = 24;
    	end
    			
    	for creep_k,creep in pairs(EnemyCreeps) do  --get weakest enemy creep nearby
         	if(creep:IsAlive() and ((not IsInTowerRange(creep:GetLocation() ,(900-npcBot:GetAttackRange()))))) then
               local creep_hp = creep:GetHealth();
                if(lowest_hp > creep_hp and creep_hp > 0 ) then
              		lowest_hp = creep_hp;
              		weakest_creep = creep;
    		  		creep_pos = weakest_creep:GetLocation();	  		
                 end
             end
        end
        	
        if(weakest_creep ~= nil) then  --if we have a weakest_enemy_creep not in their tower range
    		local rightClick =weakest_creep:GetActualIncomingDamage(npcBot:GetAttackDamage(),DAMAGE_TYPE_PHYSICAL); --estimate rightClick damage
    		if (GetUnitToLocationDistance(npcBot, creep_pos) > npcBot:GetAttackRange()) then
    			extradamage = (((GetUnitToLocationDistance(npcBot, creep_pos)-npcBot:GetAttackRange()) / npcBot:GetCurrentMovementSpeed( ))+ npcBot:GetAttackPoint() + 0.4)* rightClick * 1.1;
    		end		
    		if(lowest_hp > 0 and lowest_hp <= ( rightClick + itemdamage  +  extradamage) ) then
    			lasthit_p = 11.3; ----higher than attackhero_p becaue lasthit is more important
    			return lasthit_p, weakest_creep;
      --- no enemy target for lasthit---
    		elseif(lowest_hp > ( rightClick  + itemdamage +  extradamage)) then   
    			lasthit_p = 0;
    			return lasthit_p, weakest_creep;
    		end
    	else
    		lasthit_p = 0;
    		return lasthit_p, weakest_creep;
    	end
    end
    
    function golasthit()	
     	if ( current_action == 13) then
    		local npcBot = GetBot();
    		local lasthit_p, weakest_creep = lasthit();
    		local creep_pos = weakest_creep:GetLocation();
    		local lowest_hp = weakest_creep:GetHealth();
    		local itemdamage = 0;
    		local extradamage =0;
    		
    		if (npcBot:GetCurrentActionType( ) == BOT_ACTION_TYPE_ATTACK) then --  should add " npcBot:GetAttackTarget() == weakest_creep " but didn't work
    			return;
    		end
    		
    		if(CheckItemByName("item_quelling_blade")) then
    			itemdamage = 24;
    		end	
    			
        	if(weakest_creep ~= nil) then  --if we have a weakest_enemy_creep not in their tower range
    			local rightClick =weakest_creep:GetActualIncomingDamage(npcBot:GetAttackDamage(),DAMAGE_TYPE_PHYSICAL); --estimate rightClick damage
    			if (GetUnitToLocationDistance(npcBot, creep_pos) > npcBot:GetAttackRange()) then
    				extradamage = (((GetUnitToLocationDistance(npcBot, creep_pos)-npcBot:GetAttackRange()) / npcBot:GetCurrentMovementSpeed( ))+ npcBot:GetAttackPoint() + 0.4)* rightClick * 1.1;
    			end		    	
        		if (lowest_hp > (rightClick + itemdamage) and lowest_hp <= ( rightClick + itemdamage  +  extradamage) ) then
        			npcBot:Action_MoveToLocation(creep_pos);
        		elseif (lowest_hp <= ( rightClick +itemdamage ) and weakest_creep:IsAlive() ) then
               		npcBot:Action_AttackUnit(weakest_creep,true);
            	end
            end
    	end
    end
    Last edited by lunarbreez; 02-13-2017 at 12:12 PM.

  6. #6
    Basic Member
    Join Date
    Dec 2016
    Posts
    731
    Check my "Rolling your own Action Queue" thread/code. It shows how I store my last action.

    For last hitting purposes I likewise determine appropriate target every frame and issue my attack against them. I store the attack action and the handle of the attack target. I don't issue a new attack until either attack point is reached or my target handle changes

  7. #7
    Valve Developer
    Join Date
    Sep 2011
    Posts
    1,704
    I've added more protection in the next update to calling Action_* functions every frame -- they should no longer stall out.

  8. #8
    Basic Member
    Join Date
    Dec 2016
    Posts
    123
    Quote Originally Posted by ChrisC View Post
    I've added more protection in the next update to calling Action_* functions every frame -- they should no longer stall out.
    Thank you! Is that included in Feb 13th update? It seem that I still need check function to stop spamming Action:AttackUnit so it can function well.

  9. #9
    Valve Developer
    Join Date
    Sep 2011
    Posts
    1,704
    Hm, looks like a couple actions still don't have protection against being called too often (AttackUnit being one of them). I'll fix.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •