#How do I know what can go inside a table?

1 messages ยท Page 1 of 1 (latest)

timid spoke
#

I was looking for the duration the modifier would stay on the target but I saw only a table with the duration passed.

Does the function automatically use that duration?

Are there pre defined things in the table or is that just a "special" value passed into the modifier that we can use later?

This is the modifier for OGRE's STUN and this is the modifier which doesnt actually use the value passed in by the table.

lost mirage
#

AddNewModifier reads duration key (if exists) from that table and use it if possible (value is number). Rest key values that you specify passed too into OnCreated and OnRefresh as first argument at server side

timid spoke
vagrant hearthBOT
#

Found 1 function for AddNewModifier

๐Ÿ‡ธ CDOTA_BaseNPC:AddNewModifier(caster: CDOTA_BaseNPC|nil, ability: CDOTABaseAbility|nil, modifierName: string, modifierTable: table|nil): CDOTA_Buff
Add a modifier to this unit.

lost mirage
#

Its literally stated in api

#

Caster, ability if exists, modifier_name, table of parameters if exists

timid spoke
#

I know that, but what can I put into table of parameters ?

lost mirage
#

Number, string?, boolean. Something special like vector ignored

timid spoke
#

hmm maybe Im a little confused.

#

Where does {duration = stun_duration} get used in the modifier?

lost mirage
#

If you mean something except duration key no way to know expect case when valve provide example

timid spoke
lost mirage
#

For their modifiers

timid spoke
#

yeah, its pre-defined ?

lost mirage
#

It used by engine when modifier applied

#

(Dota itself)

timid spoke
#

How do I find what variables used for their modifiers?

timid spoke
#

oh

#

so we don't actually know? except for the examples given?

lost mirage
#

We know keys of modifier_knockback and modifier_illusions just because valve used them in their events

timid spoke
#

hmm, its not given in the api? weird

lost mirage
#

Duration used by every modifier in game if specified

timid spoke
#

hm

lost mirage
#

Even by your custom ones

timid spoke
#

yea

#

Is it infinite if I don't set a duration?

lost mirage
#

Yes

timid spoke
#

cool ๐Ÿ™‚

#

thanks :))

#

Im close to understanding ability making with lua!!

lost mirage
#

You dont need to know possible keys anyway for every modifier just because 99.9% of cases its better to remake something in lua from 0. This way you can ensure that it will always work as you expected and valve will be not able silently add some additional features. Single case when valve can hurt your custom stuff is when they decide destroy custom games

timid spoke
#

ah that does make sense

#

I guess duration is the only real thing needed for your modifier

#

even then, is there a way to reset your duration of your modifier in the modifier script?

timid spoke
lost mirage
#

For example not long ago they removed ability for refresher to cooldown in backpack. This change affected every game that rely on valve refresher instead of custom one. If item has IsRefreshable = false then no cooldown in backpack

timid spoke
#

oh ;0

#

does valve "hire" people to make custom games from the community?

#

Have they ever ran a custom game competition before?

lost mirage
#

They run once, some trash wins that, shit ton of hate and never again

timid spoke
#

oh ๐Ÿ˜ฆ

#

Was it fortivus festival?

#

I cant remember

lost mirage
#

I don't remember name

timid spoke
#

ah nevermind ๐Ÿ™‚

lost mirage
timid spoke
#

oh, thanks !

small solar
timid spoke
#

frostivus wasnt thaaaaaaaaat bad

#

!!

#

Why have they used an underscore _ to replace key and used enemies for value?

lost mirage
#

Because when you do pairs it produces two variables every loop iteration: key (underscore) and value (enemy, value stored in table by that key). In your code example key will be number of enemy in table and enemy is enemy itself. You don't need to know what number used for each enemy in table, but still must store it somewhere and thats why underscore was used (convention in many program languages) to mark variable that you must use for storing something, but actually not need at all for your code

timid spoke
#

Ah okay

#

so u could just name those 2 anything

lost mirage
#

yes

timid spoke
#

hmm, thats weird

#

in c#

foreach(item_name in name_of_collection){

}

lost mirage
#

There are cases when you need to know number

#

For example table not guarante to always use number for keys. It can be something like:
asd = 1,
wer = 4
In that case keys will be asd, wer and values 1, 4

timid spoke
#

yea, makes sense to name it properly

#

instead of just using _ which looks so weird

#
-- modifier_slardar_slithereen_crush_lua.lua
modifier_slardar_slithereen_crush_lua_slow = class({})

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

function modifier_slardar_slithereen_crush_lua_slow:IsDebuff()
    return true
end

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

function modifier_slardar_slithereen_crush_lua_slow:OnCreated( kv )
    self.ms_slow = self:GetAbility():GetSpecialValueFor("crush_extra_slow")
    self.as_slow = self:GetAbility():GetSpecialValueFor("crush_attack_slow_tooltip")
end

function modifier_slardar_slithereen_crush_lua_slow:OnRefresh( kv )
    self.ms_slow = self:GetAbility():GetSpecialValueFor("crush_extra_slow")
    self.as_slow = self:GetAbility():GetSpecialValueFor("crush_attack_slow_tooltip")
end

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

function modifier_slardar_slithereen_crush_lua_slow:DeclareFunctions()
    local funcs = {
        MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
        MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT,
    }

    return funcs
end

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

function modifier_slardar_slithereen_crush_lua_slow:GetModifierMoveSpeedBonus_Percentage( params )
    return self.ms_slow
end


function modifier_slardar_slithereen_crush_lua_slow:GetModifierAttackSpeedBonus_Constant( params )
    return self.as_slow
end```
#

How do I know what to return? for this?

function modifier_slardar_slithereen_crush_lua_slow:GetModifierAttackSpeedBonus_Constant( params )
    return self.as_slow```
lost mirage
#

Underscore used even in c# when you don't care about variable
p.GetCoordinates(out var x, out _);

timid spoke
#

oh wait, it says in the new api

#

Why is the old api so bad? Who made it?

lost mirage
timid spoke
#

ah, I guess its self explanatory

lost mirage
timid spoke
#
-- modifier_slardar_slithereen_crush_lua.lua
modifier_slardar_slithereen_crush_lua_slow = class({})

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

function modifier_slardar_slithereen_crush_lua_slow:IsDebuff()
    return true
end

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

function modifier_slardar_slithereen_crush_lua_slow:OnCreated( kv )
    self.ms_slow = self:GetAbility():GetSpecialValueFor("crush_extra_slow")
    self.as_slow = self:GetAbility():GetSpecialValueFor("crush_attack_slow_tooltip")
end```

Whats the difference between doing

local ms_slow and self.ms_slow ?
lost mirage
#

Well, you should read lua basics to understand difference between local and self

timid spoke
#

wait, does self.ms_slow mean its global for this entire script?

#

instead of just the scope of the method?

lost mirage
#

In that case self binded to certain modifier instance and local exists only in function scope

timid spoke
#

oh... I think I get it

#

it makes sense now!!!

#

But whats the point of making anything local? The scripts are so small, why not just make them all self. ?

lost mirage
#

Where you find even single local

timid spoke
#

not there but the ability script

#
-- slardar_slithereen_crush_lua.lua
slardar_slithereen_crush_lua = class({})
LinkLuaModifier( "modifier_slardar_slithereen_crush_lua", "lua_abilities/slardar_slithereen_crush_lua/modifier_slardar_slithereen_crush_lua", LUA_MODIFIER_MOTION_NONE )
LinkLuaModifier( "modifier_slardar_slithereen_crush_lua_slow", "lua_abilities/slardar_slithereen_crush_lua/modifier_slardar_slithereen_crush_lua_slow", LUA_MODIFIER_MOTION_NONE )

function slardar_slithereen_crush_lua:OnSpellStart()
    -- get references
    local radius = self:GetSpecialValueFor("crush_radius")
    local damage = self:GetAbilityDamage()
    local stun_duration = self:GetSpecialValueFor("stun_duration")
    local slow_duration = self:GetSpecialValueFor("crush_extra_slow_duration")

    -- find affected units
    local enemies = FindUnitsInRadius(
        self:GetCaster():GetTeamNumber(),
        self:GetCaster():GetOrigin(),
        nil,
        radius,
        DOTA_UNIT_TARGET_TEAM_ENEMY,
        DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
        DOTA_UNIT_TARGET_FLAG_NONE,
        FIND_ANY_ORDER,
        false
    )

    -- for each caught enemies
    for _,enemy in pairs(enemies) do
        -- Apply Damage
        local damage = {
            victim = enemy,
            attacker = self:GetCaster(),
            damage = damage,
            damage_type = DAMAGE_TYPE_PHYSICAL,
        }
        ApplyDamage( damage )

        -- Apply stun debuff
        enemy:AddNewModifier(
            self:GetCaster(),
            self,
            "modifier_slardar_slithereen_crush_lua",
            { duration = stun_duration }
        )

        -- Apply slow debuff
        enemy:AddNewModifier(
            self:GetCaster(),
            self,
            "modifier_slardar_slithereen_crush_lua_slow",
            { duration = stun_duration + slow_duration }
        )
    end
end```
#

actually, nvm.

lost mirage
#

Because modifiers from same ability can have different values

#

Lvl1 debuff and lvl2 debuff have different values

timid spoke
#

hm,

lost mirage
#

You can store in ability instance ofc using self if you wish

timid spoke
#

Does the ability script fall out of the scope when not being used?

#

wait no

#

that wouldnt make sense

#

nevermind! forget what I said

lost mirage
#

Thing is there no namespace concept in lua like in c#

timid spoke
#

oh really?

lost mirage
#

But because dota made in c++ there are some not obvious things with that

timid spoke
#

c++ has name spaces though

#

maybe not in lua idk, I haven't seen any yet

lost mirage
#

For example ability class not exists in global lua scope until you manually require it

#

Dota just loads it, uses and thats all

timid spoke
#

thats true

#

How come we use lua and not c++?

lost mirage
#

Because lua way easier to understand for everyone and way easier approach to add modding support

#

Lua was made initially for people who have close to zero knowledge about computer science

timid spoke
#

lua is looks so ugly!

lost mirage
#

It even not uses zero indexed arrays because of that

timid spoke
#

I know! I thought that was so weird

#

even for loops, we start at 1

#

I was watching some tutorial and thought that was just odd...

lost mirage
#

You can start loop at 0
for i=0,14 do
end

timid spoke
#

instead of doing 0 to < 100, they did 1 to 100

#

yea

lost mirage
#

You can even implement zero based arrays if you wish. Just default table operations will not support it

timid spoke
#

ah

#

The only thing I haven't looked at yet is game "rules" like changing maps and stuff and other game logic for custom games

#

idk how hard it is

lost mirage
#

Classes also not exists in lua

#

Valve downloaded code for that somewhere or coded it themselves for us

timid spoke
#

๐Ÿคฃ

lost mirage
#

Every class here is technically table

vagrant hearthBOT
#

Found 1 function for AddNewModifier

๐Ÿ‡ธ CDOTA_BaseNPC:AddNewModifier(caster: CDOTA_BaseNPC|nil, ability: CDOTABaseAbility|nil, modifierName: string, modifierTable: table|nil): CDOTA_Buff
Add a modifier to this unit.

timid spoke
#
self:GetCaster():AddNewModifier()```
#

Do I have to do Self:getCaster() before add modifier?

#

is that what the CDOTA_BaseNPC thing is?

lost mirage
#

Thing used before : must be npc that will get modifier

timid spoke
#

oh

#

okay

lost mirage
#

You can check in moddota api docs what type of thing every function returns

#

GetCaster returns CDOTA_BaseNPC so you can use that for addnewmodifier

timid spoke
lost mirage
#

Very very rare it specifies wrong type

timid spoke
#

hmm when I do /api I can see what it returns but not when I go on the site

lost mirage
#

Look at most right part of screenshot. Text after : is what type of object will be returned

timid spoke
#

CDOTA_Buff

lost mirage
#

Yeah

timid spoke
#

when I click it leads me here

lost mirage
#

You can use that info to check what methods/functions that type have

#

With that info for example you can do things like idk
local modifier = target:AddNewModifier...
print(modifier:GetCaster():GetUnitName())

#

This will print name of unit who applied modifier

#

Some functions like AddNewModifier have in args things like caster | nil. It means you can pass nil or caster, but due to how dota made there are list of things that you just should remember. For example passing nil to caster causes instant crash at valve servers in past (might be fixed already)

timid spoke
#

damn! okay

#

its like doing UNIT.dosomething()

#

but instead of unit, its a function that returns the unit instead

#

Unit().DoSomething() ?

lost mirage
#

: in lua is syntax sugar for .
target:AddNewModifier(caster, name, args) = target.AddNewModifier(target, caster, name, args)

#

First arg for . syntax is value of self

timid spoke
#

why?!

#

it makes less sense to me that you need something behind the function for the function to work.

lost mirage
#

If you find all that annoyning or hard to understand you can try check typescript. Typescript is way closer to c# than lua and might be easier for you

timid spoke
#

its okay ^^

#

target.AddNewModifier(target, caster, name, args) makes more sense!!

lost mirage
#

There are typescript tutorials for beginner at moddota site

timid spoke
#

its okay, I wanted to specifically learn a new language

#

i've only used c++ and c# before

#

so lua is a bit of a different style of coding

timid spoke
lost mirage
#

It also have type checking compared to lua so it makes big projects supporting is way easier, but thats up to you

timid spoke
#

๐Ÿ‘

lost mirage
#

You can even CDOTA_BaseNPC.AddNewModifier(target, caster, name, args), but i suggest you just use regular : syntax until you understand all that

timid spoke
#

alright = )

vagrant hearthBOT
#

Found 1 function for StartIntervalThink

๐Ÿ‡ธ ๐Ÿ‡จ CDOTA_Buff:StartIntervalThink(interval: float): nil
Start this modifier's think function (OnIntervalThink) with the given interval (float). To stop, call with -1.

lost mirage
#

There is also another thing to be aware related to dota: nil and null. nil means no reference to something in lua and null means you have reference in lua, but object was deleted in c++

#

For example when unit dies after certain time he will be null because he was deleted from memory in c++, but in lua you can still have reference to it. Any api methods calls for null object will fail with error in console

timid spoke
#

oh

last frost
# timid spoke I guess duration is the only real thing needed for your modifier

To clarify, you can pass variables from your ability to your modifier using this table. For example, think about Windranger's ult, where she gains bonus attack speed and "walk and fire" on a specific target - the modifier needs to know which target is the one that is should trigger the bonuses. You can pass the variable this way. Note that this table can only hold primitives: strings, booleans and numbers, and only the server side of the modifier will be aware of those values.

last frost
timid spoke
last frost
timid spoke
#

modifier script ^

#

so, im assuming duration is a pre built for this function

last frost
timid spoke
#

kk

#
TikTok

I searched the city for golden beets, one of Howie's favorite vegetables. She didn't eat it ๐Ÿ˜ž I know it's been coming for a while but I'm sure now that she's starting her molt. She's very old and it's dangerous for her. When old crabs die, it's usually from being unable to molt or getting stuck during the molt. Send Howie good vibes. This will b...

#

๐Ÿฆ€

last frost
timid spoke
#

๐Ÿ˜ 

last frost
#

Am I wrong? You complained about lua's structure and lack of type checks 5 times in this thread alone

timid spoke
#

ur not wrong :<

last frost
#

So seems like you have a lot of experience with typed languages, you are clearly someone who can handle strict languages, and understand the strength of typed languages

#

But still you force yourself to use the method that will piss you off because you will have a ton of errors in your code during runtime

#

I just don't understand why

timid spoke
#

idk either! ๐Ÿ˜ญ

#

But im too lazy to set up type script ๐Ÿ˜ฆ

#

then it would also mean I need to learn type script, but I just wanna mod dota

last frost
#

It's all handled, all you need is to install NodeJS, download moddota's Typescript template and run npm install in whichever code editor you're using

#

That's about it

timid spoke
#

I'll probably eventually come round to it

last frost
timid spoke
#

Are there any guides for general purpose things in custom games?

#

Like changing maps and stuff?

#

or like, giving each player auto levelled spells.

last frost
#

Yes

timid spoke
#

or like, positioning players through a teleporter?

last frost
timid spoke
last frost
#

Yes, there are other guides in the other sections

timid spoke
#

is it possible to change maps?

last frost
#

Yes, it was done in Aghs Lab 1 and 2

timid spoke
#

oh okay!

#

ill have a look through that code

#

its very cool that valve gives us them

last frost
#

All events are done in lua by Valve and you can look at all the non-ability code. Look at the folder dota_addons/aghanim for the project

#

Note that they replaced aghs lab 1's code with 2's. Still should cover most of what you need

timid spoke
#

@last frost have u released any custom games?

last frost
#

I've been a major part of some, yes

timid spoke
#

which ones

#

!!

#

/ which one is ur favourite ?

last frost
#

Dota IMBA is the major one I was working on