• 🏆 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!

Spell Request (Simple)

Status
Not open for further replies.
Level 7
Joined
Jul 9, 2008
Messages
253
Hello community, I'm kinda newish to JASS and I wonder if someone could make a Fireball spell, just like the non-triggered fireball spell in wc3.

The only things I would like to have in the spell:

- Damage that is stats dependant and I can easily change
- Speed that can be changed
- Duration that can be changed
- Model that can be changed
- Size of the model that can be changed
- Not vJASS
- Not GUI
- In JASS

Things like icons and tooltips aren't really important. This is more like a base spell for me so I know how it's done.

Thanks in advance, Quetzalcotl
 
Last edited:
Level 7
Joined
Jul 9, 2008
Messages
253
I'm not asking it in JASS for nothing. I want to know how you make a spell like that so I can move on from that point. So no, I don't need it in GUI.
 
Level 9
Joined
Aug 2, 2008
Messages
219
- Damage that is stats dependant and I can easily change
- Speed that can be changed
- Duration that can be changed
- Model that can be changed
- Size of the model that can be changed
- Not vJASS
- Not GUI
- In JASS

Things like icons and tooltips aren't really important. This is more like a base spell for me so I know how it's done.

  • Damage depends on the level of the spell [√]
  • Speed is adjustable [√]
  • What do you mean by duration ?
  • Model is adjustable inside the code (uses an imported dummy model) [√]
  • Size is ajdustable [√]
  • No vJass [√]
  • At least you need to create a hashtable via GUI
  • In Jass [√]
  • Uses NO tooltips and stuff [√]
JASS:
constant function EF_GetDamageRadius takes real level returns real
    return level * 150 + 80 //The damage radius of the missile when it reaches its target
endfunction

constant function EF_GetImpactDamage takes real level returns real
    return level * 30 + 40 //The damae dealt to enemies in range of the missile
endfunction

constant function EF_DummyModel takes nothing returns string
    return "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
endfunction //Selfexplaining

constant function EF_GetImpactSFX takes nothing returns string
    return "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl"
endfunction //The Special effect being displayed on an enemy when the missile explodes

constant function EF_Curve takes nothing returns real
    return 4.736 //This has incluce on the z-parabola
endfunction

constant function EF_DummyScale takes nothing returns real
    return 1.7 //The size of the dummy
endfunction

constant function EF_TimerIntervall takes nothing returns real
    return 0.02 //Moving intervall of the missiel. Better do not change
endfunction

constant function EF_GetMoveSpeed takes nothing returns real
    return 20. //Moving speed of the missile
endfunction

constant function EF_SID takes nothing returns integer
    return 'A000' //The rawcode (spell id) of this ability
endfunction

constant function EF_DID takes nothing returns integer
    return 'h000' //The rawcode of the dummy unit
endfunction

constant function EF_IsHoming takes nothing returns boolean
    return false //Gets important somwhen later...
endfunction

//Credits to Shadow1500 for this function!
constant function Parabola takes real d, real m, real c returns real
    return (-1* ((d * 2) / m - 1) * ((d * 2) / m - 1) + 1) * (m / c)
endfunction //Computes the z-value for the missile depdining on the current (D)istance, the (M)aximal distance and the (C)urve factor

constant function EF_HashKey takes nothing returns integer
    return 0x256
endfunction //A key for the hashtable to cache some temporaty data

function EF_CreateDummy takes unit u, real x, real y, real f returns unit

    set u = CreateUnit(Player(0),EF_DID(),x,y,f*bj_RADTODEG) //Create a unit with the imported dummy model
    
    call SetUnitScale(u,EF_DummyScale(),EF_DummyScale(),EF_DummyScale()) //Set its size
    call SaveEffectHandle(udg_EF_HASH,EF_HashKey(),GetHandleId(u),AddSpecialEffectTarget(EF_DummyModel(),u,"origin"))
    //Attatch an effect to the unit; visually AND in the memory
    call UnitAddAbility(u,'Aloc') //Make the unit unpickable
    call UnitAddAbility(u,'Amrf') //Make the unit flyable
    
    return u //I create the unit on a parameter because they don´t need to be nulled when they are returned
    //You should use null if you pass values
    
endfunction

function EF_AoEDamage takes nothing returns boolean

    local unit u = GetFilterUnit() //Gets a unit near to the missile
    local unit c = LoadUnitHandle(udg_EF_HASH,EF_HashKey(),1) //Gets the caster from the 'cache'
    local real dmg = LoadReal(udg_EF_HASH,EF_HashKey(),2) //GetS the damage from the 'cache'
    
    //If the unit is valid
    if IsUnitEnemy(u,GetOwningPlayer(c)) and IsUnitType(u,UNIT_TYPE_DEAD) != true and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) != true and IsUnitType(u,UNIT_TYPE_STRUCTURE) != true then
        call UnitDamageTarget(c,u,dmg,false,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
        //Deal damage...
        call DestroyEffect(AddSpecialEffect(EF_GetImpactSFX(),GetWidgetX(u),GetWidgetY(u)))
        //...and quick destroy/create a special effect
    endif
    
    set u = null
    set c = null
    return false
    
endfunction

function EF_MoveNormal takes nothing returns nothing

    local timer t = GetExpiredTimer() //Gets the timer
    local integer id = GetHandleId(t) //Gets its id to acces data from the (H)ash(T)able
    local unit u = LoadUnitHandle(udg_EF_HASH,id,1) //Gets the missile from the ht
    local location loc = GetUnitLoc(u) //Gets the current position (need location to calcuate z)
    local real dis = LoadReal(udg_EF_HASH,id,4) - EF_GetMoveSpeed() //Recalculate the distance
    local real z = Parabola(dis,LoadReal(udg_EF_HASH,id,5),EF_Curve()) - GetLocationZ(loc) //Calculates the absulute Z
    local unit c = null //Caster (needed when the missile explodes)
    
    call SetUnitX(u,GetLocationX(loc)+LoadReal(udg_EF_HASH,id,2))
    call SetUnitY(u,GetLocationY(loc)+LoadReal(udg_EF_HASH,id,3))
    //Moving the missile
    call SetUnitFlyHeight(u,z,0.)
    //Moving the missile trhough the air
    call SaveReal(udg_EF_HASH,id,4,dis)
    //Save the distance again to the ht
        
    if dis <= EF_GetMoveSpeed() +1. then //If the missile is near to its target point
    
        set c = LoadUnitHandle(udg_EF_HASH,id,0)
        set z = GetUnitAbilityLevel(c,EF_SID()) //Re-using a local
        call SaveUnitHandle(udg_EF_HASH,EF_HashKey(),1,c)
        call SaveReal(udg_EF_HASH,EF_HashKey(),2,EF_GetImpactDamage(z))
        //Putting the caster and the damage into the 'cache'
        
        call GroupEnumUnitsInRange(LoadGroupHandle(udg_EF_HASH,EF_HashKey(),0),GetWidgetX(u),GetWidgetY(u),EF_GetDamageRadius(z), Filter( function EF_AoEDamage))
        //Loops trhough all unit near the missile and damages them if they are valid
        
        call GroupClear(LoadGroupHandle(udg_EF_HASH,EF_HashKey(),0))
        //Clears the group to prevent bugs
        
        call DestroyEffect(AddSpecialEffectLoc(EF_DummyModel(),loc))
        //Show the missiles death animation
        
        call DestroyEffect(LoadEffectHandle(udg_EF_HASH,EF_HashKey(),GetHandleId(u)))
        //Removes the missile model from the dummy and from the memory
        
        call RemoveUnit(u)
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_EF_HASH,id)
        set c = null
        //Clearing leaks and save some memory
        
    endif
    
    call RemoveLocation(loc)
    
    set t = null
    set loc = null
    set u = null
    //Cleans the last leaks


endfunction

function EF_OnCastNormal takes nothing returns nothing

    local unit u = GetTriggerUnit() //Gets the caster
    local real x = GetSpellTargetX() - GetWidgetX(u)
    local real y = GetSpellTargetY() - GetWidgetY(u)
    //MATH !!!
    local real rad = Atan2(y,x) //Gets the angel between the caster and the target point (in radiants !)
    local real cos = Cos(rad)*EF_GetMoveSpeed() //Calculates the x direction
    local real sin = Sin(rad)*EF_GetMoveSpeed() //Calculates the y direction
    local real dis = SquareRoot(x*x+y*y) //Calculates the distance 
    local timer t = CreateTimer()
    local integer id = GetHandleId(t) //Gets a key for the ht
    
    call SaveUnitHandle(udg_EF_HASH,id,0,u) //Attaches the caster to the ht
    call SaveUnitHandle(udg_EF_HASH,id,1,EF_CreateDummy(null,GetWidgetX(u),GetWidgetY(u),rad)) //Creates and attaches the dummy du the ht
    call SaveReal(udg_EF_HASH,id,2,cos) //attatch x direction
    call SaveReal(udg_EF_HASH,id,3,sin) //attatch y direction
    call SaveReal(udg_EF_HASH,id,4,dis) //attatch the distance (will be decreasd while moving)
    call SaveReal(udg_EF_HASH,id,5,dis) //attatch the distance agian as maximal distance (need for the parabola func)
    
    call TimerStart(t,EF_TimerIntervall(),true, function EF_MoveNormal) //Starts the whole shit
    
    set u = null
    set t = null

endfunction

function EF_CastCheck takes nothing returns boolean
    return GetSpellAbilityId() == EF_SID() //Checks if the Correct spell is casted
endfunction

//===========================================================================
function InitTrig_Eay_Fireball takes nothing returns nothing

    local trigger trig = CreateTrigger()
    local integer i = 0
    
    set udg_EF_HASH = InitHashtable() //Creates a hashtable
    call SaveGroupHandle(udg_EF_HASH,EF_HashKey(),0,CreateGroup()) //Creates an enum group in the 'cache'
    
    //Trigger register shit beyond this line
    call TriggerAddAction( trig, function EF_OnCastNormal )
    call TriggerAddCondition(trig, Filter( function EF_CastCheck))
    
    loop //Inlined a BJ (not really necassay but i don´t care really)
        exitwhen i == bj_MAX_PLAYER_SLOTS
        call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,null)
        set i = i +1
    endloop
    
    set trig = null
    
endfunction
This is almost like Blizzards Fireball spell (including parabola movement and absolute Z) but i could not resist to change it a bit. The fireball moves straight to its target and deals AoE damage on impact. I can change this spell to a homing version just hitting one target if you want. However i put some comments in there and if you want to know more or found bugs just tell me.
 

Attachments

  • Easy Fireball sample.w3x
    32 KB · Views: 52
Level 9
Joined
Aug 2, 2008
Messages
219
I made the homing version of this spell, but it behaves a bit different from the normal one. Unlike the normal one this has no AoE effect when the missile explodes, it hits only the targeted unit (The spell won´t be triggered if you just target the ground).
I remembered the original fireball spell does stun the target unit when it explodes so i decided to add that feature also. I wrote a little script (in vanilla Jass) which stuns a unit for you (without using any object editor stuff). Well just look inside the attatched map and if there are questions just ask. :D

~TNT
 

Attachments

  • Easy Fireball sample (homing version).w3x
    34.4 KB · Views: 105
Level 7
Joined
Jul 9, 2008
Messages
253
Very nice, there is just one thing that could be different and then it would be perfect. Which is the spawn point of the fireball, it seems that the fireball spawns somewhere random around the hero which looks a bit akward, so if you can change that it would be awesome. But besides that it's very nice :)
 
Level 9
Joined
Aug 2, 2008
Messages
219
Ahh ok that happens because i create the missile directly on the caster before i add the locust swarm ability. In that moment the missile still has pathing enabled and Warcraft3 can´t spawn the missile at the desired coordinates, so it will spawn it near to the caster. I thought that doesn´t matter really much since the missile would start moving immideatly and one would hardly notice this inaccurancy.

However that can be fixed easily by modifying the EF_CreateDummy func. I guess you can do that on your own.
JASS:
function EF_CreateDummy takes unit u, real x, real y, real f returns unit

    set u = CreateUnit(Player(0),EF_DID(),x,y,f*bj_RADTODEG) //Create a unit with the imported dummy model

    call SetUnitScale(u,EF_DummyScale(),EF_DummyScale(),EF_DummyScale()) //Set its size
    call SaveEffectHandle(udg_EF_HASH,EF_HashKey(),GetHandleId(u),AddSpecialEffectTarget(EF_DummyModel(),u,"origin"))
    //Attatch an effect to the unit; visually AND in the memory
    call UnitAddAbility(u,'Aloc') //Make the unit unpickable
    call UnitAddAbility(u,'Amrf') //Make the unit flyable
    call SetUnitPosition(u,x,y)  // <--------- THIS LINE WILL FIX IT

    return u //I create the unit on a parameter because they don´t need to be nulled when they are returned
    //You should use null if you pass values

endfunction
 
Status
Not open for further replies.
Top