Spell Homing Missiles

Prometheus

Everything is mutable; nothing is sacred
Reaction score
590
Homing Missiles

Import Diff: 2/10 ~ Copying all the abilities
MUI: Yes
JESP: Yes
Constants: Yes
Units Affected: Enemy, Vulnerable
Target Type: Non-Target
Spell Info:

The caster shoots out a number of slow moving fire balls that last for 10 seconds. The fire balls will chase the randomly targeted units until they come it contact with them.

Level 1 - Shoots out 4 missiles, 100 damage if hit.
Level 2 - Shoots out 8 missiles, 200 damage if hit.
Level 3 - Shoots out 12 missiles, 300 damage if hit.

Screenie.jpg


JASS:
scope HM initializer Init
//***************************************
//      Spell Name: Homing Missiles     *
//      Spell Author: kc102/R34P3R      *
//      Optimized for vJass!            *
//***************************************

//*************************************
//    Start Configuration Functions
//*************************************
    globals
        private constant integer ABID = 'A000'
            //Replace A000 with your spell ID.
        private constant integer TRACK = 'n000'
            //The ID of the unit that follows the enemies so the flame can see them.
        private constant integer DUMID = 'n002'
            //The ID for the dummy unit.
        private constant integer DUMSPL = 'A003'
            //The ID for the dummy units spell.
        private constant integer BASENUM = 4
            //This is how many BASE units this spell will create. Meaning, at level 2 it will be 8.
        private constant real RANGE = 500
            //This is the BASE range in which we will grab a unit. Meaning, at level 2 it will be 1000.
        private constant string AUTOID = "selfdestructon"
            //The orderstring so the units autoexplodes.
        private constant string MOVE = "attackonce"
            //Makes the unit move.
        private constant string FX = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeTarget.mdl"
            //The effects attached to the unit.
        private constant string ATCHPNT = "origin"
            //Where the effect attaches to.
    endglobals
    // NoTe
    // Open up the object editor and find "Dummy Unit (Homing)", its ID is n002.
    // The tracking unit is called "Dummy Unit (Tracker)" and its ID is n000.
    // Created units last for 10 seconds, this is changable VIA the object editor.
    // They have 10 HP with a -1 regen.
    // The fields are Hit Points Maximum Base and Hit Points Regneration Rate.
    //                  The HP of the unit.             The units HP regen.
    // To edit damage, open up the object editor and find the ability "Homing Blowup (A003)"
    // Edit the level damage as you wish, it's called Full Damage Amount and Partial Damage Amount.
    // The missles have an immolation like spell.
    // To edit that find "Homing Damage (A001)" and edit the field "Damage per Interval".
    
    private constant function GetRange takes integer lvl returns real
        return RANGE*lvl
        //This function takes the above variable, RANGE, and multiplies it by the units spell level.
    endfunction
    private function GetNum takes integer lvl returns integer
        return BASENUM*lvl
        //This function takes the variable BASENUM, and multiplies it by the units spell level.
    endfunction
//*************************************
//     End Configuration Functions
//     Do not edit further unless you know what you're doing.
//*************************************
    
    globals
        private group g = CreateGroup()
        private unit caster
        private unit dummy
        private unit target
        private player pq
        private integer splvl
        private real cx
        private real cy
    endglobals
    
    private function FailSafe takes nothing returns boolean
        return true
    endfunction
    
    private function HIsAlly takes nothing returns boolean      
        if IsUnitEnemy(GetFilterUnit(),pq) and GetWidgetLife(GetFilterUnit()) > 0.405 then
            call DestroyEffect(AddSpecialEffectTarget(FX,caster,ATCHPNT))
            set dummy = CreateUnit(pq,DUMID,cx,cy,0.00)
            call SetUnitAbilityLevel(dummy,DUMSPL,splvl)
            set target = GetFilterUnit()
            call IssueImmediateOrder(dummy,AUTOID)
            call IssueTargetOrder(dummy,MOVE,target)
            set dummy = CreateUnit(pq,TRACK,GetUnitX(target),GetUnitY(target),0.00)
            call IssueTargetOrder(dummy, "move", target)
        endif
        return false
    endfunction
    
    private function HMC takes nothing returns boolean
        return GetSpellAbilityId() == ABID
    endfunction
    
    private function HMA takes nothing returns nothing
        set caster = GetTriggerUnit()
        set splvl = GetUnitAbilityLevel(caster,ABID)
        set cx = GetUnitX(caster)
        set cy = GetUnitY(caster)
        set pq = GetOwningPlayer(caster)
        
        call GroupEnumUnitsInRangeCounted(g,cx,cy,GetRange(splvl),Condition(function HIsAlly),GetNum(splvl))
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
    
        loop
        exitwhen i > 11
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,Condition(function FailSafe))
            set i = i + 1
        endloop
    
        call TriggerAddAction(t,function HMA)
        call TriggerAddCondition(t,Condition(function HMC))
    endfunction
endscope


Code:
Changelog:
1.0 - Released
1.4 - Leak cleaned, Integrated flame life into spell, Locust re-added to the dummy units, Code improved
1.5 - Code improved at Rinpun's suggestion
2.0 - Missiles Blow Up Correctly, Added a tracking unit so the missile won't lose sight of the enemy, Various other changes
2.4 - Code is now JESP
2.5 - Some useless code removed
2.7 - Various Changes
4.0 - Changed to 4.0 because of major update. Uses vJass now.
4.1 - Further code improvements.
4.2 - Further, minor improvements.
4.3 -           ||
4.4 -           ||
4.5 - Global blocks split
 

Attachments

  • Homing Missiles.w3x
    42.4 KB · Views: 422

Prometheus

Everything is mutable; nothing is sacred
Reaction score
590
Good spell! :D

Thanks

Quite a good spell, but, the Fire balls can be selected.
You need to give them the locust ability to prevent that.

The balls also last a bit too long IMO.

Yea, I removed it for certain testing purposes and forgot to readd them.
You can change how long they last in the object editor, 100 seconds, 100hp with -hp per second regen.

a screenie?

I'll upload in a min.


Edit: Stuff done! SS added!

Edit2: Is this spell JESP?

Edit3: Code improved
 

Pyrogasm

There are some who would use any excuse to ban me.
Reaction score
134
kc102 said:
Edit2: Is this spell JESP?
You don't have nearly enough constants.

In addition, all of your constants (or at least the math-related ones) should take an integer argument "level", such that people can do things like
JASS:
constant function HM_Length takes integer Level returns real
    return 100.00*(Level/3.00)+Pwr(2.00, Level)
endfunction

Instead of having to find where it's used in the code.

Also, Condition(function HM_IsAlly)) leaks a Boolexpr, and GetUnitsInRangeOfLocMatching(...) is a BJ function; replace it with the appropriate natives.

Last, all of your constants should be in one big block at the top of the code, and the spell should have a header like so:
JASS:
//***************************************
//      Spell Name: Homing Missiles     *
//          Spell Author: kc102         *
//       Follows the JESP Standard      *
//***************************************

//*************************************
//    Start Configuration Functions    
//*************************************

constant function HM_Length takes integer Level returns real
    return 100.00*(Level/3.00)+Pwr(2.00, Level)
endfunction

//And so on and so forth...

//*************************************
//     End Configuration Functions     
//*************************************
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Nice spell! I didn't actually look and download the map, but the code is good! :p

Anyways, though it does not seem it, there were a couple of BJs that I removed, here is the improved version:
JASS:
//////////////////////////////////////////////////////////////////////////
//  Homing Missiles are created whenever you cast the spell provided.
//  By design, only alive and enemy units are attacked by the homing missiles.
//////////////////////////////////////////////////////////////////////////

constant function HM_RawSpellCode takes nothing returns integer
	return 'A000' //Replace A000 with your spell ID.
endfunction

constant function HM_GetTarget takes nothing returns real
	return 500.00 //This is the range in which we will grab a unit.
endfunction

constant function HM_Loops takes nothing returns integer
    return 4 //This is how many units this spell will create, this is multiplied by the level of the ability. Change this to create or lessen the units created per level.
endfunction

constant function HM_Length takes nothing returns real
	return 100.00 //This is how long the flame lasts.
endfunction

function HM_IsAlly takes nothing returns boolean
	return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) and GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 //This checks to make sure we will only attack enemy units and alive units.
endfunction

function HM_Dummy_ID takes integer i returns integer
	local integer array p //Replace the n001, n002 and n003 with your dummy units IDs, I have created an ability for each.
	set p[1] = 'n002'
	set p[2] = 'n003'
	set p[3] = 'n001'
	return p<i>
endfunction

function HM_Actions takes nothing returns nothing
	local unit caster = GetTriggerUnit()
	local unit dummy
	local unit target
	local integer splvl = GetUnitAbilityLevel(caster, HM_RawSpellCode())
    	local integer loopa = 1
	local integer failsafe
	local real cx = GetUnitX(caster)
	local real cy = GetUnitY(caster)
	local group g = CreateGroup()
	call GroupEnumUnitsInRange(g,cx,cy,HM_GetTarget(),Condition(function HM_IsAlly))
	loop
	exitwhen loopa &gt; splvl * HM_Loops()
		set failsafe = CountUnitsInGroup(g)
		if failsafe &lt;= 0 then
			set dummy = null              
			set target = null
			set caster = null
			call GroupClear(g)
			call DestroyGroup(g)
			set g = null
			return
		endif
		set dummy = CreateUnit(GetOwningPlayer(caster), HM_Dummy_ID(splvl), cx, cy, 0.00)
		set target = FirstOfGroup(g)
		call SelectUnit(dummy,false)
		call IssueImmediateOrder(dummy, &quot;selfdestructon&quot;)
		call IssueTargetOrder(dummy, &quot;attackonce&quot;, target)
		call GroupRemoveUnit(g, target)
		call UnitApplyTimedLife(dummy, &#039;BTLF&#039;, HM_Length())
		set dummy = null
		set target = null
		set loopa = loopa + 1
	endloop
	set caster = null
	call GroupClear(g)
	call DestroyGroup(g)
endfunction

//===========================================================================
function HM_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == HM_RawSpellCode()
endfunction

function InitTrig_Homing_Missiles takes nothing returns nothing
    set gg_trg_Homing_Missiles = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Homing_Missiles, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Homing_Missiles, Condition(function HM_Conditions))
    call TriggerAddAction(gg_trg_Homing_Missiles, function HM_Actions)
endfunction</i>


@Pyrogasm: Boolexprs don't leak. If they did leak, every single GUI trigger in the entire universe for WE would leak a boolexpr due to the fact that TriggerAddCondition uses "Condition()".

@kc102: GetUnitsInRangeOfLocMatching is hazardous (dangerous :p) to use because it destroys the boolexpr, which is what you do not want to do. :)

Good job, +REP if I can!!
 

Pyrogasm

There are some who would use any excuse to ban me.
Reaction score
134
I believe that the issue of Boolexprs is a moot point. Vexorian ran tests, but I don't think most people really know whether or not destroying them is a bad idea and/or if they leak.

I said they did because I've always thought they did, else there wouldn't be the DestroyBoolExpr(whichBoolexpr) native.

Additionally, the reason that TriggerAddCondition(...) uses "Condition(function ...)" instead of a boolexpr variable is that if you did this:
JASS:
function InitTrig_SomeTrigger takes nothing returns nothing
    local boolexpr B = Condition(function SomeConditionFunc)
    call TriggerAddAction(gg_trg_SomeTrigger, B)
    call DestroyBoolExpr(B)
    set B = null
endfunction

The trigger would never pass the condition, since it wouldn't exist after being destroyed.
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
:D Well, not only Vexorian said that, grim001, Earth-Fury, and many more said not to destroy condition Boolexprs. I know it exists, but I thought that would be for something like "Filter()" or somethin'.

Anyways, go ahead and believe what you want; I'm not trying to convert you. :p

Also, "TriggerAddAction" doesn't take Boolexprs!! lol :D
Pyrogasm said:

Code:
function InitTrig_SomeTrigger takes nothing returns nothing
    local boolexpr B = Condition(function SomeConditionFunc)
    [B]call TriggerAddAction(gg_trg_SomeTrigger, B)[/B]
    call DestroyBoolExpr(B)
    set B = null
endfunction
 

Halo_king116

Working As Intended
Reaction score
153
NOTE that I am using the first version you sent me.

I found it annoying to test. The units swarmed on me and it killed them all instantly when I used the move. I didn't get to see what exactly happened. Gibe her blink, and maybe make the footmen walk a bit slower. Make the creeps respawn after a while.

Also, the flames live for too long, IMO. That damage is insane too, if the units are all close to them. They would get OWNED. And especially with the time they last, anyone nearby is doomed :p

Yes, add locust, or was it meant to be able to control? Doubt it, but that would be cool.


My thoughts :) Good job.
 

Prometheus

Everything is mutable; nothing is sacred
Reaction score
590
The fireballs fly, I need to fix that and I will ASAP.
 

Prometheus

Everything is mutable; nothing is sacred
Reaction score
590
~-\|/Updated\|/-~
Check changelog for some of the changes
 

Prometheus

Everything is mutable; nothing is sacred
Reaction score
590
Its versatility
And the rest is on our IM conversation.
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Fan of knives doesn't use specific projectiles. That's what makes this better. The actual fan of knives has an effect that actually plays its animation to make the effect, it isn't a bunch of projectiles.

I also believe fan of knives can't have a projectile speed.

And I think this one is homing, but I never looked.

@kc102:
Well, it seems you didn't correctly c'n'p my code:
JASS:
local location l = Location(cx,cy)
...
call RemoveLocation(l)
set l = null


This is bad because it wastes 3 whole lines and it isn't even being used! :p

Just remove this and you should be set to go! :D
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
No, if I just use Location(cx, cy) it leaks.

But you don't even use it. xD

When I optimized you code, you used GetUnitsInRangeOfLoc or something like that. This creates a group and gets the units in range of the loc, but it is a BJ. So you made the "cx and cy" into a location. So I thought of removing the BJ. To remove it, did "local group g = CreateGroup()" then I just simply did "call GroupEnumUnitsInRange(g,cx,cy,blahblah)". So that means that I used "cx and cy" not the location so that location is useless thus can be removed. :D
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/
  • The Helper The Helper:
    I think we need to add something to the bottom of the front page that shows the Headline News forum that has a link to go to the News Forum Index so people can see there is more news. Do you guys see what I am saying, lets say you read all the articles on the front page and you get to the end and it just ends, no kind of link for MOAR!

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top