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

Inferno Grenade v1.01

  • Like
Reactions: Deuterium
Ok, here comes my 4th JASS spell. This one is in BETA version for the time being. I need some feedback on how to improve, and if there are bugs, to point them out.
Or, you can just tell me did you like the spell :).

The caster lobs an inferno grenade at a targeted point. When the Grenade reaches it's destination, it will deal damage to nearby enemies and split itself into 8 small flames. Small flames deal half the damage the main grenade does.


//
JASS:
//***************************************************************************************************
//* ========================   
//* Inferno Grenade ver.1.00 
//* ========================  
//* Made by Shdow89 
//* 
//*
//* How to implement:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* 1. Copy the spell "Inferno Grenade" to your map.
//*      
//* 2. Copy dummy unit "Main Grenade" and "Child Grenade" to your map
//*
//* 3, Make a global variable of type hashtable and name it Hash2
//*
//* 4. Copy this trigger and the entire costu script section to your map
//*
//* 5. Go down through constants, change rawcodes of the spell and dummy units.  
//*
//* Choosable/Effects:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯   
//*    Go down through constant function and change to what you like. Units affected are:
//*    Enemy Units, Non-Magic immune, Non-Structures and living. This can be changed in the
//*    costum script section of the map.
//*    Change the models to "Main Grenade" and "Child Grenade" dummy units to grenade type
//*    you like.
//*
//* Editor's Word: 
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
//*    My fourth JASS[JESP] spell. It's currently a beta version, so post some feedback. Post if you
//*    found any bugs, improvement ideas, etc. Everything is wellcome.
//*
//* Spells Action:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
//*    The caster lobs an inferno grenade at a target point. When the Grenade reaches it's point
//*    it will deal damage to nearby enemy units and split itself into small flames, that fly to
//*    random location, dealing damage to nearby units when they reach their location.
//*    Small flames deal half the main grenade damage.        
//*
//* Credits:
//* ¯¯¯¯¯¯¯¯
//*    Shadow1500 for his Jump Parabola.
//*    The_Reborn_Devil for pointing out the mistakes.
//*   
//*
//*************************************************************************************************
constant function Inferno_GrenadeID takes nothing returns integer
    return 'A001' //Inferno Grenade ability rawcode. Change to yours!
endfunction

constant function Storm_CrowI2D takes nothing returns integer
    return 'Arav'//Strom Crow ability rawcode. If you haven't touch this spell in your map, don't change it. If you did, change it to your rawcode.
endfunction

constant function Gr_Explode_SFX takes nothing returns string
    return "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl" //!! Main Grenade death special effect.
endfunction

constant function Gr_Explode_Child_SFX takes nothing returns string
    return "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"//!! Child Grenade death SFX.
endfunction

constant function Affected_Unit_SFX takes nothing returns string
    return "Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl" //!! SFX For enemy units that receive damage by the blast.
endfunction

constant function Grenade_DummyID takes nothing returns integer
    return 'h001' // Main Grenade dummy unit rawcode. Change to yours.
endfunction

constant function Grenade_ChildDummy_ID takes nothing returns integer
    return 'h003' // Child Grenade dummy unit rawcode. Change to yours.
endfunction

constant function Grenade_Moving_Speed takes nothing returns real
    return 15.0 // Grenade moving speed, both main and child
endfunction

constant function Greande_Max_Height takes nothing returns real
    return 500.0 // Main Grenade max height reached. Consider this as a missile arc.
endfunction

constant function Grenade_Radius takes nothing returns real
    return 300.0 // Main Grenade damage radius
endfunction

constant function Child_Grenade_Radius takes nothing returns real
    return 200.0 // Child Grenade damage radius
endfunction 

constant function Damage_Grenade takes integer i returns real
    return 50.00*i // Damage dealt by main grenade. Half of this is dealt with child grenades.
endfunction   

constant function Child_Grenade_Height takes nothing returns real
    return 200.0 // Child Grenade max reached height.
endfunction

constant function Gr_Timer_Loop takes nothing returns real
    return 0.03 // How fast timer repets itself. I don't advise touching this, if you are unsure.
endfunction

constant function Child_Grenade_Number takes nothing returns integer
    return 8 // How many small grenades(flames) are spawned.
endfunction

//Done with Constants. Don't touch anything below, if you are unsure.
//==================Shadow1500's Parabola======================================================================================
function JumpParabola2 takes real dist, real maxdist,real maxheight returns real
    local real t = (dist*2)/maxdist-1
    return (-t*t+1)*maxheight
endfunction
//========================================================================================================
//Condition Trigger
function Trig_Inferno_Grenade_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Inferno_GrenadeID()
endfunction
//==================MOVING GRENADE(S)==================================================================================
function Child_Grenade_Move takes nothing returns nothing
 local timer t2 = GetExpiredTimer()
 
 local unit timmy = LoadUnitHandle(udg_Hash2, GetHandleId(t2), 10)
 local unit damager = LoadUnitHandle(udg_Hash2, GetHandleId(t2), 15)
 
//Settings for jump, move, and my empty wallet.
 local real mX              = LoadReal(udg_Hash2, GetHandleId(t2), 11)
 local real mY              = LoadReal(udg_Hash2, GetHandleId(t2), 12)
 local real mHeight         = Child_Grenade_Height()
 local real mDist           = LoadReal(udg_Hash2, GetHandleId(t2), 13)
 local real curDist         = SquareRoot((GetUnitX(timmy) - mX)*(GetUnitX(timmy) - mX)+(GetUnitY(timmy) - mY)*(GetUnitY(timmy)- mY))
 local real tweety          = JumpParabola2(curDist, mDist, mHeight)
 local real angle           = GetUnitFacing(timmy)/(180.0/bj_PI)
 local real marchX          = GetUnitX(timmy) + Grenade_Moving_Speed() * Cos(angle)
 local real marchY          = GetUnitY(timmy) + Grenade_Moving_Speed() * Sin(angle)
 
 if curDist <= Grenade_Moving_Speed() then 
  
  call PauseTimer(t2)
  call DestroyTimer(t2)
  call FlushChildHashtable(udg_Hash2, GetHandleId(t2))
  set t2 = null
  call DestroyEffect(AddSpecialEffect(Gr_Explode_Child_SFX(), GetUnitX(timmy), GetUnitY(timmy)))
  call DamageEnemiesArea(damager,Child_Grenade_Radius(),GetUnitX(timmy),GetUnitY(timmy),Damage_Grenade(GetUnitAbilityLevel(damager,Inferno_GrenadeID()))/2,true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS,Affected_Unit_SFX()) 
  call RemoveUnit(timmy)
  set timmy = null
  set damager = null
  
 else  
 
  call SetUnitPosition(timmy, marchX, marchY)
  call SetUnitFlyHeight(timmy, tweety, 0)
  set damager = null
  set timmy = null
  set t2 = null
  
endif  
endfunction


//==============MAIN GRENADE MOVE===========================================================================================
function Grenade_Fly takes nothing returns nothing
 local timer t = GetExpiredTimer()
 local timer t2 = null
 
 local unit dummy = LoadUnitHandle(udg_Hash2, GetHandleId(t), 1)
 local unit damager = LoadUnitHandle(udg_Hash2, GetHandleId(t), 5)
 
 local real x = LoadReal(udg_Hash2, GetHandleId(t), 2)
 local real y = LoadReal(udg_Hash2, GetHandleId(t), 3)

//..................Settings for Child Grenades.................................................
 local unit n_child = null
 local integer count = 0
 local integer n_angle = 0
 local real n_dist = 0.00
 local real mX = 0.0
 local real mY = 0.0
//............................................................................................. 
 
 
//Setting values for the jump parabola and grenade move. 
 local real maxHeight          = Greande_Max_Height() //Unit max Height achived, configurable in constants.
 local real maxDist            = LoadReal(udg_Hash2, GetHandleId(t), 4) //Loaded distance between start location and target location.
 local real cur_dist           = SquareRoot((GetUnitX(dummy) - x)*(GetUnitX(dummy) - x)+(GetUnitY(dummy) - y)*(GetUnitY(dummy)-y))//Current distance between target location and dummy unit.
 local real fly                = JumpParabola2(cur_dist, maxDist, maxHeight)//Using Shadow1500 jump parabola
 local real angle              = Atan2(y - GetUnitY(dummy), x - GetUnitX(dummy))//Moving angle
 local real moveX              = GetUnitX(dummy) + Grenade_Moving_Speed() * Cos(angle)//PolarProjectionX
 local real moveY              = GetUnitY(dummy) + Grenade_Moving_Speed() * Sin(angle)//PolarProjectionY
 
 if cur_dist <= Grenade_Moving_Speed() then
 
  call PauseTimer(t)
  call DestroyTimer(t)
  call FlushChildHashtable(udg_Hash2, GetHandleId(t))
  set t = null
  call DestroyEffect(AddSpecialEffect(Gr_Explode_SFX(), GetUnitX(dummy), GetUnitY(dummy)))
  call DamageEnemiesArea(damager,Grenade_Radius(),GetUnitX(dummy),GetUnitY(dummy),Damage_Grenade(GetUnitAbilityLevel(damager,Inferno_GrenadeID())),true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS,Affected_Unit_SFX())   

//Child grenades main preset actions  
    set n_angle  = 360/Child_Grenade_Number()
  loop
    set count = count + 1
  exitwhen count > Child_Grenade_Number()
    set t2  = CreateTimer()
    set n_child = CreateUnit(GetOwningPlayer(dummy),Grenade_ChildDummy_ID(), GetUnitX(dummy) + 5.0 * Cos(I2R(n_angle*count)), GetUnitY(dummy) + 5.0 * Sin(I2R(n_angle*count)), I2R(n_angle*count))
    
    call UnitAddAbility(n_child, Storm_CrowI2D())
    call UnitRemoveAbility(n_child, Storm_CrowI2D())
    
    set n_dist = GetRandomReal(200.0, 600.0)
    set mX = GetUnitX(n_child) + n_dist * Cos(GetUnitFacing(n_child)/(180.0/bj_PI))
    set mY = GetUnitY(n_child) + n_dist * Sin(GetUnitFacing(n_child)/(180.0/bj_PI))
               
    call SaveUnitHandle(udg_Hash2, GetHandleId(t2), 10, n_child) 
    call SaveReal(udg_Hash2, GetHandleId(t2), 11, mX)
    call SaveReal(udg_Hash2, GetHandleId(t2), 12, mY)
    call SaveReal(udg_Hash2, GetHandleId(t2), 13, n_dist)
    call SaveUnitHandle(udg_Hash2, GetHandleId(t2), 15, damager)
    call TimerStart(t2, Gr_Timer_Loop(), true, function Child_Grenade_Move)
    set t2 = null
  endloop
  call RemoveUnit(dummy)
  set t2 = null
  set n_child = null
  set damager = null
  set dummy = null  
 else
  
  call SetUnitPosition(dummy, moveX, moveY)
  call SetUnitFlyHeight(dummy, fly, 0)
  set dummy = null
  set damager = null
  set t2 = null
  set t = null
      
 endif
endfunction    

//=================================ACTION TRIGGER======================================================================================================
function Trig_Inferno_Grenade_Actions takes nothing returns nothing
 local timer t = CreateTimer()

 local unit cast = GetTriggerUnit()
 
 local real x = GetSpellTargetX()
 local real y = GetSpellTargetY()
 
 local real angle = Atan2(y - GetUnitY(cast), x - GetUnitX(cast))
 
 local unit dummy = CreateUnit(GetOwningPlayer(cast), Grenade_DummyID(), GetUnitX(cast)+20.0*Cos(angle), GetUnitY(cast)+20.0*Sin(angle), angle)
 local real maxDist = SquareRoot((x - GetUnitX(dummy))*(x - GetUnitX(dummy))+(y - GetUnitY(dummy))*(y - GetUnitY(dummy)))
 
 call UnitAddAbility(dummy, Storm_CrowI2D())
 call UnitRemoveAbility(dummy, Storm_CrowI2D()) 
 
 call SaveUnitHandle(udg_Hash2, GetHandleId(t), 1, dummy)
 call SaveReal(udg_Hash2, GetHandleId(t), 2, x)
 call SaveReal(udg_Hash2, GetHandleId(t), 3, y)
 call SaveReal(udg_Hash2, GetHandleId(t), 4, maxDist)
 call SaveUnitHandle(udg_Hash2, GetHandleId(t), 5, cast)
 
 call TimerStart(t, Gr_Timer_Loop(), true, function Grenade_Fly)
 
 set cast = null
 set t = null   
endfunction

//==================INIT TRIGGER=======================================================================================
function InitTrig_Inferno_Grenade takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer guza

    set guza = 0
    loop
        call TriggerRegisterPlayerUnitEvent(trig, Player(guza), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set guza = guza + 1
        exitwhen guza == 16
    endloop

    call TriggerAddCondition(trig, Condition(function Trig_Inferno_Grenade_Conditions))
    call TriggerAddAction(trig, function Trig_Inferno_Grenade_Actions)
    
    call Preload(Gr_Explode_SFX())
    call Preload(Gr_Explode_Child_SFX())
    call Preload(Affected_Unit_SFX())
    call PreloadStart()

    set udg_Hash2 = InitHashtable()
    set trig = null
endfunction

The spell is MUI and leak-less. You can edit levels, damage, number of spawns, speed, etc. For complete listing see spell code.


To Shadow1500 for his JumpParabola
To The_Reborn_Devil for pointing out the mistakes
You for dling the map :).


Updated to alpha version: 1.00.

Changelog 1.01:

- Nulled the timers ( hopefully, the right way now :))
- Added new (fixed) code





Keywords:
Grenade, Inferno, Lob, Fly, Flames, Spawn, Split
Contents

Just another Warcraft III map (Map)

Reviews
18:03, 20th Sep 2009 The_Reborn_Devil: Triggering: Triggering looks fine and there are no leaks anymore. Eye-Candy: The eye-candy is nice and the effects fits perfectly. Idea: It's a nice idea and as far as I know it's pretty original...

Moderator

M

Moderator

18:03, 20th Sep 2009
The_Reborn_Devil:


Triggering:
Triggering looks fine and there are no leaks anymore.
Eye-Candy:
The eye-candy is nice and the effects fits perfectly.
Idea:
It's a nice idea and as far as I know it's pretty original though I have seen spells that are similar to this one.
Tooltip:
The tooltip is good, but you got some grammatical errors, though that's just some trivial problems.
Implementation:
It's easy to implement as it has a manual that guides the user.
Overall:
It looks nice and it's certainly something that someone would use.

Spell Approved.
I give this spell the rating: Useful.

If there's something you feel that's incorrect just PM me.
Remember to have a good reason for why you feel it's incorrect and I might review it again :)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
oh here's what's going on

turn off your antivirus,
download the latest JNGP v5d,
install it...

then download the latest jasshelper 0.9.K,
wherever you downloaded the JNGP, replace the jasshelper folder there with the one you downloaded (dont delete the original cause there are some needed files, just OVERWRITE)

open NewGen WE, test it out... it works?

turn on antivirus :p
 
Level 14
Joined
Jan 15, 2007
Messages
349
*cough* FlushChildHashtable *cough* ... also please change "destintaion" to destination in your tooltip. Hmm... using some external systems would be also good... something like timer recycler. In the case that you are not using vJass you could make one by yourself. Ah I nearly forgot this one... you shoud set some "t2" locals to null after usage, like you should do it with every local handle...
 
Level 8
Joined
Jun 18, 2007
Messages
214
*cough* FlushChildHashtable *cough* ... also please change "destintaion" to destination in your tooltip. Hmm... using some external systems would be also good... something like timer recycler. In the case that you are not using vJass you could make one by yourself. Ah I nearly forgot this one... you shoud set some "t2" locals to null after usage, like you should do it with every local handle...

Hmm... truth to be told, since KaTTaNa's handles are no longer working, I never quite completely understood hashtables, and I didn't know they have to be recycled. So, thank you for pointing out that I need to flush them.
Now, about "t2": what do you mean? Do you mean that I need to: set timer t2 = null? Destroying them is not enough? And, I don't know what a timer recycler " is. I'm only using DamageEnemiesArea as external system (it's in custom script section), that I made.
Oh, I nearly forgot "destintaion", I hope that's a joke xD.

EDIT: I also forgot to mention that is a great honor having you comment my spell, since I learned quite a bit of JASS from your resources :). Old ones that is, lol.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I don't think this qualifies as necropost, since it's a spell... but i'll comment anyway.

I love the spell, I'm gonna use it though there are some things that bothers me.

- If it's thrown too near to the caster, it's really fast. If it's thrown far away, it looks slow-motion.

- The grenade should damage the caster if it's thrown too near :p (A bit more real) OR The grenade should have a minimum cast distance (About 200 from the caster)

- May sound a bit noob, but I can't find where to customize damage. It says 50.00*i, but I can't find 'i'. Tooptip says Lvl1 100, Lvl2 200, lvl3 300... But I can't find any reference value to change... =/

- Distance Child Grenades travel to their explosion points should be more easy to customize, I had to check through the code to find it :p

- The bomb is thrown from the models feet... Is it Soccer Bomb or something? xD Increasing the 'Z' to around 10 should make it a look bit more -hand-thrown-
 
Level 6
Joined
Aug 14, 2016
Messages
174
Great spell but...
When i'm saving my maps, has error APPCRASH, fix please.
I trying to saving map by:
Caculator Shadow And Save Map.
Press X And Yes To Save Map & Turn Off World Editor.
Please Help Us :(
 
Top