| 09-30-2007, 05:23 PM | #1 |
Hi everyone. I am having problem with triggering DoTs and haven't found any solution yet so I hope you can help me. I want to have a spell named Corruption that deals damage every 3 seconds for 18 seconds. (Like the one in WOW) I don't want to use any Globals or dummies and just one triggerfor the spell. I have tried these things and none works. JASS:function Trig_Corruption_Conditions takes nothing returns boolean if ( not ( GetSpellAbilityId() == 'A007' ) ) then return false endif return true endfunction function Trig_Corruption_Func002C takes nothing returns boolean local unit target = GetSpellTargetUnit() if ( not ( UnitHasBuffBJ(target, 'B001') == true ) ) then return false endif return true endfunction function Trig_Corruption_Actions takes nothing returns nothing local unit target = GetSpellTargetUnit() if ( Trig_Corruption_Func002C() ) then set udg_REAL = GetRandomReal(105.00, 125.00) call UnitDamageTargetBJ( GetTriggerUnit(), target, udg_REAL, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH ) call CreateTextTagUnitBJ( R2S(udg_REAL), target, 0, 10, 100, 0.00, 100, 0 ) call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 ) call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false ) call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 ) call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 ) else call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_138" ) return endif call TriggerSleepAction( 3.00 ) call TriggerExecute( GetTriggeringTrigger() ) endfunction Code:
Corruption Effect
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Corruption
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Triggering unit) has buff Corruption Warlock) Equal to True
Then - Actions
Set REAL = (Random real number between 105.00 and 125.00)
Game - Display to (All players) the text: (String(REAL))
Unit - Cause Hero[(Player number of (Owner of (Attacking unit)))] to damage (Triggering unit), dealing REAL damage of attack type Magic and damage type Death
Floating Text - Create floating text that reads (String(REAL)) above (Target unit of ability being cast) with Z offset 0.00, using font size 10.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
Floating Text - Change (Last created floating text): Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 1.50 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Else - Actions
Skip remaining actions
Wait 3.00 seconds
Trigger - Run (This trigger) (ignoring conditions) JASS:function Trig_looooooooop_Conditions takes nothing returns boolean if ( not ( GetSpellAbilityId() == 'A007' ) ) then return false endif return true endfunction function Trig_looooooooop_Actions takes nothing returns nothing local unit target = GetSpellTargetUnit() call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH ) call TriggerSleepAction( 2 ) call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH ) call TriggerSleepAction( 2 ) call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH ) call TriggerSleepAction( 2 ) endfunction The problem appears to be that WE can't detect the Target of ability being cast after waiting seconds. So maybe only jass can help here with some locals, but i dont know jass well so can you please write it for me. Thank you in advance. Wewso |
| 09-30-2007, 05:37 PM | #2 |
You need to learn to use periodic timers. Waits don't work ... well they just don't work in 95% of cases. And start using NewGen. |
| 10-01-2007, 01:19 AM | #3 |
I could show you how to do that, but... why don't you create your spell with a custom ability based on Shadow Strike?? it has all that you are requiring (even the floating text), and you won't need to trigger anything. |
| 10-01-2007, 03:37 AM | #4 |
Just a few tips to give you: This JASS:function Trig_Corruption_Conditions takes nothing returns boolean if ( not ( GetSpellAbilityId() == 'A007' ) ) then return false endif return true endfunction can be replaced with JASS:function Trig_Corruption_Conditions takes nothing returns boolean return GetSpellAbilityId() == 'A007' endfunction I dont he wants to make the damage the target recieved to be a random real. Your going to want to do something like have a function that damages the unit every three seconds this wil require you to learn to use timers. Then you need an integer that starts at zero and increases by 3 everytime the function is run. Then just use an if statement to check whether the integer is less than 18. |
| 10-01-2007, 06:02 AM | #5 |
You might want to check this out: JESP DoT Template |
| 10-01-2007, 04:17 PM | #6 | |||
Quote:
I thaught of creating a spell based on Shadow Strike but the hero Im designing is a Warlock and will have lots of those DoTs (damage over time effects). So I cant base my spells on Shadow Strike because WC3 will mess up the IDs. ![]() Quote:
Well i saw this and it looks very good in-game but it doesn't help me because: 1 It doesn't create a buff that when dispelled canceles the effect. 2 The JASS isn't quite editable and i would have problems with adding additional effects. Actualy I can't edit it at all ![]() Quote:
Timers dont help becase they need globals and i dont want any globals in my spell. Imagine how every player has cast 5 different dots on 4 different targets (2 of which will resist the spell and would want to stop the negative effect) each controled by a different player in a different team which would want to get points for the damage dealt to enemy players. Thats how messed up it is ![]() |
| 10-02-2007, 02:47 AM | #7 |
You don't need globals for timers. In fact, you usually will "attach" structs or handles to a timer to create a specific instance for that timer. My code can be modified to work based on if a unit has a specific buff or not. Here's a revised code that does such a thing (changes are in red; I have no way of showing what I removed, only what I added): JASS://***************************************************************************\\ // Spell Name: ExampleDoT \\ // Spell Author: Pyrogasm \\ // Conforms to the JESP Standard \\ //***************************************************************************\\ constant function ExampleDoT_AbilityId takes nothing returns integer return 'A000' //The spell's rawcode. endfunction constant function ExampleDoT_DummyUnitId takes nothing returns integer return 'h000' //The rawcode of a generic dummy unit. endfunction constant function ExampleDoT_BuffId takes integer Level returns integer return 'B008' endfunction constant function ExampleDoT_Duration takes integer Level returns real return 9.00 endfunction constant function ExampleDoT_TotalDamage takes integer Level returns real return 125.00+(8*Level)*(8*Level) endfunction constant function ExampleDoT_DamageInterval takes integer Level returns real return 2.00-(Level*0.50) //How often the damage occurs. endfunction constant function ExampleDoT_EffectPath takes integer Level returns string if Level == 1 then return "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl" elseif Level == 2 then return "Abilities\\Spells\\Demon\\DarkConversion\\ZombifyTarget.mdl" elseif Level == 3 then return "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" endif return "" //Safety return endfunction constant function ExampleDoT_EffectAttach takes integer Level returns string if Level == 1 then return "overhead" elseif Level == 2 then return "origin" elseif Level == 3 then return "chest" endif return "" //Safety return endfunction constant function ExampleDoT_ContinueIfDead takes integer Level returns boolean return true //If true, the target will still take damage if the caster has died. endfunction constant function ExampleDoT_FirstOnCast takes integer Level returns boolean return false //If true, the spell will damage the target in the cast function. endfunction //The total damage will be the same, however. //===========================================================================\\ //===========================================================================\\ function ExampleDoT_CastConditions takes nothing returns boolean return GetSpellAbilityId() == ExampleDoT_AbilityId() endfunction function ExampleDoT_Callback takes nothing returns nothing local timer T = GetExpiredTimer() local string TTable = GetAttachmentTable(T) local integer Level local real Duration local unit U local unit U2 = GetTableUnit(TTable, "ExampleDoT Target") local integer BuffId = ExampleDoT_BuffId(Level)) if (GetUnitAbilityLevel(U2, BuffId > 0) then //No need to see if it's alive; It won't have the buff if it's dead. set U = GetTableUnit(TTable, "ExampleDoT Caster") set Duration = ExampleDoT_Duration(Level) if GetWidgetLife(U) < 0.406 and ExampleDoT_ContinueIfDead(Level) then set U = CreateUnit(GetOwningPlayer(U), ExampleDoT_DummyUnitId(), 0.00, 0.00, 0.00) call SetTableObject(TTable, "ExampleDoT Caster", U) call UnitApplyTimedLife(U, 'BTLF', Duration) call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(ExampleDoT_DamageInterval(Level)/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null) call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level))) elseif GetWidgetLife(U) < 0.406 and not(ExampleDoT_ContinueIfDead(Level)) then call UnitRemoveAbility(U2, BuffId) else call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(ExampleDoT_DamageInterval(Level)/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null) call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level))) endif set U = null else call PauseTimer(T) call CleanAttachedVars(T) call DestroyTimer(T) endif set U2 = null set T = null endfunction function ExampleDoT_Cast takes nothing returns nothing local unit U = GetTriggerUnit() local unit U2 = GetSpellTargetUnit() local timer T = CreateTimer() local string TTable = GetAttachmentTable(T) local integer Level = GetUnitAbilityLevel(U, ExampleDoT_AbilityId()) local real Interval = ExampleDoT_DamageInterval(Level) local real Duration = ExampleDoT_Duration(Level) if ExampleDoT_FirstOnCast(Level) then call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(Interval/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null) call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level))) endif call SetTableObject(TTable, "ExampleDoT Caster", U) call SetTableObject(TTable, "ExampleDoT Target", U2) call SetTableInt(TTable, "ExampleDoT Level", Level) call TimerStart(T, Interval, true, function ExampleDoT_Callback) set U = null set U2 = null set T = null endfunction //===========================================================================\\ function InitTrig_ExampleDoT takes nothing returns nothing set gg_trg_ExampleDoT = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_ExampleDoT, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(gg_trg_ExampleDoT, Condition(function ExampleDoT_CastConditions)) call TriggerAddAction(gg_trg_ExampleDoT, function ExampleDoT_Cast) endfunction |
