• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Missplaced effect

Status
Not open for further replies.
Hi guys. I have a problem about my penguin ability =(
Well, thing is, if I stop casting the ability everything goes fine ... however, if i kill my stupid penguin before the time, everything goes as planned... except for the part that the explosion effect is created in the wrong place !! I don't know why this happens ... please help !

JASS:
scope StupidPenguin initializer Init
   
   //don't change
   private struct Mystruct
        unit caster
        integer level
        unit penguin
        real currentScale 
        timer t 
        real grow
        integer damage
        trigger end 
        triggeraction endAction
        triggercondition endCondition
        
         static method create takes nothing returns Mystruct
             local Mystruct this = Mystruct.allocate()
             set .caster = GetTriggerUnit()
             set .currentScale = 1
             set .t = CreateTimer()
             set .end = CreateTrigger()
             return this
         endmethod
         
    endstruct
//!=========================================================================!\\
//!============================SETUP START==================================!\\
//!=========================================================================!\\

    globals
        private constant integer AID = 'A000'  //ability ID
        private constant integer UNITID = 'npng' //Created unit's Id
        private constant string DEATH_EFFECT = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl" //effect shown when penguin dies
        private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl" //effect shown when units damge damage
        private constant integer RED = 0 //the red RGB color for the text tag
        private constant integer GREEN = 0 //the green RGB color for the text tag
        private constant integer BLUE = 255 //the blue RGB color for the text tag
        private constant boolean TEXT = true //if true, shows text saying damage abve units, if false, it doesn't
    endglobals
    
    
    
    private constant function GrowTime takes integer level returns integer time
        return 1 + (level * 0) //time intervail between each time the unit grows (is a cicle)
    endfunction
    
    private constant function Growth takes integer level returns real grow
        return 0.2 * level //How much the unit will grow. It grows 20% * level in this case
    endfunction
    
    private constant function Radius takes integer level returns integer radius
        return 200 + (50 * (level - 1)) //the area of damage
    endfunction
        
    private function Damage takes integer level returns integer damage
        return 5 * level //Damage increase per cicle
    endfunction
    
    private function Targets takes nothing returns boolean
        //do not change this local
        local Mystruct data = GetTriggerStructA(GetTriggeringTrigger())
        
        //this tells you the units the explosion will affect, you can change this
        //data.caster is the caster of the spell. Everytime you want to refer to the caster
        //of the spell you must use data.caster, but ONLY on this function, in the SETUP
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(data.caster)) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (GetWidgetLife(GetFilterUnit()) > 0.405)
    endfunction

//!=========================================================================!\\
//!============================SETUP END====================================!\\
//!=========================================================================!\\

    private function End_Conds takes nothing returns boolean
        return (GetSpellAbilityId() == AID)
    endfunction
//==========================================================================
    private function End_Acts takes nothing returns nothing
        //catches the trigger and runs this function
        local Mystruct data = GetTriggerStructA(GetTriggeringTrigger())
        local group g = CreateGroup()
        local unit f
        local boolexpr b = Condition(function Targets) 
        local effect deathPenguin = AddSpecialEffect(DEATH_EFFECT, GetUnitX(data.penguin), GetUnitY(data.penguin))
        local effect blood
        local texttag text
        
        if(GetWidgetLife(data.penguin) > 0.405) then
            call KillUnit(data.penguin)
        else 
             call IssueImmediateOrder(data.caster, "stop" )
        endif
        
        call GroupEnumUnitsInRange(g, GetUnitX(data.penguin), GetUnitY(data.penguin), Radius(data.level), b)
            
        loop
            set f = FirstOfGroup(g)
            exitwhen (f == null)
            call GroupRemoveUnit(g, f)
            set blood = AddSpecialEffect(BLOOD_EFFECT, GetUnitX(f), GetUnitY(f))
            
            call UnitDamageTarget(data.penguin, f, data.damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
            
            //sets the text tag if the flag is true
            if(TEXT) then
                set text = CreateTextTag()
                call SetTextTagText(text, I2S(data.damage), .023 )   
                call SetTextTagPosUnit( text, f, 0 )
                call SetTextTagColor( text, RED, GREEN, BLUE, 255 )
                call SetTextTagPermanent(text, false)
                call SetTextTagVelocity( text, 0, .0277 )
                call SetTextTagLifespan(text, 2.0)
            endif
            
            call DestroyEffect(blood)
        endloop
           
        call DestroyEffect(deathPenguin)
        call DestroyGroup(g)
        call DestroyBoolExpr(b)
        
        set b = null
        set g = null
        set deathPenguin = null
        set blood = null
        set text = null
    
        call TriggerRemoveCondition(data.end,data.endCondition)
        call TriggerRemoveAction(data.end,data.endAction)
        call DestroyTrigger(data.end)
        call ClearTriggerStructA(data.end)

        //stops the repeator timer and ends the spell once and for all
        call PauseTimer(data.t)
        call DestroyTimer(data.t)
        
        call ClearTimerStructA(data.t)
        call data.destroy()
    endfunction
//==========================================================================
    private function Size takes nothing returns nothing
        //catches the expired timer and runs this function
        local Mystruct data = GetTimerStructA(GetExpiredTimer())
        
        if(GetWidgetLife(data.penguin) > 0.405) then
            call SetUnitScale(data.penguin, data.currentScale + data.grow, data.currentScale + data.grow, data.currentScale + data.grow) 
            set data.currentScale = data.currentScale + data.grow
            set data.damage = data.damage + Damage(data.level)
        else
            call IssueImmediateOrder(data.caster, "stop" )
        endif
        
    endfunction
//==========================================================================
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == AID
    endfunction
//===========================================================================
    private function Actions takes nothing returns nothing
        local Mystruct data = Mystruct.create()
        local location loc = GetSpellTargetLoc()
        
        set data.grow = Growth(GetUnitAbilityLevel(data.caster, AID))
        set data.penguin = CreateUnit(GetOwningPlayer(data.caster), UNITID, GetLocationX(loc), GetLocationY(loc), 0)
        set data.level = GetUnitAbilityLevel(data.caster, AID)
        set data.damage = Damage(data.level)
        
        call SetUnitExploded(data.penguin, true)
        
        call SetTimerStructA(data.t, data)
        call TimerStart(data.t, GrowTime(GetUnitAbilityLevel(data.caster, AID)), true, function Size)
        
        call RemoveLocation(loc)
        set loc = null
        
        //creates the trigger that will end the spell when the hero stops channeling
        call SetTriggerStructA(data.end, data)
        call TriggerRegisterAnyUnitEventBJ( data.end, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
        set data.endCondition = TriggerAddCondition( data.end, Condition( function End_Conds ) )
        set data.endAction = TriggerAddAction( data.end, function End_Acts )
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        set gg_trg_Stupid_Penguin = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Stupid_Penguin, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
        call TriggerAddCondition( gg_trg_Stupid_Penguin, Condition( function Conditions ) )
        call TriggerAddAction( gg_trg_Stupid_Penguin, function Actions )
    endfunction
endscope

know why this happens ?
 

Attachments

  • SP.w3x
    38.3 KB · Views: 73
Last edited:
Level 23
Joined
Nov 29, 2006
Messages
2,482
well, there is nothing wrong with you triggering... except one thing

I believe this is messing it up.
call SetUnitExploded(data.penguin, true)

Since, whenever a unit explodes, it is instantly removed form the game. Thus, you have no access to it. I removed that call and then it worked =)
Thats explaining why the special effect was created on the center of the map (0 ,0)
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Correct.
And you do not detect if the penguin is killed by any way.
So your hero will still channel even if penguin gets killed instantly after entering the map.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
No idea about the model.
He checks that when the hero/unit stops channeling.
To detect when it dies a trigger would best fit this(the one he has would work, he just needs to add the event).
 
To detect when it dies a trigger would best fit this(the one he has would work, he just needs to add the event).
No it wouldn't =D
Mainly because i already tried that approach, and it was a disaster. It will require more memory and CPU, and it will conflict with the stop channel trigger.
Besides the fact it will be more difficult to manage, I also don't think that something worth doing...

Also, can anyone please tell me where I can find the explode model ?? It is the cherry on the top of the cake !!

Off-topic, btw, how do I fed your little dragon spiwn ??
 
Level 23
Joined
Nov 29, 2006
Messages
2,482
click on him?

Anyway the path to the exploding model the penguin is using is:
Objects\Spawnmodels\Orc\OrcSmallDeathExplode\OrcSmallDeathExplode.mdl

And spiwn, no he does not. Every time the penguin's size is getting larger he is checking the life there as well... which is ran by a timer. So no, its not a problem. I dont see what you mean otherwise, since I found no flaws when testing it
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
That is true, but he creates the effect when caster stops channeling not when it dies.
 
That is true, but he creates the effect when caster stops channeling not when it dies.
When the caster dies, it stops casting the channel automatically ...
So everything works perfectly =)
I'm sorry, why the hell does this require dynamic triggers...?
It is my way of coding. This way I use only one trigger instead of two =) Besides it is an excellent spell to practice some vJAss =)
Do it for fun m8 =D

Btw, thx for the path, I will test it right away !
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
You don't use dynamic triggers for this. NEVER when you can avoid it. Pretty much only damage detection and possibly reincarnation detection, and that's only as second best.

If the gobal event exists, you use that. Dynamic triggers are pretty slow to make and destroy, and just begging for trouble.
 
You don't use dynamic triggers for this. NEVER when you can avoid it. Pretty much only damage detection and possibly reincarnation detection, and that's only as second best.

If the gobal event exists, you use that. Dynamic triggers are pretty slow to make and destroy, and just begging for trouble.
.... I don't need ultra speed... Besides I made a few moments ago a post on wc3 campaign about why I use dynamic triggers. I won't repeat it. If you want to know why, than go there and read it yourself.

I find it funny how everything I do is always wrong or "begging for trouble" for you ...
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
.... I don't need ultra speed... Besides I made a few moments ago a post on wc3 campaign about why I use dynamic triggers. I won't repeat it. If you want to know why, than go there and read it yourself.

Opening your self up for a big can of worms with dynamic triggers is nothing to do with speed - it's about reliability.

I find it funny how everything I do is always wrong or "begging for trouble" for you ...

Only what is wrong or begging for trouble.
 
Opening your self up for a big can of worms with dynamic triggers is nothing to do with speed - it's about reliability.
worms ? Well, all spells I made like that never gave me problems ....
If this doesn't answer your question than please re-write your sentence in plain decent english that is related to the actual subject.

Also, The problem is fixed, thx all for help.
Now please we should stop this futile discussion Grifen.
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
Remember kids - ignore Flame Pheonix and his code, and remember that dynamic triggers are BAD, act as a catalyst for bugs, and really should be avoided if at all possible.

(I've given up on getting you, FP, to write decent code, but I don't want you leading poor newbies down the road to massive aggrovation.)
 
Remember kids - ignore Flame Pheonix and his code, and remember that dynamic triggers are BAD, act as a catalyst for bugs, and really should be avoided if at all possible.

(I've given up on getting you, FP, to write decent code, but I don't want you leading poor newbies down the road to massive aggrovation.)

aggrovation !?
See this is why I don't like you - I try the solve things as an adult and you just end with a childish comment...
Everything seems to cause bugs in your world... your problem is that although you have good will, you don't know how to help people - we either do things your way, or we suck.
You didn't even try to understand my point of view !
And ya, I admit i mess up sometimes, but you , no you are just to selfish to do it. So I will keep helping and teaching newbies like I always did. And if some day I find myself wrong, I will let them now. Unlike you, I don't force people to choose my way, i give them an option, knowing what will result from their acts.
This is our main difference, you just simply can't allow people to be different from you because you ALWAYS need to be correct...
__________________

And even when i ask for the discussion to end you just pop-up with a childish comment. I really feel like report your damn stupid post, but I won't do it, because unlike you, I have consideration for you, and I appreciate your help - however appreciating your help won't make me worship you, there are plenty of people besides you that are here to help.

Also, how can you say you've given up on me, I can count your posts with my hands ? You did a total of 10 posts or less !
Listen I'll be most happy to take lessons from you, in fact I have my msn available for people to help me (and me to help people). I know little vJASS because i talk to people by msn and they teach me, and I and there to learn.

I really wanted to be your friend and learn from you, but I see that unfortunately that is impossible.
Captain_Grifen, You have serious problem with attitude...
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
aggrovation !?
See this is why I don't like you - I try the solve things as an adult and you just end with a childish comment...
Everything seems to cause bugs in your world... your problem is that although you have good will, you don't know how to help people - we either do things your way, or we suck.
You didn't even try to understand my point of view !
And ya, I admit i mess up sometimes, but you , no you are just to selfish to do it. So I will keep helping and teaching newbies like I always did. And if some day I find myself wrong, I will let them now. Unlike you, I don't force people to choose my way, i give them an option, knowing what will result from their acts.
This is our main difference, you just simply can't allow people to be different from you because you ALWAYS need to be correct...
__________________

And even when i ask for the discussion to end you just pop-up with a childish comment. I really feel like report your damn stupid post, but I won't do it, because unlike you, I have consideration for you, and I appreciate your help - however appreciating your help won't make me worship you, there are plenty of people besides you that are here to help.

Also, how can you say you've given up on me, I can count your posts with my hands ? You did a total of 10 posts or less !
Listen I'll be most happy to take lessons from you, in fact I have my msn available for people to help me (and me to help people). I know little vJASS because i talk to people by msn and they teach me, and I and there to learn.

I really wanted to be your friend and learn from you, but I see that unfortunately that is impossible.
Captain_Grifen, You have serious problem with attitude...

Oh, yes, obvious Vex, PipeDream, Anitarf, Pyrogasm, me, etc., are all wrong and you are right?

I've seen that attitude from you far too often, even when you are blatantly wrong. I don't care what you think, and I don't really care if your code is crap. What I do care about is your "helping and teaching newbies like I always did" with totally wrong information that'll leave them with maps that'll start having apparently untraceable bugs. We have several threads on these issues, and it took us a long time to find and diagnose the problems. If you really want to learn about it, you'd go do some research on it.

And if you seriously wanted to learn from me, you'd listen when I say that dynamic triggers are bad, and are entirely the wrong solution for what you want to achieve.

PS: You cannot unilaterally end a discussion.

This is our main difference, you just simply can't allow people to be different from you because you ALWAYS need to be correct...

I only post in this forum when people stray, and intervene so as to save them a lot of strife further on. Stuff like dynamic triggers, I2H, etc. being bad is something that it took us years to find out, for example.
 
Oh, yes, obvious Vex, PipeDream, Anitarf, Pyrogasm, me, etc., are all wrong and you are right?
Please find that sentence in my posts, I don't remember ever saying such a thing.

PS: You cannot unilaterally end a discussion.
It looks neither can you.

And if you seriously wanted to learn from me, you'd listen when I say that dynamic triggers are bad, and are entirely the wrong solution for what you want to achieve.
This is excatly what I am talking about ... if I don't agree with you than I am wrong ...
I only post in this forum when people stray, and intervene so as to save them a lot of strife further on. Stuff like dynamic triggers, I2H, etc. being bad is something that it took us years to find out, for example.
Then why do you teach us how to it in your tutorials !?
Besides, I accept dynamic triggers can be bad... I just don't know why ... saying "this is bad" is no enough for me ... i need a valid reason. If you know of a tutorial that I can read to prove your point, than please point it out...
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
Then why do you teach us how to it in your tutorials !?

I do not believe I have any tutorials.

Besides, I accept dynamic triggers can be bad... I just don't know why ... saying "this is bad" is no enough for me ... i need a valid reason. If you know of a tutorial that I can read to prove your point, than please point it out...

As I said, search for the massive threads in WC3C on them, and read them. They aren't as bad as I2H, but certainly bad enough to warrant not using them when they are perfectly avoidable.
 
I do not believe I have any tutorials.
I meant "you = wc3 campaign people".

As I said, search for the massive threads in WC3C on them, and read them. They aren't as bad as I2H, but certainly bad enough to warrant not using them when they are perfectly avoidable.
I don't have time to waste reading huge threads... I prefer using my time reading tutorials that i know will help me, and creating my map.
I believe I2H is bad .... mainly because I experienced its evil with stupid Handle corruption or something like that that Vexorian explained me.
However I can't stop asking myself, how would you do this spell Grifen, using only 1 trigger and 2 events ?
 
Status
Not open for further replies.
Top