| 08-24-2007, 03:59 PM | #1 |
Requirement Jass New Gen Pack v.4b (recommend) Credits Vexorian - JassHelper PipeDream - Grimoire PitzerMike - PJass I made this Spell for Spell Making Session #9, well i didn't really continue the spell only some smaller things changed, like moving th entire spell into a scope + the usage of private/public functions and adding the option, that knocked units can destroy destructibles. However i decided to finish this spell so any CONSTRUCTIVE criticism is welcome. I hope i didn't forgot anything yet (well, it's my very first submit) ![]() Thunder Whirl is a spell, which grabs an enemy unit and use it as shield in a certain distance, depending on the level. When the target unit hits another unit both are damaged and the other unit will be knocked away from the hero. When the cast is canceled/finished the target unit will be released sliding a bit too. Ability Type: Channeling Spell Mana Cost: 75 + 10 * Level Duration: 20 seconds Cooldown: 30 seconds Damage: 7 + 2 * Level per hit Readme://*********************************************************************************************** //* Thunder Whirl * //* Created by Fireeye * //* Credits * //* JassNewGenPack: * //* Vexorian - JassHelper * //* PipeDream - Grimoire * //* PitzerMike - PJass * //* v.1.3d * //*********************************************************************************************** //*********************************************************************************************** //* IMPORTANT * //*********************************************************************************************** //* This Spell use UnitUserData aka Custom Value, * //* so you have to know if you gonna use them or not * //*********************************************************************************************** //*********************************************************************************************** //* Changelog v.1.3d * //*********************************************************************************************** //* - made all structs private so they're unaccessable from outside the scope * //* - added the size of the "Tree Destroy Rect" into the UCP * //* The size of the rect is 2 * the global in both axis * //* - some minor changes * //*********************************************************************************************** //* Changelog v.1.3c * //*********************************************************************************************** //* - replaced the global trigger var with a local trigger * //* - reorganized some lines of code in the knock back creation * //*********************************************************************************************** //* Changelog v.1.3b * //*********************************************************************************************** //* - fixed an issue with the callback action * //*********************************************************************************************** //* Changelog v.1.3 * //*********************************************************************************************** //* - increased Read Me content * //* - removed several DEGTORAD and RADTODEG parts * //* - change some things slightly * //*********************************************************************************************** //* Changelog v.1.2b * //*********************************************************************************************** //* - optimized some parts * //* - knocked units will be forced now to attack the caster * //*********************************************************************************************** //* Changelog v.1.2 * //*********************************************************************************************** //* - extended option to destroy trees (possible for target units now) * //* - knocked units will now attack again after knock ended * //* - changed Calc Formulas to private constant * //* - moved damage type and attack type to globals block * //* - extened knock option to NOT use the caster as "Anchor", when used the knocked unit * //* will slide in the angle of the target unit * //*********************************************************************************************** //* Changelog v.1.1 * //*********************************************************************************************** //* - moved the changelog into a new trigger to reduce the actual trigger length * //* - Converted entire Spell to vJASS using scope, private/public functions * //* and private constant variables * //* - added facing for caster, however it'll bug on higher speed! * //* the same applies for the target * //*********************************************************************************************** //* Changelog v.1.0b * //*********************************************************************************************** //* - target are now facing correctly (well, only with a turn speed of 0) * //* - added possibility to destroy trees when hit by knocked unit * //*********************************************************************************************** //* Changelog v.1.0a * //*********************************************************************************************** //* - removed bug, so target can not be targeted again, * //* while being under the effect of this spell * //* - fixed some smaller MUI issues * //* - added ambient sound, sounds nicer ^^ * //* - hopefully following JESP Standarts * //* - added option for finding order id without creating a new trigger * //*********************************************************************************************** //* Changelog v.0.9b * //*********************************************************************************************** //* - again some smaller bug fixes * //* - reduced the damage again for this test map, due to very high end damage * //*********************************************************************************************** //* Changelog v.9.0a * //*********************************************************************************************** //* - fixed double free * //* - fixed a huge bug with the custom values, which cause multiple knock backs without * //* being in range of the target unit * //*********************************************************************************************** //* Changelog v.0.8c * //*********************************************************************************************** //* - added slide effect * //* - added slide for the target when released * //* - reduced slide speed for the target after released, due it can cause the map to crash * //*********************************************************************************************** //* Changelog v.0.8b * //*********************************************************************************************** //* - fixed some smaller/bigger bugs * //* - added hit effect for better visibility * //* - hit damage reduced, due to high damage * //*********************************************************************************************** //*********************************************************************************************** //* How to import * //*********************************************************************************************** //* 1. Import the entire script somewhere in your map (no new trigger needed due to InitTrig, * //* which will be runned on map loading and create a new trigger, so you can put it even in * /// Script Code Section) * //* 2. Change all needed datas (look below for detailed explanations) * //* 3. Save the map * //* 4. Have fun with this spell * //*********************************************************************************************** //*********************************************************************************************** //* Lightning Effects * //*********************************************************************************************** //* ID * Name * //* CLPB * Chain Lightning - Primary Bolt * //* CLSB * Chain Lightning - Secondary Bolt * //* MBUR * Mana Burn - Bolt * //* CHIM * Lightning Attack - Chimera * //* AFOD * Finger of Death * //*********************************************************************************************** //*********************************************************************************************** //* Attack Types * //*********************************************************************************************** //* ATTACK_TYPE_CHAOS * //* ATTACK_TYPE_HERO * //* ATTACK_TYPE_MAGIC * //* ATTACK_TYPE_MELEE * //* ATTACK_TYPE_NORMAL * //* ATTACK_TYPE_PIERCE * //* ATTACK_TYPE_SIEGE * //*********************************************************************************************** //*********************************************************************************************** //* TerrainItem * //*********************************************************************************************** //* This is the item used for checking the pathability, this contains the raw code of the item * //* type used * //* It have to be a valid item id or the entire pathing check won't work * //*********************************************************************************************** //*********************************************************************************************** //* DestroyTreesKnocked + DestroyTreesCycle * //*********************************************************************************************** //* These values controls if the target unit / knocked unit will destroy Trees when getting * //* too close, if you set these values to true i would also recommend a trigger making the * //* the trees regrowing after some time * //*********************************************************************************************** //*********************************************************************************************** //* DecreaseKBSpeed / StartKBSpeed * //*********************************************************************************************** //* Both values control the Knockspeed of knocked units * //* The StartKBSpeed contains the initial Speed and the DecreaseKBSpeed contains the reduction * //* After every literation * //* For the values i personnaly prefer an initial Speed between 9 and 18, well only if you don't* //* change the timer timeout, so i'll give you a value for v/sec ~300 - 600 * //* Calculation Formula used: (1 / TimerTimeOut) * Speed * //* For the DecreaseKBSpeed I recommend a value between 0.25 and 2 * //* The reduction would be (v/sec) ~ 8,33 - 66,67 * //* The Formula used is the same as the one used for StartKBSpeed * //*********************************************************************************************** //*********************************************************************************************** //* UseCasterAsAnchor * //*********************************************************************************************** //* If you use this option the knocked units will always be knocked away from the caster * //* But if you set this value to false the knocked unit will be knocked away from the target * //* So it can be possible that the knocked unit will get closer to the caster * //*********************************************************************************************** //*********************************************************************************************** //* KBPauseUnit * //*********************************************************************************************** //* If this value is set to true the knocked unit will be pause unable to do anything till it * //* stopped sliding, but if this value is false the unit will still be able to cast / attack and* //* move for a certain degree depending on the knock speed * //*********************************************************************************************** //*********************************************************************************************** //* DamageType * //*********************************************************************************************** //* if this value is DAMAGE_TYPE_UNIVERSAL only the Armor Type can change the damage taken * //* but if you use DAMAGE_TYPE_NORMAL the amount of armor will also reduce the taken damage * //* The other DAMAGE_TYPES don't have any other effects to my knowledge * //*********************************************************************************************** //*********************************************************************************************** //* AttackType * //*********************************************************************************************** //* This defines the Type of Damage dealt, for a complete list scroll a bit up * //* I normally use ATTACK_TYPE_CHAOS + DAMAGE_TYPE_UNIVERSAL due you can be sure then, that the * //* target unit will get the calculated damage * //* (as long as you don't change the gameplay constants) * //*********************************************************************************************** //*********************************************************************************************** //* PickRange * //*********************************************************************************************** //* If a unit gets withing this distance to the target unit it'll be knocked as long as it fits * //* into the knock filter (which requires a bit JASS Knowledge and will be explained later) * //*********************************************************************************************** //*********************************************************************************************** //* SpeedForMinDis * //*********************************************************************************************** //* This is speed the target unit will be attracted to the caster, you also set this to a * //* negative value so the distance between caster and target increase * //* This might bug when the unit is closer than the minimal distance * //*********************************************************************************************** //*********************************************************************************************** //* StartCircleSpeed * //*********************************************************************************************** //* This is the value for the initial circle speed in degree * //* If not change the target unit will have traveled (1/TimerTimeOut)*StartCircleSpeed degree * //* in this case ~133,33°/sec * //*********************************************************************************************** //*********************************************************************************************** //* EffectInterval * //*********************************************************************************************** //* This value contains how often the SlideEffect will be created, i recommend a value >= 7 * //* A value of 7 will create around 5 effects/second in standart configuration * //* To calculate the amounts effects created every second use the follwing formula * //* 1/(TimerTimeOut*EffectInterval) * //*********************************************************************************************** //*********************************************************************************************** //* SlideEffect / HitEffectAdd / HitEffect / CasterEffect * //*********************************************************************************************** //* SlideEffect contains as its name say the effect created @ the locations of knocked units * //* HitEffectAdd contains an additional effect when a unit is hit by the target unit * //* HitEffect this is the "primary" effect created on collision * //* This is the effect created @ the location of the caster * //*********************************************************************************************** //*********************************************************************************************** //* ASeax * //*********************************************************************************************** //* Due i'm not expirienced with the EAX option i can not say anything here nor * //* recommend anything, i personaly would use the initial value, due it work ;) * //*********************************************************************************************** //*********************************************************************************************** //* ASWantToFadeOut / ASFadeOut * //*********************************************************************************************** //* If this value is true then the created sound will be faded out when the caster stops * //* channeling the spell, the fade out speed is stored in ASFadeOut * //*********************************************************************************************** //*********************************************************************************************** //* ASFadeIn * //*********************************************************************************************** //* This is the fade in speed (how fast you have max volume) * //*********************************************************************************************** //*********************************************************************************************** //* AS3D / ASCutoff * //*********************************************************************************************** //* If AS3D is true then the volume of the played sound depends on the distance to source * //* also this enables ASCutoff which stops the sound when you're out of range (ASCutoffRange) * //*********************************************************************************************** //*********************************************************************************************** //* ASLoop * //*********************************************************************************************** //* If you set this to false the Sound will be played only once and stop then, ... duh * //*********************************************************************************************** //*********************************************************************************************** //* ASVolume * //*********************************************************************************************** //* The volume of the played sound in % ... (no recommendation due volume is relative) * //*********************************************************************************************** //*********************************************************************************************** //* ASDuration * //*********************************************************************************************** //* The duration of the sound, to find out the value go into the sound editor and type in the * //* number without those ":" and you got the correct value * //*********************************************************************************************** //*********************************************************************************************** //* ASChannel * //*********************************************************************************************** //* The channel used by the sound, there are various channels, e.g. combat environment, etc. * //* don't ask me which number is which channel i only know that 10 should be environment * //*********************************************************************************************** //*********************************************************************************************** //* ASCutoffRange * //*********************************************************************************************** //* The range used when activating ASCutoff, remember that this also takes the Z Distance in * //* account so don't choose a too low value (like 1000) * //*********************************************************************************************** //*********************************************************************************************** //* AmbientSound * //*********************************************************************************************** //* The path of the sound played while channeling the spell * //*********************************************************************************************** //*********************************************************************************************** //* LightningId * //*********************************************************************************************** //* The id of the lightning created between Caster and Target, scroll up for a complete list * //* (only complete if the *.slk isn't modified) * //*********************************************************************************************** //*********************************************************************************************** //* AbilityId * //*********************************************************************************************** //* The Raw Code of the used Dummy Ability (IT HAVE TO BE A CHANNELING ABILITY!) * //*********************************************************************************************** //*********************************************************************************************** //* TimerTimeOut * //*********************************************************************************************** //* The Refresh Rate of this spell, a lower value will increase the needed processing power * //* but the movements will look smoother if it doesn't lagg (don't forget to reduce/increase * //* the old values when you change this value) however a lower value will decrease the needed * //* processing power which is pretty important due not everyone got a really good computer * //* I personally recommend a value between 0.02 and 0.03 * //*********************************************************************************************** //*********************************************************************************************** //* Special Thanks * //*********************************************************************************************** //* Alexander244 for constructive critique and review * //* blue da noob for reviewing too * //* Moyack for reviewing and contructive critique * //* Rising_Dusk for reminding me to finish this ReadMe xD * //*********************************************************************************************** Spell Code://*********************************************************************************************** //* Thunder Whirl * //* Created by Fireeye * //* Credits * //* JassNewGenPack: * //* Vexorian - JassHelper * //* PipeDream - Grimoire * //* PitzerMike - PJass * //* v.1.3d * //*********************************************************************************************** scope ThunderWhirl //*********************************************************************************************** //* Private Keywords for Caster Struct and Knockback Struct * //*********************************************************************************************** private keyword KnockBack private keyword Cast //*********************************************************************************************** //* UCP (User Configuration Part) * //*********************************************************************************************** //* For a detailed explanation look in the Read Me! * //*********************************************************************************************** //*********************************************************************************************** //* formulas * //*********************************************************************************************** private constant function DecreaseCircleSpeed takes integer level returns real return level*0.0012 //The increament/decreament of the speed endfunction private constant function DistanceFormula takes integer level returns real return 325.00-level*25.00 //To calculate the minimal distance between caster and target endfunction private constant function DamageFormula takes integer level returns real return 7.00+level*2.00 //The hit damage endfunction //*********************************************************************************************** //* globals + structs * //*********************************************************************************************** globals private integer orderid = 0 //Set this to your order id, if you don't know the order id leave it 0 private constant integer TerrainItem = 'afac' //Raw Code of item for path check private constant boolean DestroyTreesKnocked = true //Should knocked units kill trees? private constant boolean DestroyTreesCycle = true //The same but for target unit private constant real TreeHitR = 96 //If DestroyTrees is enabled this will declare the size of the used rect private constant real DecreaseKBSpeed = .25 //How fast the knocked unit should reach 0 private constant real StartKBSpeed = 15. //Start Knockback Speed private constant boolean UseCasterAsAnchor = true //setting it to false will manipulate the knockback angle private constant boolean KBPauseUnit = true //set to false if you don't want to pause the knocked unit private constant damagetype DamageType = DAMAGE_TYPE_UNIVERSAL //UNIVERSAL don't take the armor amount in account while NORMAL does private constant attacktype AttackType = ATTACK_TYPE_CHAOS //What kind of damage you want to deal (Readme for more informations) private constant real PickRange = 100. //The collision range for target unit to knock units private constant real SpeedForMinDis = 5. //r-Speed to reach Min Distance private constant real StartCircleSpeed = 4. //Start Speed of target unit (in degree) private constant integer EffectInterval = 10 //How often a slide effect should be created, have to be > 0 private constant string SlideEffect = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl" //The slide effect private constant string HitEffectAdd = "Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl" //The additional collision effect private constant string HitEffect = "Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl" //The collision effect private constant string CasterEffect = "Abilities\\Spells\\Other\\Monsoon\\MonsoonRain.mdl" //The effect created @ the position of the caster private constant string ASeax = "DefaultEAXON" //Don't really know this option private constant boolean ASWantToFadeOut = false //Do you want to fade out the Sound effect? private constant integer ASFadeOut = 2 //Fadeout rate private constant integer ASFadeIn = 2 //Fadein rate private constant boolean ASCutoff = true //Should the sound stop playing when out of range? private constant boolean AS3D = true //Should it be a 3-D Sound? private constant boolean ASLoop = true //Loop ... private constant integer ASVolume = 200 //Volumen in % private constant integer ASDuration = 1622 //Sound duration, you can find it in the sound editor private constant integer ASoundChannel = 10 //The channel used by the sound private constant real ASCutoffRange = 10000. //Playing Range of this sound private constant string AmbientSound = "Abilities\\Spells\\Other\\Monsoon\\MonsoonRainLoop.wav" //The sound file path private constant string LightningId = "CLPB" //The lightning id ... private constant integer Abilityid = 'A000' //The id of the dummy ability private constant real TimerTimeOut = 0.03 //The Timer Time Out, lower values = smoother, but faster any maybe more buggy //*************************************************************************************** //* UCP ending * //*************************************************************************************** private timer Timer = CreateTimer() private integer loopi = 0 private Cast array glob private integer Integer = 0 private KnockBack array kbglob private integer kbInteger = 0 private group GetUnit = CreateGroup() private group KBGroup = CreateGroup() private group AlreadyTarget = CreateGroup() private item TerrainCheck private boolexpr Bex = null private rect TreeRect endglobals private struct Cast sound ambientsound = null unit caster = null real x1 = 0 real y1 = 0 unit target = null lightning l = null effect e1 = null effect e2 = null real damage = 0 real speed = 0 real angle = 0 real cdistance = 0 real mindistance = 0 real increament = 0 method onDestroy takes nothing returns nothing call DestroyLightning(this.l) call DestroyEffect(this.e1) call DestroyEffect(this.e2) call StopSound(this.ambientsound,true,ASWantToFadeOut) set this.caster = null set this.ambientsound = null set this.target = null set this.l = null set this.e1 = null set this.e2 = null endmethod endstruct private struct KnockBack unit u = null unit caster = null real speed = 0 real xfactor = 0 real yfactor = 0 integer i = 1 method onDestroy takes nothing returns nothing set this.u = null set this.caster = null endmethod endstruct //*********************************************************************************************** //* Conditions * //*********************************************************************************************** private function Cast_Conditions takes nothing returns boolean return GetSpellAbilityId() == Abilityid endfunction private function KBFilter takes nothing returns boolean local unit u = GetFilterUnit() local Cast dat = glob[loopi] return IsPlayerEnemy(GetOwningPlayer(u),GetOwningPlayer(dat.caster)) and u != dat.target and not IsUnitInGroup(u,KBGroup) and IsUnitType(u,UNIT_TYPE_GROUND) and GetWidgetLife(u) > .405 endfunction private function LoopConditions takes nothing returns boolean local Cast dat = glob[loopi] return GetUnitCurrentOrder(dat.caster) == orderid and orderid != 0 and GetWidgetLife(dat.caster) > .405 and GetWidgetLife(dat.target) > .405 endfunction //*********************************************************************************************** //* Knockback * //*********************************************************************************************** private function CreateKB takes nothing returns nothing local unit u = GetEnumUnit() local KnockBack kbdat = KnockBack.create() local Cast dat = glob[loopi] local real angle local real ux local real uy set kbdat.u = u call SetUnitPathing(u,false) if UseCasterAsAnchor then set angle = Atan2(GetUnitY(u)-GetUnitY(dat.caster),GetUnitX(u)-GetUnitX(dat.caster)) else set angle = Atan2(GetUnitY(u)-GetUnitY(dat.target),GetUnitX(u)-GetUnitX(dat.target)) endif if u != dat.target then set kbdat.speed = StartKBSpeed set ux = GetUnitX(u) set uy = GetUnitY(u) call DestroyEffect(AddSpecialEffect(HitEffectAdd,ux,uy)) call DestroyEffect(AddSpecialEffect(HitEffect,ux,uy)) call UnitDamageTarget(dat.caster,dat.target,dat.damage,true,false,AttackType,DamageType,WEAPON_TYPE_WHOKNOWS) call UnitDamageTarget(dat.caster,u,dat.damage,true,false,AttackType,DamageType,WEAPON_TYPE_WHOKNOWS) else set kbdat.speed = dat.cdistance*dat.speed*2/3 set angle = dat.angle+(bj_PI/2) endif set kbdat.xfactor = Cos(angle) set kbdat.yfactor = Sin(angle) call PauseUnit(u,KBPauseUnit) call SetUnitUserData(u,kbInteger) set kbdat.caster = dat.caster call GroupAddUnit(KBGroup,u) set kbglob[kbInteger] = kbdat set kbInteger = kbInteger + 1 set u = null endfunction private function KnockbackDestroyTrees takes nothing returns nothing call KillDestructable(GetEnumDestructable()) endfunction private function KBActions takes nothing returns nothing local unit u = GetEnumUnit() local integer i = GetUnitUserData(u) local KnockBack kbdat = kbglob[i] local real cx = GetUnitX(u)+(kbdat.xfactor*kbdat.speed) local real cy = GetUnitY(u)+(kbdat.yfactor*kbdat.speed) if kbdat.u == u then if DestroyTreesKnocked then call SetRect(TreeRect,cx-TreeHitR,cy-TreeHitR,cx+TreeHitR,cy+TreeHitR) call EnumDestructablesInRect(TreeRect,null,function KnockbackDestroyTrees) endif call SetItemPosition(TerrainCheck,cx,cy) if GetItemX(TerrainCheck)==cx and GetItemY(TerrainCheck)==cy then call SetUnitX(u,cx) call SetUnitY(u,cy) endif call SetItemVisible(TerrainCheck,false) set kbdat.speed = kbdat.speed - DecreaseKBSpeed set kbdat.i = kbdat.i + 1 if kbdat.i > EffectInterval then call DestroyEffect(AddSpecialEffect(SlideEffect,cx,cy)) set kbdat.i = kbdat.i - EffectInterval endif if kbdat.speed <= 0.405 then call SetUnitUserData(u,0) call PauseUnit(u,false) call SetUnitPathing(u,true) call IssueTargetOrder(u,"attack",kbdat.caster) call kbdat.destroy() set kbInteger = kbInteger - 1 if kbInteger > 0 then set kbglob[i] = kbglob[kbInteger] endif call GroupRemoveUnit(KBGroup,u) endif else call SetUnitUserData(u,0) call GroupRemoveUnit(KBGroup,u) call PauseUnit(u,false) call SetUnitPathing(u,true) endif set u = null endfunction //*********************************************************************************************** //* Cycle Actions * //*********************************************************************************************** private function Callback takes nothing returns nothing local Cast twdat local real x1 local real y1 local real x2 local real y2 set loopi = 0 loop exitwhen loopi >= Integer set twdat = glob[loopi] if GetWidgetLife(twdat.target) <= 0.405 then call IssueImmediateOrder(twdat.caster,"stop") endif if LoopConditions() then set x1 = twdat.x1 set y1 = twdat.y1 set twdat.angle = twdat.angle + twdat.speed set twdat.speed = twdat.speed + twdat.increament if twdat.cdistance >= twdat.mindistance + SpeedForMinDis then set twdat.cdistance = twdat.cdistance - SpeedForMinDis elseif twdat.cdistance <= twdat.mindistance - SpeedForMinDis then set twdat.cdistance = twdat.cdistance + SpeedForMinDis elseif twdat.cdistance != twdat.mindistance then set twdat.cdistance = twdat.mindistance endif if twdat.angle >= 2*bj_PI then set twdat.angle = twdat.angle - 2*bj_PI endif set x2 = x1+twdat.cdistance*Cos(twdat.angle) set y2 = y1+twdat.cdistance*Sin(twdat.angle) call SetUnitX(twdat.target,x2) call SetUnitY(twdat.target,y2) if DestroyTreesCycle then call SetRect(TreeRect,x2-TreeHitR,y2-TreeHitR,x2+TreeHitR,y2+TreeHitR) call EnumDestructablesInRect(TreeRect,null,function KnockbackDestroyTrees) endif call SetUnitFacing(twdat.target,twdat.angle*(bj_RADTODEG)) call SetUnitFacing(twdat.caster,twdat.angle*(bj_RADTODEG)) call MoveLightning(twdat.l,true,x1,y1,x2,y2) call GroupEnumUnitsInRange(GetUnit,x2,y2,PickRange,Bex) call ForGroup(GetUnit,function CreateKB) call GroupAddGroup(GetUnit,KBGroup) call GroupClear(GetUnit) set loopi = loopi + 1 else call GroupAddUnit(GetUnit,twdat.target) call ForGroup(GetUnit,function CreateKB) call GroupRemoveUnit(AlreadyTarget,twdat.target) call GroupClear(GetUnit) call twdat.destroy() set Integer = Integer - 1 set glob[loopi] = glob[Integer] endif endloop call ForGroup(KBGroup,function KBActions) if Integer <= 0 and kbInteger <= 0 then call PauseTimer(Timer) endif endfunction //*********************************************************************************************** //* Cast Actions * //*********************************************************************************************** private function Cast_Actions takes nothing returns nothing local unit caster = GetTriggerUnit() local unit target = GetSpellTargetUnit() local Cast twdat = Cast.create() local integer level = GetUnitAbilityLevel(caster,Abilityid) local real cx = GetUnitX(caster) local real cy = GetUnitY(caster) local real tx = GetUnitX(target) local real ty = GetUnitY(target) if target != null and not IsUnitInGroup(target,AlreadyTarget) then if orderid == 0 then set orderid = GetUnitCurrentOrder(caster) endif set twdat.caster = caster set twdat.target = target set twdat.l = AddLightning(LightningId,true,cx,cy,tx,ty) set twdat.ambientsound = CreateSound(AmbientSound,ASLoop,AS3D,ASCutoff,ASFadeIn,ASFadeOut,ASeax) call SetSoundDuration(twdat.ambientsound,ASDuration) call SetSoundChannel(twdat.ambientsound,ASoundChannel) call SetSoundDistanceCutoff(twdat.ambientsound,ASCutoffRange) call SetSoundVolume(twdat.ambientsound,ASVolume) call SetSoundPosition(twdat.ambientsound,cx,cy,32.00) call StartSound(twdat.ambientsound) set twdat.angle = Atan2(ty-cy,tx-cx) set twdat.speed = StartCircleSpeed*bj_DEGTORAD set twdat.increament = DecreaseCircleSpeed (level)*bj_DEGTORAD set twdat.x1 = cx set twdat.y1 = cy set twdat.cdistance = SquareRoot((tx-cx)*(tx-cx)+(ty-cy)*(ty-cy)) set twdat.mindistance = DistanceFormula(level) set twdat.damage = DamageFormula(level) set twdat.e1 = AddSpecialEffect(CasterEffect,cx,cy) set twdat.e2 = AddSpecialEffect(CasterEffect,cx,cy) set glob[Integer] = twdat call PauseUnit(target,true) call GroupAddUnit(AlreadyTarget,target) set Integer = Integer + 1 if Integer == 1 then call TimerStart(Timer,TimerTimeOut,true,function Callback ) endif else call PauseUnit(caster,true) call IssueImmediateOrder(caster,"stop") call PauseUnit(caster,false) endif set caster = null set target = null endfunction public function InitTrig takes nothing returns nothing local trigger tr = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(tr, EVENT_PLAYER_UNIT_SPELL_CHANNEL ) call TriggerAddCondition(tr, Condition( function Cast_Conditions ) ) call TriggerAddAction(tr, function Cast_Actions ) call Preload(LightningId) call Preload(CasterEffect) call Preload(HitEffect) call Preload(HitEffectAdd) call Preload(SlideEffect) set Bex = Condition(function KBFilter) set TreeRect = Rect(256.0 , 2400.0 , 448.0 , 2656.0) set TerrainCheck = CreateItem(TerrainItem,0.00,0.00) call SetItemVisible(TerrainCheck,false) endfunction endscope ---Update v.1.2 --- fixed/added all things mentioned by Alexander244, hadn't much time yet to test everything, but it should work without any problem. ---Update v.1.3 --- sorry for the long waiting for an update, were pretty busied, however i hope everything is fine now. ---Update v1.3b --- Fixed a more or less serious thing in the callback function. ---Update v1.3c --- Some code lines were removed, also i made the scope change suggested by moyack ---Update v1.3d --- Hopefully the last update, made the structs private, added the option to set the size of the destructable rect and change some smaller parts. |
| 08-24-2007, 04:17 PM | #2 |
Ooh... Looks nice. |
| 08-24-2007, 04:56 PM | #3 |
Well the code looks great, I only don't like this: JASS:
set tw_destroytrees = Rect(256.0 , 2400.0 , 448.0 , 2656.0)
hardcoded things are BAD. either turn this into constants or put a good comment above that line to explain wtf is that. Besides from that spell could use a main comment header describing in general terms how it works. Good coding is not enough, you have to document it so people would understand it. And people tend to forget even what their own code was doing after a while. Comments, comments, comments... ... more comments. |
| 08-24-2007, 06:49 PM | #4 |
I liked it a lot in the spell session, and it's even better now :) Initial feedback:
|
| 08-24-2007, 07:22 PM | #5 |
1. ok, i'll add the option to configure both seperat 2. I'll add a option for that too 3. Ok, thanks will be fixed next version 4. Not a big deal will be added 5. Ok, i'll write it in the Read Me 6. Ok, no big problem either 7. done I'll do everything tomorrow and update the first post then. |
| 08-25-2007, 02:24 PM | #6 |
A few more things;
|
| 08-26-2007, 11:57 AM | #7 |
1. i know, but it won't do it due it doesn't have any affect of the performance 2. i gonna change that 3. omg, thank you very much, i really hate it when such a thing happens 4. ok, will be inlined 5. fixed it with an attack command instead of doing damage, no nasty work around required then ![]() Don't know if i'll update the spell today, maybe tomorrow. Offtopic: +rep for reviewing and suggestions |
| 08-27-2007, 12:09 PM | #8 |
Haven't read the other posts so I may repeat others' points.
|
| 09-04-2007, 01:34 AM | #9 |
Other comments:
|
| 09-25-2007, 01:02 AM | #10 |
Nearly three weeks after the fact... Will this be seeing an update in the near future? If not, I fear I may be toasting it. |
| 09-30-2007, 06:49 AM | #11 |
Oh it looks good, I'm gonna try it :D Btw, Mr.Dusk, when's the next spell session? I've browsed previous spell sessions before and they were great. |
| 10-01-2007, 08:35 PM | #12 | |
Quote:
And whenever I can think up a decent theme for it and I sort out the results of the last one. I may end up just forfeiting my win so that people don't think I cheated or hacked or some shit. See my signature for more information, I covered most of it there. And just so other mods know -- He updated this and didn't post to bump it. (He actually PMed me that he did) So don't graveyard this until it gets at least a few more rounds of review. |
| 10-09-2007, 01:05 AM | #13 |
@Fireeye: Please post when you have a new version or improvement please, Rising_Dusk is not the only moderator here. I've checked Fireeye's spell, and here's what I've found thus far:
|
| 10-09-2007, 12:47 PM | #14 |
Ok, i gonna post when i'm updating the spell. However i found a serious but dumb mistake in my own Spell... These 2 lines cause a problem, which will let the target unit orbit TOO fast around the caster, don't know why i wrote there a RADTODEG, i already fixed it (Removing the *57.29577 part). JASS:set x2 = x1+twdat.cdistance*Cos(twdat.angle*57.29577) set y2 = y1+twdat.cdistance*Sin(twdat.angle*57.29577) Do you mean using something like this? JASS:
public function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
call TriggerAddCondition( t, Condition( function Cast_Conditions ) )
call TriggerAddAction( t, function Cast_Actions )
call Preload(LightningId)
call Preload(CasterEffect)
call Preload(HitEffect)
call Preload(HitEffectAdd)
call Preload(SlideEffect)
set Bex = Condition(function KBFilter)
set TreeRect = Rect(256.0 , 2400.0 , 448.0 , 2656.0)
set TerrainCheck = CreateItem(TerrainItem,0.00,0.00)
call SetItemVisible(TerrainCheck,false)
endfunction
set glob[Integer] = twdat but i'm too lazy to make test right now so i changed it Any other constructive critiques are welcome. |
| 10-10-2007, 05:46 PM | #15 | |
Quote:
I mean this: JASS:scope ThunderWhirl // Here's the globals, structs and all other stuff used // This function will say good bye!!! // public function preload takes nothing returns nothing // call Preload(LightningId) // call Preload(CasterEffect) // call Preload(HitEffect) // call Preload(HitEffectAdd) // call Preload(SlideEffect) // set Bex = Condition(function KBFilter) // set TreeRect = Rect(256.0 , 2400.0 , 448.0 , 2656.0) // set TerrainCheck = CreateItem(TerrainItem,0.00,0.00) // call SetItemVisible(TerrainCheck,false) // endfunction // the other code //=========================================================================== function InitTrig_ThunderWhirl takes nothing returns nothing // call ExecuteFunc("ThunderWhirl_preload") Bye bye function XD set gg_trg_ThunderWhirl = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_ThunderWhirl, EVENT_PLAYER_UNIT_SPELL_CHANNEL ) call TriggerAddCondition( gg_trg_ThunderWhirl, Condition( function Cast_Conditions ) ) // check that I've removed the prefixes call TriggerAddAction( gg_trg_ThunderWhirl, function Cast_Actions ) // because this function now is inside the scope. call Preload(LightningId) call Preload(CasterEffect) call Preload(HitEffect) call Preload(HitEffectAdd) call Preload(SlideEffect) set Bex = Condition(function KBFilter) set TreeRect = Rect(256.0 , 2400.0 , 448.0 , 2656.0) set TerrainCheck = CreateItem(TerrainItem,0.00,0.00) call SetItemVisible(TerrainCheck,false) endfunction endscope //<= Check where did I put the endscope About this line of code set glob[Integer] = integer(twdat), it is mandatory in order to guarantee compatibility with newer versions of JassHelper, because this will generate a serious syntax error. EDIT: Here's the thread related with the integer() stuff: http://www.wc3campaigns.net/showthread.php?t=96463 |
