CustomGames.ru - Dota 2 пользовательские игры

Полезные API для ваших кастомок (30.07.2016 обновлено)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Se7eN

  • Продвинутый
  • 298
  • Мощь: 11
  • King
Здесь будут размещены готовые и проверенные APIшки, которые вы сможете подключить к своему моду и не париться за них, так как они 100% рабочие.
API - какая-нибудь функция, которая расширяет ваши возможности.
Допустим в стандартном API от Valve нет функции ResetAllAbilityCooldowns() которая бы перезарядила полностью кулдауны героя на предметах и способностях. Или допустим нет такой функции, которая перед дуэлью сохраняла его позицию, хп, ману, кулдауны, а затем после дуэли возвращала эти значение.
Авторские права соблюдены, я выкладываю только те API, которые нам предоставили на GitHub'e или свои лично.

Предупреждение: это не тема для вопросов "как вставить их к себе?", поскольку если вы не умеете вставлять эти функции, то лучше сначала научиться их писать. Этот топик для экономии времени.

ResetAllAbilitiesCooldown(unit, refresh_items) - перезаряжает способности героя и все его предметы.
Если вторым параметром стоит true, то будут перезаряжены и предметы.
Спойлер
Код
function ResetAllAbilitiesCooldown(table unit, bool refresh_items) 
local abilities = unit:GetAbilityCount()
for i = 0, abilities-1 do
local ability = unit:GetAbilityByIndex(i)
if ability and not ability:IsCooldownReady() then
ability:EndCooldown()
end
end
if unit:HasInventory() and refresh_items then
for i = 0, 5 do
local item = unit:GetItemInSlot(i)
if item and not item:IsCooldownReady() then
item:EndCooldown()
end
end
end
end
[свернуть]

AddRandomAttribute(hero, amount) - повышает случайный аттрибут у героя на указанную величину.
hero - герой
amount - насколько повысить
Спойлер
Код
function AddRandomAttribute(hero,amount)
local atr = 0
local rnd = math.random(1,3)
if rnd == 1
then
atr = hero:GetStrength()
hero:ModifyStrength(amount)
end

if rnd == 2
then
atr = hero:GetAgility()
hero:ModifyAgility(amount)
end

if rnd == 3
then
atr = hero:GetIntellect()
hero:ModifyIntellect(amount)
end
hero:CalculateStatBonus()

end
[свернуть]

CheckRuneModifiersAndRemove(hero) - удаляет эффекты рун с героя. Функция написана дедовским способом, зато никаких проверок.
Спойлер
Код
function CheckRuneModifiersAndRemove(hero)
hero:RemoveModifierByName("modifier_rune_doubledamage")
hero:RemoveModifierByName("modifier_rune_haste")
hero:RemoveModifierByName("modifier_rune_invis")
hero:RemoveModifierByName("modifier_rune_regen")
end
[свернуть]

IsExpSkill(abilityname) - у меня на карте некоторые способности при касте дают опыт. Так вот именно эта функция может быть простеньким примером проверки того, та ли эта способность, которая дает опыт.
Можно переписать под проверку чего угодно - определенного предмета, способности, названия юнитов и прочее.
И еще если вам нужно проверить таблицу на наличие в ней определенного значения - тоже сюда.
abilityname - название способности.
Спойлер
Код
function IsExpSkill(abilityname)
local SS = {
"omni_bless_datadriven",
"omni_incagi_datadriven",
"omni_anaphema_datadriven",
"omni_holylight_datadriven",
"invoker_alacrity",
"invoker_coldsnap",
"satir_marionet"
}
  for _,v in pairs(SS) do
if v == abilityname then return true end
end
return false
end
[свернуть]

function AddExp(hero,amount) - простая функция добавления опыта. Чтобы не запариваться с этими true, false и писать быстрее.
Спойлер
Код
function AddExp(hero,amount)
hero:AddExperience(amount, false, false)
end
[свернуть]

Связка функций function SaveAbout(hero) и function RestorePos(hero)
function SaveAbout(hero) - сохраняет местоположение, хп, кулдауны на скиллах, ману
function RestorePos(hero) - возвращает старые значение хп, кулдауны на скиллах, ману
Нужно, например, перед дуэлью сохранить все. Потом допустим сделать героя фулловым, перезарядить скиллы. Далее герой дерётся и потом вы возвращается его на старое место откуда взяли, вместе с кулдаунами хп и маной.
Спойлер
Код
function SaveAbout(hero) 

hero.position = hero:GetAbsOrigin()
hero.mana = hero:GetMana()
hero.hp = hero:GetHealth()
hero.saved = true

local count = hero:GetAbilityCount()
--GetCooldownTimeRemaining()
for i = 0, count do
local ability = hero:GetAbilityByIndex(i)
if ability:GetLevel() == 0 then hero.ability[i] = nil
else
if ability and not ability:IsCooldownReady() then
hero.ability[i] = ability:GetCooldownTimeRemaining()
end
end
end
DeepPrintTable(hero)
print("saved")
end

function RestorePos(hero) --восстановить кдшки, хп, ману и позиция героя после дуэли
if hero.saved then
local position = hero.position
local hp = hero.hp
local mana = hero.mana
hero.saved = false
hero:SetHealth(hp)
local count = hero:GetAbilityCount()
FindClearSpaceForUnit(hero, position, false)
for i = 0, count do
if hero.ability[i] ~= nil then
hero:GetAbilityByIndex(i):StartCooldown(hero.ability[i])
end
end

hero.position = nil
hero.hp = nil
hero.mana = nil
for i = 0,5 do
hero.ability[i] = nil
end
end
end
[свернуть]

HeroHasItemsFromList(hero) - проверяет есть ли у героя предмет из списка (можете прописать, например, зелья)
не забудьте внести в таблицу itemz список предметов, которые будете проверять. У меня важно делить слоты на оружия, зелья и т.п. поэтому и была написана эта апишка
Спойлер
Код
function IsHeroHasItemsFromList(hero)
local itemz = {"item_tetragrammaton", "item_seven"}
for _,v in pairs(armor) do
if hero:HasItemInInventory(v) then return true end
end
return false
end
[свернуть]


Связка функция ItemDrop + ReleaseItem. Первая отвечает за дроп с шансом, вторая за выброс его как лут.
Здесь у меня 3 параметра hero (убийца героя), boss (умирающий юнит), chance (шанс) Не ошибитесь.
Если надо дропнуть  другое с другим шансом, либо дублируете функцию, либо дописываете прямо здесь с новой таблицей и новым списком. Допустим кинжалы дропаются с 5% шансом, а зелья с 90%.
Спойлер
Код
function ItemDrop(hero,boss,chance)
local point = boss:GetAbsOrigin()
local name = boss:GetUnitName()
local drop = {} --список предметов для дропа тут, пишете все предметы.
drop[1] = "item_cursed_gloves"
drop[2] = "item_big_axe"
drop[3] = "item_ring_of_decrease"
drop[4] = "item_armor_plate"
drop[5] = "item_amulet_of_life"
drop[6] = "item_evasion_wings"
drop[7] = "item_cat_figure_of_resistance"
drop[8] = "item_rosary"
drop[9] = "item_circlet_of_majesty"
drop[10] = "item_helm_of_strength"
drop[11] = "item_platinum_cutter"

if RollPercentage(chance) then
local itemz = drop[math.random(#drop)]
local item = CreateItem(itemz, hero,hero)
ReleaseItem(point,item)
end



end

function ReleaseItem(point,item)
CreateItemOnPositionSync( point, item )
item:LaunchLoot(false, 300, 0.75, point+RandomVector(50))
end
[свернуть]
« Последнее редактирование: 01-08-2016, 13:26:17 от Se7eN »

Оффлайн Se7eN

  • Продвинутый
  • 298
  • Мощь: 11
  • King
Резервный пост для обновлений.
« Последнее редактирование: 30-07-2016, 10:18:20 от Se7eN »

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
table SaveAbilitiesCooldowns(hUnit) - сохраняет кд абилок и айтемов юнита в таблицу
Спойлер
Код
function SaveAbilitiesCooldowns(unit)
    if not unit then return end
   
    local savetable = {}
    local abilities = unit:GetAbilityCount() - 1
    for i = 0, abilities do
        if unit:GetAbilityByIndex(i) then
            savetable[i] = unit:GetAbilityByIndex(i):GetCooldownTimeRemaining()
        end
    end

    savetable.items = {}

    for i = 0, 5 do
        if unit:GetItemInSlot(i) then
            savetable.items[unit:GetItemInSlot(i)] = unit:GetItemInSlot(i):GetCooldownTimeRemaining()
        end
    end

    return savetable
end
[свернуть]

nil SetAbilitiesCooldowns(hUnit, table) - устанавливает значение кд айтемов и абилок юнита из сохраненной таблицы.

Спойлер
Код
function SetAbilitiesCooldowns(unit, settable)
    local abilities = unit:GetAbilityCount() - 1
    if not settable or not unit then return end
    for i = 0, abilities do
        if unit:GetAbilityByIndex(i) then
            unit:GetAbilityByIndex(i):StartCooldown(settable[i])
            if settable[i] == 0 then
                unit:GetAbilityByIndex(i):EndCooldown()
            end
        end
    end

    if settable.items then
        for item, cooldown in pairs(settable.items) do
            if item and IsValidEntity(item) then
                item:EndCooldown()
                item:StartCooldown(cooldown)
            end
        end
    end
end
[свернуть]

Так как использовать кучу демедж фильтров не тру(да и они могут не работать вообще если их несколько), а лайфстил от магии сделать нужно, то я запилил такую вот штуку.
В ваш демедж фильтр
Спойлер
Код
if (damagetype_const > 1 or skill_name ~= "") then
local callback_data = {
caster = attacker,
target = victim,
skill_name = skill_name,
damage = damage,
damage_type = damagetype_const,
}
MagicLifesteal:GlobalListen(callback_data)
end
[свернуть]
И как отдельную библиотеку, которую подключите:
Спойлер
Код
MagicLifesteal = class({})

local disabled_lifesteal_skills = {
["necrolyte_heartstopper_aura"] = 1,
["item_blade_mail"] = 1,
}

function MagicLifesteal:GlobalListen( keys )
local caster = keys.caster
local target = keys.target
local damage = keys.damage
local skill_name = keys.skill_name
 
  if disabled_lifesteal_skills[skill_name] then return end

  if target:IsIllusion() then return end

local lifesteal_pct = 0;
if target == caster then return end
if caster:HasModifier("modifier_skeleton_king_reincarnation_scepter_active") then return end

if target:IsHero() then lifesteal_pct = MagicLifesteal:_GetUnitMagicLifesteal_toHero(caster) / 100
else lifesteal_pct = MagicLifesteal:_GetUnitMagicLifesteal_toCreep(caster) / 100 end

if lifesteal_pct == 0 then return end

local particle_lifesteal = "particles/items3_fx/octarine_core_lifesteal.vpcf"
local lifesteal_fx = ParticleManager:CreateParticle(particle_lifesteal, PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:SetParticleControl(lifesteal_fx, 0, caster:GetAbsOrigin())

if damage*lifesteal_pct  < 1 or damage*lifesteal_pct  > caster:GetHealth() or damage*lifesteal_pct > 1000000 then return end

caster:Heal(damage*lifesteal_pct , caster)
end

function MagicLifesteal:_GetUnitMagicLifesteal_toCreep(unit)
local total_lifesteal = 0;
if not unit:HasInventory() then return 0 end

for item_name, lifesteal_data in pairs(self.items) do
if unit:HasItemInInventory(item_name) then
local item = MagicLifesteal:_FindItemInInventory(unit, item_name)

if (lifesteal_data.creep) then
local amount = item:GetSpecialValueFor(lifesteal_data.creep)
if amount > total_lifesteal then total_lifesteal = amount end
end

if(lifesteal_data.all) then
local amount = item:GetSpecialValueFor(lifesteal_data.all)
if amount > total_lifesteal then total_lifesteal = amount end
end
end
end

for ability_name, lifesteal_data in pairs(self.abilities) do
if unit:HasAbility(item_name) then

local ability = unit:FindAbilityByName(ability_name)

if (lifesteal_data.creep) then
local amount = ability:GetSpecialValueFor(lifesteal_data.creep)
if amount > total_lifesteal then total_lifesteal = amount end
end

if(lifesteal_data.all) then
local amount = ability:GetSpecialValueFor(lifesteal_data.all)
if amount > total_lifesteal then total_lifesteal = amount end
end

end
end
return total_lifesteal;
end

function MagicLifesteal:_GetUnitMagicLifesteal_toHero(unit)
local total_lifesteal = 0;
if unit or not unit:HasInventory() then return 0 end
for item_name, lifesteal_data in pairs(self.items) do
if unit:HasItemInInventory(item_name) then
local item = MagicLifesteal:_FindItemInInventory(unit, item_name)

if (lifesteal_data.hero) then
local amount = item:GetSpecialValueFor(lifesteal_data.hero)
if amount > total_lifesteal then total_lifesteal = amount end
end

if(lifesteal_data.all) then
local amount = item:GetSpecialValueFor(lifesteal_data.all)
if amount > total_lifesteal then total_lifesteal = amount end
end
end
end

for ability_name, lifesteal_data in pairs(self.abilities) do
if unit:HasAbility(item_name) then

local ability = unit:FindAbilityByName(ability_name)

if (lifesteal_data.hero) then
local amount = ability:GetSpecialValueFor(lifesteal_data.hero)
if amount > total_lifesteal then total_lifesteal = amount end
end

if(lifesteal_data.all) then
local amount = ability:GetSpecialValueFor(lifesteal_data.all)
if amount > total_lifesteal then total_lifesteal = amount end
end

end
end
return total_lifesteal;
end

function MagicLifesteal:_FindItemInInventory(unit, item_name)
for i = 0, 5 do
local item = unit:GetItemInSlot(i)
if item and item:GetName() == item_name then
return item;
end
end
end

function MagicLifesteal:RegisterLifestealAbility( ability_name, all_lifesteal)
self.abilities[ability_name] = self.abilities[ability_name] or {}
self.abilities[ability_name].all = all_lifesteal;
end

function MagicLifesteal:RegisterLifestealAbility( ability_name, hero_lifesteal, creep_lifesteal)
self.abilities[ability_name] = self.abilities[ability_name] or {};
self.abilities[ability_name].hero = hero_lifesteal;
self.abilities[ability_name].creep = creep_lifesteal;
end

function MagicLifesteal:RegisterLifestealItem(item_name, all_lifesteal)
self.items[item_name] = self.items[item_name] or {};
self.items[item_name].all = all_lifesteal;
end

function MagicLifesteal:RegisterLifestealItem(item_name, hero_lifesteal, creep_lifesteal)
self.items[item_name] = self.items[item_name] or {};
self.items[item_name].hero = hero_lifesteal;
self.items[item_name].creep = creep_lifesteal;
end

function MagicLifesteal:_init()
_G._MagicLifesteal = {}
_G._MagicLifesteal.main = function( keys ) MagicLifesteal:GlobalListen( keys ); end

self.items = {}
self.abilities = {}
--MagicLifesteal:RegisterLifestealItem("item_octarine_core", "hero_lifesteal", "creep_lifesteal")
MagicLifesteal:RegisterLifestealItem("item_octarine_core_2", "hero_lifesteal", "creep_lifesteal")

end

MagicLifesteal:_init()
[свернуть]
Что бы добавить ваши айтемы можно закинуть в этой же библиотеке в _init функцию или вообще куда угодно и когда угодно.
MagicLifesteal:RegisterLifestealItem(item_name, lifesteal_hero_key, lifesteal_creep_key)
либо
MagicLifesteal:RegisterLifestealItem(item_name, total_lifesteal_key)
lifesteal_hero_key, lifesteal_creep_key, total_lifesteal_key - ключевые слова из AbilitySpecial из датадривена для этого предмета.

Для лайфстила с абилок есть две другие функции, работающие по сути так же:
MagicLifesteal:RegisterLifestealAbility( ability_name, hero_lifesteal_key, creep_lifesteal_key)
MagicLifesteal:RegisterLifestealAbility( ability_name, all_lifesteal_key)


Ну и если вдруг не нужно лайфстилить с некоторых скиллов, в начале библиотеки есть табличка запрещенных на лайфстил скиллов(ибо лайфстилит с ЛЮБОЙ абилки, или с ЛЮБОГО типа урона не физического при атаке с руки).
« Последнее редактирование: 26-07-2016, 12:36:06 от CryDeS »

Оффлайн Adam Smith

  • Друзья CG
  • 468
  • Мощь: 6
  • жрять жри его
Здесь будут размещены готовые и проверенные APIшки, которые вы сможете подключить к своему моду и не париться за них, так как они 100% рабочие.
API - какая-нибудь функция, которая расширяет ваши возможности.
Допустим в стандартном API от Valve нет функции ResetAllAbilityCooldowns() которая бы перезарядила полностью кулдауны героя на предметах и способностях. Или допустим нет такой функции, которая перед дуэлью сохраняла его позицию, хп, ману, кулдауны, а затем после дуэли возвращала эти значение.
Авторские права соблюдены, я выкладываю только те API, которые нам предоставили на GitHub'e или свои лично.

Предупреждение: это не тема для вопросов "как вставить их к себе?", поскольку если вы не умеете вставлять эти функции, то лучше сначала научиться их писать. Этот топик для экономии времени.

ResetAllAbilitiesCooldown(unit) - перезаряжает способности героя и все его предметы.

Спойлер
Код
function ResetAllAbilitiesCooldown(table unit, bool refresh_items) 
local abilities = unit:GetAbilityCount()
for i = 0, abilities-1 do
local ability = unit:GetAbilityByIndex(i)
if ability and not ability:IsCooldownReady() then
ability:EndCooldown()
end
end
if unit:HasInventory() and refresh_items then
for i = 0, 5 do
local item = unit:GetItemInSlot(i)
if item and not item:IsCooldownReady() then
item:EndCooldown()
end
end
end
end
[свернуть]
Брат, всем пофиг на авторские права, у меня вон украли код абилки, воложили прямо на форуме и у МЕНЯ начали спрашивать как она работает
By PG.Freeman

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Хаххаха, о каких авторских правах идет речь? Кто-то из русскоязычных моддеров патентует свою интеллектуальную собственность?  :D

Тему плюсую, сам подобное задвигал, но только разными топиками. Я обычно готовые функции выкладываю с приставкой в теме "Кодим функции".

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Хаххаха, о каких авторских правах идет речь? Кто-то из русскоязычных моддеров патентует свою интеллектуальную собственность?  :D

Тему плюсую, сам подобное задвигал, но только разными топиками. Я обычно готовые функции выкладываю с приставкой в теме.
Авторские права не нужны.
Кто знает тот поймет
Цитировать
U can use all files and all code in ur projects. Fuck copyright bro ;)
Good luck.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Для тех кому DeepPrintTable мешает с его 'излишним' описанием структуры таблицы.
И для тех кто хочет задать вопрос 'как вывести ключи и значения из таблицы, я не понимать!'
Код
function PrintKeys( keys )
if not keys or type(keys) ~= "table" then print("PrintKeys error, expected table, got " .. type(keys) ); return; end

for key, value in pairs(keys) do print(key, value) end
end

Оффлайн Se7eN

  • Продвинутый
  • 298
  • Мощь: 11
  • King
Код
function RemoveItemByName(hero, item_name)
local hendl = ""
    for i=0,5 do
    hendl = hero:GetItemInSlot(i)
        if hendl and hendl:GetName() == item_name then
        hero:RemoveItem(hendl)
        end
    end
end
Удаляет у героя определенный предмет по названию. Если после RemoveItem поставить break, то удаляться будет всего 1 предмет. Если использовать функцию как в оригинале, то удалятся все похожие предметы. (Допустим в 4 слотах будут лежать зельки - все пропадут)

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Есть огромный косяк в этой функции - заряды и стаки, ты их не учитываешь.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Код
function RemoveItemByName(hero, item_name)
local hendl = ""
    for i=0,5 do
    hendl = hero:GetItemInSlot(i)
        if hendl and hendl:GetName() == item_name then
        hero:RemoveItem(hendl)
        end
    end
end
Удаляет у героя определенный предмет по названию. Если после RemoveItem поставить break, то удаляться будет всего 1 предмет. Если использовать функцию как в оригинале, то удалятся все похожие предметы. (Допустим в 4 слотах будут лежать зельки - все пропадут)
Handle, КАРЛ, HANDLE.
Вместо удаления через RemoveItem используй UTIL_Remove, ибо первая не удаляет объект из игры, и он останется висеть мертвым грузом, и вот вообще не факт что мусорщик его удалит.

Оффлайн Se7eN

  • Продвинутый
  • 298
  • Мощь: 11
  • King
Скрипт работает отлично, претензии не приняты.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Скрипт работает отлично, претензии не приняты.
твоя_фотка_бесплатно_и_без_смс
[свернуть]

Оффлайн ZLOY

  • Супермодератор
  • 367
  • Мощь: 4
UTIL_Remove когда-то вызывал проблемы с поднятием новых предметов, после удаления ним.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
UTIL_Remove когда-то вызывал проблемы с поднятием новых предметов, после удаления ним.
Дроп и айтем разные объекты, дроп тоже нужно удалять.

Оффлайн ZLOY

  • Супермодератор
  • 367
  • Мощь: 4
Ты не понял.
Если удалить из инвентаря предмет с помощью UTIL_Remove, то слот остается как-бы занятым и со временем герой не сможет поднимать предметы. Возможно это пофиксили уже.