• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Help with this script

Status
Not open for further replies.
Level 13
Joined
Aug 19, 2014
Messages
1,111
Need help on this script guys.....

JASS:
library EnchantedJavelin uses CTL, SpellEffectEvent, WorldBounds,

/*******************************************************************************
                                CONFIGURABLES                        
*******************************************************************************/

globals
    private constant integer ABIL_ID = 'ACc3' // raw code of ability "Enchanted Javelin Ability"
    private constant integer DUM_ABIL_ID = 'ANfb' // raw code of ability "Enchanted Javelin (Stun)"
    private constant integer BUFF_ID = 'BSTN' // raw code of buff "Enchanted Javelin"
    
    private constant integer DUMMY_ID = 'njks' // raw code of unit "Enchanted Javelin Dummy"
    private constant integer RED = 255 // red vertex color of spell projectile
    private constant integer GREEN = 255 // green vertex color of spell projectile
    private constant integer BLUE = 255 // blue vertex color of spell projectile
    private constant integer TRANS = 255 // transparency of spell projectile, where 0 is fully transparent
    private constant real SCALE = 1.5 // scale size of spell projectile
    private constant real HEIGHT = 100. // flying height of spell projectile
    private constant real SPEED = 1000. // distance travelled per second by spell projectile
    private constant real COLLISION = 100. // collision contact size of spell projectile
    private constant real ANGLE_RATE = 0. // maximum turning degree of spell projectile per second
    
    private constant string FX = "Abilities\\Spells\\Human\\SpellSteal\\SpellStealMissile.mdl" // special effect used when damgage is dealt
    private constant string FX_AT = "chest" // attachment point of FX
    
    private constant boolean PRELOAD = true // preloads resources if true
    
    private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
    
    private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type
    private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type
endglobals

// area of effect
private constant function GetArea takes integer level returns real
    return 150.0
endfunction

// damage dealt
private constant function GetDamage takes integer level returns real
    return 40. * level + 60.
endfunction

// distance travelled by missile
private constant function GetDistance takes integer level returns real
    return 1200.
endfunction

// slow duration
private constant function GetDuration takes integer level returns real
    return 3.
endfunction

// homing detection area
private constant function GetHomeArea takes integer level returns real
    return 600.
endfunction

// target types allowed for dealing damage
private constant function GetFilter takes unit caster, unit target returns boolean
    return /*
    */ not IsUnitType(target, UNIT_TYPE_DEAD) and /* target is alive
    */ IsUnitEnemy(target, GetOwningPlayer(caster)) and /* target is an enemy of caster
    */ not IsUnitType(target, UNIT_TYPE_STRUCTURE) and /* target is not a structure
    */ not IsUnitType(target, UNIT_TYPE_MECHANICAL) and /* target is not mechanic
    */ not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) /* target is not magic immune
    */
endfunction

/*******************************************************************************
                            END CONFIGURABLES                        
*******************************************************************************/

globals
    private group G = bj_lastCreatedGroup
endglobals

private struct Firebolt extends array
    private static constant real TIMEOUT = 0.031250000
    private static integer array store
    
    private unit u
    private real dur
    
    implement CTLExpire
        set this.dur = this.dur - TIMEOUT
        
        if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
            set thistype.store[GetUnitUserData(this.u)] = 0
        
            call UnitRemoveAbility(this.u, DUM_ABIL_ID)
            call UnitRemoveAbility(this.u, BUFF_ID)
            call this.destroy()
        endif
    implement CTLEnd
    
    public static method apply takes unit u, real dur returns nothing
        local thistype this
        local integer id = GetUnitUserData(u)
        
        if thistype.store[id] == 0 then
            set this = thistype.create()
            set this.u = u
            set thistype.store[id] = this
            
            call UnitAddAbility(u, DUM_ABIL_ID)
            call UnitMakeAbilityPermanent(u, true, DUM_ABIL_ID)
        else
            set this = thistype.store[id]
        endif
        
        set this.dur = dur
    endmethod
endstruct

private struct Main extends array
    private static constant real TIMEOUT = 0.031250000
    private static constant real TRUE_SPEED = SPEED * TIMEOUT
    private static constant real TRUE_ANGLE_RATE = ANGLE_RATE * TIMEOUT * bj_DEGTORAD
    private static constant real PI_2 = bj_PI * 2
    
    private unit u
    private unit dummy
    private unit target
    private real area
    private real dmg
    private real dist
    private real dur
    private real homeArea
    private real sin
    private real cos
    
    implement CTL
        local unit u
        local unit target
        local boolean b = false
        local real x
        local real y
        local real dx
        local real dy
        local real r
        local real minDist
        local real facing
    implement CTLExpire
        set target = null
        set b = false
        set x = GetUnitX(this.dummy)
        set y = GetUnitY(this.dummy)
        set minDist = this.homeArea * this.homeArea
    
        call GroupEnumUnitsInRange(G, x, y, this.homeArea + ENUM_RADIUS, null)
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            call GroupRemoveUnit(G, u)
                
            set dx = GetUnitX(u) - x
            set dy = GetUnitY(u) - y
            set r = dx * dx + dy * dy
                
            if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.homeArea) and r < minDist then
                if IsUnitInRangeXY(u, x, y, COLLISION) then
                    set b = true
                    call GroupClear(G)
                    exitwhen true
                else
                    set minDist = r
                    set target = u
                endif
            endif
        endloop
        
        if b then
            call GroupEnumUnitsInRange(G, x, y, this.area + ENUM_RADIUS, null)
            loop
                set u = FirstOfGroup(G)
                exitwhen u == null
                call GroupRemoveUnit(G, u)
                
                if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.area) then
                    call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_AT))
                    call UnitDamageTarget(this.u, u, this.dmg, true, false, ATK, DMG, null)
                    call Firebolt.apply(u, this.dur)
                endif
            endloop
        
            call KillUnit(this.dummy)
            call this.destroy()
        else
            set this.target = target
            set facing = GetUnitFacing(this.dummy) * bj_DEGTORAD

            if this.target != null then
                set r = Atan2(GetUnitY(this.target) - y, GetUnitX(this.target) - x)
                
                if r < 0 then
                    set r = r + PI_2
                endif
                
                if facing < r then
                    set facing = facing + PI_2
                endif
                
                if facing - r < bj_PI then
                    set facing = facing - TRUE_ANGLE_RATE
                elseif facing - r > bj_PI then
                    set facing = facing + TRUE_ANGLE_RATE
                else
                    set facing = r
                endif
            endif
            
            set x = x + TRUE_SPEED * Cos(facing)
            set y = y + TRUE_SPEED * Sin(facing)
            call SetUnitFacing(this.dummy, facing * bj_RADTODEG)
            if x > WorldBounds.minX and y > WorldBounds.minY and x < WorldBounds.maxX and y < WorldBounds.maxY then
                call SetUnitX(this.dummy, x)
                call SetUnitY(this.dummy, y)
            endif
            
            set this.dist = this.dist - TRUE_SPEED
            if this.dist <= 0 then
                call KillUnit(this.dummy)
                call this.destroy()
            endif
        endif
    implement CTLNull
        set u = null
        set target = null
    implement CTLEnd

    private static method onCast takes nothing returns boolean
        local thistype this = thistype.create()
        local integer level
        local real a
        
        set this.u = GetTriggerUnit()
        set a = Atan2(GetSpellTargetY() - GetUnitY(this.u), GetSpellTargetX() - GetUnitX(this.u))
        set this.dummy = CreateUnit(GetOwningPlayer(this.u), DUMMY_ID, GetUnitX(this.u), GetUnitY(this.u), a * bj_RADTODEG)
        set this.target = null
        set level = GetUnitAbilityLevel(this.u, ABIL_ID)
        set this.area = GetArea(level)
        set this.dmg = GetDamage(level)
        set this.dist = GetDistance(level)
        set this.dur = GetDuration(level)
        set this.homeArea = GetHomeArea(level)
        
        call SetUnitVertexColor(this.dummy, RED, GREEN, BLUE, TRANS)
        call SetUnitScale(this.dummy, SCALE, 0, 0)
        call SetUnitFlyHeight(this.dummy, HEIGHT, 0)
        
        return false
    endmethod

    private static method onInit takes nothing returns nothing
        static if PRELOAD then
            local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
            call UnitAddAbility(u, DUM_ABIL_ID)
            call RemoveUnit(u)
            set u = null
        endif
        
        call RegisterSpellEffectEvent(ABIL_ID, function thistype.onCast)
    endmethod
endstruct

endlibrary

I'm trying to make it stun the enemy unit that it collided with but it just damages them.

By the way this script is copied from this spell pack :fp: http://www.hiveworkshop.com/forums/spells-569/artesia-spellpack-v1-1-1-a-242401/ In which I reproduce the Arcane Missile script that I got some errors and now its okay.
 
Level 7
Joined
Oct 19, 2015
Messages
286
In its original version, this spell just slowed the damaged units, it did not stun them. The slow effect was achieved by adding a passive ability to the unit that decreased its speed (likely based on tornado slow aura). It is not possible to achieve a stun effect in this way, since a passive ability that could stun the unit that has it does not exist. You need to cast an active stun ability onto the unit instead. Just passing an active stun ability into code designed to handle a passive ability like you do now can not work, you need to recode that section of the spell.

The easiest solution would be to find a stun system (for example something like this) and then use that system to apply the stun. You would just need to replace this line with the stun system equivalent: call Firebolt.apply(u, this.dur) If you do this, then the whole Firebolt struct becomes unnecessary and can be deleted, along with the DUM_ABIL_ID and BUFF_ID constants.
 
Last edited:
Level 13
Joined
Aug 19, 2014
Messages
1,111
In its original version, this spell just slowed the damaged units, it did not stun them. The slow effect was achieved by adding a passive ability to the unit that decreased its speed (likely based on tornado slow aura). It is not possible to achieve a stun effect in this way, since a passive ability that could stun the unit that has it does not exist. You need to cast an active stun ability onto the unit instead. Just passing an active stun ability into code designed to handle a passive ability like you do now can not work, you need to recode that section of the spell.

The easiest solution would be to find a stun system (for example something like this) and then use that system to apply the stun. You would just need to replace this line with the stun system equivalent: call Firebolt.apply(u, this.dur) If you do this, then the whole Firebolt struct becomes unnecessary and can be deleted, along with the DUM_ABIL_ID and BUFF_ID constants.

Thanks for the reply dude, I thought it will be very simple :ogre_haosis: I have no idea on how to write VJass but anyway I'll try what you said.
 
Status
Not open for further replies.
Top