You are that guy? great, now youj will feel bashed by me again.
I decided to start comenting about spells but just the technical side, your spells are good (well a pair not that much but the rest is good enough)
Next is something I wrote at home after reading your triggers (anti BJ functions and memory leaks are important to prevent lag):
CryptLordSpellSet
=================
Introduction:
- First of all I want to say thanks for this map, because It is the best example I've ever seem of what not to do when making JASS enhanced spells, people often think that making a spell in JASS means it is coded better than in GUI, but that's not the case this time, why? Because It doesn't use any of JASS' advantages besides handle variables.
Don't take it wrong, the spells are fine, but you really need to Learn JASS as in "Learn JASS" not just use JASS.
General:
- Excesive Usage of BJ functions that should never be used, for example used GetUnitAbilityLevelSwapped (worthless swap function) instead of GetUnitAbilityLevel (fast, clean native).
- I am completelly sure, you ARE not aware that functions may have arguments. Proof:
function GetLevelDemage takes nothing returns real
local real DemageAmount
// LEVEL 1
if ( GetUnitAbilityLevelSwapped('A000', GetSpellAbilityUnit()) == 1 ) then
set DemageAmount = 200.00
return DemageAmount
// LEVEL 2
elseif ( GetUnitAbilityLevelSwapped('A000', GetSpellAbilityUnit()) == 2 ) then
set DemageAmount = 400.00
return DemageAmount
// LEVEL 3
elseif ( GetUnitAbilityLevelSwapped('A000', GetSpellAbilityUnit()) == 3 ) then
set DemageAmount = 600.00
return DemageAmount
// TO ADD MORE LEVELS CONTINUE FROM HERE
else
set DemageAmount = 0.00
return DemageAmount
endif
endfunction
Could have been replaced with:
function GetLevelDemage takes integer level returns real
return (level*200)
endfunction
And just call GetLevelDemage( - level of the ability - )
- VERY GENERIC function names inside spells scripts. For example a spell has GetLevelDemage , the other spell has GetLevelAbilityDemage. Is this a problem? Yes, of course it is a problem, please if a function is only used by a single spell include the spell's name on the function's name. And if a function is used by more than one spell then make it an utility function that goes to the map's header.
- Completelly Ignores the fact that SetUnitAbilityLevel exists. Proof:
function GetLevelAbility takes nothing returns integer
local integer Disase
// Level 1
if ( GetUnitAbilityLevelSwapped('A004', GetSpellAbilityUnit()) == 1 ) then
set Disase = 'A005'
return Disase
// Level 2
elseif ( GetUnitAbilityLevelSwapped('A004', GetSpellAbilityUnit()) == 2 ) then
set Disase = 'A006'
return Disase
// Level 3
elseif ( GetUnitAbilityLevelSwapped('A004', GetSpellAbilityUnit()) == 3 ) then
set Disase = 'A007'
return Disase
// TO ADD MORE LEVELS CONTINUE FROM HERE
else
return 0
endif
endfunction
Uses an ability for each level instead of one dummy ability for all levels and just change the level of that ability by convenience.
- Leaks, thousands of memory leaks: It was just the right time for wc3c to be completelly away and Cubasis' tutorial lost, I won't ellaborate, but things like call SetUnitPositionLoc( Mover, PolarProjectionBJ(GetUnitLoc(Mover), 20.00, Angle) ) have 2 major leaks in total, please do some researches and fix this.
- GUI like conditions! I always hated the JASS generated by GUI and your conditions look like that:
function StrikeDemageConditions takes unit Caster, unit Target returns boolean
if (not ( IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) == true ) ) then
set Caster = null
set Target = null
return false
endif
if (not ( IsUnitType(Target, UNIT_TYPE_STRUCTURE) == false ) ) then
set Caster = null
set Target = null
return false
endif
if (not ( IsUnitAliveBJ(Target) == true ) ) then
set Caster = null
set Target = null
return false
endif
if (not ( IsUnitType(Target, UNIT_TYPE_MAGIC_IMMUNE) == false ) ) then
set Caster = null
set Target = null
return false
endif
if (not ( Target != Caster ) ) then
set Caster = null
set Target = null
return false
endif
set Caster = null
set Target = null
return true
endfunction
first of all, ==true and ==false are signs of not knowing anything about how JASS' booleans work.
Second, this is my version of that condition function, by the way setting things to null is not needed by arguments (BY the way, this means you actually know how to use arguments! How come you have those ugly Demeger functions then?
function StrikeDemageConditions takes unit Caster, unit Target returns boolean
return (Target != Caster) and ( IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) ) and not(IsUnitType(Target, UNIT_TYPE_STRUCTURE)) and not(IsUnitType(u,UNIT_TYPE_DEAD)) and not(IsUnitType(Target, UNIT_TYPE_MAGIC_IMMUNE))
endfunction
Even if you wanted it to be easier to read / change, there are better ways thatn GUI like ways:
function StrikeDemageConditions takes unit Caster, unit Target returns boolean
loop
exitwhen (Caster==Target) or (IsUnitType(Target,UNIT_TYPE_DEAD) //Fundamental ones
exitwhen not(IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) ) //Only Enemies
exitwhen IsUnitType(Target,UNIT_TYPE_STRUCTURE) or IsUnitType(Target,UNIT_TYPE_MAGIC_IMMUNE) //Immune types
return false
endloop
return false
endfunction
Now how it takes like 20% of the text needed by your function.
- 0 anti rawcode change help. You have to change the same rawcode thousands of times literally.
- I really have to say something, If a spell has bugs and you are aware of them you should really fix the bugs instead of release the spell.
Specific:Bloody Pile:
- It has a trigger with an order event in pseudo JASS. It has weird things like:
call SetUnitMoveSpeed( Caster, 1000.00 )
And Later:
call SetUnitMoveSpeed( Caster, GetUnitDefaultMoveSpeed(Caster) )
This is awful because:
* Unit Speed can't be higher than 522, so this thing is worthless.
* Setting the unit's speed to its default will make it lose any speed bonus by items, and will generally screw everything if it was influenced by a speed buff/debuff-
* I actually advice everybody against using SetUnitMoveSpeed at all. If you want to increase a unit's speed use an ability that's the only safe way to do it.
- "Disase Flap"
Please, USE a Loop! please! too much repetive code for me
- "Air Strike"
First spell of this kind that actually uses a dummy flying version of the hero. Be aware that if you have a hero, add the hero Medivh's raven form using a trigger, then remove that ability from the hero. The hero becomes able to have a flying height, and you don't have to worry about it getting stuck later.
- Seriously about loops:
"I newer trust loops If you have something better use that instead of a loop"
I have something better, it is called dark magic, yes you use a spell over your CPU and done! something better than loops.
Seriously loops are fine, there is nothing wrong with loops, use loops whenever it is needed.
"You may noticed some codes repeating themselves. I don't know what is wrong with for loop it does not works properly. i have tested the for loop integer with texts it goes like 1,2,3,4,4,2,1(and some other combinations) it sometimes loops for 10 times sometimes only 4 thats why i made it like that."
First of all, never use GUI's for loop, it uses a GLOBAL variable for the integer, so probably after the waits that variable just got changed and that's the reason of those weird numbers, use a local integer variable and done!
function Trig_Disase_Flap_Actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location point = GetSpellTargetLoc()
local integer Level = GetLevelAbility()
local integer i=1
call TriggerSleepAction( 0.02 )
call PauseUnitBJ( true, caster ) //Use PauseUnit(caster,true) please
call SetUnitAnimation( caster, "Spell Channel" )
call SetUnitFacingTimed( caster, ( GetUnitFacing(caster) - 180.00 ), 0 )
call TriggerSleepAction( 0.02 )
call PauseUnitBJ( true, caster ) //Why pause the unit again? I don't get it
loop
call CreateEffects( caster, point, Level )
exitwhen i>7
call TriggerSleepAction( 0.30 )
set i=i+1
endloop
call TriggerSleepAction( 0.02 )
call ResetUnitAnimation( caster )
call PauseUnitBJ( false, caster ) //Use PauseUnit(caster,false)
set caster = null
set point = null
endfunction
By the way, TriggerSleepAction has the same results with values lower than 0.2 it doesn't matter what you use, the wait is always the lowest quantity of time you can make it wait