Page 3 of 6 FirstFirst 1 2 3 4 5 ... LastLast
Results 21 to 30 of 57

Thread: Performance & Memory monitoring

  1. #21
    Basic Member
    Join Date
    May 2014
    Posts
    270
    Quote Originally Posted by The Nomad View Post
    It's fine. I have little time to code lately so instead of doing stuff inefficiently on the run I can just chat up here. If it's useful, I am more than happy to do it.
    Thank you .

    Quote Originally Posted by The Nomad View Post
    I never tested if it works right in multiple envs (meaning the way D2 does it). The easiest way to test is setting a print in a generic file and see if it prints the correct unit name. This might work for generic files like item purchases, item/ability usages and modes. But I am unsure of bot_generic.
    I've tested it in item_purchase, ability_item_usage, mode rune, farm, side_shop, secret_shop, ward, team_roam generic. All of them print the correct unit name every time I tried to reload the script but not for bot_generic. In bot_generic some may print the correct unit name and some may doesn't print unit name at all. For example : In the printed console below only Visage that doesn't have the correct bot_generic unit name (it doesn't even print it). Sometimes I found 2 bots that doesn't have the unit name printed.
    Code:
    [VScript] bot_generic for npc_dota_hero_storm_spirit
    [VScript] item_purchase_generic for npc_dota_hero_storm_spirit
    [VScript] ability_item_usage_generic for npc_dota_hero_storm_spirit
    [VScript] mode_secret_shop_generic for npc_dota_hero_storm_spirit
    [VScript] mode_side_shop_generic for npc_dota_hero_storm_spirit
    [VScript] mode_rune_generic for npc_dota_hero_storm_spirit
    [VScript] mode_team_roam_generic for npc_dota_hero_storm_spirit
    [VScript] mode_farm_generic for npc_dota_hero_storm_spirit
    [VScript] mode_ward_generic for npc_dota_hero_storm_spirit
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_rattletrap
    [VScript] item_purchase_generic for npc_dota_hero_rattletrap
    [VScript] ability_item_usage_generic for npc_dota_hero_rattletrap
    [VScript] mode_secret_shop_generic for npc_dota_hero_rattletrap
    [VScript] mode_side_shop_generic for npc_dota_hero_rattletrap
    [VScript] mode_rune_generic for npc_dota_hero_rattletrap
    [VScript] mode_team_roam_generic for npc_dota_hero_rattletrap
    [VScript] mode_farm_generic for npc_dota_hero_rattletrap
    [VScript] mode_ward_generic for npc_dota_hero_rattletrap
    [VScript] ================================================
    [VScript] item_purchase_generic for npc_dota_hero_visage
    [VScript] ability_item_usage_generic for npc_dota_hero_visage
    [VScript] mode_secret_shop_generic for npc_dota_hero_visage
    [VScript] mode_side_shop_generic for npc_dota_hero_visage
    [VScript] mode_rune_generic for npc_dota_hero_visage
    [VScript] mode_team_roam_generic for npc_dota_hero_visage
    [VScript] mode_farm_generic for npc_dota_hero_visage
    [VScript] mode_ward_generic for npc_dota_hero_visage
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_witch_doctor
    [VScript] item_purchase_generic for npc_dota_hero_witch_doctor
    [VScript] ability_item_usage_generic for npc_dota_hero_witch_doctor
    [VScript] mode_secret_shop_generic for npc_dota_hero_witch_doctor
    [VScript] mode_side_shop_generic for npc_dota_hero_witch_doctor
    [VScript] mode_rune_generic for npc_dota_hero_witch_doctor
    [VScript] mode_team_roam_generic for npc_dota_hero_witch_doctor
    [VScript] mode_farm_generic for npc_dota_hero_witch_doctor
    [VScript] mode_ward_generic for npc_dota_hero_witch_doctor
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_tiny
    [VScript] item_purchase_generic for npc_dota_hero_tiny
    [VScript] ability_item_usage_generic for npc_dota_hero_tiny
    [VScript] mode_secret_shop_generic for npc_dota_hero_tiny
    [VScript] mode_side_shop_generic for npc_dota_hero_tiny
    [VScript] mode_rune_generic for npc_dota_hero_tiny
    [VScript] mode_team_roam_generic for npc_dota_hero_tiny
    [VScript] mode_farm_generic for npc_dota_hero_tiny
    [VScript] mode_ward_generic for npc_dota_hero_tiny
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_furion
    [VScript] item_purchase_generic for npc_dota_hero_furion
    [VScript] ability_item_usage_generic for npc_dota_hero_furion
    [VScript] mode_secret_shop_generic for npc_dota_hero_furion
    [VScript] mode_side_shop_generic for npc_dota_hero_furion
    [VScript] mode_rune_generic for npc_dota_hero_furion
    [VScript] mode_team_roam_generic for npc_dota_hero_furion
    [VScript] mode_farm_generic for npc_dota_hero_furion
    [VScript] mode_ward_generic for npc_dota_hero_furion
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_alchemist
    [VScript] item_purchase_generic for npc_dota_hero_alchemist
    [VScript] ability_item_usage_generic for npc_dota_hero_alchemist
    [VScript] mode_secret_shop_generic for npc_dota_hero_alchemist
    [VScript] mode_side_shop_generic for npc_dota_hero_alchemist
    [VScript] mode_rune_generic for npc_dota_hero_alchemist
    [VScript] mode_team_roam_generic for npc_dota_hero_alchemist
    [VScript] mode_farm_generic for npc_dota_hero_alchemist
    [VScript] mode_ward_generic for npc_dota_hero_alchemist
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_bane
    [VScript] item_purchase_generic for npc_dota_hero_bane
    [VScript] ability_item_usage_generic for npc_dota_hero_bane
    [VScript] mode_secret_shop_generic for npc_dota_hero_bane
    [VScript] mode_side_shop_generic for npc_dota_hero_bane
    [VScript] mode_rune_generic for npc_dota_hero_bane
    [VScript] mode_team_roam_generic for npc_dota_hero_bane
    [VScript] mode_farm_generic for npc_dota_hero_bane
    [VScript] mode_ward_generic for npc_dota_hero_bane
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_phoenix
    [VScript] item_purchase_generic for npc_dota_hero_phoenix
    [VScript] ability_item_usage_generic for npc_dota_hero_phoenix
    [VScript] mode_secret_shop_generic for npc_dota_hero_phoenix
    [VScript] mode_side_shop_generic for npc_dota_hero_phoenix
    [VScript] mode_rune_generic for npc_dota_hero_phoenix
    [VScript] mode_team_roam_generic for npc_dota_hero_phoenix
    [VScript] mode_farm_generic for npc_dota_hero_phoenix
    [VScript] mode_ward_generic for npc_dota_hero_phoenix
    [VScript] ================================================
    [VScript] bot_generic for npc_dota_hero_sand_king
    [VScript] item_purchase_generic for npc_dota_hero_sand_king
    [VScript] ability_item_usage_generic for npc_dota_hero_sand_king
    [VScript] mode_secret_shop_generic for npc_dota_hero_sand_king
    [VScript] mode_side_shop_generic for npc_dota_hero_sand_king
    [VScript] mode_rune_generic for npc_dota_hero_sand_king
    [VScript] mode_team_roam_generic for npc_dota_hero_sand_king
    [VScript] mode_farm_generic for npc_dota_hero_sand_king
    [VScript] mode_ward_generic for npc_dota_hero_sand_king
    [VScript] ================================================
    20171005022546_1.jpg

    Quote Originally Posted by The Nomad View Post
    You seem to be a fan of "not condition". Did you know that there is a difference between this?
    Yep, I knew that. I just wanna make the code shorter, but that's not a good idea for the VM. I should prolly change it to variable == condition.

    Quote Originally Posted by The Nomad View Post
    As for more advice it depends... if I am to pick one I'd say that you are calling the same thing at least 20 times in teh same frame: GetUnitToLocationDistance(bot, runeLoc). You run it in each function multiplied by the number of runes and allied members. Why not cache it? The call itself is not expensive, but it's done 5 times in a frame and it can add up. It won't degrade FPS but optimizing it won't hurt. It will also simplify your code and allow easier maintanance.
    ...
    Why calculate the distance to your bot inside the loop? Even if you need the extra accuracy it is not worth it. Also, it's the same one in all functions. Isn't it? Maybe with a few 0.0000... units difference.
    Ah, you're correct. Dang it brain why you work like a zombie! :P

    Quote Originally Posted by The Nomad View Post
    Try Target:CanBeSeen(). That is usually the problem. I had it in my bots too. Try it and see if it works. if the GetBot() handle is nil, then IsNull() won't work anyway and would just throw an error. This is why I think enemy vision is a factor, especially since Chris resets the handles.
    Also note that there is a chance that the handles can change in the same frame.
    Hmmmm... so that' the problem. I'll add it in the check.

    Quote Originally Posted by The Nomad View Post
    As a side note, when I play with your bots with super mega debugs on your bot code spams a lot of warnings and mistakes. Mostly about operating code on bots that aren't seen. Not saying it in a bad way, of course, I have a lot of fun with it and I move so slow with my bot that I can't even comment on speed of updates.
    That's what I've asked recently. That console spam. I already do CanBeSeen() check on all spell usage in MyUtility.lua, but maybe it happens in the MinionThink() for heroes that have minion like Visage, Chen, Enchantress. I did a mistake on Brood before by making the spider web to attack because I haven't done a check for the minion name. I noticed some bots that have minion that I haven't override like Veno, Shadow Shaman, or Undying spamming "...the unit doesn't have movement capability..." warning every time they spawn. I've tried to override it and the warning are gone. Any idea on how to get the source of the warnings?

    Quote Originally Posted by The Nomad View Post
    (one of the reasons I aske you why your code has such weird var names or references and you said you just copy paste them between bots cos it's faster).
    And in the end the question is whether you care about quantity or quality. Sure, var names don't make the bot faster or better. But that kind of attitude reflects in the whole product, not just a function or variable name in the end
    Yep I regret that decission to copy paste the same variable and function usage after I see there are so much stuff to change. I want to change it but I still find which one the better template form, from the one in ability_item_usage_lion/crystal_maiden.lua or ability_item_usage_zuus/jakiro.lua or even my new plan on the new template form plus I don't have enough time to change it for now.

    Quote Originally Posted by The Nomad View Post
    As I said, don't take it as an attack, it's just my opinion, even if it is a stupid or silly one...
    Nope, I'll take it as feedback to improve the script and how I do the bot scripting. Thanks for the feedback.

    Quote Originally Posted by The Nomad View Post
    Obviously, you can't set engine functions local. So you can't do local function Think() or local function GetDesire().
    Or at least I haven't tried, but my guess is it won't work. Local functions and variables inside a module are similar to private members. They can only be seen
    inside that module.
    I got it Sir!

    Quote Originally Posted by The Nomad View Post
    It will print 3 one the first call, but the second loop will loop twice. It won't loop three times and show a nil value.
    I think you are confused because you think # shows the number of elements inside a table. It doesn't. Yes, you read correctly: # does not show you how many elements there are inside a table
    Seriously?!! OMG why I didn't print the record first before said it proved?? Shame on me . I thought it always guarantee you a correct number of elements inside a table. But if I set the last index to nil every frame I'll always get the correct number of elements inside a table, wont I? I've tried it like this :
    Code:
    local itemToPurchase = {
            "item_radiance",
            "item_shivas_guard",
            "item_guardian_greaves",
            "item_lotus_orb",
            "item_blade_mail",
            "item_mekansm",
            "item_arcane_boots",
            "item_magic_wand",
    	"item_poor_mans_shield"
    };
    
    function GetDesire()
    
    	if #itemToPurchase > 0 and bot:GetUnitName() == 'npc_dota_hero_witch_doctor' then
    		print(bot:GetUnitName()..":"..tostring(#itemToPurchase ))
    		for k,v in pairs(itemToPurchase) do
    			print(tostring(k)..v)
    		end
    		itemToPurchase [#itemToPurchase] = nil
    	end
    
    end
    And here is the complete print
    Code:
    [VScript] npc_dota_hero_witch_doctor:9
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] 5item_blade_mail
    [VScript] 6item_mekansm
    [VScript] 7item_arcane_boots
    [VScript] 8item_magic_wand
    [VScript] 9item_poor_mans_shield
    [VScript] npc_dota_hero_witch_doctor:8
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] 5item_blade_mail
    [VScript] 6item_mekansm
    [VScript] 7item_arcane_boots
    [VScript] 8item_magic_wand
    [VScript] npc_dota_hero_witch_doctor:7
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] 5item_blade_mail
    [VScript] 6item_mekansm
    [VScript] 7item_arcane_boots
    [VScript] npc_dota_hero_witch_doctor:6
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] 5item_blade_mail
    [VScript] 6item_mekansm
    [VScript] npc_dota_hero_witch_doctor:5
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] 5item_blade_mail
    [VScript] npc_dota_hero_witch_doctor:4
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] 4item_lotus_orb
    [VScript] npc_dota_hero_witch_doctor:3
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] 3item_guardian_greaves
    [VScript] npc_dota_hero_witch_doctor:2
    [VScript] 1item_radiance
    [VScript] 2item_shivas_guard
    [VScript] npc_dota_hero_witch_doctor:1
    [VScript] 1item_radiance
    Last edited by arz_on4dt; 10-04-2017 at 01:39 PM.

  2. #22
    Basic Member
    Join Date
    Sep 2017
    Posts
    56
    Quote Originally Posted by ChrisC View Post
    GetNearby*() rebuilds all lists of potentially-nearby (less than 1600 distance) units when called, though that list is cached for 300ms. Every call to GetNearby*() does distance-filtering on that potentially-nearby list (since that's pretty fast, and you might want to ask often for various distances), so your distance-filtering will be frame-accurate, even if the list of potential units might be up to 300ms out of date.

    GetUnitList() does the same thing, but only caches for the current frame. So subsequent calls in the same frame are basically free.
    If that's the case, do you happen to know why GetUnitList() seems to be the heaviest function by quite a margin according to my RealTime() based performance impact checks?


    The only proper way to count the elements in Lua 5.1 is this:
    Is there a reason not to use table.getn() ?

  3. #23
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,018
    Quote Originally Posted by arz_on4dt View Post
    I've tested it in item_purchase, ability_item_usage, mode rune, farm, side_shop, secret_shop, ward, team_roam generic. All of them print the correct unit name every time I tried to reload the script but not for bot_generic. In bot_generic some may print the correct unit name and some may doesn't print unit name at all. For example : In the printed console below only Visage that doesn't have the correct bot_generic unit name (it doesn't even print it). Sometimes I found 2 bots that doesn't have the unit name printed.
    I don't understand. Hmm. It might be because Visage has minions (?) Can you try with 5 bots that don't have minions?

    Quote Originally Posted by arz_on4dt View Post
    Yep, I knew that. I just wanna make the code shorter, but that's not a good idea for the VM. I should prolly change it to variable == condition.
    Well it is better to check than to take my word for it. That is how it usually is in most languages, I admited I wasn't sure 100%, but as I said, "not condition" is too fast to consider. It was just an example of things you expect vs what they are.

    Quote Originally Posted by arz_on4dt View Post
    Hmmmm... so that' the problem. I'll add it in the check.
    I am guessing, but I haven't done any 5v5 60 minute games yet. I just had problems with some last hits when my bot went to lower ground and lost vision. This check removed those warnings.

    Quote Originally Posted by arz_on4dt View Post
    Seriously?!! OMG why I didn't print the record first before said it proved?? Shame on me . I thought it always guarantee you a correct number of elements inside a table. But if I set the last index to nil every frame I'll always get the correct number of elements inside a table, wont I? I've tried it like this :
    # stops at the first nil element. That's why it works when you reduce table sizes from [1] or from [#].
    Also, working on indexes like this:
    Code:
    MyTab[#MyTab + 1] = 3
    ... is not the same as ...
    Code:
    table.insert(MyTab,3);
    There is more magic done in the table.insert call. But also more overhead. For most cases MyTab[#MyTab + 1] = 3 is enough and the function call doesn't really justify, except when you need to put it at specific indeses and you need to shift all values.
    Same for table.remove. However, table.remove will also update the cached size operator #. So if you remove a middle element using table.remove, then # will show the correct value for arrays. But again, the function call isn't justifiable on the long run.
    If it's not a time-critical point in your flow, you can call table.remove IF you really need #. But you can just use the function I gave you. Difference is, # only works on arrays. Mine works on dictionaries as well, where you won't have a size operator.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  4. #24
    Basic Member aveyo's Avatar
    Join Date
    Aug 2012
    Location
    EU West
    Posts
    2,927
    Rather OT, but I've tried to do a wait equivalent in vscript lua and failed miserably. Might be because of lack of sleep..
    If it's not too much trouble, do any of you have a working example that does not simply block and crash the game? Note that Think stuff / GameRules are not available (at game startup) and no useful events trigger either.
    Mean time I use my proven cfg delay on the console side

  5. #25
    Basic Member
    Join Date
    May 2014
    Posts
    270
    Quote Originally Posted by The Nomad View Post
    I don't understand. Hmm. It might be because Visage has minions (?) Can you try with 5 bots that don't have minions?
    My bad. I have bot_hero_name.lua on some heroes to override the MinionThink(). That's why it doesn't load the bot_generic.lua file.

    Quote Originally Posted by The Nomad View Post
    I am guessing, but I haven't done any 5v5 60 minute games yet. I just had problems with some last hits when my bot went to lower ground and lost vision. This check removed those warnings.
    Yep, I think it's because of no CanBeSeen() check in the condition. I added it and that warning never show up again even the game has run for 30 minutes. If I didn't add that check it'll show IsNull() warning even in early 5 minutes of the game. Here is the check now:
    Code:
    if enemy ~= nil and enemy:IsNull() == false and enemy:CanBeSeen() and GetUnitToUnitDistance(bot, enemy) < nRadius then
    ...
    end
    So it's check for nil first and then IsNull(), isn't it? If I didn't add IsNull() the warning still show up even though I've added CanBeSeen() check.

  6. #26
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,018
    Quote Originally Posted by aveyo View Post
    Rather OT, but I've tried to do a wait equivalent in vscript lua and failed miserably. Might be because of lack of sleep..
    If it's not too much trouble, do any of you have a working example that does not simply block and crash the game? Note that Think stuff / GameRules are not available (at game startup) and no useful events trigger either.
    Mean time I use my proven cfg delay on the console side
    What you are asking for is what's known as a latent function which doesn't exist in Lua. You can achieve pseudo-latent functions using coroutines. But it's tricky. Also, if done wrong, you might end up killing the D2 process in the end.
    But what's the use-case here? I mean if execution is paused, then it's paused. If you have a full takeover, I'd expect you'd pause an action that is done in Think(). But if you pause the current execution and Think is paused, then nothing happens (basically, if the bot dies it will be akin to killing a player while typing). If you do it inside a mode (if you are not doing a full takeover) it's pointless cos another mode might take control. So what is it that you are trying to achieve?

    Quote Originally Posted by arz_on4dt View Post
    Yep, I think it's because of no CanBeSeen() check in the condition. I added it and that warning never show up again even the game has run for 30 minutes. If I didn't add that check it'll show IsNull() warning even in early 5 minutes of the game. Here is the check now:
    Code:
    if enemy ~= nil and enemy:IsNull() == false and enemy:CanBeSeen() and GetUnitToUnitDistance(bot, enemy) < nRadius then
    ...
    end
    So it's check for nil first and then IsNull(), isn't it? If I didn't add IsNull() the warning still show up even though I've added CanBeSeen() check.
    Yes. Keep in mind IsNull() might not work on some units like creeps and you'll get an error. We need Chris to help us here and export the function for all units.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  7. #27
    Basic Member aveyo's Avatar
    Join Date
    Aug 2012
    Location
    EU West
    Posts
    2,927
    Quote Originally Posted by The Nomad View Post
    What you are asking for is what's known as a latent function which doesn't exist in Lua. You can achieve pseudo-latent functions using coroutines. But it's tricky. Also, if done wrong, you might end up killing the D2 process in the end.
    But what's the use-case here? I mean if execution is paused, then it's paused. If you have a full takeover, I'd expect you'd pause an action that is done in Think(). But if you pause the current execution and Think is paused, then nothing happens (basically, if the bot dies it will be akin to killing a player while typing). If you do it inside a mode (if you are not doing a full takeover) it's pointless cos another mode might take control. So what is it that you are trying to achieve?
    The goal was simple: substring behavior_score from dota_game_account_debug then add it as parameter to top_bar_message, and present it x seconds after launch for y seconds.
    I could pretty print it with a delay just fine in console cfg, but not send it as parameter to top_bar_message, hence going for vscript instead.
    And since this happens in the "startup" vm, no modules are available. No surprise there, pure lua is very limited sans modules. I'm just sad I almost got it working - a stand-alone basic timer function that blocked very little.
    So I'm reusing my ancient cfg delay method instead (implemented it long before exec_async got introduced) and it gets the job done trough sendtoconsole (example here).

  8. #28
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,018
    I don't think so. Without modules, I think even less of a chance. Are you sure you don't have anything, even the standard libs?
    If it's for the console, you might pull it off with coroutines tbh. Just make sure you don't get into a loop to spawn 99999999 subthreads.
    Explanations on the normal, high and very high brackets in replays: here, here & here
    Why maphacks won't work in D2: here

  9. #29
    Basic Member
    Join Date
    May 2014
    Posts
    270
    @The Nomad
    Is there anything else I can optimize so I don't get any high execution time warning for AbilityLevelUpThink()?
    Code:
    local BotsInit = require( "game/botsinit" );
    local MyModule = BotsInit.CreateGeneric();
    
    local bot = GetBot();
    
    print(bot:GetUnitName());
    
    if  ( bot:GetUnitName() == 'npc_dota_hero_monkey_king' and 
        (( DotaTime() < -60 and bot:GetLocation() ~= Vector(0.000000, 0.000000, 0.000000) ) or ( DotaTime() > -60 and bot:IsInvulnerable() )))
        or bot:IsInvulnerable() or bot:IsHero() == false or string.find(bot:GetUnitName(), "hero") == false or bot:IsIllusion()
    then
    	return;
    end
    
    local build = "NOT IMPLEMENTED";
    
    if string.find(GetBot():GetUnitName(), "hero") then
    	build = require(GetScriptDirectory() .. "/builds/item_build_" .. string.gsub(GetBot():GetUnitName(), "npc_dota_hero_", ""));
    end
    
    if build == "NOT IMPLEMENTED" then 
    	return; 
    end
    
    --clone skill build to bot.abilities in reverse order 
    --plus overcome the usage of the same memory address problem for bot.abilities in same heroes game which result in bot failed to level up correctly 
    bot.abilities = {};
    for i=1, math.ceil(#build['skills']/2) do
    	bot.abilities[i] = build['skills'][#build['skills']-i+1]; 
    	bot.abilities[#build['skills']-i+1] = build['skills'][i];
    end
    
    --prevent dota_bot_reload_script for breaking skill build
    local first_ability = bot:GetAbilityByName(bot.abilities[#bot.abilities]);
    if first_ability ~= nil and first_ability:GetLevel() > 0 then
    	for i=#bot.abilities, #bot.abilities-bot:GetLevel()+1, -1 do
    		bot.abilities[i] = nil;
    	end
    end
    
    function AbilityLevelUpThink()  
    	if ( GetGameState() ~= GAME_STATE_PRE_GAME and GetGameState() ~= GAME_STATE_GAME_IN_PROGRESS ) 
    	   or bot:IsInvulnerable() or bot:IsHero() == false or bot:IsIllusion() 
    	   or bot:GetAbilityPoints() == 0 or #bot.abilities == 0
    	then
    		return;
    	end
    	
    	local lastIdx = #bot.abilities;
    	
    	if bot.abilities[lastIdx] ~= "-1" then
    		local ability = bot:GetAbilityByName(bot.abilities[lastIdx]);
    		if ability ~= nil and ability:CanAbilityBeUpgraded() and ability:GetLevel() < ability:GetMaxLevel() then
    			if bot:GetUnitName() == "npc_dota_hero_troll_warlord" and bot.abilities[lastIdx] == "troll_warlord_whirling_axes_ranged" then
    				if ability:IsHidden() then
    					bot:ActionImmediate_LevelAbility("troll_warlord_whirling_axes_melee");
    				else
    					bot:ActionImmediate_LevelAbility(bot.abilities[lastIdx])
    				end
    			elseif bot:GetUnitName() == "npc_dota_hero_keeper_of_the_light" and bot.abilities[lastIdx] == "keeper_of_the_light_illuminate" then
    				if ability:IsHidden() then 
    					local ability = bot:GetAbilityByName("keeper_of_the_light_spirit_form_illuminate");
    					if ability:IsHidden() == false then
    						bot:ActionImmediate_LevelAbility("keeper_of_the_light_spirit_form_illuminate");
    					else
    						return;
    					end	
    				else
    					bot:ActionImmediate_LevelAbility(bot.abilities[lastIdx])
    				end			
    			elseif ability:IsHidden() then
    				return;	
    			else
    				bot:ActionImmediate_LevelAbility(bot.abilities[lastIdx]);
    			end	
    			bot.abilities[lastIdx] = nil;
    		else	
    			bot.abilities[lastIdx] = nil;
    		end
    	else
    		bot.abilities[lastIdx] = nil;
    	end	
    end
    
    return MyModule;
    Here is the screenshot
    20171007114346_1.jpg
    Last edited by arz_on4dt; 10-06-2017 at 10:48 PM.

  10. #30
    Basic Member
    Join Date
    Mar 2012
    Posts
    2,018
    WOW! 33 ms is a lot. There may be a design issue there. Please explain this code:

    Code:
    	local lastIdx = #bot.abilities;
    	
    	if bot.abilities[lastIdx] ~= "-1" then
                ... level up ...
    	else
    		bot.abilities[lastIdx] = nil;
    	end
    So, you are checking the size of the table and as long as the ability is not -1, you're leveling up. If it is -1, then you're setting the ability from the list to nil, so you can switch to the next one. Where do you set it to -1? How and why? If I were to guess I'd say that code is executed each frame, until a successful level up because of the == -1 vs ~= -1 conditions. I assume you are attempting to try to track the list to know where to continue from, but it seems a complicated way at first glance. I know "-1" is a marker for you, but it makes code readability hard (as you can see from my question) because it's inconsistent: we all know abilities have a certain name structure. But here comes "-1" out of nowhere

    Until you show me the -1 part, I can't tell what the problem is, but I would guess it's not the actual function causing it, but the design.


    Minor note:
    Code:
    ( bot:GetUnitName() == 'npc_dota_hero_monkey_king' and 
        (( DotaTime() < -60 and bot:GetLocation() ~= Vector(0.000000, 0.000000, 0.000000) ) or ( DotaTime() > -60 and bot:IsInvulnerable() )))
        or bot:IsInvulnerable() or bot:IsHero() == false or string.find(bot:GetUnitName(), "hero") == false or bot:IsIllusion()
    IsInvulnerable() is checked twice; It doesn't really matter whether DotaTime() is or isn't smaller or greater than -60. Even if that condition isn't met, you do a "clean" IsInvulnerable() check immediately after. This doesn't affect performance, it just doesn't make sense. Performance wise it just returns a bool so there is a small overhead (depending on how D2 saved that information natively, but it should still be fast). But I told you some time ago about var names and warned you about maintenance around a month ago, you said it's fine, but now you said I was right because it's harder to update and fix it :P So I recommend you clean up those conditions but carefully as to not break anything.
    What you should avoid as I wrote among other replies here is string operations. You are checking if the unit here is a hero. The proper way to do it is if bot:IsHero(). Use native as much as you can, especially if it does the job for you.
    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
  •