| 07-03-2008, 03:40 AM | #1 |
Here's my submission for the eleventh spell contest. Changelog Flyswatter Throws target enemy into the air. While the enemy is falling, the Crypt Lord gains damage from each nearby ally which he unleashes in a powerful strike. The target takes 180 damage from falling to the ground, and the Crypt Lord's strike deals 40 damage per nearby ally. Code:scope Flyswatter globals private integer AbilityID = 'A000' private integer DummyUnitID = '0000' private string OrderID = "channel" private attacktype AttackType = ATTACK_TYPE_NORMAL private damagetype DamageType = DAMAGE_TYPE_UNIVERSAL private real FallBaseDamage = 180. private real FallDamagePerLevel = 90. private real StrikeBaseDamage = 40. private real StrikeDamagePerLevel = 20. private timer Timer = CreateTimer() private integer Counter = 0 private integer array Structs private real TimerInterval = 0.025 endglobals private function filter takes nothing returns boolean return IsUnitAlly(GetFilterUnit(), GetOwningPlayer(bj_meleeNearestMine)) and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitAbilityLevel(GetFilterUnit(), 'Avul') <= 0 endfunction private constant function StrikeDamage takes integer lvl returns real return StrikeBaseDamage+(StrikeDamagePerLevel*(lvl-1)) endfunction private constant function FallDamage takes integer lvl returns real return FallBaseDamage+(FallDamagePerLevel*(lvl-1)) endfunction private function Z takes real x, real y returns real local location L = Location(x,y) local real h = GetLocationZ(L) call RemoveLocation(L) set L = null return h endfunction private struct Dat unit Caster real Cx real Cy real Cz real Ca = 0. real Cv = 0. unit Target real Tx real Ty real Tz real Ta = 0. real Tv = 60. real Time = 0. group RayGroup = CreateGroup() integer Lvl boolean Anim = false boolean Canceled = false boolean TLanded = false boolean CLanded = false boolean Attacked = false boolean Struck = false real RayTimer = 0. effect e1 effect e2 real EQ = 3. real dmg = 0. static method onCreate takes unit caster, unit target returns Dat local Dat dat = Dat.create() set dat.Caster = caster set dat.Target = target set dat.Lvl = GetUnitAbilityLevel(caster, AbilityID) call UnitAddAbility(dat.Caster, 'Amrf') call UnitRemoveAbility(dat.Caster, 'Amrf') call UnitAddAbility(dat.Target, 'Amrf') call UnitRemoveAbility(dat.Target, 'Amrf') set dat.Cx = GetUnitX(dat.Caster) set dat.Cy = GetUnitY(dat.Caster) set dat.Cz = GetUnitFlyHeight(dat.Caster) set dat.Tx = GetUnitX(dat.Target) set dat.Ty = GetUnitY(dat.Target) set dat.Tz = GetUnitFlyHeight(dat.Target) call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl", dat.Tx, dat.Ty)) call DestroyEffect(AddSpecialEffect("AObjects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", dat.Tx, dat.Ty)) call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\VengeanceMissile\\VengeanceMissile.mdl", dat.Target, "chest")) call UnitAddAbility(dat.Target, 'Avul') return dat endmethod endstruct private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AbilityID endfunction private function Callback takes nothing returns nothing local Dat dat = 0 local integer i = Counter - 1 local group g local unit u local unit v loop exitwhen i < 0 set dat = Structs[i] set dat.Time = dat.Time + TimerInterval if dat.Canceled == false and OrderId2String(GetUnitCurrentOrder(dat.Caster)) != OrderID then set dat.Canceled = true call SetUnitTimeScale(dat.Caster, 1.) if GetWidgetLife(dat.Caster) > 0.405 then call SetUnitAnimation(dat.Caster, "Channel") else call SetUnitAnimation(dat.Caster, "Death") endif endif if dat.RayTimer > 0. then set dat.RayTimer = dat.RayTimer - TimerInterval if dat.RayTimer <= 0. then loop set u = FirstOfGroup(dat.RayGroup) exitwhen u == null call SetUnitX(u, dat.Cx) call SetUnitY(u, dat.Cy) call SetUnitFlyHeight(u, dat.Cz, 0.) call KillUnit(u) call GroupRemoveUnit(dat.RayGroup, u) endloop call DestroyGroup(dat.RayGroup) endif endif if dat.EQ > 0. then if IsUnitSelected(dat.Target, GetLocalPlayer()) or IsUnitSelected(dat.Caster, GetLocalPlayer()) then call CameraSetEQNoiseForPlayer(GetLocalPlayer(), dat.EQ) endif set dat.EQ = dat.EQ - 0.225 if dat.EQ <= 0. then call CameraClearNoiseForPlayer(GetLocalPlayer()) if dat.CLanded and dat.TLanded then call dat.destroy() set Counter = Counter - 1 if Counter <= 0 then set Counter = 0 call PauseTimer(Timer) else set Structs[i] = Structs[Counter] endif endif endif endif //Target if dat.Tz >= 0. and dat.TLanded == false then set dat.Ta = dat.Ta + 1.25 set dat.Tz = ( dat.Tz + dat.Tv ) - ( dat.Ta) call SetUnitFlyHeight(dat.Target, dat.Tz, 0.) call SetUnitX(dat.Target, dat.Tx) call SetUnitY(dat.Target, dat.Ty) elseif dat.TLanded == false then set dat.TLanded = true set dat.Tz = 0. set dat.EQ = 12. call SetUnitFlyHeight(dat.Target, dat.Tz, 0.) call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", dat.Tx, dat.Ty)) call UnitRemoveAbility(dat.Target, 'Avul') call UnitDamageTarget(dat.Caster, dat.Target, FallDamage(dat.Lvl), true, false, AttackType, DamageType, WEAPON_TYPE_WHOKNOWS) if dat.CLanded and dat.EQ <= 0. then call dat.destroy() set Counter = Counter - 1 if Counter <= 0 then set Counter = 0 call PauseTimer(Timer) else set Structs[i] = Structs[Counter] endif endif endif //Caster if dat.Cz < 0 and dat.CLanded == false then set dat.CLanded = true call SetUnitFlyHeight(dat.Caster, 0., 0.) if GetWidgetLife(dat.Caster) > 0.405 then call SetUnitAnimation(dat.Caster, "reset unit animation") endif call SetUnitTimeScale(dat.Caster, 1.) if OrderId2String(GetUnitCurrentOrder(dat.Caster)) == OrderID then call IssueImmediateOrder(dat.Caster, "stop") endif if dat.TLanded and dat.EQ <= 0. then call dat.destroy() set Counter = Counter - 1 if Counter <= 0 then set Counter = 0 call PauseTimer(Timer) else set Structs[i] = Structs[Counter] endif endif elseif dat.Canceled == false and dat.CLanded == false then if dat.Time > 1. then if dat.Anim == false then call SetUnitAnimation(dat.Caster, "Channel") set dat.Cv = 16.5 set dat.Anim = true endif set dat.Ca = dat.Ca + 0.25 set dat.Cz = ( dat.Cz + dat.Cv ) - ( dat.Ca) call SetUnitFlyHeight(dat.Caster, dat.Cz, 0.) call SetUnitX(dat.Caster, dat.Cx) call SetUnitY(dat.Caster, dat.Cy) endif if dat.Tv - dat.Ta <= -30. and dat.Attacked == false then call SetUnitAnimation(dat.Caster, "Spell Alternate") call QueueUnitAnimation(dat.Caster, "Channel") set dat.e1 = AddSpecialEffectTarget("Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruptionSpecialArt.mdl", dat.Caster, "left hand") set dat.e2 = AddSpecialEffectTarget("Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruptionSpecialArt.mdl", dat.Caster, "right hand") set g = CreateGroup() set bj_meleeNearestMine = dat.Caster call GroupEnumUnitsInRange(g, dat.Cx, dat.Cy, 800., Condition(function filter)) loop set u = FirstOfGroup(g) exitwhen u == null set v = CreateUnit(Player(15), '0000', GetUnitX(u), GetUnitY(u), GetRandomReal(0, 360)) call SetUnitX(v, GetUnitX(u)) call SetUnitY(v, GetUnitY(u)) call AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl", v, "origin") call UnitAddAbility(v, 'Amrf') call UnitRemoveAbility(v, 'Amrf') call SetUnitFlyHeight(v, GetUnitFlyHeight(u), 0.) call GroupAddUnit(dat.RayGroup, v) set dat.dmg = dat.dmg + StrikeDamage(dat.Lvl) call GroupRemoveUnit(g, u) endloop call DestroyGroup(g) set dat.RayTimer = 0.1 call SetUnitTimeScale(dat.Caster, 1.8) set dat.Attacked = true endif if dat.Struck == false and RAbsBJ(dat.Tz - dat.Cz) <= 25 then set dat.Canceled = true call SetUnitTimeScale(dat.Caster, 1.) set dat.Tv = dat.Tv - 80. call DestroyEffect(dat.e1) call DestroyEffect(dat.e2) call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\AncestralGuardianMissile\\AncestralGuardianMissile.mdl", dat.Target, "chest")) call UnitRemoveAbility(dat.Target, 'Avul') call UnitDamageTarget(dat.Caster, dat.Target, dat.dmg, true, false, AttackType, DamageType, WEAPON_TYPE_WHOKNOWS) call GroupClear(dat.RayGroup) set dat.Struck = true endif elseif dat.Canceled == true and dat.CLanded == false then set dat.Ca = dat.Ca + 0.5 set dat.Cv = dat.Cv - 0.5 set dat.Cz = ( dat.Cz + dat.Cv ) - ( dat.Ca) call SetUnitFlyHeight(dat.Caster, dat.Cz, 0.) endif set i = i - 1 endloop set g = null set u = null set v = null endfunction private function Actions takes nothing returns nothing local Dat dat = Dat.onCreate(GetSpellAbilityUnit(), GetSpellTargetUnit()) if Counter == 0 then call TimerStart(Timer, TimerInterval, true, function Callback) endif set Structs[Counter] = dat set Counter = Counter + 1 endfunction function InitTrig_Flyswatter takes nothing returns nothing local unit preload = CreateUnit(Player(0), '0000', 0., 0., 0.) call UnitAddAbility(preload, 'A000') call RemoveUnit(preload) call Preload("Abilities\\Weapons\\AncestralGuardianMissile\\AncestralGuardianMissile.mdl") call Preload("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl") call Preload("Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruptionSpecialArt.mdl") call Preload("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl") set gg_trg_Flyswatter = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_Flyswatter, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(gg_trg_Flyswatter, Condition(function Conditions)) call TriggerAddAction(gg_trg_Flyswatter, function Actions) set preload = null endfunction endscope |
| 07-03-2008, 04:45 AM | #2 |
Awexome stuff; and I'm sure that since you used his jumping animation for the up-swing, then the claws-downward "Impale" animation in mid-air... Well, needless to say, that's freakin' awexome. I hope we're allowed more than one vote. :P |
| 07-03-2008, 07:04 AM | #3 |
Pretty cool, but the climax of the animation happens too high up imo. |
| 07-03-2008, 10:37 AM | #4 |
This would also be insanely imba with the Undead and their ability to raise massive armies of Skellingtons. |
| 07-03-2008, 11:00 AM | #5 |
For the code you can use [hiddenjass][/hiddenjass] instead of putting Jass tags within hidden tags. Its a great idea for a spell, but as ShadowWolf said it would be better if it were slightly lower down. |
| 07-03-2008, 05:36 PM | #6 | |
Quote:
Except the actual stats of the skill don't really matter with this contest. Hell, my skill instakerplodes a group of enemies in one shot. |
| 07-04-2008, 12:57 AM | #7 |
Very cool looking! |
| 07-04-2008, 01:22 AM | #8 |
Updated; made a couple small fixes in accordance with the suggestions. (see first post) |
| 07-04-2008, 03:24 AM | #9 | |
Quote:
I know, that does not reduce how imba it would be, it has no imapct whatseover on the contest, but it's still imba. |
| 07-04-2008, 06:02 AM | #10 |
@ off-topic: lol Jack Skellington The spell itelf is awesome, the concept is great, not just some flashy effects that deal super damage. I have one criticism though, the phoenix fire doesn't quite look good lol. Good job man! |
| 10-01-2008, 05:30 PM | #11 |
Congratulations on winning the contest! I checked the code over briefly to make sure there were no glaring mistakes and I found none. (It was fast!) Additionally, the first post doesn't specify if the spell is JESP compliant or not, so I put it in spells. If it is/ever becomes JESP compliant, I'll move it over to the other forum. |
| 10-01-2008, 09:31 PM | #12 |
I don't recall ever reading about a bug with this spell. (especially one so severe as to make you so utterly disgusted with it) Just tell me what the bug is. I assume that the submission thread has been deleted since the spell has been accepted, so it's kind of hard for me to look it up. |
| 10-01-2008, 09:32 PM | #13 | |
Quote:
|
| 10-01-2008, 09:45 PM | #14 | |
alright. So if I understand correctly, this huge argument is over this: Quote:
I've never casted the spell without the fire phoenix effect being played. It is a very brief effect, so perhaps your FPS is too low to render the lightnings before they are removed. I'll look at the death animation thing. And about your complaints that its not JESP and doesnt have a "clear setup section", to be quite honest I don't really care. I think that it's easy enough to set up, and it wasn't a requirement of this contest to make the spells JESP. It seems like your beef is with the majority of the voters who do not follow your standards for deciding what makes a spell good, not with me or my spell. EDIT: added 3 lines of code to fix the death animation of the hero if he dies while casting. |
| 10-02-2008, 08:23 AM | #15 |
I moved some offtopic posts to the site discussion forum, please continue your discussion there. |
