找回密码
 点一下
查看: 1680|回复: 2

【原创】追击技能模板(更新)

[复制链接]
发表于 2009-2-20 13:12:22 | 显示全部楼层 |阅读模式
已经有点对移动单位这种东西没兴趣了…………
(被自己忍无可忍的和谐掉了)

不说了……

可以实现:Dota:裂魂人的加速冲刺、屠夫钩锁的一部分效果
(效果相反的迅速远离可以通过设置速度为负数来达到)

更新了更新了~~2009.2.21更新了~~

代码:
[codes=jass]globals
    gamecache Chase_GC = null
    //游戏缓存
    integer Chase_Data_Int = 0
    real Chase_Data_Real = 0.0
    boolean Chase_Data_Bool = false
    string Chase_Data_Str = null
    real Chase_X = 0.0
    real Chase_Y = 0.0
    real Chase_speed = 0.0
    real Chase_speed_add = 0.0
    real Chase_radius = 0.0
    unit Chase_Target = null
    group Chase_TheGroup = null
    timer Chase_TheTimer = null
    group Chase_GetGroup = null
    //对code-action的辅助参数。
    boolean Chase_CanAttack = false
    boolean Chase_IsFacing = false
    //内部辅助参数。
endglobals
//Copy这个

function ChaseInit takes nothing returns nothing
    call FlushGameCache(InitGameCache( "Chase.w3v" ))
    set Chase_GC = InitGameCache( "Chase.w3v" )
    set Chase_GetGroup = CreateGroup()
endfunction
//你把Chase_GC设置成你的GameCache(推荐)或者这样都可以(但你要保证Chase_GC不为空)
//必须将Chase_GetGroup设置为一个非空group

function H2I takes handle h returns integer
    return h
    return 0
endfunction

function I2U takes integer i returns unit
    return i
    return null
endfunction

function I2G takes integer i returns group
    return i
    return null
endfunction

function I2BE takes integer i returns boolexpr
    return i
    return null
endfunction

function C2I takes code c returns integer
    return c
    return 0
endfunction

function I2C takes integer i returns code
    return i
    return null
endfunction

function DistanceBetweenLocs takes real x1, real y1, real x2, real y2 returns real
    local real dx = x2 - x1
    local real dy = y2 - y1
    return SquareRoot( dx * dx + dy * dy )
endfunction

function AngleBetweenTwoLocs2Angle_Second takes real x1, real y1, real x2, real y2 returns real
    return bj_RADTODEG * Atan2( y2 - y1, x2 - x1) + 180.0
endfunction

function ChaseAbility_Flush takes timer ti, string ti_s, boolean destroy, group g returns nothing
    if destroy then
        call PauseTimer( ti )
        call DestroyTimer( ti )
        call DestroyGroup( g )
        call FlushStoredMission( Chase_GC, ti_s )
    endif
endfunction

function ChaseAbility_Move takes nothing returns nothing
    local unit u = GetEnumUnit()
    local real x = GetUnitX( u )
    local real y = GetUnitY( u )
    local real distance = DistanceBetweenLocs( x, y, Chase_X, Chase_Y )
    local real angle = AngleBetweenTwoLocs2Angle_Second( Chase_X, Chase_Y, x, y )
    if distance <= Chase_speed or distance <= Chase_radius then
        set x = Chase_X
        set y = Chase_Y
        set Chase_CanAttack = true
        call GroupAddUnit( Chase_GetGroup, u )
    else
        set x = x + Chase_speed * Cos( angle * bj_DEGTORAD )
        set y = y + Chase_speed * Sin( angle * bj_DEGTORAD )
    endif
    if Chase_IsFacing then
        call SetUnitFacing( u, angle )
    endif
    call SetUnitX( u, x )
    call SetUnitY( u, y )
    set u = null
endfunction

function ChaseAbility_Action takes nothing returns nothing
    local timer ti = GetExpiredTimer()
    local string ti_s = I2S(H2I( ti ))
    local unit u = I2U( GetStoredInteger( Chase_GC, ti_s, "target" ) )
    local real x = GetStoredReal( Chase_GC, ti_s, "target_x" )
    local real y = GetStoredReal( Chase_GC, ti_s, "target_y" )
    local group g = I2G( GetStoredInteger( Chase_GC, ti_s, "group" ) )
    local real timeout = GetStoredReal( Chase_GC, ti_s, "timeout" )
    local real elapsed = GetStoredReal( Chase_GC, ti_s, "elapsed" )
    local real time = GetStoredReal( Chase_GC, ti_s, "time" )
    local real action_time = GetStoredReal( Chase_GC, ti_s, "time_group_action_run" )
    local real speed = GetStoredReal( Chase_GC, ti_s, "speed" )
    local real speed_add = GetStoredReal( Chase_GC, ti_s, "speed_add" )
    local code chase_c = I2C( GetStoredInteger( Chase_GC, ti_s, "chase_group_action" ) )
    local code target_c = I2C( GetStoredInteger( Chase_GC, ti_s, "target_action" ) )
    local boolean destroy = GetStoredBoolean( Chase_GC, ti_s, "destroy" )
    local boolean stop = GetStoredBoolean( Chase_GC, ti_s, "stop" )
    local real radius = GetStoredReal( Chase_GC, ti_s, "getradius" )
    local boolean IsFacing = GetStoredBoolean( Chase_GC, ti_s, "facing" )
    if elapsed < time or time <= 0.0 then
        if u != null then
            set x = GetUnitX( u )
            set y = GetUnitY( u )
        endif
        set Chase_Target = u
        set Chase_X = x
        set Chase_Y = y
        set Chase_radius = radius
        set Chase_speed = speed
        set Chase_speed_add = speed_add
        set Chase_CanAttack = false
        set Chase_IsFacing = IsFacing
        call GroupClear( Chase_GetGroup )
        call ForGroup( g, function ChaseAbility_Move )
        set Chase_TheGroup = g
        set Chase_TheTimer = ti
        set Chase_speed = speed / timeout
        set Chase_speed_add = speed_add / timeout
        if chase_c != null and ModuloReal( elapsed, action_time ) == 0.0 then
            set Chase_Data_Int = GetStoredInteger( Chase_GC, ti_s, "help" )
            set Chase_Data_Real = GetStoredReal( Chase_GC, ti_s, "help" )
            set Chase_Data_Bool = GetStoredBoolean( Chase_GC, ti_s, "help" )
            set Chase_Data_Str = GetStoredString( Chase_GC, ti_s, "help" )
            call ForGroup( g, chase_c )
        endif
        call StoreReal( Chase_GC, ti_s, "elapsed", elapsed + timeout )
        if Chase_CanAttack and target_c != null then
            call ForGroup( Chase_GetGroup, target_c )
        endif
        call StoreReal( Chase_GC, ti_s, "speed_add", Chase_speed_add * timeout )
        call StoreReal( Chase_GC, ti_s, "speed", Chase_speed * timeout + Chase_speed_add * timeout )
        call StoreReal( Chase_GC, ti_s, "getradius", Chase_radius )
        call GroupRemoveGroup( Chase_GetGroup, g )
        call StoreInteger( Chase_GC, ti_s, "help", Chase_Data_Int )
        call StoreReal( Chase_GC, ti_s, "help", Chase_Data_Real )
        call StoreBoolean( Chase_GC, ti_s, "help", Chase_Data_Bool )
        call StoreString( Chase_GC, ti_s, "help", Chase_Data_Str )            
        set Chase_Data_Int = 0
        set Chase_Data_Real = 0.0
        set Chase_Data_Bool = false
        set Chase_Data_Str = null
        set Chase_TheGroup = null
        set Chase_TheTimer = null
        if (stop and Chase_CanAttack) or FirstOfGroup( g ) == null then
            call ChaseAbility_Flush( ti, ti_s, destroy, g )
        endif
        //-------------------------
        set Chase_Target = null
        set Chase_X = 0.0
        set Chase_Y = 0.0
        set Chase_radius = 0.0
        set Chase_speed = 0.0
        set Chase_speed_add = 0.0
        set Chase_CanAttack = false
        set Chase_IsFacing = false
        call GroupClear( Chase_GetGroup )
    else
        call ChaseAbility_Flush( ti, ti_s, destroy, g )
    endif
    set u = null
    set g = null
    set chase_c = null
    set target_c = null
    set ti_s = null
    set ti = null
endfunction

function ChaseAbility takes timer TheTimer, unit target, real x, real y, group g, real getradius, real timeout, real maxtime, real speed, real speed_add, real time_group_action_run, boolean destroy, boolean stopwhen_firstunit_hit_target, boolean Isfacing, code chase_group_action, code target_action returns nothing
    local timer ti = null
    local string ti_s = null
    if TheTimer == null then
        set ti = CreateTimer()
    else
        set ti = TheTimer
    endif
    set ti_s = I2S(H2I( ti ))
    call StoreInteger( Chase_GC, ti_s, "help", Chase_Data_Int )
    call StoreReal( Chase_GC, ti_s, "help", Chase_Data_Real )
    call StoreBoolean( Chase_GC, ti_s, "help", Chase_Data_Bool )
    call StoreString( Chase_GC, ti_s, "help", Chase_Data_Str )
    if target != null then
        call StoreInteger( Chase_GC, ti_s, "target", H2I( target ) )
    else
        call StoreReal( Chase_GC, ti_s, "target_x", x )
        call StoreReal( Chase_GC, ti_s, "target_y", y )
    endif
    call StoreInteger( Chase_GC, ti_s, "group", H2I( g ) )
    call StoreReal( Chase_GC, ti_s, "speed", speed * timeout )
    call StoreReal( Chase_GC, ti_s, "speed_add", speed_add * timeout )
    call StoreReal( Chase_GC, ti_s, "getradius", getradius )
    call StoreReal( Chase_GC, ti_s, "time", maxtime )
    call StoreReal( Chase_GC, ti_s, "timeout", timeout )
    call StoreReal( Chase_GC, ti_s, "time_group_action_run", time_group_action_run )
    call StoreInteger( Chase_GC, ti_s, "chase_group_action", C2I( chase_group_action ) )
    call StoreInteger( Chase_GC, ti_s, "target_action", C2I( target_action ) )
    call StoreBoolean( Chase_GC, ti_s, "destroy", destroy )
    call StoreBoolean( Chase_GC, ti_s, "facing", Isfacing )
    call StoreBoolean( Chase_GC, ti_s, "stop", stopwhen_firstunit_hit_target )
    call TimerStart( ti, timeout, true, function ChaseAbility_Action )
    set ti_s = null
    set ti = null
endfunction[/codes]

函数说明:
更新:timer TheTimer  用来计时的Timer(如果为null则函数自动创建一个)
unit target    被追击的目标(可以设为null,但x和y必需)
real x    目标点的X坐标(若x和y设为无意义值,则单位必需)
real y    目标点的Y坐标(若x和y设为无意义值,则单位必需)
group g   追击的一群/个人
real getradius   当距离小于getradius时,算是追上了目标
real timeout     每多少秒位移
real maxtime     最多追击多少秒(设为负数,永久追击)
real speed       初始追击速度(距离/秒)
real speed_add   加速度(速度/秒)
real time_group_action_run 每多少秒运行chase_group_action(此real必须为timeout倍数)
boolean destroy   是否在停止后删除group(更新:如果设为false,则Timer也会保留,并且不会清空Timer的缓存内容,反之则清除timer)
boolean stopwhen_firstunit_hit_target  是否停止在【追击单位中的第一波单位追上了目标】
更新:boolean Isfacing 设置是否让追击的单位朝向被追击者
code chase_group_action  一个函数:在追击过程中运行
code target_action  当每一个单位追上目标时,运行此函数。
以上两个函数说明:
GetEnumUnit():获得追击的单位
你可以在调用ChaseAbility之前设置这四个全局变量:
[codes=jass]    integer Chase_Data_Int = 0
    real Chase_Data_Real = 0.0
    boolean Chase_Data_Bool = false
    string Chase_Data_Str = null[/codes]
然后,当这个action执行时,这四个全局变量储存的值就是你赋给他们的值(如果没赋值则是默认的0/0.0/false/null)。
在action运行中,可以为这四个全局变量赋值
action执行后,这四个全局变量值将传递给下一个被牵引单位运行的action。
这一次所有的单位action全部运行完毕后,这四个全局变量值将被存储起来,再下一次运行时,四个全局变量的值就是上一次赋的值。
注意!当运行完ChaseAbility后,这四个全局变量就会被自动清空。
这两个函数的全局变量参数说明:
real Chase_X = 0.0  目标的X坐标
real Chase_Y = 0.0  目标的Y坐标
real Chase_speed = 0.0  追击的速度(已包括加速度,是按距离/秒来算的)
real Chase_speed_add = 0.0  追击的加速度(是按速度/秒来算的)
real Chase_radius = 0.0  能算是追上了的半径范围
unit Chase_Target = null  目标
更新:
group Chase_TheGroup = null  追击单位组(其中不包含已追上的)
timer Chase_TheTimer = null  用来计时的Timer
group Chase_GetGroup = null  追上的单位组
特殊说明:
Chase_GetGroup 应是一个常量,也就是说,你只能引用它里面的单位,对他ForGroup遍历单位,但绝不可以GroupClear什么对Group本身的动作、对它用GroupRemoveXX和GroupAddXX,也是一种高危行为。至于设置它为空,那你就祈祷在你把它又一次赋以一个group之前,不会因你的技能而魔兽崩坏就是了。
更新:特殊说明(可以说是指导):
你现在可以先创建一个自己的TheTimer,然后用ReturnBug+GameCache为它存储自定义的值了,在code执行时,你可以从Chase_TheTimer获得你的TheTimer,最后……这些存储的数据你就可以读取了。也就是说,你现在可以有无数个自定义值了。
有些危险,但一个很好的东东:
在<GameCache>, <Timer Handle String>的目录(GameCache中)下,
你可以改动/引用这些string key中的值:
integer(unit) "target" : 你可以在中途改变目标(H2I)
real "target_x" : 你可以在中途改变目标点(与目标不是一回事)的X坐标
real "target_y" : 你可以在中途改变目标点(与目标不是一回事)的Y坐标
integer(group) "group" : 你可以在中途改变追击的单位们(H2I)
real "timeout" : 你可以在中途改变运行时间的间隔(不幸的是,这只是认为而已,真正的timer运行间隔不是按这个来的)
real "elapsed" : 你可以在中途改变已运行时间
real "time" : 你可以在中途改变总运行时间
real "time_group_action_run" : 你可以在中途改变在追击过程中运行的函数运行间隔
real "speed" : 你可以在中途改变速度(距离/秒*间隔),不过正确的方式是用全局变量传递,因为全局变量的值会覆盖你存储的值。
real "speed_add" : 你可以在中途改变加速度(速度/秒*间隔),不过正确的方式是用全局变量传递,因为全局变量的值会覆盖你存储的值。
integer(code) "chase_group_action" : 你可以在中途改变在追击过程中运行的函数(C2I)
integer(code) "target_action" : 你可以在中途改变追击到后运行的函数(C2I)
boolean "destroy" : 你可以在中途改变是否删除Group和Timer并清除Timer的缓存
boolean "stop" : 你可以在中途改变是否停止在【追击单位中的第一波单位追上了目标】
real "getradius" : 你可以在中途改变算是追击到的距离。
boolean "facing" : 你可以在中途改变是否让追击的单位朝向被追击者。
好吧,我承认在模板code中,我又进步了一步……~~

更新:特殊说明:
你可以在code中设置Chase_speed和Chase_radius,然后这两个量就会在下一次timer执行时起作用。

截图:无(我没有动态截图的工具)

希望大家多多支持我~~有Bug一定要回帖/发短消息给我这个帐号~~

最后,照例为我的JASS技能教程求精~~

最后的最后,哀叹:为什么没人给我的技能模板奖励呢?为啥呢?

Tow.w3x

28 KB, 下载次数: 34

评分

参与人数 4威望 +33 收起 理由
crazyforyou + 15 好多模板
hydralisk + 15
扎克斯fair + 1 优秀文章
biackese + 2 优秀文章

查看全部评分

发表于 2009-2-20 16:19:18 | 显示全部楼层
顶啊!!
回复

使用道具 举报

发表于 2009-2-20 17:08:09 | 显示全部楼层
LZ不妨把之前的帖子合成一个教程系列吧,那样挺好~~~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-5-6 22:10 , Processed in 0.288399 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表