Tutorial Creating Realistic Projectiles With The Particle System (W.I.P.)

l-hate_you

New Member
Reaction score
6
Need help

I'm not Mr.JASS or anything but I've been pretty successful with this tutorial. The trigger will create a grenade at the correct spawn point and the grenade will explode in the alotted time but there is no arc [or bounce.] (There may be bounce but it has never arced correctly to allow me to see it happen.) When I cast the spell the grenade is created and simply moves straight upwards slowly before exploding correctly in a few seconds. There is no X or Y movement :confused:

Note: I have imported all the JASS native script into my map from both the vector and LinkedList systems, my prediction that either my trigger is wrong or the ParticleMain trigger is messed up (exact version from the map, which is in my map, is posted) So here they are. I based my casting trigger off of Chocobo's JASS because the original trigger only did what I stated above but... Chocobo's is no different. (I assume that it is intended that both triggers do the same thing but Chocobos is more interchangeable)

Main Trigger, Same as Chocobo's version but with my own Ability Raw Code
JASS:
function Trig_Grenade_Conditions takes nothing returns boolean
return GetSpellAbilityId()=='A00R'
endfunction


function DestroyEffectTimed takes effect eff,real duration returns nothing
call PolledWait(duration)
call DestroyEffect(eff)
endfunction

function Trig_Grenade_Actions takes nothing returns nothing
local unit h=GetSpellAbilityUnit()
local location l=GetSpellTargetLoc()
local real x=GetLocationX(l)-GetUnitX(h)
local real y=GetLocationY(l)-GetUnitY(h)
local real a=Atan2BJ(y,x)
local real aoa
local unit u=CreateParticle(GetOwningPlayer(h),'e000',GetUnitX(h),GetUnitY(h),a)
local real array r
local integer i=udg_clsParticlePlace[GetUnitUserData(u)]
set udg_vectorX<i>=udg_vectorX<i>-udg_vectorX[SpawnPlaceOffset()]*CosBJ(a)
set udg_vectorY<i>=udg_vectorY<i>-udg_vectorY[SpawnPlaceOffset()]*SinBJ(a)
set udg_vectorZ<i>=udg_vectorZ<i>-udg_vectorZ[SpawnPlaceOffset()]+1
set r[2]=750
set r[0]=RMinBJ(r[2],SquareRoot(x*x+y*y))
set r[1]=SquareRoot(r[2]*VectorGetLength(G()))
set aoa=(bj_PI/2)-(Asin((r[0]*VectorGetLength(G()))/(r[1]*r[1]))/2)
call SetUnitTimeScalePercent(u,10.00)
call ParticleSetSpeed(u,Cos(aoa)*CosBJ(a)*r[1],Cos(aoa)*SinBJ(a)*r[1],r[1]*Sin(aoa))
call ParticleAddForce(u,G())
call ParticleLinkConditionTrigger2Func(u,ParticleGroundHit(),&quot;GroundHit_Bounce&quot;)
call ParticleLinkConditionTrigger2Func(u,ParticleDeath(),&quot;Death_ExplodeNade&quot;)
call UnitApplyTimedLife(u,&#039;BTLF&#039;,2.)
set l=null
set h=null
set u=null
endfunction

function DamageArea takes unit source,real maxdmg,integer damageV,real radius returns nothing
local integer i=0
local integer originV
local real array r
local group g=CreateGroup()
local unit c
call GroupEnumUnitsInRange(g,udg_vectorX[damageV],udg_vectorY[damageV],radius,null)
loop
set c=FirstOfGroup(g)
exitwhen c==null
if GetUnitState(c,UNIT_STATE_LIFE)&gt;0 then
set r[0]=GetUnitX(c)
set r[1]=GetUnitY(c)
set r[2]=GetZ(r[0],r[1])
set originV=VectorCreate(r[0],r[1],r[2])
if IsPointInSphere(originV,damageV,radius) then
call VectorSubtract(originV,damageV)
set r[5]=(radius-VectorGetLength(originV))/radius*maxdmg
call UnitDamageTarget(source,c,r[5],true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
call VectorDestroy(originV)
endif
call GroupRemoveUnit(g,c)
endloop
call DestroyGroup(g)
set g=null
set c=null
endfunction


function CreateExplosion takes player p,string path,real x,real y,real z,real facing,real size,real time returns nothing
local unit u=CreateUnit(p,&#039;e001&#039;,x,y,facing)
local effect e
call SetUnitX(u,x)
call SetUnitY(u,y)
call MakeUnitFlyable(u)
call SetUnitAnimationByIndex(u,90)
call SetUnitScale(u,size,size,size)
call SetUnitFlyHeight(u,z-GetZ(x,y),0)
if time==0 then
call DestroyEffect(AddSpecialEffectTarget(path,u,&quot;origin&quot;))
else
set e=AddSpecialEffectTarget(path,u,&quot;origin&quot;)
endif
call KillUnit(u)
set u=null
if time&gt;0 then
call DestroyEffectTimed(e,time)
endif
set e=null
endfunction




function Death_ExplodeNade takes nothing returns nothing
local unit u=GetEnumUnit()
local integer p=udg_clsParticlePlace[GetUnitUserData(u)]
call CreateExplosion(GetOwningPlayer(u),&quot;Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl&quot;,udg_vectorX[p],udg_vectorY[p],udg_vectorZ[p],GetRandomReal(0,360),1.,5.)
call CreateExplosion(GetOwningPlayer(u),&quot;Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl&quot;,udg_vectorX[p],udg_vectorY[p],udg_vectorZ[p],GetRandomReal(0,360),3.,0)
call DamageArea(u,275,p,256.)
call RemoveParticle(u,true)
set u=null
endfunction


//===========================================================================
function InitTrig_Grenade takes nothing returns nothing
    set gg_trg_Grenade = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Grenade, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Grenade, Condition( function Trig_Grenade_Conditions ) )
    call TriggerAddAction( gg_trg_Grenade, function Trig_Grenade_Actions )
endfunction</i></i></i></i></i></i>


Exact character-for-character version of the first Particle System trigger from the map posted on the first post of this thread
JASS:


// ************************************************************************************************************************
// **                                                                                                                    **
// **                                      Particle Engine, moving objects dynamically                                   **
// **                                                  Created by iNfraNe                                                **
// **                                                                                                                    **
// ************************************************************************************************************************

//                                                  USER CHANGABLE CONSTANTS

constant function ParticlePeriod takes nothing returns real
  return 0.025 //Warning: changing this value may cause lag.
endfunction

constant function DummyRawCode takes nothing returns integer
  return &#039;e000&#039; //Special dummy unit, having animations for changing angle on projectiles
endfunction

function SpawnPlaceOffset takes nothing returns integer
  if udg_particleSpawnOffset == 0 then
    set udg_particleSpawnOffset = VectorCreate(25,0,50) //X is parallel to the model, Y is perpendicular to the model
  endif
  return udg_particleSpawnOffset
endfunction

//                                                    INTERNAL FUNCTIONS

function H2I takes handle h returns integer
  return h
  return 0
endfunction

function I2TR takes integer i returns trigger
  return i
  return null
endfunction

function GetZ takes real x, real y returns real
  local location loc = Location(x,y)
  local real r = GetLocationZ(loc)
  call RemoveLocation(loc)
  set loc = null
  return r
endfunction

function CreateEvalTrig takes code cb returns trigger
  local trigger t = CreateTrigger()
  call TriggerAddCondition(t,Condition(cb))
  return t
endfunction

function MakeUnitFlyable takes unit u returns nothing
  call UnitAddAbility(u, &#039;Amrf&#039;)
  call UnitRemoveAbility(u, &#039;Amrf&#039;)
endfunction

function MapSizeXLow takes nothing returns real
  if udg_MapSize[0] == 0. then
    set udg_MapSize[0] = GetRectMinX(GetWorldBounds())
  endif
  return udg_MapSize[0]
endfunction
function MapSizeXHigh takes nothing returns real
  if udg_MapSize[1] == 0. then
    set udg_MapSize[1] = GetRectMaxX(GetWorldBounds())
  endif
  return udg_MapSize[1]
endfunction
function MapSizeYLow takes nothing returns real
  if udg_MapSize[2] == 0. then
    set udg_MapSize[2] = GetRectMinY(GetWorldBounds())
  endif
  return udg_MapSize[2]
endfunction
function MapSizeYHigh takes nothing returns real
  if udg_MapSize[3] == 0. then
    set udg_MapSize[3] = GetRectMaxY(GetWorldBounds())
  endif
  return udg_MapSize[3]
endfunction


//Do not try to init an empty string (&quot;&quot;) it will lose its index.
function clsStringIndexInitString takes string s returns integer
  local integer i = 0
  local integer j = -1
  loop
    exitwhen i &gt; 8191
    if udg_clsStringIndexString<i> == &quot;&quot; or udg_clsStringIndexString<i> == null or udg_clsStringIndexString<i> == s then
      set j = i
      set i = 8192
    endif
    set i = i + 1
  endloop
  if j &lt; 0 then
    call BJDebugMsg(&quot;|cffff0000Critical Error:|r Could not add string to array, last added condition will fail.&quot;)
    return -1
  endif
  set udg_clsStringIndexString[j] = s

  return j
endfunction
function clsStringIndexGetString takes integer i returns string
  return udg_clsStringIndexString<i>
endfunction

function clsParticleCreate takes unit u returns boolean
  local integer i = 0
  local integer j = -1
  loop
    exitwhen i &gt; 8191
    if not udg_clsParticleTaken<i> then
      set j = i
      set i = 8192
    endif
    set i = i + 1
  endloop
  if j &lt; 0 then
    return false
  endif

  set udg_clsParticleTaken[j] = true
  set udg_clsParticlePlace[j] = VectorCreate(GetUnitX(u), GetUnitY(u), GetZ(GetUnitX(u), GetUnitY(u)) + VectorGetZ(SpawnPlaceOffset()))
  set udg_clsParticleSpeed[j] = VectorCreate(0,0,0)
  set udg_clsParticleForces[j] = LL_NewList(0)
  set udg_clsParticleConditions[j] = LL_NewList(0)
  set udg_clsParticleConditionStrings[j] = LL_NewList(0)

  call SetUnitUserData(u,j)

  return true
endfunction
function clsParticleDestroy takes unit u returns nothing
  local integer i = GetUnitUserData(u)
  if not udg_clsParticleTaken<i> then
    return
  endif
  call VectorDestroy(udg_clsParticlePlace<i>)
  call VectorDestroy(udg_clsParticleSpeed<i>)
  call LL_DestroyList(udg_clsParticleForces<i>)
  call LL_DestroyList(udg_clsParticleConditions<i>)
  call LL_DestroyList(udg_clsParticleConditionStrings<i>)
  set udg_clsParticleTaken<i> = false
endfunction

function GetAttachedDummyEffect takes integer i returns effect
  return udg_clsParticleDummyEffect<i>
endfunction





//                                                   USER USABLE FUNCTIONS






function CreateParticle takes player p, integer utype, real x, real y, real facing returns unit
  local unit u = CreateUnit(p, utype, x, y, facing)
  set x = x+CosBJ(facing)*VectorGetX(SpawnPlaceOffset())+SinBJ(facing)*VectorGetY(SpawnPlaceOffset())
  set y = y+SinBJ(facing)*VectorGetX(SpawnPlaceOffset())+CosBJ(facing)*VectorGetY(SpawnPlaceOffset())

  call SetUnitX(u, x)
  call SetUnitY(u, y)
  if not clsParticleCreate(u) then
    call BJDebugMsg(&quot;|cffff0000Error:|r could not initialize particle class in function |cffffcc00CreateParticle|r, see the documentation for help.&quot;)
    call RemoveUnit(u)
    return null
  endif

  call MakeUnitFlyable(u)
  call GroupAddUnit(udg_particleGroup, u)

  return u
endfunction

function CreateProjectile takes player p, string path, real x, real y, real facing returns unit
  local unit u = CreateUnit(p, DummyRawCode(), x, y, facing)
  local integer i
  set x = x+CosBJ(facing)*VectorGetX(SpawnPlaceOffset())+SinBJ(facing)*VectorGetY(SpawnPlaceOffset())
  set y = y+SinBJ(facing)*VectorGetX(SpawnPlaceOffset())+CosBJ(facing)*VectorGetY(SpawnPlaceOffset())

  call SetUnitX(u, x)
  call SetUnitY(u, y)

  if not clsParticleCreate(u) then
    call BJDebugMsg(&quot;|cffff0000Error:|r could not initialize particle class in function |cffffcc00CreateProjectile|r, see the documentation for help.&quot;)
    call RemoveUnit(u)
    return null
  endif
  set i = GetUnitUserData(u)
  set udg_clsParticleDummyEffect<i> = AddSpecialEffectTarget(path, u, &quot;origin&quot;)

  call MakeUnitFlyable(u)
  call GroupAddUnit(udg_particleGroup, u)

  return u
endfunction

function MakeParticle takes unit u returns nothing
  local integer p
  if not clsParticleCreate(u) then
    call BJDebugMsg(&quot;|cffff0000Error:|r could not initialize particle class in function |cffffcc00MakeParticle|r, see the documentation for help.&quot;)
    return
  endif
  set p = udg_clsParticlePlace[GetUnitUserData(u)]
  set udg_vectorZ[p] = udg_vectorZ[p] - udg_vectorZ[SpawnPlaceOffset()] + 1
  call MakeUnitFlyable(u)
  call GroupAddUnit(udg_particleGroup, u)
endfunction

function RemoveParticle takes unit u, boolean removeunit returns nothing
  local effect e = GetAttachedDummyEffect(GetUnitUserData(u))
  
  if e != null then
    call DestroyEffect(e)
  endif

  //Destroy class, VERY important
  call clsParticleDestroy(u)

  call GroupRemoveUnit(udg_particleGroup, u)
  if removeunit then
    call KillUnit(u)
    call RemoveUnit(u)
  endif
  set e = null
endfunction

function ParticleSetSpeed takes unit u, real x, real y, real z returns nothing
  local integer i = GetUnitUserData(u)
  local integer v = udg_clsParticleSpeed<i>
  set udg_vectorX[v] = x
  set udg_vectorY[v] = y
  set udg_vectorZ[v] = z

  if GetAttachedDummyEffect(i) != null then
    set i = R2I(Atan2BJ(udg_vectorZ[v], SquareRoot(udg_vectorX[v]*udg_vectorX[v]+udg_vectorY[v]*udg_vectorY[v]))+0.5)+90
    call SetUnitAnimationByIndex(u, i)
  endif
endfunction

function ParticleLinkConditionTrigger2Func takes unit u, trigger t, string s returns nothing
  local integer i = GetUnitUserData(u)
  local integer hi = H2I(t)

  if LL_GetListItem(udg_clsParticleConditions<i>, 0) == 0 then
    call LL_UpdateListItem(udg_clsParticleConditions<i>, 0, hi)
    call LL_UpdateListItem(udg_clsParticleConditionStrings<i>, 0, clsStringIndexInitString(s))
  else
    call LL_AddListItemFront(udg_clsParticleConditions<i>, hi)
    call LL_AddListItemFront(udg_clsParticleConditionStrings<i>, clsStringIndexInitString(s))
  endif
endfunction

function ParticleUnlinkCondition takes unit u, trigger t returns nothing
  local integer i = GetUnitUserData(u)
  local integer hi = H2I(t)
  local location list = udg_clsParticleConditions<i>
  local integer j = LL_FindListItem(list,hi,0)
  call LL_RemoveListItem(list, j)
  call LL_RemoveListItem(udg_clsParticleConditionStrings<i>, j)
  set list = null
endfunction

function ParticleAddForce takes unit u, integer vector returns nothing
  local integer i = GetUnitUserData(u)
  if LL_GetListItem(udg_clsParticleForces<i>, 0) == 0 then
    call LL_UpdateListItem(udg_clsParticleForces<i>, 0, vector)
  else
    call LL_AddListItemFront(udg_clsParticleForces<i>, vector)
  endif
endfunction

function ParticleRemoveForce takes unit u, integer vector returns nothing
  local integer i = GetUnitUserData(u)
  local location list = udg_clsParticleForces<i>
  local integer j = LL_FindListItem(list,vector,0)
  call LL_RemoveListItem(list, j)
  set list = null
endfunction





//                                                     INTERNAL FUNCTIONS




function CheckConditions takes integer i returns nothing
  local location condlist = udg_clsParticleConditions<i>
  local location strlist = udg_clsParticleConditionStrings<i>
  local trigger t
  local string s
  loop
    exitwhen condlist == null
    set t = I2TR(LL_r2i(GetLocationX(condlist)))
    if TriggerEvaluate(t) then
      set s = clsStringIndexGetString(LL_r2i(GetLocationX(strlist)))
      if s != &quot;&quot; and s != null then
        call ExecuteFunc(s)
      endif
    endif
    set condlist = LL_ly(condlist)
    set strlist = LL_ly(strlist)
  endloop
  set t = null
  set condlist = null
  set strlist = null
endfunction

function CalcForces takes integer i returns integer
  local location list = udg_clsParticleForces<i>
  local integer a
  local integer tv
  local integer totv = VectorCreate(0,0,0)
  loop
    set a = LL_r2i(GetLocationX(list))
    if a &gt; 0 then
      set tv = VectorAmplify(a, ParticlePeriod())
      call VectorAdd(totv,tv)
      call VectorDestroy(tv)
    endif
    set list = LL_ly(list)
    exitwhen list == null
  endloop
  set list = null
  return totv
endfunction

function MoveParticle takes unit u, integer i, integer dp returns nothing
  local integer p = udg_clsParticlePlace<i>
  local integer v = udg_clsParticleSpeed<i>
  local integer tv
  local integer j
  set tv = VectorAmplify(v, ParticlePeriod())
  call VectorAdd(p,tv)
  call VectorAdd(p,dp)
  call VectorDestroy(tv)
  if udg_vectorX[p] &lt; MapSizeXLow() or udg_vectorX[p] &gt; MapSizeXHigh() or udg_vectorY[p] &lt; MapSizeYLow() or udg_vectorY[p] &gt; MapSizeYHigh() then
    //Remove the particle before it is moved outside the map to stop crashes from happening
    call RemoveParticle(u,true)
    return
  endif
  call SetUnitX(u,udg_vectorX[p])
  call SetUnitY(u,udg_vectorY[p])
  call SetUnitFlyHeight(u,udg_vectorZ[p]-GetZ(udg_vectorX[p], udg_vectorY[p]),0.)

  if GetAttachedDummyEffect(i) != null then
    set j = R2I(Atan2BJ(udg_vectorZ[v], SquareRoot(udg_vectorX[v]*udg_vectorX[v]+udg_vectorY[v]*udg_vectorY[v]))+0.5)+90
    call SetUnitAnimationByIndex(u, j)
  endif
  call SetUnitFacing(u, Atan2BJ(udg_vectorY[v], udg_vectorX[v]))
endfunction

function CalcSpeed takes integer i, integer dv returns nothing
  local integer v = udg_clsParticleSpeed<i>
  call VectorAdd(v, dv)
endfunction

function particleMainLoop takes nothing returns nothing
  local unit u = GetEnumUnit()
  local integer i = GetUnitUserData(u)
  local integer forces = CalcForces(i)
  local integer tv = VectorAmplify(forces, ParticlePeriod())
  call VectorScale(tv, 0.5)
  call MoveParticle(u,i,tv)
  call CalcSpeed(i,forces)
  call VectorDestroy(tv)
  call VectorDestroy(forces)
  call CheckConditions(i)
  set u = null
endfunction

function Trig_ParticleMain_Actions takes nothing returns nothing
  call ForGroup(udg_particleGroup, function particleMainLoop)
endfunction

function InitTrig_ParticleMain takes nothing returns nothing
  set gg_trg_ParticleMain = CreateTrigger()
  call TriggerRegisterTimerEventPeriodic(gg_trg_ParticleMain, ParticlePeriod())
  call TriggerAddAction(gg_trg_ParticleMain, function Trig_ParticleMain_Actions)
endfunction

</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Since I just copy-and-pasted is this expected? Is the grenade only supposed to rise up and explode and I have to change it myself? or should the grenade be thrown in an arc and bounce, deflecting off walls on the way (which I have the natives for- correct? The natives from Vector and LinkedList?)

Side Note: I assume LinkedList doesn't have much to do with physics but thats besides the point

Can somebody please point me in the right direction here :D (I actually know simple JASS and see how the casting trigger works, just not so much the ParticleMain and the loopy vector stuff :) )

P.S. If you want to see the other function from the Particle System just say so, it contains Gravity, Wind, Ground Hit, and Particle Death, things that don't concern me at the time being and hopefully never do
 

Chocobo

White-Flower
Reaction score
409
Requires :
- Vector System
- Particle System & Linked Lists

Linked Lists have nothing to do with physics, it is just to use "classes" by using the 2 reals of locations.


Btw, for my trigger, you need to copy and to paste in a trigger called "Grenade".
You need to replace all with the correct Ids :
- 'A00R' was the integer of main spell
- 'e000' was the grenade unit
- 'e001' was the special dummy unit given in the Particle System (notice it is replaced twice to Loc(X,Y) because a single one (without SetUnitX/Y) may collide)


G() doesn't concern for you? If it doesn't, then your bullet "may" go without bouncing.
Also you need the main function GroundHit_Bounce given in the Particle System.


To adjust the duration of the explosion, just change the line :

JASS:
call UnitApplyTimedLife(u,&#039;BTLF&#039;,2.)


Change the real number 2. to the value of your wants.


The grenade may also be killed if you give it a low life, so it may explode when a bullet hits it.


To change the damage dealt by the grenade, and also it's radius, change this line :

JASS:
call DamageArea(u,275,p,256.)


u = The main source of damage and also the point.
275. = The max damage dealt in reals
p = The location of Vector Damage (damage will be modified from loc of Origin Vector and loc of Damage Vector)
256. = The radius size in reals
 

l-hate_you

New Member
Reaction score
6
Sorry for blabbering on about everything thats working fine for me- When I cast my spell with those triggers it spawns a grenade and then (this is the problematic part --->) the grenade rises straight up instead of acting like it is being thrown. Understand? This is what I need help on. I want to know why these triggers don't make the grenade travel in the direction I throw it in, its really puzzling me... thanks

P.S. I have the entire particle system I just didnt post the second trigger in it with the bouncing part for the sake of space.
 
L

Leafs

Guest
Well, to start off, thanks for the awesome tutorial. Followed the whole grenade part, and got one save error I can't seem to fix :( . It's on the call condition part
JASS:
   call TriggerAddCondition( gg_trg_ThrowGrenade, Condition( function Trig_ThrowGrenade_Conditions ) )
and apparently it's expecting a function name... Thanks again for the tutorial and your time. Oh, and how do you find a unit ID of a custom unit?

-Leafs
 
L

Leafs

Guest
Alright, thanks for the help on my previous post, yes that was it. Now it returns no errors and I've checked all my unit IDs and spell IDs, they all check out. But when I go to test it, nothing happens... All that the caster unit does is play their casting animation and then stop. :confused:
 

Chocobo

White-Flower
Reaction score
409
Alright, thanks for the help on my previous post, yes that was it. Now it returns no errors and I've checked all my unit IDs and spell IDs, they all check out. But when I go to test it, nothing happens... All that the caster unit does is play their casting animation and then stop. :confused:

Add debug messages?
 
L

Leafs

Guest
The debug checks out, nothing seems to be wrong apart from the actions.
 
L

Leafs

Guest
Trigger name: ThrowGrenade
JASS:
function Trig_ThrowGrenade_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;A000&#039;
endfunction

function Trig_ThrowGrenade_Actions takes nothing returns nothing
local location casterpos = GetUnitLoc(GetSpellAbilityUnit())
local location topos = GetSpellTargetLoc()
local unit u = CreateParticle(GetOwningPlayer(GetSpellAbilityUnit()),&#039;h001&#039;,GetLocationX(casterpos),GetLocationY(casterpos),GetUnitFacing(GetSpellAbilityUnit()))
call ParticleSetSpeed(u,GetLocationX(topos)-GetLocationX(casterpos),GetLocationY(topos)-GetLocationY(casterpos),1200)
call ParticleLinkConditionTrigger2Func(u, ParticleGroundHit(), &quot;GroundHit_Bounce&quot;)
call ParticleLinkConditionTrigger2Func(u, ParticleDeath(), &quot;Death_Remove&quot;)
call ParticleAddForce(u, G())
call RemoveLocation(casterpos)
call RemoveLocation(topos)
set casterpos=null
set topos=null
set u = null
endfunction

//===========================================================================
function InitTrig_ThrowGrenade takes nothing returns nothing
    set gg_trg_ThrowGrenade = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ThrowGrenade, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ThrowGrenade, Condition( function Trig_ThrowGrenade_Conditions ) )
    call TriggerAddAction( gg_trg_ThrowGrenade, function Trig_ThrowGrenade_Actions )
endfunction
 
L

Leafs

Guest
Sorry for the double post, but I got it to work.
Stupid me... Wrong dummy unit id v.v Nevertheless, thanks for all your help and time guys.

I have one last question however. On the script in the post above this one, how would I change the location so in my ability I can still target anywhere, but the grenade will only be able to go so fast and so far. Kind of like in Elimination Tournament.
 
L

Leafs

Guest
Is it possible to make a unit that nades would bounce off of? If so, how?
Oh, and how do you change the intensity of gravity and the direction/intensity of wind?
 

Chocobo

White-Flower
Reaction score
409
Is it possible to make a unit that nades would bounce off of? If so, how? (1)
Oh, and how do you change the intensity of gravity and the direction/intensity of wind? (2)

(1) : I don't understand what you are saying.

(2) : Use Particle Supplement Functions in the Particle System..

Code:
function G takes nothing returns integer
  if udg_forceGravity == 0 then
    set udg_forceGravity = VectorCreate(0,0,-2500)
  endif
  return udg_forceGravity
endfunction

function Wind takes nothing returns integer
  if udg_forceWind == 0 then
    set udg_forceWind = VectorCreate(-500,-1000,0)
  endif
  return udg_forceWind
endfunction

..and modify these functions by adding your own conditions.

Remember to clean up the Vectors instead of re-creating every vector (else it'll reach vector limit).
 
L

Leafs

Guest
You know how when the grenade hits a wall or the ground and it bounces? Well I'd like to have the same effect with a unit. For example you make a unit called wall with a human outpost model and the grenade hits it. Instead of going through it, it'd bounce off like it were terrain. And by clean up the vectors you mean "set forceWind = null"?
 

Chocobo

White-Flower
Reaction score
409
You know how when the grenade hits a wall or the ground and it bounces? Well I'd like to have the same effect with a unit. For example you make a unit called wall with a human outpost model and the grenade hits it. Instead of going through it, it'd bounce off like it were terrain.

.. not possible because scaling, else would be inaccurate - if you want that, create a new function, add conditions, and if a unit is in range, use AngleBetweenPoints(... , ....) and move the unit using offset... but you will need like a hundred of conditions since you may want it to hit or not to hit.. but well, it will be the hitting part you'll modify instead.
 
L

Leafs

Guest
Hmmm... Earlier in this thread you mentioned func packs. I'd be interested in some to experiment with so I wouldn't have to ask you so many questions... One with a gravity well effect (like the one here) would be greatly appreciated as well.
 

oscarheights

New Member
Reaction score
0
This is really cool and I look forward to testing my map using the grenade system. I have very limited knowledge of Jass and know only basic Java so the problem I am having is a bit perplexing to me. I managed to take down my list of errors from 346 to 1. This is what blocks my path:

call TriggerAddCondition( gg_trg_ThrowGrenade, Condition( function Trig_ThrowGrenade_Conditions ) )
:banghead:
Apparently that is lacking a function name. What can I do to fix this, and for future reference- just what is that line of code doing?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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