找回密码
 点一下
查看: 2171|回复: 6

caster 系统的几个例子

[复制链接]
发表于 2008-12-9 18:57:50 | 显示全部楼层 |阅读模式
[jass]
//=========================================================================
// The trigger's condition, if item type of the item being manipulated is
// 'I004' which is the rawcode of the "Rune of illusion" item then
// run the trigger (return true)
//
function Rune_of_Illusions_Conditions takes nothing returns boolean
    return ( GetItemTypeId(GetManipulatedItem()) == 'I004' )
endfunction


//=========================================================================
// The trigger's action, just call the caster system's function
//
function Rune_of_Illusions_Actions takes nothing returns nothing

local unit u = GetTriggerUnit() // Keeping the unit in a variable
                                 // should make things easier for us later

    //
    // We need a caster to cast illusions on the unit that acquired the rune
    // So we'll use CasterCastAbility

    //
    // The readme says that CasterCastAbility is :
    //
    //
    // function CasterCastAbility takes player owner, integer abilid, string order, widget target, boolean instant returns unit
    //

    // then we call it:
    //
          call  CasterCastAbility(GetOwningPlayer(u),     'A00M',      "852274"   ,    u         , true)
    //
    // * Use "The owner of the Triggering unit" as owner of the illusion ability to cast
    //
    // * The rawcode of the ability we want to cast is 'A00M' (Illusions (Caster))
    //
    // * Illusions doesn't have an order string, some research let us know that its order id is 852254
    //   so  we use "852254" as order argument
    //
    // * The target is simply the Triggering Unit itslef, so use u
    //
    // * Illusions is instant, so put a true for the instant argument
    //

set u=null
//
//It is required to do this for every handle-derived type variable that does not point to a permanent object
//Unless it is a timer, in that case it might be risky

endfunction



//===========================================================================
//
// This trigger's init function (run on map init)
//
// Create the trigger, add conditions, actions, events
//
function InitTrig_Rune_of_Illusions takes nothing returns nothing


    set gg_trg_Rune_of_Illusions = CreateTrigger(  )

    // Run the trigger when a hero picks up an item.
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Rune_of_Illusions, EVENT_PLAYER_UNIT_PICKUP_ITEM )

    call TriggerAddCondition( gg_trg_Rune_of_Illusions, Condition( function Rune_of_Illusions_Conditions ) )
    call TriggerAddAction( gg_trg_Rune_of_Illusions, function Rune_of_Illusions_Actions )
endfunction



[/jass]

[jass]
//======================================================================================================================
// The condition: Run the trigger only if the Casted Spell is 'A008' (Scroll of rejuvenation triggerer)
//
function Scroll_of_Rejuvenation_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A008' )
endfunction

//======================================================================================================================
function Scroll_of_Rejuvenation_Actions takes nothing returns nothing

local unit u = GetTriggerUnit() // Keeping the unit in a variable
                                 // should make things easier for us later

// Get the unit coordinates in 2 real variables:
//
local real x = GetUnitX(u)
local real y = GetUnitY(u)

    // We need some casters to cast rejuvenation on the allies around the casting unit
    // So we'll use CasterCastAbilityAOE


    //
    // The readme says that CasterCastAbilityAOE is :
    //
    //
    // function CasterCastAbilityAOE takes player owner, integer abilid, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
    //

       call     CasterCastAbilityAOE(GetOwningPlayer(u),     'A005'    ,"rejuvination"  ,x      ,y   , 500        , true              , true)
    //
    // * Uses The owner of the Triggering unit
    // * The rawcode of the ability we want it to cast is 'A005'
    // * The order string of the ability is "rejuvination"
    // * Use x,y as the center of the AOE circle
    // * The area of effect is 500.0
    // * The ability is a good buff, so it should only affect allies then 'goodeffect' is true
    // * Rejuventation is instant, so 'instant' is true as well


//Again, set the unit variable to null before the function ends:
set u=null

endfunction

//======================================================================================================================
// Just your typical Trigger initializer, the event we want is SPELL_EFFECT because that's the event that triggers
// just when the unit has lost cooldown and mana,
//
function InitTrig_Scroll_of_Rejuvenation takes nothing returns nothing
    set gg_trg_Scroll_of_Rejuvenation = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Scroll_of_Rejuvenation, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Scroll_of_Rejuvenation, Condition( function Scroll_of_Rejuvenation_Conditions ) )
    call TriggerAddAction( gg_trg_Scroll_of_Rejuvenation, function Scroll_of_Rejuvenation_Actions )
endfunction

[/jass]


[jass]
function Mass_Slow_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A00J' )
endfunction

function Mass_Slow_Actions takes nothing returns nothing

local location loc =GetSpellTargetLoc() //The target location
local unit u       =GetTriggerUnit()
local integer l
local real area

    call PolledWait( 0.75 ) //For appearance sake, it looks better with this delay.



    set l = GetUnitAbilityLevel( u,'A00J')


    set area = 100.0 + l*50.0 // prepare the Area argument


    call CasterCastAbilityLevelAOELoc( GetOwningPlayer(u), 'A00K', l ,"slow", loc, area, false, true)

    //
    // CasterCastAbilityLevelAOELoc has got 2 variations from CasterCastAbilityAOE , first of all it uses
    // a location variable, second it has an extra argument called level to set the level of the ability
    // to cast.
    //
    // In this case we are using the spell target location and the level of the spell as those arguments.
    //
    //
    // Notice that our area argument uses a formula based on level, it is 150. for level 1, 200 for level 2, etc
    //
    // It is a negative instant spell to cast so the last values are false and true.
    //

    call RemoveLocation(loc)

set loc=null
set u=null

endfunction



//===========================================================================
function InitTrig_Mass_Slow takes nothing returns nothing
    set gg_trg_Mass_Slow = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Mass_Slow, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Mass_Slow, Condition( function Mass_Slow_Conditions ) )
    call TriggerAddAction( gg_trg_Mass_Slow, function Mass_Slow_Actions )
endfunction

[/jass]

[jass]
function Cripple_Everything_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A00W' )
endfunction

///
// Our filter would only accept units that are not the triggering unit
//
function Cripple_Everything_NoTriggerUnit takes nothing returns boolean
    return ( GetTriggerUnit() != GetFilterUnit() )
endfunction

globals

    ///
    // Our filter, it is a global so we can reuse it
    //
    boolexpr Criple_Everything_Filter = null

endglobals

function Cripple_Everything_Actions takes nothing returns nothing

    //
    // We need some casters to cast cripple on every unit around the casting unit,
    // but should ignore the casting unit
    // A normal AOE function won't work since they automatically effect allies or enemies
    // - they don't allow more complicated choices
    //
    // So we'll use CasterCastAbilityGroup , cause it takes a Unit Group argument

local group g = CreateGroup()    //The unit group we are gonna use
local unit u  = GetTriggerUnit()
local real x  = GetUnitX(u)
local real y  = GetUnitY(u)

    ///
    // Add units in a radius of 500.0 to the group , using the CS_ version ensures an
    // ability-like Area of effect.
    //
    // We are using the boolexpr we assign in the Init function, this boolexpr points to our
    // filter function, so any unit in range that is not the Triggering Unit will be added
    // to the group
    //

    call CS_EnumUnitsInAOE(g, x, y, 500.0,  Criple_Everything_Filter)

    ///
    // function CasterCastAbilityGroup      takes player owner, integer abilid, string order, group targetgroup, boolean instant returns nothing
    //
       call     CasterCastAbilityGroup(     GetOwningPlayer(u),         'A006',    "cripple",                 g, true )

    /// Calling this function is like calling the AOE cast functions by with a group argument.
    //  'A006' is the cripple (caster) ability.
    //


    call DestroyGroup(g) // We don't need the group anymore, destroy it to avoid memory leaks.

set g=null
set u=null
endfunction

//================================================================================================
function InitTrig_Cripple_Everything takes nothing returns nothing

    ///
    // We assign the filter, this just makes things easier since we won't have to destroy the
    // boolexpr everytime cause we will reuse it instead.
    //
    set Criple_Everything_Filter = Condition(function Cripple_Everything_NoTriggerUnit )

    set gg_trg_Cripple_Everything = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cripple_Everything, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Cripple_Everything, Condition( function Cripple_Everything_Conditions ) )
    call TriggerAddAction( gg_trg_Cripple_Everything, function Cripple_Everything_Actions )
endfunction




[/jass]

[jass]
function Muradins_Hammer_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A00Q' )
endfunction

function Muradins_Hammer_Actions takes nothing returns nothing

local unit u=GetTriggerUnit()                          //
local location loc1 = GetUnitLoc(u)                    // Since we want to use DistanceBetweenPoints, we
local location loc2 = GetUnitLoc(GetSpellTargetUnit()) // are forced to use locations, the unit's and the target's
local real towait

    ///
    // In this case, we need to cast a thunderclap ability at the position of the target unit
    // Just at the moment the hammer reaches it
    // We'll need a little trick and CasterCastAbilityPointLoc

    ///
    // The missile speed of the triggerer ability is 1000, the trigger has to wait (distance)/1000 seconds
    // (speed equals distance/time , it is a known basic formula)
    //
    set towait=DistanceBetweenPoints(loc1, loc2) / 1000.00

    /// Using locations is often unnecesary and more complicated than coordinates, this time I used
    // the DistanceBetweenPoints function for readability's sake, but another is to use just coordinates
    // and use the point distance formula, or just make a DistanceBetweePointsXY version.
    //


    call PolledWait( towait )  // Wait towait, gametime seconds (btw, PolledWait is not accurate with small values)


    ///
    // function CasterCastAbilityPointLoc   takes player owner, integer abilid, string order, location loc, boolean instant returns unit
    //

       call     CasterCastAbilityPointLoc(GetOwningPlayer(u)  ,         'A00P',"thunderclap", loc2        , true)

    ///
    // CasterCastAbilityPointLoc will simply cast a point targetable or no-target spell in the point you pass it
    // as argument, thunderclap is instant and the rawcode of the dummy ability is A00P
    //

///
// Cleanup:
//
    call RemoveLocation(loc2)
    call RemoveLocation(loc1)
set loc2=null
set loc1=null
set u=null
endfunction

//===========================================================================
function InitTrig_Muradins_Hammer takes nothing returns nothing
    set gg_trg_Muradins_Hammer = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Muradins_Hammer, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Muradins_Hammer, Condition( function Muradins_Hammer_Conditions ) )
    call TriggerAddAction( gg_trg_Muradins_Hammer, function Muradins_Hammer_Actions )
endfunction





[/jass]

[jass]

function Trig_Thors_Hammer_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A00L' )
endfunction

function Trig_Thors_Hammer_Actions takes nothing returns nothing

local location loc = GetSpellTargetLoc()
local unit     u   = GetTriggerUnit()

    // We need some casters to cast a chain lightning based ability against the units around the target point
    // But we want the casters to cast the spell from the position of the casting unit
    // So we need to use CasterCastAbilityAOELoc and both sourcehack and delay hack

    ///
    // CasterSetCastSourceLoc is needed to tell the system that next spell should be casted from this
    // point, it is rather easy to use, just give it a point argument.
    //
    call CasterSetCastSourceLoc(loc)


    ///
    // CasterSetRecycleDelay will make the next caster function wait 3.0 seconds before recycling
    // the caster thus giving it enough time so the spell credits the player correctly.
    //
    //   In this case we need some time for the chain lightning , 3.0 is probably higher than what we
    // need but it is better to use a high value than to use a lower value than what we need.
    //
    // The function is easy to use, just use a real argument for the time to wait.
    //
    call CasterSetRecycleDelay( 3.0 )

    ///
    //  Just call CasterCastAbilityAOELoc , this shouldn't be hard to understand if you followed
    // the previous lessons. It is a negative ability and it is NOT instant
    //

    call CasterCastAbilityAOELoc( GetOwningPlayer(u), 'A00F', "chainlightning", loc, 200, false, false)


    ///
    // The cleanup:
    //
    call RemoveLocation(loc)
set loc=null
set u=null
endfunction

//===========================================================================
function InitTrig_Thors_Hammer takes nothing returns nothing
    set gg_trg_Thors_Hammer = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Thors_Hammer, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Thors_Hammer, Condition( function Trig_Thors_Hammer_Conditions ) )
    call TriggerAddAction( gg_trg_Thors_Hammer, function Trig_Thors_Hammer_Actions )
endfunction





[/jass]

[jass]


function Trig_Grenade_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A012' )
endfunction

function Trig_Grenade_Actions takes nothing returns nothing

local unit u = GetTriggerUnit()
local location loc1 = GetUnitLoc(u)
local location loc2 = GetSpellTargetLoc()

local integer dopt


    // What if you need to use a projectile effect with arc ?
    // You need a unit with that model and make it simulate the arc
    // My projectile functions take a model argument and do all the work for you without any extra unit types
    // .
    // In this sample we also want the projectile to do aoe damage
    // Just directly use : DamagingProjectileLaunchAOELoc

    ///
    // Play the attack animation - (Item abilities don't play animations)
    //
    call SetUnitAnimation( u, "attack" )

    call PolledWait(0.5) //An small delay doesn't hurt, would make
                             // it look more like it is throwing the grenade

    // -------------------------------- Calling the function: ---------------------------------
    // There's a very special thing about the DamagingProjectileLaunchAOELoc function it uses
    // damageoptions, damageoptions is something included in the caster system to configure
    // the way the spells do damage. Your map and spells will often have really specific needs
    // and this system was the best I could think about to make it re-usable enough.
    //
    //   So this sample will have to deal with damage options, setting and using them is easy.
    // Will just use the dopt variable to store them, damageoptions are summed up
    //


    set dopt = DamageTypes(ATTACK_TYPE_SIEGE,DAMAGE_TYPE_FORCE)
    set dopt = dopt + DamageOnlyTo(UNIT_TYPE_GROUND) + DamageTrees()

    //
    // For more info check the `Damage and Target Options′ section of the readme, these damage options
    // would make it do siege, force damage, hurt only ground units and also kill trees.
    //

    //
    //
    // function DamagingProjectileLaunchAOELoc takes unit hurter, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
    //

    call DamagingProjectileLaunchAOELoc(u,"Abilities\\Weapons\\Mortar\\MortarMissile.mdl", 800.0, 0.25, loc1, 60, loc2, 0, 200,200,true, dopt)

    // unit hurter     : the unit we want to credit for kills, u in this case
    // string modelpath: the path of the effect we want for missile
    // real speed      : the speed of the missile, 800 this time
    // real arc        : The arc (works like world editor's) we want a 0.25
    // location loc1   : The start point of the projectile, coincidentally we use loc1 as this argument
    // real z1         : The start height, 60.0 this time
    // location loc2   : The target point of the projectile, coincidentally we use loc2 as this argument
    // real z2         : The target z, 0.0 this time (hits the ground)
    // real aoeradius  : The area of effect of the 'explosion' (200.0 , this time)
    // real damage      : The damage to cause (200.0 this time)
    // bool affectallied: Should the damage hurt allies?, true for this sample.

    // integer damageoptions : Here we use the damageoptions we just created.

   
    // the usual required cleanup
    call RemoveLocation(loc1)
    call RemoveLocation(loc2)
set u=null
set loc1=null
set loc2=null
endfunction

//===========================================================================
function InitTrig_Grenade takes nothing returns nothing
    set gg_trg_Grenade = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Grenade, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Grenade, Condition( function Trig_Grenade_Conditions ) )
    call TriggerAddAction( gg_trg_Grenade, function Trig_Grenade_Actions )
endfunction





[/jass]
 楼主| 发表于 2008-12-9 19:01:11 | 显示全部楼层
中级教程
[jass]
function Nova_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A00Z' )
endfunction

function Nova_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local location loc=GetUnitLoc(u)
local location pol

local integer  i //counter for the loop


    call PolledWait( 0.50 )

    call CasterSetCastSourceLoc(loc) //All caster abilities in this instant will start at this point.
    call CasterSetRecycleDelay(5)  //All casters of this instant will wait 5.0 seconds for recycle

    // The damage from shockwave is not instant, let's say the damage will be of 5 seconds
    // Determine the Recycling delay to 5 seconds for next called caster system functions


    set i=1
    loop
        exitwhen i>36

        // And now is when we actually cast the shockwave, the loop simply allows us to get numbers
        // from 1 to 36 to use later for angle.


        //Polar projection from hero loc to 50.0 distance units, using i*10.0 as angle:
        set pol=PolarProjectionBJ(loc, 50.00, i*10.0 )


        call CasterCastAbilityPointLoc( GetOwningPlayer(u), 'A010', "carrionswarm", pol, false)
        //
        // We wanted to cast ability A018, based on shockwave against the pol point, notice that
        // CasterSetCastSourceLoc and CasterSetRecycleDelay are affecting this call
        //

        // Clean the point referenced by pol.
        call RemoveLocation( pol )

        set i=i+1
    endloop

///
// More cleanup:
//
call RemoveLocation(loc)
set loc=null
set pol=null
set u=null
endfunction

//===========================================================================
function InitTrig_Nova takes nothing returns nothing

    ///
    // Here we use OnAbilityEffect instead of all the usual trigger event registering, besides
    // of only requiring one line and no condition function, it is also faster when many spells
    // are registered like this over many spells registered with the normal trigger method.
    //
    call OnAbilityEffect('A00Z',"Nova_Actions")


endfunction

[/jass]

[jass]


function Poisonous_Weeds_Actions takes nothing returns nothing
local location loc= GetSpellTargetLoc()
local location pol
local unit u = GetTriggerUnit()
local integer i
local real ang
local real dis
local real scale
local integer pow
local integer dopt
local unit    c


    // Make a caster with no model, but using the Permanent AOE poison ability
    // we  need CasterUseAbilityStaticLoc for this,


    call CasterUseAbilityStaticLoc( GetOwningPlayer(u) , "Abilities\\\\Spells\\\\NightElf\\\\Tranquility\\\\Tranquility.mdl", 'A015', 20.0 , loc)
    ///
    // The ability we want to cast is A015, during 20.0 seconds on point loc.
    //

    call SetUnitScale( udg_currentcaster, 0.75, 0.75, 0.75 )
    ///
    // We now that the udg_currentcaster variable holds the last caster used, in this case it holds
    // the one we just created with CasterUseAbilityStaticLoc
    //

    call PolledWait( 2.0 )


    ///
    // Prepare damageoptions for the damagers
    //
    set dopt= DamageTypes(ATTACK_TYPE_CHAOS,DAMAGE_TYPE_PLANT) + DontDamageSelf()

    set i = 0
    loop
        exitwhen i > 9

        // Determining the distance for the polar projection
        set ang = GetRandomInt(1, 360)
        set dis = GetRandomReal(0, 250.00)


        set pol = PolarProjectionBJ( loc, dis , ang)




        set pow = ModuloInteger(i, 3 ) //power of current weed

        //
        ///
        // This one has got a lot of arguments:
        //
        // function AddAreaDamagerForUnitLoc takes
        ///         unit hurter,
        ///         string modelpath,
        ///         string targetart, string targetattach,
        ///         location loc,
        ///         real damage , real damageperiod, real duration, real area,
        //          boolean affectallies, integer DamageOptions returns unit
        //
        set c=      AddAreaDamagerForUnitLoc( u, "Abilities\\\\Spells\\\\NightElf\\\\EntanglingRoots\\\\EntanglingRootsTarget.mdl", "","", pol, 10+pow*10 ,1, 20, 50+pow*50, true, dopt)
        //
        ///
        // The unit we want to credit is u (Triggering Unit)              : u
        // the path of the damager is the entangling roots model          : "Abilities\\\\Spells\\\\NightElf\\\\EntanglingRoots\\\\EntanglingRootsTarget.mdl"
        // use no targetart then no targetattach argument is needed either: "",""
        // The point is the one we just calculated, pol                   : pol
        // We are using the pow variable to calculate some balance
        // related things, 10+10*pow is the damage to do each 1 second
        // during 20 seconds. over 50+50*pow area units                   : 10+pow*10 ,1, 20, 50+pow*50
        // finally, wether it should affect allies and the damageoptions  : true, dopt.



        set scale = 0.5+pow*0.5 // Determines the size of the current weed (based from the power)


        call SetUnitScale( c, scale,scale,scale )


        call SetUnitFacingTimed( c, GetRandomReal(0, 360.00), 0 )
        call RemoveLocation(pol) //clean the pol location.

        ///
        // Notice we assigned directly to c, it also works that way, or you we have used udg_currentcaster like
        // last time.

        set i=i+1
    endloop

///
// more cleanup
//
call RemoveLocation(loc)
set loc=null
set pol=null
set c=null
set u=null
endfunction

//===========================================================================
function InitTrig_Poisonous_Weeds takes nothing returns nothing
    call OnAbilityEffect('A014',"Poisonous_Weeds_Actions")
endfunction


[/jass]

[jass]


function InitTrig_Green_Fire_Balls takes nothing returns nothing
    call OnAbilityEffect('A013',"Green_Fire_Balls_Actions")
endfunction

//===========================================================================
function Green_Fire_Balls_Actions takes nothing returns nothing
local unit u      = GetTriggerUnit()
local unit target = GetSpellTargetUnit()

local location loc=GetUnitLoc(u)
local integer i
local real    x
local real speed
local real damage
local real scale

    call SetUnitAnimation(u, "attack" )

    set i = 0
    loop
        exitwhen i>4

          //
         // The function we want to call this time is DamagingProjectileLaunchTargetLoc :
        //
        //: function DamagingProjectileLaunchTargetLoc takes
        //:     unit hurter,
        //:     string modelpath,
        //:     real speed,
        //:     real arc,
        //:     location loc,
        //:     real z1,
        //:     unit target,
        //:     real zoffset,
        //:     real damage,
        //:     attacktype attT,
        //:     damagetype dmgT
        //: returns unit
        //

        // Speed and damage depend on i:
        set speed = i * 80 + 200.00
        set damage=200-i*25

        call DamagingProjectileLaunchTargetLoc(u, "Abilities\\\\Weapons\\\\GreenDragonMissile\\\\GreenDragonMissile.mdl", speed, 0.0 , loc , 100.0 , target, 100.0 , damage, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE )
        //
        // Arc is 0.0,  100.0 of height always.


        set scale = 40.0 + i * 30.0
        call SetUnitScalePercent( udg_currentcaster, scale, scale, scale )
        ///
        // So, udg_currentcaster holds the last created caster, we change the scale depending on the i number

        set i = i + 1

    endloop

call RemoveLocation(loc)
set loc=null
set target=null
set u=null
endfunction

[/jass]



[jass]


function InitTrig_Stone_of_Ligthning takes nothing returns nothing
    call OnAbilityEffect('A017',"Stone_of_Ligthning_Actions")
endfunction

//===========================================================================
function Stone_of_Ligthning_Actions takes nothing returns nothing
local unit     u   = GetTriggerUnit()
local location loc = GetUnitLoc(u)
local location tar = GetSpellTargetLoc ()
local location pol
local integer  i
local integer  dopt


    call SetUnitAnimation( u, "attack" )




    // I wanted a bigger energy ball for the first one, so I needed to increase the scale, and to use function ProjectileLaunchEx
    // notice I use 1.5 for scale argument.
    //
    call ProjectileLaunchExLoc( GetOwningPlayer(u) , "Abilities\\\\Spells\\\\Orc\\\\LightningBolt\\\\LightningBoltMissile.mdl", 1.5, 255, 255, 255, 255, 522, 0.15, loc, 0, tar, 200.0 )


    set dopt=DamageTypes(ATTACK_TYPE_CHAOS,DAMAGE_TYPE_LIGHTNING)
    // The damage will be chaos (ignore armor) and lightning (magical)

    set i = 1
    loop
        exitwhen i > 10

        set pol = PolarProjectionBJ(tar, i*25.0 , GetRandomInt(1, 360)) //distance: i*25, angle: random


        //: function DamagingProjectileLaunchAOELoc takes
        //:     unit hurter,
        //:     string modelpath,
        //:     real speed,
        //:     real arc,
        //:     location loc1,
        //:     real z1,
        //:     location loc2,
        //:     real z2,
        //:     real aoeradius,
        //:     real damage,
        //:     boolean affectallied,
        //:     integer DamageOptions
        //:     returns unit

        call DamagingProjectileLaunchAOELoc( u, "Abilities\\\\Weapons\\\\FarseerMissile\\\\FarseerMissile.mdl", 100.0 , 0.35, tar, 275.0 , pol, 50, 100,50 ,true, dopt)
        call RemoveLocation(pol)
        set i = i + 1
    endloop
call RemoveLocation(tar)
call RemoveLocation(loc)
set tar=null
set loc=null
set u=null
set pol=null
endfunction



[/jass]

[jass]
function InitTrig_Queltallas_Revenge takes nothing returns nothing
    call OnAbilityEffect( 'A00H' ,"Queltallas_Revenge_Actions")
endfunction

//===========================================================================
function Queltallas_Revenge_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local location loc =GetUnitLoc(u)
local location pol
local real off
local integer dopt
local integer l= GetUnitAbilityLevel(u,'A00H') //level of the spell
local integer i //counter

local real    dmg = 50.0 + 25.00 * l //determine the damage
local real   area = 200.0            //determine the area

    loop
        exitwhen (GetUnitCurrentOrder(u) != OrderId("starfall"))
        // Once the mage stops channeling starfall his order id will be quite different right?
        // Exit the loop once the current order of the triggering unit is not starfall

        ///
        // Destroying an special effect just after you create it, might sound weird, but it does clean the link
        // + shows the special effect, it is a painless way of making it work.
        //
        call DestroyEffect( AddSpecialEffectLoc( "Abilities\\\\Spells\\\\Items\\\\SpellShieldAmulet\\\\SpellShieldCaster.mdl", loc) )


        // A little random offset for the angles, so it doesn't look the same everytime
        set off = GetRandomReal(0, 36.0 )

        set i = 0
        loop
            exitwhen i>4


            set pol=PolarProjectionBJ(loc, 100.0, off+i*72.0)

            call DestroyEffect( AddSpecialEffectLoc( "Abilities\\\\Spells\\\\Undead\\\\ReplenishMana\\\\ReplenishManaCasterOverhead.mdl", pol ) )

            call RemoveLocation(pol)

            set i=i+1
        endloop


        set dopt=DamageTypes(ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DIVINE) + DamageException(UNIT_TYPE_UNDEAD,3.0)
        // The Damage Options choosen are a chaos attack type, a divine (magical) damage, and it will do 3 times the damage to undead units

        // notice we can't just save the dopt value once and then reuse it, because there are waits.



        // Determines the area
        // -------------------------------- Calling the function: ---------------------------------
        // function DamageUnitsInAOEEx takes unit hurter, real damage, real x, real y, real radius, boolean affectallied, integer DamageOptions returns nothing
        // To call it use:
        //
        //
           call     DamageUnitsInAOEExLoc(u, dmg , loc, area , false, dopt)

        // wait 1 second, then repeat the loop
        call PolledWait( 1.00 )
    endloop
   
call RemoveLocation(loc)
set loc = null
set pol = null
set u=null
endfunction







[/jass]
回复

使用道具 举报

 楼主| 发表于 2008-12-9 19:02:06 | 显示全部楼层
高级教程
[jass]

//***************************************************************************
//*                                                                         *
//* Ice Wave                                                                *
//* ˉˉˉˉˉˉˉˉ                                                                *
//*   Sometimes the included functions are not enough, and you have to use  *
//* GetACaster and RecicleCaster, this example is only for JASS users. I     *
//* brought this Spell directly from my map where it was a hero ability.    *
//*                                                                         *
//*    Requires:                                                            *
//*       -The Ice Wave Ability                                             *
//*       -The Caster System                                                *
//*       -All the Ice Wave Damage And Freezing abilities                   *
//*       -This Trigger (make sure the Configuration Section is pointing    *
//*                      to the right abilities rawcodes)                   *
//*                                                                         *
//***************************************************************************

//===========================================================================
// Ice Wave Spell Configuration:
//
function IceWave_SpellId takes nothing returns integer
    return 'A00V' //* Ice Wave Ability Rawcode
endfunction

function IceWave_WavesPerLevel takes integer level returns integer
    return 8 + level*2 //* Number of Ice Strikes per level forumula
endfunction

function IceWave_AuxAbility takes nothing returns integer
    return 'A00E' /// Ice Wave damage and freezing Ability should have the same levels as ice wave
endfunction

//===========================================================================
function Trig_IceWave_Actions takes nothing returns nothing
local unit u=GetTriggerUnit() //let's save Triggering unit to the local variable u
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local location loc=GetSpellTargetLoc()
local real facing=Atan2(GetLocationY(loc) - y, GetLocationX(loc) - x) //The angle between the hero and the target by any chance?
local integer a=1
local unit ice=GetACaster() // Save an available Caster in the ice local variable
local integer l=GetUnitAbilityLevel( GetTriggerUnit(), IceWave_SpellId() )

    call RemoveLocation(loc) // We no longer need that point
    call SetUnitPosition(ice,x,y) // Move ice to the position of the unit
    call SetUnitOwner( ice, GetOwningPlayer(GetTriggerUnit()), false) // Make the owner of ice the same as the owner of the triggering unit
    call UnitAddAbility( ice, IceWave_AuxAbility()) // Add the level's frost nova ability to the caster
    call SetUnitAbilityLevel( ice, IceWave_AuxAbility(),l)
    call UnitRemoveAbility( ice, 'Aloc') // Will make the caster targeteable again
    call SetUnitInvulnerable( ice, true) // Make the caster invulnerable (so it can only be targeted by the frost nova spell)
    loop
        exitwhen a >= IceWave_WavesPerLevel( l )
        // the loop should end once all the frost novas were casted
        call SetUnitPosition( ice, x+a*100*Cos(facing)+GetRandomReal(0, 100 ), y+a*100*Sin(facing)+GetRandomReal(0, 100))
        // Move the caster to a polar projection
        call IssueTargetOrder( ice, "frostnova", ice )
        // Order the caster to frost nova itself
        call TriggerSleepAction( 0)
        // Wait the lowest amount of time possible
        set a=a+1
    endloop
    call SetUnitInvulnerable( ice, false)
    call UnitAddAbility( ice, 'Aloc')
    call RecicleCaster( ice) // Will recicle the caster and give it back to the available casters group.
set u=null
set loc=null
set ice=null
endfunction

//===========================================================================
function InitTrig_IceWave takes nothing returns nothing
local integer a=0
    call PreloadAbility( IceWave_AuxAbility())
    call OnAbilityEffect(IceWave_SpellId(), "Trig_IceWave_Actions")
endfunction



[/jass]
回复

使用道具 举报

 楼主| 发表于 2008-12-9 19:02:51 | 显示全部楼层
[jass]
//********************************************************************************************************
//*
//* Inferno
//* ˉˉˉˉˉˉˉ
//*
//* This is the JASS example, you will note here total usage of Attacheable Variables and tables
//* it also shows how to use CollisionMissiles and Angles_MoveAngleTowardsAngle
//*
//* I included this , because it is a complex script, that considers a lot of things and
//* completelly shows the power of attacheable variables, and even it got to the issue
//* sometimes happen when dealing with return bug based systems such like the attacheable
//* variables.
//*
//* Requires:
//*          - The Inferno Ability
//*          - The Caster System ( http://wc3campaigns.net/vexorian/ )
//*          - This Trigger (MAKE SURE TO change the rawcodes in the trigger to
//*                          the correct ones of your map)
//* Notes:
//*       - The Ability's Caster art often appears on the caster
//*       - The Ability's Second Caster art field is the attachment point of the caster art.
//*       - The Ability's Missile art field is the bolt model
//*       - The Ability's Target art appears on the affected units.
//*       - The Ability's Second Target art field is the attachment point of the target art.
//*
//********************************************************************************************************

//========================================================================================================
// Inferno Spell Configuration:
//
constant function Inferno_SpellId takes nothing returns integer
    return 'A00N' //Inferno's ability Rawcode in your map
endfunction
//
constant function Inferno_LaunchInterval takes real level returns real
    return 0.12-0*level //The period of time between each bolt launch
endfunction
//
constant function Inferno_ManaDrainPerLaunch takes real level returns real
    return 0.4+level*0.1 //Mana drained per bolt launch
endfunction
//
constant function Inferno_BufferMana takes real level returns real
    return 9+2*level //The minimum mana the caster has to have to continue casting inferno
endfunction
//
constant function Inferno_Scale takes real level returns real
    return 1.2+0.1*level //The scale of the bolts
endfunction
//
constant function Inferno_MaxTurnAngle takes real level returns real
    return 2+0*level //The maximum angle changed per 0.05 seconds (when changing the direction)
endfunction
//
constant function Inferno_Speed takes real level returns real
    return 700+0*level //The speed of the bolts
endfunction
//
constant function Inferno_Area takes real level returns real
    return 400+100*level //The area of effect of the spell, aka max distance the bolts can move.
endfunction
//
constant function Inferno_MaxLaunchDistVariation takes real level returns real
    return 50.0-0*level //The maximum variation of distance for the initial position of the bolts
endfunction
//
constant function Inferno_MaxLaunchAngleVariation takes real level returns real
    return 45.0-0*level //The maximum variation of angular position for the initial position of the bolts
endfunction
//
constant function Inferno_Damage takes real level returns real
    return 5+1*level //Damage done by each bolt
endfunction
//
constant function Inferno_BoltCollisionSize takes real level returns real
    return 45+10*level //Collision size of the bolts (how close an unit must be to the bolt to get damage)
endfunction
//
constant function Inferno_TargetEffectCooldown takes nothing returns real
    return 0.5 //The cooldown of the target effect spawn
endfunction
//
constant function Inferno_EffectDeadAnimationTime takes nothing returns real
    return 0.5 //The duration of the missile effect's dead animation
endfunction
//
function Inferno_DamageOptions takes integer level returns integer
    return DamageTypes(ATTACK_TYPE_CHAOS,DAMAGE_TYPE_FIRE)+DamageOnlyEnemies()
//
//  Does chaos damage that only affects enemy units.
//
// Other damage options can be used, and the ones here changed, check caster system's readme
// for more information
//
endfunction
//
constant function Inferno_Order takes nothing returns integer
    return OrderId("monsoon")
//
// The order id of the ability used as base ability, not important if you just copied the ability in the
// map, but if you needed to have it based on let's say, blizzard, just replace that here.
//
endfunction
//
constant function Inferno_EnableAI takes nothing returns boolean
    return true
//
// When it is true, non human player owned units that cast this spell will use a special AI encoded here
// that will allow them to use Inferno in a clever way, rather than just staying on a line of
// as they usually do, to test the AI try facing the bloodmage on the top left zone of this map.
//
endfunction

//==================================================================================================
function Trig_Inferno_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Inferno_SpellId()
endfunction

//=============================
struct Inferno_TriggerData
//A good, safe way to attach content of types different to integer using CSSafeCache is through the
// use of structs, here we are declaring the struct using to store the trigger's information.
//
// Every instance of the trigger requires a certain trigger to be created in order to handle orders
//
    unit          u    = null
    integer       l    = 0
    real          f    = 0.0
    triggeraction ac   = null
    integer       b    = 0

    boolean       hasturntimer = false
    timer         turntimer = null
endstruct


struct Inferno_Attach
// So this one just keeps things we usually attach to ... collision missiles, and timers
//
    unit    u
    integer l
    real    f
    real    c
    trigger trig
endstruct

function Inferno_AngleTurning takes nothing returns nothing
local timer t=GetExpiredTimer()
local Inferno_Attach dat=Inferno_Attach( GetCSData(t) )
local real f=dat.f
local real c=dat.c
local real x=Angles_MoveAngleTowardsAngle(c,f,Inferno_MaxTurnAngle(dat.l))
local Inferno_TriggerData td= Inferno_TriggerData( GetCSData(dat.trig)  )

    set td.f=x
    set dat.c=x
    if (ModuloReal(x,360)+0.0000001>ModuloReal(f,360)) and (ModuloReal(x,360)-0.0000001<ModuloReal(f,360)) then
        set td.hasturntimer=false
        call dat.destroy()
        call ReleaseTimer(t)
    endif
set t=null
endfunction

function Inferno_PrepareAngleTurning takes trigger t, real c, real f returns nothing
local timer x=NewTimer()
local Inferno_Attach at= Inferno_Attach.create()
local Inferno_TriggerData td

    set at.trig=t
    set at.f=f
    set at.c=c
    call SetCSData(x, integer(at) )
    set td=Inferno_TriggerData( GetCSData(t) )
    set td.turntimer=x
    set td.f=c
    set td.hasturntimer=true
    call TimerStart(x,0.04,true,function Inferno_AngleTurning)
set x=null
endfunction

function Inferno_ResetFX takes nothing returns nothing
local timer x=GetExpiredTimer()
local Inferno_Attach at= Inferno_Attach( GetCSData(x) )

    call AttachBoolean(at.u,"Inferno_IgnoreFX",false)
    call at.destroy()
    call ReleaseTimer(x)
set x=null
endfunction

function Inferno_BoltImpact takes nothing returns nothing
local unit m=GetTriggerCollisionMissile()
local Inferno_Attach at = Inferno_Attach( CollisionMissile_GetTag(m) ) //See how we are using CollisionMissile tags instead of CSData.

local unit o=at.u
local unit u=GetTriggerUnit()
local integer l
local integer s
local real f
local timer x

    if (u!=null) then
        set l=at.l
        set f=GetDamageFactorByOptions(o,u,Inferno_DamageOptions(l))
        if f!=0 then
            set s=Inferno_SpellId()
            if not(GetAttachedBoolean(u,"Inferno_IgnoreFX")) then
                call DestroyEffect(AddSpellEffectTargetById(s,EFFECT_TYPE_TARGET,u,GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1)))
                call AttachBoolean(u,"Inferno_IgnoreFX",true)
                set x=NewTimer()
                set at=Inferno_Attach.create()
                set at.u=u
                call SetCSData(x, integer(at) )
                call TimerStart(x,Inferno_TargetEffectCooldown(),false,function Inferno_ResetFX)
               set x=null
            endif
            call UnitDamageTarget(o,u,Inferno_Damage(l)*f,true,false,null,null,null)
        endif
    else
        call at.destroy() //cleanup now that the collision missile has died...
    endif
set u=null
set m=null
set o=null
endfunction

function Inferno_Launch takes boolean cfc, unit u, integer l,real f returns nothing
local unit m
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real a
local real d
local integer s=Inferno_SpellId()
local Inferno_Attach at

    if GetWidgetLife(u)>0 then
        if GetRandomInt(0,100)<=10 then
            call DestroyEffect(AddSpellEffectTargetById(s,EFFECT_TYPE_CASTER,u,GetAbilityEffectById(s,EFFECT_TYPE_CASTER,1)))
        endif
        if cfc  then
            call SetUnitFacing(u,f)
        endif
        set a=Inferno_MaxLaunchAngleVariation(l)
        set d=GetRandomReal(0,Inferno_MaxLaunchDistVariation(l))
        set a=(f + GetRandomReal(-a,a))*bj_DEGTORAD
        set m=CollisionMissile_Create(GetAbilityEffectById(Inferno_SpellId(),EFFECT_TYPE_MISSILE,0),x+d*Cos(a),y+d*Sin(a),f,Inferno_Speed(l),0,Inferno_Area(l),60,false,Inferno_BoltCollisionSize(l),function Inferno_BoltImpact)
        set at = Inferno_Attach.create()
        call CollisionMissile_SetTag(m, integer(at) ) //Again, we are using collisionmissile tags here.

        set f=Inferno_Scale(l)
        call SetUnitScale(m,f,f,f)
        call SetUnitOwner(m,GetOwningPlayer(u),true)
        call SetUnitColor(m,GetPlayerColor(GetOwningPlayer(u)) )
        set at.u=u
        set at.l=l

    endif

set m=null
endfunction

function Inferno_EndTurn takes nothing returns nothing
local timer t=GetExpiredTimer()
local Inferno_Attach at = Inferno_Attach( GetCSData(t) )
    call AttachReal(at.u,"Inferno_Current",0)
    call at.destroy()
    call ReleaseTimer(t)
set t=null
endfunction

function Inferno_PrepareTurn takes unit u, real f returns nothing
local timer t=NewTimer()
local Inferno_Attach at = Inferno_Attach.create()
   
    set at.u=u
    if f==0 then
        set f=0.1
    endif
    call AttachReal(u,"Inferno_Current",f)
    call SetCSData(t, integer(at) )
    call TimerStart(t,2,false,function Inferno_EndTurn)
set t=null
endfunction

function Inferno_DetectDirChangeT takes nothing returns nothing
local timer x=GetExpiredTimer()
local Inferno_Attach at = Inferno_Attach( GetCSData(x) )
local Inferno_TriggerData td
    if GetUnitCurrentOrder(at.u)!=Inferno_Order() then
        set td=Inferno_TriggerData( GetCSData( at.trig ) )
        set td.b=40
    endif
    call ReleaseTimer(x)
    call at.destroy()
set x=null
endfunction

function Inferno_DetectDirChange takes trigger t, unit u returns nothing
local timer x=NewTimer()
local Inferno_Attach at = Inferno_Attach.create()

    set at.trig=t
    set at.u=u
    call SetCSData(x, integer(at) )
    call TimerStart(x,0,false,function Inferno_DetectDirChangeT)
set x=null
endfunction

function Inferno_AI takes trigger t, unit u, integer l,real f returns boolean
local group g=CreateGroup()
local unit p
local player ow=GetOwningPlayer(u)
local unit tar=null
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local integer d
local real gra
local integer b=0
local integer cl
local real max=Inferno_Area(l)
    call GroupEnumUnitsInRange(g,x,y,max,null)
    set max=max*max
    loop
        set p=FirstOfGroup(g)
        exitwhen p==null
        call GroupRemoveUnit(g,p)
        if IsUnitEnemy(p,ow) and (GetWidgetLife(p)>0) and IsUnitVisible(p,ow) then
            set d=R2I(1000.*(max-(Pow(GetUnitX(p)-x,2)+Pow(GetUnitY(p)-y,2))))
            if IsUnitType(p,UNIT_TYPE_HERO) then
                set cl=(GetHeroLevel(p)*2)*d
            else
                set cl=(GetUnitLevel(p))*d
            endif
            if (cl>b) then
                set b=cl
                set tar=p
            endif
        endif
    endloop
    call DestroyGroup(g)
    if tar!=null then
        set gra=Atan2BJ(GetUnitY(tar)-y,GetUnitX(tar)-x)
        call Inferno_PrepareAngleTurning(t,f,gra)
    endif

set ow=null
set p=null
set g=null
set tar=null
return (b!=0)
endfunction

function Inferno_Control takes nothing returns nothing
//
// Main control trigger
// A trigger is created by Trig_Inferno_Actions, that trigger uses this function, the trigger
// You may like to read Trig_Inferno_Actions first as it explains what data it is attaching to the trigger
// executes each (launch interval) seconds, or when the unit starts the effect of a spell or stops casting
//
local trigger t=GetTriggeringTrigger() //The trigger is run, you can use this function to know which trigger we are talking about

local Inferno_TriggerData d= Inferno_TriggerData( GetCSData(t) )
                          // Let me explain this mess:
                          //   GetCSData(t)         : With this, we recover that unique integer value we attached before, remember?
                          //  Inferno_TriggerData() : This just converts that value to our struct.


local integer l= d.l                //This was saved in the function below.
local real f
local integer b= d.b                // "" "" ""
local unit u=d.u                    // '' '' ''
local eventid e=GetTriggerEventId()
// A trigger may have multiple events, so this works for letting us know which event caused
// the trigger to execute

    if (b>=1) then
        if (e==EVENT_UNIT_SPELL_EFFECT) then
            set d.b=b+40
            set b=40
        else
            set d.b=b+1
        endif
    endif
    if (b==0) then   
        set f=GetUnitState(u,UNIT_STATE_MANA)
        if (f<Inferno_BufferMana(l)) then
            call PauseUnit(u,true)
            call IssueImmediateOrder(u,"stop")
            call PauseUnit(u,false)
            set b=40
            set d.b=40
        else
            call SetUnitState(u,UNIT_STATE_MANA,f-Inferno_ManaDrainPerLaunch(l))
            if ((Inferno_EnableAI()) and (GetPlayerController(GetOwningPlayer(u))!=MAP_CONTROL_USER)) then
                if not(d.hasturntimer) and (GetRandomInt(0,100)<=10) then
                    if not( Inferno_AI(t,u,l,d.f))  then
                        call PauseUnit(u,true)
                        call IssueImmediateOrder(u,"stop")
                        call PauseUnit(u,false)
                        set b=40
                        set d.b=b
                    endif
                endif
            endif
        endif
    endif
    set f=d.f
    if (b==0) and (e==EVENT_UNIT_SPELL_ENDCAST) then
        call Inferno_DetectDirChange(t,u)
        set d.b=b+1
        if d.hasturntimer then
            call Inferno_Attach( GetCSData(d.turntimer) ).destroy() //important cleanup here, easy to miss
            call ReleaseTimer(d.turntimer)
            set d.hasturntimer=false
        endif
        call Inferno_PrepareTurn(u, d.f )
    endif

    if (b<40) then
        call Inferno_Launch((b==0),u, l,f)
    endif
    if (b>=40) then
        // We are doing cleanup here. Please notice:
        call TriggerRemoveAction(t,d.ac) //Removing the triggeraction (good that we stored it, right?)
        call d.destroy()                 //Also recycle the object (quite important)

        call DestroyTrigger(t)           //Don't forget the trigger...
    endif
set u=null
set t=null
set e=null
endfunction


function Trig_Inferno_Actions takes nothing returns nothing
//
//This is the first thing that runs whenever a hero starts casting the inferno spell
//
local unit u=GetTriggerUnit()
local integer s=GetSpellAbilityId()
local integer l=GetUnitAbilityLevel(u,s)
local location loc=GetSpellTargetLoc()
local real f=Atan2BJ(-GetUnitY(u)+GetLocationY(loc) ,-GetUnitX(u)+GetLocationX(loc))
local Inferno_TriggerData d  =Inferno_TriggerData.create() //let's create our TriggerData object!
local trigger t=CreateTrigger()
// Creating a trigger in game is really important when you want to go for multinstance
// Spells, this trigger is used to detect whenever the unit starts or stops casting the spell
local real c

    call SetCSData(t, integer(d) ) //We are linking our TriggerData object to the trigger t.
                                     // You can get a unique integer value from a struct using integer()
                                     // This value will allow us to later get the data.

    set d.u=u  //Save u at "u" for t
    set d.l=l  //Also save the level of the spell for t


    set c=GetAttachedReal(u,"Inferno_Current")     //If the unit was already casting inferno, the current direction should be saved
                                                   //On the attached variable "Inferno_Current"

    if c!=0 then                                   //If c is not 0, then inferno was being cast
        call Inferno_PrepareAngleTurning(t,c,f)    //So use inferno's turning function
    else
        set d.b = 0
        set d.f = f                                //If c is 0 then the unit was not casting inferno and just use the current angle for f
    endif

    call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SPELL_ENDCAST) //Register the Stops casting an ability event for the trigger t
    call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SPELL_EFFECT)  //Register the Starts the effect of an ability event for the trigger t

    set d.ac=TriggerAddAction(t,function Inferno_Control)
   //Another application for Attacheable variables is fixing the TriggerAction leak, this
   //is an evil leak, if you create a trigger in game and give it a trigger action, you have
   //To remove it from the trigger, else it will leak.

   // But if we find our way to link the trigger action to the trigger so we might destroy it later, we can fix it.

    call TriggerRegisterTimerEvent(t,Inferno_LaunchInterval(l),true)
   //Make a periodic event for the trigger, so it is execute each Inferno_LaunchInterval() seconds
    call TriggerRegisterTimerEvent(t,0,false)
   //Will make the Trigger execute instantly after this current trigger ends execution

call RemoveLocation(loc) //Remove point so it doesn't leak
set loc=null
set u=null
//weird bugs if you set t=null , yes, in very rare situations the return bug, and thereby
//attacheable variables get really weird bugs, this is related to how the stuff works, an
//depends on weird combinations of factors-
endfunction

//===========================================================================
function InitTrig_Inferno takes nothing returns nothing
    call OnAbilityEffect(Inferno_SpellId(),"Trig_Inferno_Actions")
endfunction



[/jass]
回复

使用道具 举报

 楼主| 发表于 2008-12-9 19:04:45 | 显示全部楼层
[jass]
//============================================================================================
// Preload Abilities:
// Use call PreloadAbility('code') to avoid first time cast lag of an ability
//
function Abilities_Preload takes nothing returns nothing
   

    call PreloadAbility('A00G') // Blinding Light Curse:

    call PreloadAbility('A00F') // Chain lightning for Thor's Hammer :

    call PreloadAbility('A00M') // Illusions (Caster)

    call PreloadAbility('A006') // Cripple for the scroll of Darkness :

    call PreloadAbility('A003') // Rune of bloodlust's bloodlust :

    call PreloadAbility('A00P') // Muradin's hammer 's thunderclap :

    call PreloadAbility('A005') // Rejuvenation for the scroll:
   
    call PreloadAbility('A000') // Polymorph for the staff:

    call PreloadAbility('A018') // Nova's Shockwave

    ///
    // Preload Laggy Models:
    //
    call Preload( "Abilities\\\\Spells\\\\Human\\\\FlameStrike\\\\FlameStrikeEmbers.mdl" )
    call Preload( "Abilities\\\\Spells\\\\Human\\\\FlameStrike\\\\FlameStrikeDamageTarget.mdl" )

    call Preload( "Abilities\\\\Weapons\\\\FarseerMissile\\\\FarseerMissile.mdl")
endfunction

//========================================================================================
// 'Abilities Preload' "Trigger"'s init script (always called on init:)
//
function InitTrig_Abilities_Preload takes nothing returns nothing


    call ExecuteFunc("Abilities_Preload")
    //
    // ExecuteFunc calls a function using its name and also uses another thread to do so
    // because it uses another thread it is a good idea to use it on probably heavy
    // initialization commands like, in this case, preloading of abilities.


endfunction

[/jass]
回复

使用道具 举报

 楼主| 发表于 2008-12-9 19:06:16 | 显示全部楼层
[jass]
//********************************************************************************************************
//*
//* Ability Pool
//* ˉˉˉˉˉˉˉˉˉˉˉˉ
//* This is a JASS example, it uses the Pool class in other to have easy randomization of abilities
//* without repeating any until the AbilityPool is empty, in that case it adds the abilities again.
//*
//********************************************************************************************

//============================================================================================
globals
    integer udg_AbilityPool=0
    constant integer MaxSheepNumber = 7  // Ressurection messes this value
endglobals

function AddAbilitiesToPool takes nothing returns nothing

    call PoolAddItem( udg_AbilityPool, 'AHav')
    call PoolAddItem( udg_AbilityPool, 'AHbn')
    call PoolAddItem( udg_AbilityPool, 'AHbz')
    call PoolAddItem( udg_AbilityPool, 'AHds')
    call PoolAddItem( udg_AbilityPool, 'AHfs')
    call PoolAddItem( udg_AbilityPool, 'AHhb')
    call PoolAddItem( udg_AbilityPool, 'AHre')
    call PoolAddItem( udg_AbilityPool, 'AHdr')

    call PoolAddRawcodes(udg_AbilityPool, "AHtb;AHtc;AOvd;AOcl;AOhw;AOhx;AOmi;AOre;AOsh;AOws")
  // Yes, it is possible to do this, but not recomended, beware that you are sacrificing efficiency
  // in exchange of saving some lines and writting work.

  // It is not too important during map init time, since they save lines, it would actually make things
  // faster since the download time will be smaller

    call PoolAddItem( udg_AbilityPool, 'AOwk')
    call PoolAddItem( udg_AbilityPool, 'AUan')
    call PoolAddItem( udg_AbilityPool, 'AUcs')
    call PoolAddItem( udg_AbilityPool, 'AUdr')
    call PoolAddItem( udg_AbilityPool, 'AUdd')
    call PoolAddItem( udg_AbilityPool, 'AUdc')
    call PoolAddItem( udg_AbilityPool, 'AUdp')
    call PoolAddItem( udg_AbilityPool, 'AUfu')
    call PoolAddItem( udg_AbilityPool, 'AUfn')
    call PoolAddItem( udg_AbilityPool, 'AUim')
    call PoolAddItem( udg_AbilityPool, 'AUsl')
    call PoolAddItem( udg_AbilityPool, 'AEbl')
    call PoolAddItem( udg_AbilityPool, 'AEer')
    call PoolAddItem( udg_AbilityPool, 'AEfk')
    call PoolAddItem( udg_AbilityPool, 'AEim')
    call PoolAddItem( udg_AbilityPool, 'AEmb')
    call PoolAddItem( udg_AbilityPool, 'AEsh')
    call PoolAddItem( udg_AbilityPool, 'AEsf')
    call PoolAddItem( udg_AbilityPool, 'AEtq')
    call PoolAddItem( udg_AbilityPool, 'ANbr')
    call PoolAddItem( udg_AbilityPool, 'ANbf')
    call PoolAddItem( udg_AbilityPool, 'ANch')
    call PoolAddItem( udg_AbilityPool, 'ANdh')
    call PoolAddItem( udg_AbilityPool, 'ANfd')
    call PoolAddItem( udg_AbilityPool, 'ANfb')
    call PoolAddItem( udg_AbilityPool, 'ANfl')
    call PoolAddItem( udg_AbilityPool, 'ANht')
    call PoolAddItem( udg_AbilityPool, 'ANdr')
    call PoolAddItem( udg_AbilityPool, 'ANms')
    call PoolAddItem( udg_AbilityPool, 'ANmo')
    call PoolAddItem( udg_AbilityPool, 'ANrf')
    call PoolAddItem( udg_AbilityPool, 'ANst')
    call PoolAddItem( udg_AbilityPool, 'ANto')
    call PoolAddItem( udg_AbilityPool, 'ACam')
    call PoolAddItem( udg_AbilityPool, 'ACbl')
    call PoolAddItem( udg_AbilityPool, 'ACcn')
    call PoolAddItem( udg_AbilityPool, 'ACcv')
    call PoolAddItem( udg_AbilityPool, 'ACcs')
    call PoolAddItem( udg_AbilityPool, 'ACde')
    call PoolAddItem( udg_AbilityPool, 'Adsm')
    call PoolAddItem( udg_AbilityPool, 'Anhe')
    call PoolAddItem( udg_AbilityPool, 'ACif')
    call PoolAddItem( udg_AbilityPool, 'ACsw')
    call PoolAddItem( udg_AbilityPool, 'ACff')
    call PoolAddItem( udg_AbilityPool, 'A00V')
    call PoolAddItem( udg_AbilityPool, 'A00N')
    call BJDebugMsg("\\t|c20C0C0C0[Debug] ability pool (re)created|r")
endfunction

function AddAbilitiesToSheep takes unit sheep returns nothing
local integer a=0
local integer c
    loop
        if CountItemsInPool( udg_AbilityPool) <= 0 then
            call AddAbilitiesToPool()
        endif
        exitwhen a>5
        set c=PoolPickRandomItem( udg_AbilityPool)
        call PoolRemoveItem( udg_AbilityPool, c)
        call UnitAddAbility( sheep, c)
//        call UnitAddAbility( sheep, 'Awan')
        call UnitMakeAbilityPermanent( sheep, true, c)
//        call UnitMakeAbilityPermanent( sheep, true, 'Awan')
        set a=a+1
    endloop
endfunction

function SheepShow takes nothing returns nothing
local unit sheep
local real c
local rect r
    loop
        call PolledWait(GetRandomReal(1,4))
        loop
            exitwhen CountLivingPlayerUnitsOfTypeId('n003', Player(12)) < MaxSheepNumber
            call TriggerSleepAction(0.5)
        endloop
        set r=gg_rct_sheep_invasion
        set sheep=CreateUnit( Player(12), 'n003', GetRandomReal(GetRectMinX(r),GetRectMaxX(r)), GetRandomReal(GetRectMinY(r),GetRectMaxY(r)), GetRandomReal(0,359))
        set r=null
        call AddAbilitiesToSheep( sheep)
        if GetUnitAbilityLevel(sheep, 'AOmi') <= 0 then
            call SetUnitVertexColor( sheep, GetRandomInt(0,255), GetRandomInt(0,255), GetRandomInt(0,255), 255)
            set c=GetRandomReal(0.9,2)
            call SetUnitScale( sheep, c,c,c)
        endif
        call DestroyEffect( AddSpecialEffectTarget( "Abilities\\\\Spells\\\\NightElf\\\\Blink\\\\BlinkTarget.mdl", sheep, "origin"))
    endloop
endfunction

//============================================================================================
function InitTrig_Pools_demo takes nothing returns nothing

    set udg_AbilityPool=CreatePool()
    call AddAbilitiesToPool()   
    set gg_trg_Pools_demo = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Pools_demo, Player(0), "random", false )
    call TriggerAddAction( gg_trg_Pools_demo, function SheepShow )

endfunction




[/jass]
回复

使用道具 举报

发表于 2008-12-15 17:20:36 | 显示全部楼层
转载文章,劳动精神值得鼓励。

希望将来转载的同时能加上基本介绍,并且对于类似这种较旧的演示,希望能对其中可以改进的地方加入自己的意见,谢谢。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-2 20:48 , Processed in 0.093032 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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