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

[JASS] First JASS-spell ever (newb-question)

Status
Not open for further replies.
Level 28
Joined
Jan 26, 2007
Messages
4,789
Hi, I've been learning JASS for... 2 and a half days now and thought "hey, let's create a spell".
I didn't want to create anything fancy, so here is the idea:

Spell Idea:
When a certain AoE-ability is cast, every enemy unit inside that AoE will be hit by storm bolt.
As the level of the spell increases, the amount of targets hit by the spell will increase.
I've used dummies for the storm bolt and the AoE-spell is based of Blizzard.

Problem:
The problem is that the spell doesn't always work, I've tried it multiple times and got a 10% activation chance (I've tested the map twice, casted the spell 10 times in each run, in the first run the spell activated 2 times, in the second run it didn't activate at all - that makes 2/20, or 10% -.-).
Of course, I want it to activate whenever I want it, 10% isn't enough...


JASS:
function MS_C takes nothing returns boolean
return GetSpellAbilityId()=='A001'
endfunction

function MS_A takes nothing returns nothing
local group g
local integer i
local unit dummy
local location array TempLoc
local unit array Unit
local integer targets

set i = 0
set Unit[1] = GetSpellAbilityUnit()
set TempLoc[1] = GetUnitLoc(Unit[1])
set TempLoc[2] = GetSpellTargetLoc()
set targets = (2 + (GetUnitAbilityLevelSwapped('A001', Unit[1])))
set g = GetUnitsInRangeOfLocAll(800.00, TempLoc[2])

loop
      exitwhen i == targets
      set Unit[2] = FirstOfGroup(g)
      if IsUnitEnemy(Unit[2], GetOwningPlayer(Unit[1]))==true then
      call GroupRemoveUnit(g,Unit[2])
      set i = i + 1
      set dummy = CreateUnitAtLoc(GetOwningPlayer(Unit[1]), 'h000', GetUnitLoc(Unit[1]), 0.00)
      call IssueTargetOrderBJ(dummy, "thunderbolt", Unit[2])
      call UnitApplyTimedLifeBJ (1.50, 'BTLF', dummy)
      call UnitDamageTargetBJ( Unit[1], Unit[2], ( I2R(GetHeroStatBJ(bj_HEROSTAT_STR, Unit[1], true)) * 2.50 ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
      set dummy = null
      endif
endloop

set Unit[1] = null
set Unit[2] = null
set TempLoc[1] = null
set TempLoc[2] = null
set g = null
endfunction


function InitTrig_My_Spell takes nothing returns nothing
local trigger spell
set spell=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(spell, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(spell, Condition(function MS_C))
call TriggerAddAction(spell, function MS_A)
endfunction

Narrow the problem down:
I've created simple messages that occured at logically placed times in the trigger.
This is what I have found out:

  • Everything before the loop always works as expected
  • The loop itself only activates in 10% of the cases (when the actual spell works)
  • Everything after the loop does not activate if the loop isn't activated


Object Info:
  • Dummy (h000): 10k mana, 1000 mana regen - has the abilities "locust", "invulnerable", "Storm Bolt".
  • Blizzard (A001): 800 AoE, 900 cast range.
  • Storm Bolt (A000): 0 mana cost, 0 cooldown, 0 cast time, 2000 cast range.

Any help is appreciated.
Please do not begin shouting for obvious fails -.-
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,537
I cleaned your spell up a bit for you as far as syntax, but it's not gona fix anything (I think)

JASS:
function MS_C takes nothing returns boolean
	return GetSpellAbilityId()=='A001'
endfunction

function MS_A takes nothing returns nothing
	local group g
	local integer i=0
	local unit dummy
	local location array TempLoc
	local unit array Unit
	local integer targets=2+GetUnitAbilityLevelSwapped('A001',Unit[1])
	set Unit[1]=GetSpellAbilityUnit()
	set TempLoc[1]=GetUnitLoc(Unit[1])
	set TempLoc[2]=GetSpellTargetLoc()
	set g=GetUnitsInRangeOfLocAll(800.,TempLoc[2])
	loop
		exitwhen i==targets
		set Unit[2]=FirstOfGroup(g)
		if IsUnitEnemy(Unit[2],GetOwningPlayer(Unit[1])) then
		call GroupRemoveUnit(g,Unit[2])
		set i=i+1
		set dummy=CreateUnitAtLoc(GetOwningPlayer(Unit[1]),'h000',GetUnitLoc(Unit[1]),0.)
		call IssueTargetOrderBJ(dummy,"thunderbolt",Unit[2])
		call UnitApplyTimedLifeBJ(1.5,'BTLF',dummy)
		call UnitDamageTargetBJ(Unit[1],Unit[2],I2R(GetHeroStatBJ(bj_HEROSTAT_STR,Unit[1],true))*2.5,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL)
		set dummy=null
		endif
	endloop
	set Unit[1]=null
	set Unit[2]=null
	set TempLoc[1]=null
	set TempLoc[2]=null
	set g=null
endfunction

function InitTrig_My_Spell takes nothing returns nothing
	local trigger spell=CreateTrigger()
	call TriggerRegisterAnyUnitEventBJ(spell,EVENT_PLAYER_UNIT_SPELL_EFFECT)
	call TriggerAddCondition(spell,Condition(function MS_C))
	call TriggerAddAction(spell,function MS_A)
endfunction
 
Level 1
Joined
Sep 25, 2007
Messages
5
Judging from cast range and the AoE affect of the spell, the gap is only 100. You may have had your hero within the 800 range? If so, the loop will never end if the first unit of the group is not your enemy (could be your hero).

And using a boolexpr with the GetUnitsInRangeOfLocMatching for detecting only enemy units can replace the if/endif section inside the loop.

And
JASS:
exitwhen i==targets
to
JASS:
exitwhen i>=targets or FirstOfGroup(g)== null
will end the loop if there are no units in the group.
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
Judging from cast range and the AoE affect of the spell, the gap is only 100. You may have had your hero within the 800 range? If so, the loop will never end if the first unit of the group is not your enemy (could be your hero).

And using a boolexpr with the GetUnitsInRangeOfLocMatching for detecting only enemy units can replace the if/endif section inside the loop.

And
JASS:
exitwhen i==targets
to
JASS:
exitwhen i>=targets or FirstOfGroup(g)== null
will end the loop if there are no units in the group.

Thanks a lot, I have removed the unit from the group even if it wasn't an enemy (of course) and it worked.
The "exitwhen" is also a good improvement, I didn't realise that when writing the code.

You have deserved your very first rep ;)

Solved
 
Last edited:
It isn't working for me... I can start NewGen WE, but I can't test the maps and NewGen Warcraft gives a critical error.
(Something about wehack.lua that is a nil value...)

If you searched the JNGP thread, i'm sure you could solve your NewGen problem.

JNGP is essential if you want to make efficient code, faster, cleaner and easier.
 
Level 15
Joined
Dec 18, 2007
Messages
1,098
Oh, just remember this next time you code a spell (or this time), an array can contain about 1000++ values if my memory serves m correctly. Since it can store such a large amount of values, try not to use them unless absolutely neccesary as you are only using about 2 of the 1000+ values.
I would not recommend using arrays for a purpose as small as this. An array contains 8192 values, no more and no less. For something like this it's like killing a fly with a bazooka. (In other words, don't use arrays unless they are actually needed)
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
If you searched the JNGP thread, i'm sure you could solve your NewGen problem.

JNGP is essential if you want to make efficient code, faster, cleaner and easier.

Actually, the problem I have isn't in any FAQ, Troubleshooting, or anything else that contains a list of problems.
I've searched for it, but didn't find any positive result that could help me out...

Zack1996 said:
Oh, just remember this next time you code a spell (or this time), an array can contain about 1000++ values if my memory serves m correctly. Since it can store such a large amount of values, try not to use them unless absolutely neccesary as you are only using about 2 of the 1000+ values.
Thanks for the tip ;)
In GUI, it's normal to create arrays, otherwise you've got hundreds of global variables, but that's no problem when using locals, of course ;)
(I've been using GUI for a little over 4 years, so it's pretty hard to not think of GUI when coding).

Thanks for your replies, by the way :p
 
Status
Not open for further replies.
Top