• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] Dummy Unit problem

Status
Not open for further replies.
Level 1
Joined
Jul 28, 2011
Messages
5
Hello,

I'm quite new in the JASS universe, and I'm trying to convert my projectile system to it. However, when I cast the spells, they do not appear at all. I think it's the CreateUnitAtLoc function, because I can't even create a Footman (which is modeled and I should see if the bug was with the special effect). What's even stranger, I got no compiler error in JassNewGen.

Here's the whole trigger. Thanks in advance for the help.
Notice that ProjectileData is a global. (A structure too)

JASS:
function Trig_ProjectileCreation_Conditions takes nothing returns boolean

    // Returns true if the Caster Unit is a Sorcerer, else returns false
    if(IsUnitInGroup(GetSpellAbilityUnit(), SorcererGroup) == true) then
        return true
    endif
    
    return false
    
endfunction

function Trig_ProjectileCreation_Actions takes nothing returns nothing

    local location SorcererPosition = GetUnitLoc(GetSpellAbilityUnit()) // Sorcerer's actual position
    local location TargetPoint = GetSpellTargetLoc() // Spell target point
    local unit Dummy // Projectile
    
    // Creation of the projectile - PROBLEM THERE
    set Dummy = CreateUnitAtLoc(GetOwningPlayer(GetSpellAbilityUnit()), 'h000', SorcererPosition, AngleBetweenPoints(SorcererPosition, TargetPoint))
    
    if(GetSpellAbilityId() == 'A004') then // Fireball
        call SetUnitUserData(Dummy, 1)
    elseif(GetSpellAbilityId() == 'A006') then // Water Bolt
        call SetUnitUserData(Dummy, 2)
    elseif(GetSpellAbilityId() == 'A005') then // Earth Strike
        call SetUnitUserData(Dummy, 3)
    elseif(GetSpellAbilityId() == 'A000') then // Wind Blast
        call SetUnitUserData(Dummy, 4)
    elseif(GetSpellAbilityId() == 'A003') then // Lightning Bolt
        call SetUnitUserData(Dummy, 5)
    endif
    
    call AddSpecialEffectTargetUnitBJ("chest", Dummy, ProjectileData[GetUnitUserData(Dummy)].Model) // Adding appropriate model to the unit
    call GroupAddUnit(SpellGroup, Dummy) // Adding Dummy to the spellgroup
    
    // Delete locations
    set SorcererPosition = null
    set TargetPoint = null

endfunction

function InitTrig_ProjectileCreation takes nothing returns nothing

    set gg_trg_ProjectileCreation = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_ProjectileCreation, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_ProjectileCreation, Condition(function Trig_ProjectileCreation_Conditions))
    call TriggerAddAction(gg_trg_ProjectileCreation, function Trig_ProjectileCreation_Actions)
    
endfunction
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
The conditions:
JASS:
function Trig_ProjectileCreation_Conditions takes nothing returns boolean

    // Returns true if the Caster Unit is a Sorcerer, else returns false
    if(IsUnitInGroup(GetSpellAbilityUnit(), SorcererGroup) == true) then
        return true
    endif
    
    return false
endfunction

Can be written as:

JASS:
function Trig_ProjectileCreation_Conditions takes nothing returns boolean
    // Returns true if the Caster Unit is a Sorcerer, else returns false
    return IsUnitInGroup(GetSpellAbilityUnit(), SorcererGroup)
endfunction

Also, always use coordinates in JASS. Always.
Like this:
JASS:
local real x = GetUnitX(GetSpellAbilityUnit())
local real y = GetUnitY(GetSpellAbilityUnit())
local unit dummy

set dummy = CreateUnit(Player(0), 'h000', x, y, 0.)

Never use BJ's (which are highlighted red). You can use:
JASS:
call AddSpecialEffectTarget("chest", Dummy, ProjectileData[GetUnitUserData(Dummy)].Model)

But I think the problem might have to do with the condition. When/where do you set that group?
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Honestly, Ima do like this...
JASS:
function Trig_ProjectileCreation_Actions takes unit u, integer spellID, real spelltargetX, real spelltargetY returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local unit Dummy = CreateUnit(GetOwningPlayer(u),'h000', x, y, 0)
    
    //This is best to store in an integer array then loop it here...
    if spellID == 'A004' then // Fireball
        call SetUnitUserData(Dummy, 1)
    elseif spellID == 'A006' then // Water Bolt
        call SetUnitUserData(Dummy, 2)
    elseif spellID == 'A005' then // Earth Strike
        call SetUnitUserData(Dummy, 3)
    elseif spellID == 'A000' then // Wind Blast
        call SetUnitUserData(Dummy, 4)
    elseif spellID == 'A003' then // Lightning Bolt
        call SetUnitUserData(Dummy, 5)
    endif
    
    call AddSpecialEffectTarget("SFXModelHere", Dummy, "chest")
    call GroupAddUnit(udg_SpellGroup, Dummy) // Adding Dummy to the spellgroup
    
    // Delete locations
    set Dummy = null
endfunction

function Trig_ProjectileCreation_Conditions takes nothing returns boolean
    // Returns true if the Caster Unit is a Sorcerer, else returns false
    if GetUnitTypeId(GetTriggerUnit())=='RAW ID OF SORCERER HERE' then
        call Trig_ProjectileCreation_Actions(GetTriggerUnit(), GetSpellAbilityId(), GetSpelltargetX(), GetSpellTargetY())
    endif
    return false
endfunction

function InitTrig_ProjectileCreation takes nothing returns nothing
    set gg_trg_ProjectileCreation = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_ProjectileCreation, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_ProjectileCreation, Condition(function Trig_ProjectileCreation_Conditions))    
endfunction
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
@ mckill: that's a good solution, though the condition you used is different :p (well, I don't know about the initial condition though - as I said: might be a problem with that).
Oh, and use "0." instead "0" when using reals - it will automatically do "I2R(0)" then as far as I know.


Another problem I see in the initial script: you never actually remove the location... (massive mistake)!
 
Level 1
Joined
Jul 28, 2011
Messages
5
SorcererGroup was declared there, in another trigger

JASS:
// Globals
globals

    real SpellRadius = 72.00 // General spell hit radius
    group SorcererGroup = null // All Sorcerers
    group SpellGroup = null // All traveling spells
    Projectile array ProjectileData[30] // Projectile Data

endglobals

And I add the unit there (Notice that this trigger works perfectly)
JASS:
set LastCreatedSorcerer = CreateUnitAtLoc(GetOwningPlayer(GetTriggerUnit()), 'h001', TemporaryLocation, bj_UNIT_FACING) 

[...]

call GroupAddUnit(SorcererGroup, LastCreatedSorcerer) // Adds the Sorcerer to the sorcerer group


I'll try mckill solution, and I will edit shortly.
BTW, why are locations so bad? (Just forgot the RemoveLocation there..)
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
Projectile array ProjectileData[30] // Projectile Data shouldn't be there declaration which type of variable is it? like real or integer?

Also, both global group declaration should be some like:
JASS:
    group SorcererGroup = CreateGroup() // All Sorcerers
    group SpellGroup = CreateGroup() // All traveling spells

Locations are slow, and if you want to know why, thats the answer: wc3 engine does not rely on 'points/locations' but first converts them to coordinates and then uses those for further purpose. Sticking with reals as coordinates is better and makes your trigger more efficient because the convertion does not occur.
 
Level 1
Joined
Jul 28, 2011
Messages
5
EDIT: Seems that the condition was the problem, and the unit was not properly added in the other trigger. Thus, I saw (and it was obvious) that my ProjectileMovement trigger did not apply. What's wrong with that GroupAddUnit function? It's not even a BJ :/

(Sorry, doublepost, epic fail)
 
Level 1
Joined
Jul 28, 2011
Messages
5
Thanks, now my ProjectileMovement system works.
However, my noobness has no limit and don't know what happens there:

JASS:
if(GetSpellAbilityId() == 'A004') then // Fireball
        call SetUnitUserData(Dummy, 1)
    elseif(GetSpellAbilityId() == 'A006') then // Water Bolt
        call SetUnitUserData(Dummy, 2)
    elseif(GetSpellAbilityId() == 'A005') then // Earth Strike
        call SetUnitUserData(Dummy, 3)
    elseif(GetSpellAbilityId() == 'A000') then // Wind Blast
        call SetUnitUserData(Dummy, 4)
    elseif(GetSpellAbilityId() == 'A003') then // Lightning Bolt
        call SetUnitUserData(Dummy, 5)
    endif

This is supposed to be an identification system for the spell (Collision triggers), but the line

JASS:
call AddSpecialEffectTarget(ProjectileData[GetUnitUserData(Dummy)].Model, Dummy, "chest")

Always use the fifth model (Lightning Bolt). If it was related to GetSpellAbilityId(), there would be no model at all, since the Lightning Bolt part of the condition is an elseif and not an else.

Notice that the event is

call TriggerRegisterAnyUnitEventBJ(gg_trg_ProjectileCreation, EVENT_PLAYER_UNIT_SPELL_EFFECT)

Even if it is a BJ, the whole trigger works, so I don't get the problem here, since UserData of units is not a var that I created myself and failed with the initialization. Besides, ProjectileData[x].Model is always a different model, I've just checked.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
you should put this in a loop...

something like...
JASS:
local integer i = 0
loop
   set i = i+1
   if GetSpellAbilityId() == udg_SPELLID[i] then
        call SetUnitUserData(Dummy, i)
   endif
   exitwhen i >= 5
endloop

the udg_SPELLID[] is an integer array variable which is created in initialization..

sample;
  • Set SPELLID[1] = 'A004'
  • Set SPELLID[2] = 'A006'
  • Set SPELLID[3] = 'A005'
  • Set SPELLID[4] = 'A000'
  • Set SPELLID[5] = 'A003'
 
Status
Not open for further replies.
Top