Results 1 to 10 of 10

Thread: IsCourierAvailable()

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

    Question IsCourierAvailable()

    @ChrisC - can we make this API take a handle to a courier or an index number for courier so that we can use it on a specific courier if we have more than one?

    As I "extremely slowly" work on my WebBased-AI (really busy with real-life work stuff the past few weeks) I am imagining that bots might be very good at micro-ing 3+ couriers at the same time.

    PS - any chance for a UNIT_LIST_COURIER aggregator for GetUnitList()? Pretty please?

    PSS - the wiki really needs an update (many functions, constants, etc missing)

    PSSS - any update on GetUnitPotentialValue() being fixed

  2. #2
    Basic Member
    Join Date
    Dec 2016
    Posts
    611
    PSSSS - based on some feedback on my FullOverwrite of bots - it looks like the courier state flags are a bit messed up after the "fix" to the courier action type a patch or two ago.

    I have the following code:
    Code:
        if bot:IsAlive() and (bot:GetStashValue() > 500 or bot:GetCourierValue() > 0 or U.HasImportantItem()) and state ~= COURIER_STATE_DELIVERING_ITEMS then
            bot:ActionImmediate_Courier(courier, COURIER_ACTION_TAKE_AND_TRANSFER_ITEMS)
            return
        end
    I am told that the bots now fight over the courier, which indicates to me the COURIER_STATE_DELIVERING_ITEMS is possibly not being set correctly (or quickly enough) when a bot calls the above.

  3. #3
    Valve Developer
    Join Date
    Sep 2011
    Posts
    1,665
    There may be a slight delay, but I'm seeing them switch to it properly.

  4. #4
    Basic Member
    Join Date
    Oct 2016
    Posts
    170
    there are probably multiple bots who have stash value over 500?
    they are always going to fight in that case.
    even the script i use that checks highest value stash, they fight for a bit in the prints, but the guy with highest stash ends up getting it.

  5. #5
    Basic Member
    Join Date
    Dec 2016
    Posts
    611
    Quote Originally Posted by Yavimaya View Post
    there are probably multiple bots who have stash value over 500?
    they are always going to fight in that case.
    even the script i use that checks highest value stash, they fight for a bit in the prints, but the guy with highest stash ends up getting it.
    That should be the case though because of the AND rules I have in place:
    bot:IsAlive() and (bot:GetStashValue() > 500 or bot:GetCourierValue() > 0 or U.HasImportantItem()) and state ~= COURIER_STATE_DELIVERING_ITEMS

    The last part should make it "fail" when another bot is getting their items delivered.

  6. #6
    Basic Member
    Join Date
    Dec 2016
    Posts
    611
    Re-reading the complaint, it seems it was more that a human was playing alongside my bots and the bots were stealing the courier from the human. Makes me wonder if the courier states are not set when a human does an action?

  7. #7
    Basic Member
    Join Date
    Oct 2016
    Posts
    170
    there is a "delay" if you will, but it isnt a real delay, it is the same as most skill usage, it is repeated a few times before it actually happens (or maybe it is my bad scripting that does that).
    so even though you have that tagged on at the end, before it goes into that state, all bots will succeed in using the courier, it will just be the last guy that used it before the state change that actually gets his things delivered.
    now this doesnt fix your player usage issue, but it is my best explanation of why the bots would fight over it.

    for the player, you need to add a "not IsPlayerbot()" to make them not take it from humans - or atleast is the easiest way.

    e.g. the guts of the code i use:

    Code:
    if IsCourierAvailable() and not IsCourierNearShop(npcCourier) then
    	
    		if npcBot:IsAlive() and npcBot:GetStashValue() > 0 and not IsInvFull(npcBot) then
    			local numPlayer =  GetTeamPlayers(GetTeam());
    			local maxVal = 0;
    			_G.TransTarget = nil;
    			for i = 1, #numPlayer
    			do
    			--print(numPlayer[i]..tostring(IsPlayerBot(numPlayer[i])));
    				if GetTeamMember(i) ~= nil and IsPlayerBot(numPlayer[i]) and GetTeamMember(i):IsAlive() then
    					local SVal = GetTeamMember(i):GetStashValue();
    					if SVal ~= 0 and SVal > maxVal then
    						maxVal = SVal;
    						_G.TransTarget = GetTeamMember(i);
    					end
    				end
    			end
    				if _G.TransTarget ~= nil and  _G.TransTarget:IsAlive() then
    				--print(_G.TransTarget:GetUnitName().."       taketransf")
    				_G.TransTarget:ActionImmediate_Courier( npcCourier, COURIER_ACTION_TAKE_AND_TRANSFER_ITEMS )
    				return
    				end
    		elseif not npcBot:IsAlive() and npcBot:GetCourierValue() > 0 and npcCourier:DistanceFromFountain() == 0 then
    			--print(npcBot:GetUnitName().."          return stash")
    			npcBot:ActionImmediate_Courier( npcCourier, COURIER_ACTION_RETURN_STASH_ITEMS );
    			return
    		end
    		
    	elseif GetCourierState( npcCourier ) == COURIER_STATE_MOVING and (_G.TransTarget ~= nil and not _G.TransTarget:IsAlive()) then    -- _G. sets global?
    		--print(npcBot:GetUnitName().."             bot dead return")
    		npcBot:ActionImmediate_Courier( npcCourier, COURIER_ACTION_RETURN );
    		return
    	end
    Last edited by Yavimaya; 06-29-2017 at 05:08 PM.

  8. #8
    Basic Member
    Join Date
    Mar 2012
    Posts
    1,679
    Apart from making IsCourierAvaiable() unit-scoped, I think we could use 2 new functions: the one that is used by the 7.00 UI that counts how many slots a player uses on the courier (the little number over the courier icon) and the function that is used to draw the player's main hero icon when using it. I think that way we can at least use a not-nil condition on that. I know it is not always updated even on the UI as well as it gets overwritten when multiple players use it, but I think it'll help a great deal in bot games. I assume it returns the last player that used the courier when the courier is busy.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  9. #9
    Here is a way to change this without breaking people's code:

    global IsCourierAvailable() -> returns true if at least 1 courier is available
    unit based IsAvailable() -> returns true if the courier is available

  10. #10
    Basic Member
    Join Date
    Mar 2012
    Posts
    1,679
    But then we'd maybe need an extended class for couriers (returned by GetCourier(id)), I think? It's be silly to have courier-context abilities available to any unit. Plus it will allow more customizaiton for couriers (by adding our own functions for instance) A very nice approach was done the same way for custom games where each object had its own set of functions (which was limited by inheritance ).

    And yes I agree with both nostrademous and Platinum_dota2.

    On a related note: I still find couriers "frozen" in the middle of the field in native bot games. Not sure if it is a courier issue or a bot issue since I expect the bots to use a transfer&return just like humans.. There are also moments when the courier doesn't respond to my "call" from the HUD button (even in normal all-pick games, not just bots).
    Last edited by The Nomad; 07-03-2017 at 11:52 AM.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

Posting Permissions

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