Template Projectile Template!

Vestras

Retired
Reaction score
249
I created this because many people asked how to make a projectile explode when it got into range of enemy units. Well, I created this to show how easy it is.

Uses CSSafety and ABC.
Requires NewGen and little-medium JASS experience.

Code:
JASS:
library PST

globals
// Below: Needed for the code, don't edit.
private unit GLOBALUNIT
private real Range
private attacktype Atype
private damagetype Dtype
private real dmg
private string sfx
endglobals

private struct Data
     timer t
     timer ti
     unit dummy
     unit caster
     real facing
     real createx
     real createy
     location currentloc
     player owner
     trigger dietrig
     
        private method onDestroy takes nothing returns nothing
        call ReleaseTimer(.t)
        call ReleaseTimer(.ti)
        call ClearTimerStructA(.t)
        call ClearTimerStructA(.ti)
        call RemoveLocation(.currentloc)
        set .currentloc = null
        set .dummy = null
        set .owner = null
        set .createy = 0.00
        set .createx = 0.00
        set .facing = 0.00
        set .t = null
        set .ti = null
        call DestroyTimer(.t)
        call DestroyTimer(.ti)
        endmethod
endstruct

private function Move takes nothing returns nothing
   local Data d = GetTimerStructA(GetExpiredTimer())
   local real x
   local real y
   
   set x = GetLocationX(d.currentloc) + 5.00 * Cos(d.facing * bj_DEGTORAD)
   set y = GetLocationY(d.currentloc) + 5.00 * Sin(d.facing * bj_DEGTORAD)
   
        call SetUnitPosition(d.dummy, x, y)
        set d.currentloc = GetUnitLoc(d.dummy)
        
        set x = 0.00
        set y = 0.00
endfunction

private function Group takes nothing returns nothing
local unit u = GetEnumUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
   call DestroyEffect(AddSpecialEffect(sfx, x, y))
   call UnitDamageTarget(GLOBALUNIT, u, dmg, false, true, Atype, Dtype, WEAPON_TYPE_WHOKNOWS)
endfunction

private function InRangeConds takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GLOBALUNIT)) == true ) and ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false ) and ( GetWidgetLife(GetFilterUnit())>.405 )
endfunction

private function InRange takes nothing returns boolean
    local Data d = GetTimerStructA(GetExpiredTimer())
    local real x = GetLocationX(d.currentloc)
    local real y = GetLocationY(d.currentloc)
    local group g = CreateGroup()
    
    call GroupEnumUnitsInRange(g, x, y, Range, Filter(function InRangeConds))
    call ForGroup(g, function Group)
    
      if CountUnitsInGroup(g) >= 1 then
        call ClearTriggerStructA(d.dietrig)
        call DestroyTrigger(d.dietrig)
        set d.dietrig = null
        call KillUnit(d.dummy)
        call d.destroy()
    endif
    return false
endfunction

private function GroupConds takes nothing returns boolean
   return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GLOBALUNIT)) == true ) and ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false ) and ( GetWidgetLife(GetFilterUnit())<.405 )
endfunction

private function DummyDie takes nothing returns boolean
    local Data d = GetTriggerStructA(GetTriggeringTrigger())
    local real x = GetUnitX(d.dummy)
    local real y = GetUnitY(d.dummy)
    local unit u
    local group g = CreateGroup()
    call GroupEnumUnitsInRange(g, x, y, 256.0, Filter(function GroupConds))
    
        call DestroyEffect(AddSpecialEffect(sfx, x, y))
        call KillUnit(d.dummy)
        loop
            set u = FirstOfGroup(g)
            exitwhen CountUnitsInGroup(g) <= 0
               call UnitDamageTarget(d.caster, u, dmg, false, true, Atype, Dtype, WEAPON_TYPE_WHOKNOWS)
            call GroupRemoveUnit(g, u)
        endloop
        call d.destroy()
    
    call DestroyGroup(g)
    set g = null
    set u = null
    return false
endfunction

public function Create takes integer DummyID, string FX, real Damage, real r, real LivingTime, attacktype attype, damagetype datype returns nothing
     local Data d = Data.create()
     set d.caster = GetTriggerUnit()
     set d.owner = GetOwningPlayer(d.caster)
     set d.facing = GetUnitFacing(d.caster)
     set d.createx = GetUnitX(d.caster) + 35.00 * Cos(d.facing * bj_DEGTORAD)
     set d.createy = GetUnitY(d.caster) + 35.00 * Sin(d.facing * bj_DEGTORAD)
     set d.dummy = CreateUnit(d.owner, DummyID, d.createx, d.createy, d.facing)
     set d.currentloc = GetUnitLoc(d.dummy)
     set sfx = FX
     set GLOBALUNIT = d.caster
     set Range = r
     set Atype = attype
     set Dtype = datype
     set dmg = Damage
     
    call UnitApplyTimedLife(d.dummy, 'BTLF', LivingTime)
     
    set d.t = NewTimer()
    call SetTimerStructA(d.t, d)
    call TimerStart(d.t, 0.01, true, function Move)
    
    set d.ti = NewTimer()
    call SetTimerStructA(d.ti, d)
    call TimerStart(d.ti, 0.01, true, function InRange)
    
    set d.dietrig = CreateTrigger()
    call TriggerRegisterUnitEvent(d.dietrig, d.dummy, EVENT_UNIT_DEATH)
    call TriggerAddCondition(d.dietrig, Filter(function DummyDie))
    call SetTriggerStructA(d.dietrig, d)
endfunction

endlibrary


Screenshot:
Not needed, it's just a fireball being fired of.

Well, enjoy.
 

Flare

Stops copies me!
Reaction score
662
Does entering unit work for InRange?

Also, how does this help people with very little JASS experience? I doubt they can even read it, so how can they use it effectively? Wouldn't it be much simpler to allow you call the function with a given max distance, dummy unit, angle, damage, speed etc? Makes it easier for the end-user (even though it can result in a long function call :p)

You should make the Damage into a function that takes a unit argument (so people can deal stat-based damage, or scaling damage, for example)

Also, I don't see where .inrangetrig is destroyed :p
 

Vestras

Retired
Reaction score
249
Does entering unit work for InRange?

Also, how does this help people with very little JASS experience? I doubt they can even read it, so how can they use it effectively? Wouldn't it be much simpler to allow you call the function with a given max distance, dummy unit, angle etc? Makes it easier for the end-user (even though is can result in a long function call :p)

Also, I don't see where .inrangetrig is destroyed :p

Does a trigger need to be destroyed? I just nulled it.

Uhm.. Well, maybe I should change it to little-medium JASS experience. Hehe.

And yes, entering unit works for InRange.
 

Trollvottel

never aging title
Reaction score
262

Insane!

Shh I didn't edit this, go away.
Reaction score
122
When copying into your map, remember to delete the line in the function "InRangeConds"! There is text beside the line you should delete.


you may want to mention that its somewere in the middle of your code, else newbs may try and look up top were the object id's are placed.

Edit:
how would we set the damage in a range (say 1 - 100)? i belive adding that would make your trigger more usefull.
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
I can't see why anyone with limited JASS knowledge would know how to use this properly. A SetUnitXY function with arguments would be a lot easier to use for any GUI user.
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
There are a few leaks, and it desyncs for Macs (I think... Well it should :p )..

I'll optimize it and fix the stuff for joo, hold on a sec.
 

Vestras

Retired
Reaction score
249
There are a few leaks, and it desyncs for Macs (I think... Well it should :p )..

I'll optimize it and fix the stuff for joo, hold on a sec.

No, please, I'll do it myself.


I am gonna make it so that you will only need to call a function. Like;

JASS:
call PST_Actions('h000', "(My fx string)")


Would that be better?

And trollvottel, I'm not blind :p

What does indent mean?
 

Flare

Stops copies me!
Reaction score
662
What does indent mean?

If you take a look at dictionary.com's meaning of indentation
the leaving of space or the amount of space left between a margin and the start of an indented line

Link (but that's just how I go about indenting code, I'm sure other users have different ways of doing it)

If you can't see the difference between the indentation and no indentation there... and incase you think your current code is indented, it is, but not very well at all.

And you are gonna need a much longer function call than that :p (I can see at least 6 or 7 arguments being required)
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Ok, fine I won't. :p

Anyway, I've heard that UnitDamagePoint desyncs for macs (I think, something along those lines) so you should instead use a group and loop through each unit, dealing damage. It is a simple technique. You can probably use FirstOfGroup() looping, it might be a bit of a hassle doing otherwise.
 

Vestras

Retired
Reaction score
249
Ok, fine I won't. :p

Anyway, I've heard that UnitDamagePoint desyncs for macs (I think, something along those lines) so you should instead use a group and loop through each unit, dealing damage. It is a simple technique. You can probably use FirstOfGroup() looping, it might be a bit of a hassle doing otherwise.

I will.

Why isn't it MUI? couldn't I just use PUI, then?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • 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

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top