/////////////////////////////////////////////////////////////////////==============================================================// LIGHTNINGS 1.5// eubz//============================================================== ////This is a very simple spell but could be useful for maps.////THANKS TO:// Luorax, iAyanami, and Adiktuz//==============================================================//WHAT THIS SPELL DO://Creates lightnings around a target that deals damage//to its sorrounding units which are enemies of the caster.//Level 1 - 50 damage, 250 AoE//Level 2 - 100 damage, 500 AoE//Level 3 - 150 damage, 750 AoE//==============================================================////HOW TO IMPORT://1. copy all these codes into your map OR copy the trigger labeled Lightning.//2. create an ability for this spell or just copy the custom ability in this map for this spell.////==============================================================/////////////////////////////////////////////////////////////////////////////////////==============================================================library Lightnings initializer Init
//==========================================================//THE GLOBALS BELOW CAN BE CONFIGURED=======================globalsprivateconstantreal DAMAGE =50//the damage dealt (you can set this)privateconstantreal AREA_OF_EFFECT =250//how large is the lightning AoE(you can set this)privateconstantstring SFX ="Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"//the SFX model pathprivateconstantinteger ABIL_CODE ='A001'//the ability IDprivateconstantattacktype A_TYPE =ATTACK_TYPE_NORMALprivateconstantdamagetype D_TYPE =DAMAGE_TYPE_NORMALendglobals//END OF CONFIGURATIONS======================================constantnative UnitAlive takesunit id returnsbooleanprivateconstantfunction areaEffect takesinteger level returnsrealreturn AREA_OF_EFFECT*level
endfunctionprivateconstantfunction damageInflict takesinteger level returnsrealreturn DAMAGE*level
endfunctionprivateconstantfunction GetFilter takesunit caster,unit u returnsbooleanreturnIsUnitEnemy((u),GetOwningPlayer(caster))/*
*/and UnitAlive(u)/*
*/andnotIsUnitType((u),UNIT_TYPE_STRUCTURE)/*
*/andnotIsUnitType((u),UNIT_TYPE_MAGIC_IMMUNE)endfunction//============================================================================privatefunction lightningsConditions takesnothingreturnsbooleanreturnGetSpellAbilityId()== ABIL_CODE
endfunction//===========================================================================//from here, we'll start the real lightning spellglobalsprivategroup g =bj_lastCreatedGroupendglobalsprivatefunction lightningActions takesnothingreturnsnothinglocalreal damage
localreal d
localunit caster
localunit target
localreal x
localreal y
localunit u
localinteger level
set caster =GetTriggerUnit()set target =GetSpellTargetUnit()set x =GetUnitX(target)set y =GetUnitY(target)set level =GetUnitAbilityLevel(caster, ABIL_CODE)set d = areaEffect(level)set damage = damageInflict(level)callGroupEnumUnitsInRange(g, x, y, d,null)loopset u =FirstOfGroup(g)exitwhen u ==nullif GetFilter(caster, u)thencallUnitDamageTarget(caster,u,damage,true,false,A_TYPE,D_TYPE,null)endifcallGroupRemoveUnit(g, u)endloopset caster =nullset target =nullif d >0thenloopset d = d -10exitwhen d <0callDestroyEffect(AddSpecialEffect(SFX,x+d*Cos(d+50*bj_DEGTORAD),y+d*Sin(d+50*bj_DEGTORAD)))endloopendifendfunctionprivatefunction Init takesnothingreturnsnothinglocaltrigger L
set L =CreateTrigger()callTriggerRegisterAnyUnitEventBJ( L,EVENT_PLAYER_UNIT_SPELL_EFFECT)callTriggerAddCondition( L,Condition(function lightningsConditions ))callTriggerAddAction( L,function lightningActions )endfunctionendlibrary//====================================================================//Code by eubz//
Rating - 4.33 (3 votes)
(Hover and click)
Moderator Comments
Useful
11th June 2012
The Reborn Devil:
The code is okay now, but I still feel the
if d >0then
should be moved or just removed entirely. This is because it's actually redundant in its current position, due to the exit condition in the loop. Anyway, it meets the criteria, so it's approved.
Status: Approved
Rating: Useful
previous
9th June 2012
The Reborn Devil:
It seems most issues have been dealt with, although I'm still stumped by this:
if d >0then
If the AOE being less than 0 really is a possibility wouldn't it be better to have that check further up? Not too far up you have this line:
callGroupEnumUnitsInRange(g, x, y, d,null)
which wouldn't work afaik if the AOE (the variable d) is less than 0.
There's also another issue I didn't spot before. Your effect loop could potentially run indefinitely if this condition is not met:
d ==0
which could easily happen if the AOE is not divisible by 10 (which is the amount you decrement it by). Simple example would be if d is 5. Decrementing it by 10 would result in -5, which is not 0. Changing the exit condition to
d <0
would easily solve that.
You also forgot to null "target", which is necessary now that it's a local.
previous
8th June 2012
The Reborn Devil:
The first I notice is that the names of these constants could be better:
At first glance it may seem that A_CODE and A_TYPE are somehow connected, while they're not. Having understandable names, especially for constants is key.
You may want to move some of the functions around a bit to help people find what they need to easily customize things. Something like this:
Jass:
globalsprivateconstantreal DAMAGE =50//the damage dealt (you can set this)privateconstantreal AREA_OF_EFFECT =250//how large is the lightning AoE(you can set this)privateconstantstring SFX ="Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"//the SFX model pathprivateconstantinteger A_CODE ='A001'//the ability IDprivateconstantattacktype A_TYPE =ATTACK_TYPE_NORMALprivateconstantdamagetype D_TYPE =DAMAGE_TYPE_NORMALendglobalsprivateconstantfunction areaEffect takesinteger level returnsrealreturn AREA_OF_EFFECT*level
endfunctionprivateconstantfunction damageInflict takesinteger level returnsrealreturn DAMAGE*level
endfunctionprivateconstantfunction GetFilter takesunit caster,unit u returnsbooleanreturnIsUnitEnemy((u),GetOwningPlayer(caster))/*
*/and UnitAlive(u)/*
*/andnotIsUnitType((u),UNIT_TYPE_STRUCTURE)/*
*/andnotIsUnitType((u),UNIT_TYPE_MAGIC_IMMUNE)endfunction//The rest of the spell continues from here
Do you really need these to be globals:
Jass:
privateunit caster
privateunit target
privatereal d
privatereal damage
?
Also, this line:
set angle =0
which is near the end of "lightningActions" is unnecessary.
Last, but not least:
Jass:
if d >=d then<code>endif
..Wat? Maybe I'm incredibly stupid, but seems to me that this if-then does absolutely nothing. The variable "d" is of course equal to itself.
Other than that it seems the issues Bribe pointed out have been solved, and as soon as you've fixed the points I've listed, it should be ready for approval.
previous
26 May 2012
Bribe: You are nulling the locals now but for some reason you aren't removing them, so you have a handle leak x2 in that function now.
You should be using coordinates instead of locations if you're using JASS, and also should be using a global group instead of a dynamic group for this.
previous
21st May 2012
Bribe: Please analyze the highlighted changes I suggest for your spell:
Jass:
//////////////////////////////////////////////////////////////////////////////// LIGHTNING 1.1 //// ////This is a very simple spell but could be useful for maps. ////What you will just do is to copy all these codes into your map and then ////create an ability for this. I recommend you use Acid Bomb as base ability ////==========================================================================///////////////////////////////////////////////////////////////////////////////library LightningSpellinitializer Initnative UnitAlive takesunit id returnsboolean//==========================================================privatefunction Conditions takesnothingreturnsbooleanreturnGetSpellAbilityId()=='A001'endfunction//==========================================================globals//THE GLOBALS BELOW CAN BE CONFIGUREDprivatereal dam =50//the damage dealt (you can set this)privatereal AoE =250//how large is the lightning AoE(you can set this)privatestring o ="origin"//you might want to configure the attachment pointprivatestring s ="Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"//the SFX model pathprivateinteger a_code ='A001'//the ability ID//END OF CONFIGURATIONSprivateunit caster
privateunit target
privatelocation loc
privatereal d
privatereal damage
endglobals//==============================================================//Don't touch anything belowprivatefunction Actions takesnothingreturnsnothinglocalreal angle =0localgroup g =CreateGroup()localunit u
localreal x=GetSpellTargetX()localreal y=GetSpellTargetY()set caster =GetTriggerUnit()set target =GetSpellTargetUnit()set loc =GetUnitLoc(target)set d = AoE*GetUnitAbilityLevel(caster,a_code)set damage = dam*GetUnitAbilityLevel(caster,a_code)//==============================================================//The damage partcallGroupEnumUnitsInRangeOfLoc(g,loc,d,null)loopset u =FirstOfGroup(g)exitwhen u ==nullifIsUnitEnemy(u,GetOwningPlayer(caster))andUnitAlive(u)andnotIsUnitType(u,UNIT_TYPE_STRUCTURE)andnotIsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)thencallUnitDamageTarget(caster,u,damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)endifcallGroupRemoveUnit(g, u)endloop//==============================================================//For some SFX---------------if d >=d thenloopset d = d -10set angle = angle +50exitwhen d ==0callDestroyEffect(AddSpecialEffect(s,x+d*Cos(angle*bj_DEGTORAD),y+d*Sin(angle*bj_DEGTORAD)))endloopset angle =0endifcallRemoveLocation(loc)set loc =nullcallDestroyGroup(g)set g =nullendfunction//===========================================================================privatefunction Init takesnothingreturnsnothinglocaltrigger L
set L =CreateTrigger()callTriggerRegisterAnyUnitEventBJ( L,EVENT_PLAYER_UNIT_SPELL_EFFECT)callTriggerAddCondition( L,Condition(function Lightnings_Conditions ))callTriggerAddAction( L,function Lightning_Actions )endfunctionendlibrary//====================================================================//Code by eubz//
Even still, this is not exactly ready for approval. Creation/destruction of groups where unnecessary, creation/destruction of locations where unnecessary, in these cases, respectively, use a global group and use coordinates.
I wonder if I have to still remove the location here.
Yes, you have; locations are bad in general, especially combined with a polar projection call (which is one of the worst BJ's I know about; there's a reason why BJ's were named after "Bad Job" [/jk])
it uses globals though so its not plain jass... XD...
maybe you should just combine the conditions and actions and just put the spell id as a global so that the user can still change it without going deep into the code...
and I would recommend channel as a base ability as that spell was made for triggered spells...
also, you have a group leak... it would be better to just use one global group instead of creating a local one...
and for better configuration, the filter could be made into a separate function placed at the top of the other codes so the user can easily modify the units that can be hit by this...
the damage formula and the AoE formula should also be placed as a separate function for better configurability...
and the configurable globals should come before the non-configurable ones...
This is actually vjass category not jass so...hmmm
I noticed that a lot of vJASS spells is in JASS category,well, that's wrong!
Many times I have reviewed both categories,mann there is no order,everything is mixed up.
Maybe some people here think that vjass and jass one and the same,but simply not,the differences are obvious.
I think the moderators should pay attention to such things