dota2不显示金钱加金钱的代码

dota2作弊模式怎么给机器人加钱_百度知道
dota2作弊模式怎么给机器人加钱
提问者采纳
Cheat Commands无,需要控制台sv_cheats 1情况下输入dota_bot_give_gold xxx不会用控制台请百度
提问者评价
来自团队:
其他类似问题
为您推荐:
dota2的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁只需一步,快速开始
后使用快捷导航没有帐号?
查看: 11694|回复: 19
DOTA2IMBA全部源代码和代码逻辑
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
前方高能预警!非战斗人员请尽快登录!
才可以下载或查看,没有帐号?
本帖最后由 Xavier 于
15:49 编辑
发现最近语言表达能力下降严重…… 如果你看了这些东西,有啥看不懂的,请在下方直接回复看不懂的那些问题… 我会挑时间答复。
目前DOTA2RPG所处的阶段,就像是D2WT所处的阶段,Alpha测试,编辑器所处的这一阶段也就决定了,DOTA2IMBA这样的项目,在目前无法做到很长远,因为过两个月,最多半年的时间,在工具Beta,甚至是发布之后,随着他所基于的DOTA源代码更新到最新版本的DOTA(现在编辑器的DOTA版本依然是6.81),现在的很多工作就会瞬间被崩溃。
所以,我从开始做的时候,就定位了这一个项目,是作为一个试验(或者说是教学)项目的存在。
因此,在写了一个半礼拜的代码之后,我决定公开这个项目的所有源代码,并进行一定的解析,来作为一个教学。
同时,鉴于DOTA2IMBA,所使用的地形是官方的DOTA2地形,所以,整个项目几乎所有的工作就是代码代码代码代码代码代码代码代码代码代码。
所以,这篇文档就是一个DOTA2的代码编写教程。
所实现的,是一大堆类·DOTA的技能。
一、代码的结构。
DOTA2的一个RPG之中,与代码直接相关的,非资源文件夹的部分主要是两个,scripts/npc和scripts/vscripts,其中,scripts/npc本质上也是一些资源文件,但是因为其中存在的一些文件,特别是scripts/npc/npc_abilities_custom.txt中有大量的触发逻辑部分存在,所以一般也认为是代码文件。
有一些KV文件,虽然里面是代码,但是其实更多是作为一种资源文本存在的,他们的地位就像其他语言中的设定ini或者xml文件。
<font color="#. scripts/npc文件夹
这个文件夹里面一般包含这么几个文件
这几个文件要注意以下几点:
自定义技能
虽然说,看起来在DOTA2IMBA里面,自定义技能是必须有的,但是,需要完全自定义的技能其实很少,我在 自定义技能的文件中,基本上所做的工作很多是提供一个接口,来让马甲来释放真正的技能。
自定义技能我一般会比较喜欢用Lua来实现一些比较特殊的效果,在自定义文件中完成所有的工作的情况其实很少。
(好吧,我试着去找一个完全使用KV来完成技能效果的技能,结果发现完全没有… 有的技能甚至只写一个OnSpellStart之后就直接开始调用Lua文件来完成之后所有的技能效果(其实,在DOTA2RPG中,多使用Lua来完成技能效果,比起用KV,其实更好控制,而且更自由,代码的重用度也相对较高,在KV文件中,虽然是一样的东西,但是你有很多时候不得不一模一样的照抄一遍。))
重写技能所需要做的是,直接复制官方的原版技能,修改其中的某些字段,那么这个技能就会继承原版技能中除了你有定义的字段之外的所有属性,很适合那些修改技能某些属性的技能。
[Actionscript3] 纯文本查看 复制代码&mirana_leap&
&AbilityCooldown&
&20.0 16.0 12.0 8.0&
可以看到这个例子,只有三行,他就可以将白虎的跳的冷却时间降低到 20/16/12/8,也就无需做其他操作。
在IMBA中,我所做的大多数工作,都是将某些技能的蓝耗/施法前摇/冷却时间都改为0,来方便让马甲释放这个技能。
在我所制作的IMBA中,小牛的沟壑,是在当玩家的技能完成施法前摇之后,在玩家的左边,右边,左前方,右前方的某些特定的位置(具体的算法之后有机会就讲),创建一个马甲,之后使用马甲来释放真正的沟壑技能,为了保证让马甲能放出技能,把蓝耗和冷却时间改为0虽然并不一定说是必须的,但是改了总归是安全一点,施法前摇(AbilityCastPoint)改为0就很重要,这样就能避免说,创建了马甲之后,会有额外的延迟。
自定义物品
在DOTA2中,自定义物品和自定义技能并无二致,他们从文件结构到字段的范式,都是一样的,所以,在DOTA2中,可以这么认为:自定义物品≈自定义技能,唯一的区别就是物品有几个特殊的字段,例如物品的价格等等。在目前,我并没有制作任何的自定义物品。
= = 有点累,这么写我觉得会有一些乱…
这样吧,之后我挑几个英雄来写一下他们整个实现的过程吧。
创造力 +20
X大的教学贴最爱看了~
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
本帖最后由 Xavier 于
15:34 编辑
DOTA2IMBA英雄技能之——火枪手
在DOTA2IMBA中,我给火枪手设计了五个技能,他们分别是
Q榴霰弹 W爆头 E瞄准 D填弹 R暗杀
下面我一个一个说明一下每个技能的效果和他们的实现方式:
榴霰弹的效果是,向技能的目标位置会释放一束榴霰弹,同时在目标位置生成一个弹片区域(其实就是原版的榴霰弹技能)。
我们从KV文件开始说起:
[Actionscript3] 纯文本查看 复制代码&sniper_shrapnel_imba&
&BaseClass&
&ability_datadriven&
&AbilityTextureName&
&sniper_shrapnel&
&AbilityBehavior&
&DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING&
&AbilityUnitDamageType&
&DAMAGE_TYPE_MAGICAL&
&AbilityCastRange&
&AbilityCastPoint&
&0.3 0.3 0.3 0.3&
&AbilityCooldown&
&15.0 15.0 15.0 15.0&
&AbilityDamage&
&12 24 36 48&
&AbilityManaCost&
&120 120 120 120&
&AOERadius&
&AblityCastAnimation&
&ACT_DOTA_CAST_ABILITY_1&
&OnSpellStart&
&LinearProjectile&
&ScriptSelectPoints&
&ScriptFile&
&scripts/vscripts/abilities/hero_sniper.lua&
&Function&
&GenerateShrapnelPoints&
&EffectName&
&particles/units/heroes/hero_batrider/batrider_flamebreak.vpcf&
&MoveSpeed&
&StartPosition&
&attach_attack1&
&StartRadius&
&EndRadius&
&TargetTeams&
&DOTA_UNIT_TARGET_TEAM_ENEMY&
&TargetTypes&
&DOTA_UNIT_TARGET_HERO&
&TargetFlags&
&DOTA_UNIT_TARGET_FLAG_NONE&
&HasFrontalCone&
&ProvidesVision&
&VisionRadius&
&RunScript&
&ScriptFile&
&scripts/vscripts/abilities/hero_sniper.lua&
&Function&
&OnShrapnelStart&
&OnProjectileHitUnit&
&DeleteOnHit&
&DAMAGE_TYPE_MAGICAL&
&%shrapnel_damage&
&Knockback&
&Target& &TARGET&
&Center& &CASTER&
&Distance&
&Duration&
&AbilitySpecial&
&var_type&
&FIELD_INTEGER&
&var_type&
&FIELD_INTEGER&
&shrapnel_damage&
&30 40 50 65&
我们可以看到,在OnSpellStart,也就是技能开始施法之后,我们在他之后进行了两个动作
一、往中心为POINT(技能施法点),目标点为ScriptSelectPoints(使用Lua文件返回的表来选择点),所使用的函数是scripts/vscripts/abilities/hero_sniper.lua中的GenerateShrapnelPoints
LinearProjectile没什么好说的,只要格式对,就会对目标地点释放一个线性投射物(比如说白虎的箭就是线性投射物),这里我们来看看GenerateShrapnelPoints这个函数
[Golang] 纯文本查看 复制代码function GenerateShrapnelPoints( keys)
-- 从keys中获取数据,这里为什么能有keys.Radius和keys.Count呢?
-- 请回到KV文件中看调用这个函数的位置。
local radius = keys.Radius or 400
local count = keys.Count or 10
local caster = keys.caster
-- 之后我们获取施法者,也就是火枪面向的单位向量,和他的原点
-- 之后把他的面向单位向量*2000,乘出来的结果就是英雄所面向的
-- 2000距离的向量,再加上原点的位置,那么得到的就是英雄前方2000的那个点。
local caster_fv = caster:GetForwardVector()
local caster_origin = caster:GetOrigin()
local center = caster_origin + caster_fv * 2000
-- 我们要做的散弹是发射Count个弹片,所以我们就进行Count次循环
-- 之后在center,也就是我们上面所计算出来的,英雄面前2000距离的位置
-- 周围radius距离里面随机一个点,并把他放到result这个表里面去
local result = {}
for i = 1, count do
-- 这里先使用一个RandomFloat来获取一个从0到半径值的随机半径
之后用RandomVector函数来在这个半径的圆周上获取随机一个点,
-- 这样最后得到的vec就是那么一个圆形范围里面的随机一个点了。
local random = RandomFloat(0, radius)
local vec = center + RandomVector(random)
table.insert(result,vec)
-- 之后我们把这个地点列表返回给KV
-- 举一反三的话,我们也可以做出比如说,向周围三百六十度,每间隔60度的方向各释放一个线性投射物的东西
-- 这个大家自己试验就好
return result
二、执行了一个RunScript,所执行的是scripts/vscripts/abilities/hero_sniper.lua中的OnShrapnelStart函数,所传递的值表的类型是POINT(这个非常重要!根据这个Target的不同,传递给Lua的装箱之后的数据也不同。)
这个函数其实很简单:
[Golang] 纯文本查看 复制代码function OnShrapnelStart(keys)
local caster = keys.caster
local point = keys.target_points[1]
local ability = keys.ability
if not ( caster and point and ability ) then return end
CreateDummyAndCastAbilityAtPosition(caster, &sniper_shrapnel&, ability:GetLevel(), point, 30, false)
在获取了caster(施法者),point(施法点),还有ability(技能实体)并确认他们的有效性之后(这个很重要!虽然这里并没有意义,但是养成检查数据有效性的习惯是重要的(最好在return之前还打上出错的输出代码,方便自己知道啥时候在这里出错返回了),因为有的时候,有些技能,在目标变为魔免之后,由于你并没有指定可以对魔免单位有效的Flag,会导致技能的目标所传递的单位为nil)
在确认他们有效性之后,执行了一个函数,CreateDummyAndCastAbilityAtPosition,顾名思义,就是创建一个马甲,并在某个地点释放一个技能。
这个函数并不是一个API函数,而是在hero_sniper.lua这个文件一开始的时候,使用require('abilities/ability_generic')引入的scripts//vscripts/abilities/ability_generic.lua这个文件中的一个函数。
[Actionscript3] 纯文本查看 复制代码-- 在施法者的位置创建一个马甲,并对目标地点释放技能
-- owner: handle 马甲的所有者,一般为施法者
-- ability_name: string 所要释放的技能名称
-- ability_level: int 技能等级
-- position: Vector 释放位置
-- release_delay: float 马甲的排泄延迟,要注意,这个延迟应该比技能可能的持续时间长,否则可能直接导致游戏崩溃
-- scepter: OPTIONAL bool 是否给马甲创建A杖
function CreateDummyAndCastAbilityAtPosition(owner, ability_name, ability_level, position, release_delay, scepter)
local dummy = CreateUnitByNameAsync(&npc_dummy&, owner:GetOrigin(), false, owner, owner, owner:GetTeam(),
function(unit)
print(&unit created&)
unit:AddAbility(ability_name)
unit:SetForwardVector((position - owner:GetOrigin()):Normalized())
local ability = unit:FindAbilityByName(ability_name)
ability:SetLevel(ability_level)
ability:SetOverrideCastPoint(0)
if scepter then
local item = CreateItem(&item_ultimate_scepter&, unit, unit)
unit:AddItem(item)
unit:SetContextThink(DoUniqueString(&cast_ability&),
function()
unit:CastAbilityOnPosition(position, ability, owner:GetPlayerID())
unit:SetContextThink(DoUniqueString(&Remove_Self&),function() print(&removing dummy units&, release_delay) unit:RemoveSelf() end, release_delay)
return unit
之后要说的是,火枪的大招
一、如何给一个副技能赋予等级
在我所制作的IMBA里面,火枪的大招由两个技能组成,一个是作为副技能的D,一个是大招R
我们所要接触到的第一个问题就是,怎样在玩家学习大招的时候,也给D技能赋予等级。
对此,我所使用的是在abilities/AbilityCore.lua里面所添加的事件监听器。
为了让监听器的代码可以有更多的重用性,我的事件监听如下。
[Golang] 纯文本查看 复制代码-- 监听玩家学习技能事件
ListenToGameEvent(&dota_player_learned_ability&, Dynamic_Wrap(AbilityCore, &OnPlayerLearnedAbility&), self)
对应的事件响应:
[Golang] 纯文本查看 复制代码-- 用来在英雄学习某个技能的时候做出对应操作
require('abilities/hero_juggernaut') -- 监听疾风剑客击杀英雄事件
require('abilities/hero_sniper') -- 监听学习大招事件,来给火枪手设置购买子弹的技能等级
require('abilities/hero_lich') -- 用来自动释放NOVA
require('abilities/hero_nevermore')
function AbilityCore:OnPlayerLearnedAbility(keys)
print(&LEARNED ABILITY HANDLER&)
-- 获取学习技能的玩家实体
local player = EntIndexToHScript(keys.player)
if not player then return end
-- 获取英雄
local hero = player:GetAssignedHero()
if hero then
local hero_name = hero:GetUnitName()
if self[hero_name] and self[hero_name].LearnAbilityHandler then
-- 调用对应的接口
print(&LEARNED ABILITY HANDLER CALLING HERO SCRIPT, hero:&, hero:GetUnitName(),&ability:&,keys.abilityname)
self[hero_name]:LearnAbilityHandler(keys, hero, keys.abilityname)
这里比较特别的一个用法是: self[hero_name]:LearnAbilityHandler()这个函数的写法。
确实,这么写是有些奇怪,不过,好用就行,对吧? self[&npc_dota_hero_sniper&] == self.npc_dota_hero_sniper
在我们上面通过require('abilities/hero_sniper'),引入abilities/hero_sniper.lua内容:
[Golang] 纯文本查看 复制代码if AbilityCore.npc_dota_hero_sniper == nil then
AbilityCore.npc_dota_hero_sniper = class({})
-- self[hero_name]:LearnAbilityHandler(keys, hero, keys.abilityname)
function AbilityCore.npc_dota_hero_sniper:LearnAbilityHandler(keys, hero, ability_name)
if ability_name == &sniper_assassinate_imba& then
local ABILITY = hero:FindAbilityByName('sniper_restore_imba')
if ABILITY then
print(&ABILITY FOUND SNIPER RESTORE IMBA&)
ABILITY:SetLevel(1)
这个 AbilityCore.npc_dota_hero_sniper:LearnAbilityHandler(keys, hero, ability_name) 函数就会被调用并执行了。
当然,这个LearnAbilityHandler处理的不仅仅是Sniper的内容,还会处理诸如Lich学习Nova的事件,来每隔一段时间自动对周围敌方单位释放一次Nova
如果你并不需要多次使用,直接在player_learn_ability的事件响应中直接写明代码自然是更好的做法。
二、ModifierStacks的使用方法:
为了给玩家显示当前的子弹数量,我们使用一个可以累积的BUFF(比如说蝙蝠的叠油什么的)来储存玩家当前拥有多少个子弹。
[Actionscript3] 纯文本查看 复制代码&sniper_restore_imba&
&BaseClass&
&ability_datadriven&
&AbilityTextureName&
&sniper_assassinate&//TODO
&AbilityType&
&DOTA_ABILITY_TYPE_BASIC&
&AbilityBehavior&
&DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_CHANNELLED | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE&
&AbilityChannelTime&
&AbilityCooldown&
&MaxLevel&
&OnSpellStart&
&ApplyModifier&
&ModifierName&
&modifier_sniper_restore&
&RunScript&
&ScriptFile&
&scripts/vscripts/abilities/hero_sniper.lua&
&Function&
&OnBuyingBullets&
&OnChannelSucceeded&
&RemoveModifier&
&ModifierName&
&modifier_sniper_restore&
&OnChannelInterrupted&
&RemoveModifier&
&ModifierName&
&modifier_sniper_restore&
&Modifiers&
&modifier_sniper_restore&
&Duration&
&ThinkInterval&
&OverrideAnimation&
&ACT_DOTA_VICTORY&
&RemoveOnDeath&
&OnIntervalThink&
&RunScript&
&ScriptFile&
&scripts/vscripts/abilities/hero_sniper.lua&
&Function&
&OnBuyingBullets&
&FireSound&
&EffectName&
&Ability.AssassinateLoad&
&FireEffect&
&EffectName&
&particles/units/heroes/hero_tinker/tinker_rockets.vpcf&
&EffectAttachType&
&attach_overhead&
&modifier_sniper_bullets&
&IsPurgable&
&ModifierAttributes&
&MODIFIER_ATTRIBUTE_MULTIPLE&
&AbilitySpecial&
&var_type&
&FIELD_INTEGER&
&bullet_prize&
&30 60 100&
不去管那些音效和特效的部分,几个和程序逻辑有关的
OnSpellStart中的RunScript和ApplyModifier
Modifier中的OnIntervalThink-&RunScript完成了购买子弹的核心部分。
OnSpellStart中的RunScript,以及OnIntervalThink中的RunScript,执行的代码是一样的:
[Golang] 纯文本查看 复制代码function OnBuyingBullets(keys)
print(&[SNIPER:] OnBuyingBullets -&&)
local caster = keys.caster
local ability = keys.ability
-- 如果玩家没有Modifier
if not caster:HasModifier(&modifier_sniper_bullets&) then
-- 这里使用的函数非官方,而是'abilities/ability_generic'中的函数
AddModifier(caster, caster, ability, &modifier_sniper_bullets&, nil)
caster:SetModifierStackCount(&modifier_sniper_bullets&,keys.ability,1)
-- 获取玩家的Modifier叠加数
local bullets_count = caster:GetModifierStackCount(&modifier_sniper_bullets&,keys.ability)
-- 如果超过上限,停止玩家的持续性施法过程,并FireHUD中定义的自定义游戏事件来显示对应的错误信息。
if bullets_count &= 10 then
caster:Stop()
FireGameEvent( 'custom_error_show', { player_ID = caster:GetPlayerID(), _error = &#sniper_bullets_full& } )
-- 获取子弹的单价
local bullet_prize = ability:GetSpecialValueFor(&bullet_prize&)
-- 如果玩家有足够的金钱
if caster:GetGold()
&= bullet_prize then
-- 计算增加一颗子弹之后的数字,用math.min来保证数字不会超过10
bullets_count = math.min(bullets_count + 1,10)
-- 扣掉玩家对应的金钱
caster:ModifyGold(-bullet_prize, false, 0)
-- 显示一个浮动文字
DebugDrawText(caster:GetOrigin() + Vector(0,0,100), &- &..tostring(bullet_prize), true, 0.5)
-- 设置Modifier叠加数
caster:SetModifierStackCount(&modifier_sniper_bullets&,keys.ability,bullets_count)
-- else的话,就是玩家的金钱不够了,对应显示的错误消息就是金钱不足,这个消息是官方的字段中就有的,也就可以不用在addon_schinese中定义
caster:Stop()
FireGameEvent( 'custom_error_show', { player_ID = caster:GetPlayerID(), _error = &#dota_hud_error_not_enough_gold& } )
print(& -&[SNIPER:] OnBuyingBullets&)
至于大招的本体部分,KV文件就不多说了,只要是英文差不多OK的人应该都看得懂。
以下是主体部分。
[Golang] 纯文本查看 复制代码function OnSniperAssassStartChannel(keys)
print(&[SNIPER:] OnSniperAssassStartChannel -&&)
local caster = keys.caster
local ability = keys.ability
-- 计算暗杀开始瞄准的时间并保存
local time = GameRules:GetGameTime()
caster:SetContext(&assass_start_time&,tostring(time),0)
print(& -&[SNIPER:] OnSniperAssassStartChannel&)
function OnSniperAssassHitUnit(keys)
print(&[SNIPER:] OnSniperAssassHitUnit -&&)
-- 获取施法者
local caster = keys.caster
-- 获取技能
local ability = keys.ability
-- 获取目标
local target = keys.target_entities[1]
if not( caster and ability and target) then return end
-- 计算读条时间
local time = GameRules:GetGameTime()
local channel_start_time = caster:GetContext(&assass_start_time&)
if channel_start_time == nil then channel_start_time = time end
local channel_time = time - channel_start_time
-- 计算技能伤害 - 与瞄准等级相关
local base_damage = ability:GetLevelSpecialValueFor(&base_damage&, ability:GetLevel() -1)
local damage_increase_per_second = ability:GetLevelSpecialValueFor(&damage_increase_per_second&, ability:GetLevel() -1)
local take_aim_ability = caster:FindAbilityByName(&sniper_take_aim_imba&)
local take_aim_level = take_aim_ability:GetLevel()
local damage_to_deal = base_damage + damage_increase_per_second * channel_time * take_aim_level
-- 计算爆头秒杀概率 - 与爆头等级相关
local head_shot_chance = ability:GetLevelSpecialValueFor(&head_shot_chance&, ability:GetLevel() -1)
local head_shot_increase_per_second = ability:GetLevelSpecialValueFor(&head_shot_chance_per_second&, ability:GetLevel() -1)
local head_shot_ability = caster:FindAbilityByName(&sniper_headshot_imba&)
local headshot_level = head_shot_ability:GetLevel()
local head_shot_chance = head_shot_chance + head_shot_increase_per_second * channel_time * headshot_level
print(&CALCULATION RESULT&, damage_to_deal,head_shot_chance)
-- 造成伤害
local damage_dealt = ApplyDamage({
victim = target,
attacker = caster,
damage = damage_to_deal,
damage_type = DAMAGE_TYPE_PHYSICAL,
damage_flags = 0,
ability = ability
-- 随机计算是否爆头
local random_result = RandomInt(1,100)
random_result &= head_shot_chance then
print(&HEAD SHOT!!!&)
local target_health = target:GetHealth()
local damage_dealt = ApplyDamage({
victim = target,
attacker = caster,
damage = target_health,
damage_type = DAMAGE_TYPE_PURE,
damage_flags = 0,
ability = ability
ScreenShake(target:GetOrigin(), 20, 0.1, 1, 1000, 0, true)
DebugDrawText(target:GetOrigin() + Vector(0,0,150),&#sniper_head_shot&,true,2)
FireGameEvent(&show_center_message&, {message = &HEAD SHOT!&, duration = 2})
-- 计算子弹数量并更新
local ability_restore = caster:FindAbilityByName(&sniper_restore_imba&)
local bullets_count = caster:GetModifierStackCount(&modifier_sniper_bullets&,ability_restore)
local bullets_end = math.max(bullets_count -1, 0)
caster:SetModifierStackCount(&modifier_sniper_bullets&,ability_restore,bullets_end)
print(ability_restore, bullets_count, bullets_end)
print(& -&[SNIPER:] OnSniperAssassHitUnit&)
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
本帖最后由 Xavier 于
15:41 编辑
DOTA2IMBA英雄技能之——剑圣
剑圣这个英雄的技能要说的第一个事就是,怎么让玩家杀死某个单位之后刷新CD?
[Golang] 纯文本查看 复制代码function AbilityCore.npc_dota_hero_juggernaut:LearnAbilityHandler(keys, juggernaut, ability_name)
if ability_name == &juggernaut_wind_blade_imba& then
self._hero = juggernaut
ListenToGameEvent(&entity_killed&,Dynamic_Wrap(AbilityCore.npc_dota_hero_juggernaut, &OnJuggKilledEntity&),self)
function AbilityCore.npc_dota_hero_juggernaut:OnJuggKilledEntity(keys)
-- 确保击杀者是剑圣
local caster = EntIndexToHScript(keys.entindex_attacker)
if caster ~= self._hero then return end
-- 确保被击杀的单位是英雄
local target = EntIndexToHScript(keys.entindex_killed)
if not target then return end
if not target:IsRealHero() then return end
-- 确保剑圣身上有疾风剑客状态
if not caster:HasModifier(&modifier_juggernaut_wind_blade_imba&) then return end
-- 找到两个技能并重置CD
local ability_blade_fury = caster:FindAbilityByName(&juggernaut_blade_fury_imba&)
local ability_wind_blade = caster:FindAbilityByName(&juggernaut_wind_blade_imba&)
ability_blade_fury:EndCooldown()
ability_wind_blade:EndCooldown()
这里我用的办法是,当英雄学习了“疾风剑客”这个技能之后,就开始监听单位被击杀事件。
在发现剑圣在拥有疾风剑客状态的状况下,击杀了某个英雄,,就对对应的两个技能做出EndCooldown的操作。
当然了,你可以可以在疾风剑客的开始,和结束的时候,来对应地开始和结束事件的监听,那样看起来会比较容易写。
对应于EndCooldown,还有一个API函数为ability:StartCooldown(float cooldownTime),用这两个函数连续使用
做出诸如:杀人之后减少20%其他技能CD,使用某个技能之后所有技能减少1秒CD什么的,也是一些简单的事情,大家举一反三即可。
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
本帖最后由 Xavier 于
16:11 编辑
DOTA2IMBA英雄——TINKER(技能KV,LUA,HUD之间的配合)
1,自定义游戏事件
[Actionscript3] 纯文本查看 复制代码&CustomEvents&
&custom_error_show&
&player_ID&
&imba_laser_disappear&
&PlayerID&
&imba_laser_hit_unit&
&PlayerID&
2,制作一个Fla文件(创建一个名为Tinker.fla的文件):
&&·设置文件的类(点击任何空白位置,并在属性窗口中设置类名为TinkerLaser,要与下一步的.as文件中的class名一致)
1.png (12.44 KB, 下载次数: 1)
10:05 上传
&&·按CTRL+F8新建一个元件,类型设置为影片剪辑,名称设置为block
2.png (4.31 KB, 下载次数: 1)
10:05 上传
&&·绘制block
3.png (10.14 KB, 下载次数: 1)
10:05 上传
&&·绘制好的block会显示在库中,之后我们拖动一个到舞台中
4.png (7.48 KB, 下载次数: 1)
10:05 上传
·设置这个block的实例(拖动出来的东西)的实例名为block
5.png (6.3 KB, 下载次数: 1)
10:05 上传
至此,fla画完了。
3,编写他的AS代码:(创建一个同样名为TinkerLaser的.as文件到.fla文件的同一位置)
[Actionscript3] 纯文本查看 复制代码&#65279;package
import flash.display.MovieC
import ValveLib.G
import ValveLib.ResizeM
public class TinkerLaser extends MovieClip {
//这三个变量是DOTA2引擎所必须拥有的变量
//包括下面的onLoaded和onScreenSizeChanged,都是必须的
public var gameAPI:O
public var globals:O
public var elementName:S
//定义BLOCK元件
public var block:MovieC
public function TinkerLaser() {
trace(&TINKER LASER: TinkerLaser&);
public function onLoaded() : void {
trace(&TINKER LASER: onLoaded&);
//让UI可见
//允许UI的尺寸能够随着玩家屏幕的大小变化而变化,保证UI填满整个屏幕
Globals.instance.resizeManager.AddListener(this);
//在AS中监听对应的两个游戏事件
this.gameAPI.SubscribeToGameEvent(&imba_laser_hit_unit&, this.ShowBlock);
this.gameAPI.SubscribeToGameEvent(&imba_laser_disappear&, this.HideBlock);
//在初始的时候,让block不可见
block.visible =
//imba_laser_hit_unit的事件响应
public function ShowBlock( args:Object ){
trace(&TINKER LASER: ShowBlock&);
//获取玩家ID
var pID:int = this.globals.Players.GetLocalPlayer();
//如果玩家ID等于事件中传递进来的玩家ID,那么就显示block
//游戏事件的监听,每个玩家的HUD都会收到这个游戏事件
//为了区分这个玩家是否需要显示block
//我们在游戏事件中定义了玩家的ID
//在这里再使用this.globals.Players.GetLocalPlayer()来获取当前HUD的玩家ID
//相匹配的话,就显示对应的HUD
if( pID == args.PlayerID ) {
trace(pID.toString())
block.visible =
//原理和上面的显示一样,只不过visible=true改成visible=false,来隐藏UI
public function HideBlock( args:Object ){
trace(&TINKER LASER: HideBlock&);
var pID:int = this.globals.Players.GetLocalPlayer();
if( pID == args.PlayerID) {
if(block.visible == true){
block.visible =
public function onScreenSizeChanged():void
trace(&TINKER LASER: onScreenSizeChanged&);
//让block控件的宽度和高度等于舞台的高度和宽度,保证填充整个屏幕
block.width = stage.stageW
block.height = stage.stageH
在这里,要注意,ValveLib这两个文件包,你需要和我一样,将对应的文件夹也放到你的fla文件位置,否则编译不会通过。
做完了FLA和AS,就点击发布来编译成swf文件,并放到resource/flash3文件夹中。
并编辑该文件夹中的custom_ui.txt,告知引擎要载入TinkerLaser.swf
就像这样:
4, 编写激光技能:
[Actionscript3] 纯文本查看 复制代码&tinker_laser_imba&
&BaseClass&
&ability_datadriven&
&AbilityTextureName&
&tinker_laser&
&AbilityCastAnimation&
&ACT_DOTA_CAST_ABILITY_1&
&AbilityBehavior&
&DOTA_ABILITY_BEHAVIOR_UNIT_TARGET&
&AbilityUnitTargetTeam&
&DOTA_UNIT_TARGET_TEAM_ENEMY&
&AbilityUnitTargetType&
&DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC&
&AbilityUnitDamageType&
&DAMAGE_TYPE_PURE&
&AbilityCastRange&
&AbilityCastPoint&
&0.53 0.53 0.53 0.53&
&AbilityCooldown&
&14.0 14.0 14.0 14.0&
&AbilityDamage&
&80 160 240 320&
&AbilityManaCost&
&95 120 145 170&
//在技能开始的时候
&OnSpellStart&
//执行代码,函数为OnLaserCasted
&RunScript&
&ScriptFile&
&scripts/vscripts/abilities/hero_tinker.lua&
&Function&
&OnLaserCasted&
//为目标添加计时Modifier
&ApplyModifier&
&ModifierName&
&modifier_hero_count_down&
&Modifiers&
//计时Modifier
&modifier_hero_count_down&
&IsPurgable&
&Duration&
&%duration_hero&
&IsHidden&
&0&//TODO 1
//当Modifier消失(也就是到时的时候),执行OnLaserModifierDestroy函数
&OnDestroy&
&RunScript&
&ScriptFile&
&scripts/vscripts/abilities/hero_tinker.lua&
&Function&
&OnLaserModifierDestroy&
&AbilitySpecial&
&var_type&
&FIELD_FLOAT&
&duration_hero&
&3.0 3.0 3.0 3.0&
&var_type&
&FIELD_FLOAT&
&duration_creep&
&6.0 6.0 6.0 6.0&
&var_type&
&FIELD_INTEGER&
&miss_rate&
&100 100 100 100&
&var_type&
&FIELD_INTEGER&
&900 900 900 900&
5, 编写Lua代码
[Golang] 纯文本查看 复制代码-- 当玩家释放IMBA的激光,创建一个马甲释放真正的激光,并显示显示黑屏
function OnLaserCasted(keys)
local target = keys.target_entities[1]
local caster = keys.caster
local ability = keys.ability
if not (target and caster and ability ) then return end
-- 创建马甲并对目标释放真正的激光,上面火枪那边说过了
CreateDummyAndCastAbilityOnTarget(caster, &tinker_laser&, ability:GetLevel(), target, 10, false)
-- 只有在目标是英雄的时候,才需要处理显示黑屏
if not target:IsRealHero() then return end
-- 通过触发游戏事件来给激光的目标显示黑屏
-- 在HUD监听到这个事件之后,就会进行对应的处理
FireGameEvent(&imba_laser_hit_unit&,{PlayerID = target:GetPlayerID()})
-- 在Buff持续时间结束之后,移除黑屏
function OnLaserModifierDestroy(keys)
local target = keys.target_entities[1]
if not target then return end
if not target:IsRealHero() then return end
-- 和显示一样,只不过触发的事件不一样而已
FireGameEvent(&imba_laser_disappear&,{PlayerID = target:GetPlayerID()})
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
本帖最后由 Xavier 于
16:03 编辑
挖好了坑… 再填……
基本填满,对于DOTA2IMBA各种项目的文件中,如果有什么不懂的,也可以在这个帖子里面提出,我在有时间的时候会解答。
主题帖子积分
在线时间71 小时
主题帖子积分
Lv:3 空明术士, 积分 362, 距离下一级还需 238 积分
Lv:3 空明术士, 积分 362, 距离下一级还需 238 积分
imba项目工作量巨大,一人之力恐难完成
主题帖子积分
在线时间588 小时
主题帖子积分
先求tinker
对hud和技能交互比较好奇 看看和我想的是不是一样
主题帖子积分
在线时间197 小时
主题帖子积分
简直无情的教程啊,还有这么好的函数。
主题帖子积分
在线时间50 小时
主题帖子积分
Lv:2 长袍法师, 积分 256, 距离下一级还需 44 积分
Lv:2 长袍法师, 积分 256, 距离下一级还需 44 积分
弱弱的问一下,
在指定的位置创建一个马甲,并对目标地点释放技能
这个马甲是什么意思啊,用在什么样的场合?
马甲=傀儡&
主题帖子积分
在线时间588 小时
主题帖子积分
弱弱的问一下,
在指定的位置创建一个马甲,并对目标地点释放技能
马甲是一种 看不见 无法控制 玩家也感受不到的东西
用处有很多 比如帮助英雄施法 因为马甲施法是不需要英雄做出施法动作的
或者开特定区域的视野
主题帖子积分
在线时间25 小时
主题帖子积分
Lv:1 隐谧贤者, 积分 84, 距离下一级还需 66 积分
Lv:1 隐谧贤者, 积分 84, 距离下一级还需 66 积分
马甲就是WAR3里的隐藏施法单位吧。
主题帖子积分
在线时间55 小时
主题帖子积分
简直无情{:3_46:}&&I need more...more!{:3_59:}
主题帖子积分
在线时间23 小时
主题帖子积分
Lv:1 隐谧贤者, 积分 77, 距离下一级还需 73 积分
Lv:1 隐谧贤者, 积分 77, 距离下一级还需 73 积分
问一下 这些实现的效率怎么样 比如说一些监听代码 我觉得貌似很耗资源吧.
主题帖子积分
在线时间711 小时
主题帖子积分
热爱让我们并肩
问一下 这些实现的效率怎么样 比如说一些监听代码 我觉得貌似很耗资源吧.
如果一个人尽可能做好能做的事情,那这个世界就一定会因为这件事情而变得更美好一点。
主题帖子积分
在线时间588 小时
主题帖子积分
tinker的as部分的onresize里只把block的长宽调整的和屏幕一样大
中心坐标是怎么固定在屏幕中央的?
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
tinker的as部分的onresize里只把block的长宽调整的和屏幕一样大
中心坐标是怎么固定在屏幕中央的?
MovieClip是x,y,width和height,如果不改xy属性,他的左上角就总是在0,0
主题帖子积分
在线时间294 小时
主题帖子积分
Lv:4 虚灵先知, 积分 1186, 距离下一级还需 14 积分
Lv:4 虚灵先知, 积分 1186, 距离下一级还需 14 积分
本帖最后由 学习 于
12:06 编辑
[Golang] 纯文本查看 复制代码-- 这个东西暂时没有用
-- 不过可以用来在英雄被选择之后,
-- 就初始化一些东西
function AbilityCore:RegisterHeroes(keys)
local nNewState = GameRules:State_Get()
if nNewState == DOTA_GAMERULES_STATE_PRE_GAME then
for i=-1,9 do
local hPlayer = PlayerResource:GetPlayer(i)
if hPlayer then
local hHero = hPlayer:GetAssignedHero()
if hHero == nil then
我打印keys的:& &splitscreenplayer& && && && && && && &&&= -1 (number)
这个是否是触发事件的玩家id??
如果是的话应该不用循环10个玩家吧?
主题帖子积分
在线时间153 小时
主题帖子积分
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[mw_shl_code=golang,true]-- 这个东西暂时没有用
-- 不过可以用来在英雄被选择之后,
-- 就初始化一些东 ...
不是,从字面来理解,这个splitscreenplayer,应该是Source引擎为了双人同屏操作的FPS游戏留下的东西,在DOTA2里面,这个永远都是-1,也就是非有效玩家ID
主题帖子积分
在线时间0 小时
主题帖子积分
Lv:1 隐谧贤者, 积分 11, 距离下一级还需 139 积分
Lv:1 隐谧贤者, 积分 11, 距离下一级还需 139 积分
好厉害啊!
黑科技玩的6
搞的仅是些奇奇怪怪的玩意儿。
因为这位扛把子的存在,将某个领域的水平拉升了一大截。
挖坑不填,重度拖延,大家快来鄙视他!
阿哈利姆魔法隐修议会之成员。
这是一位毁人不倦的教程编写者。
这位大魔导师对史前魔法研究的贡献将永被铭记。
在曾经的知识荒原上,闪耀着他开拓的脚印。
这枚奖章的拥有者是在AMHC抽中过奖的幸运儿。
创意无限,脑洞大开!
用以表彰对《平妖乱》热忱的勇士。
Powered by

我要回帖

更多关于 dota2可靠金钱 的文章

 

随机推荐