• 🏆 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!

I don't get this

Status
Not open for further replies.
Level 2
Joined
Jan 1, 2014
Messages
14
I have a few set of example triggers my teacher gave me. All I tried worked, except this one.

What I tried is, in the AoE I cast my spell (like the Blizard spell), I want to Cripple all the targets (the Single Target spell). The result I'm receiving is similiar to a Howl of Terror: not where I target the AoE, but instead around my unit.

JASS:
scope Cripple//Casts a Single Target spell in an AoE (MassCripple)

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00D'
endfunction

private function Actions takes nothing returns nothing
    local real x = GetUnitX(GetTriggerUnit())
    local real y = GetUnitY(GetTriggerUnit())
    local integer l = GetUnitAbilityLevel(GetTriggerUnit(),'A00D')
    local real area = 400+l*100
    call CastAreaEnemy(GetTriggerUnit(),'A00E',l,"cripple",x,y,area,0.5)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition( function Conditions ) )
    call TriggerAddAction(t, function Actions )
    set t = null
endfunction

endscope

I give, I give, it's years since I last tried codes instead of GUI, that's why I forgot if there was something else to edit, like that " local real area = 400+l*100"
Can you help me?
 
Last edited by a moderator:
Level 23
Joined
Apr 16, 2012
Messages
4,041
the problem is most likely in initializing the real x and real y

You should instead do:

JASS:
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()

because currently, you initialze x and y to the X and Y of casting unit, not the target
 
Level 2
Joined
Jan 1, 2014
Messages
14
edo494, you fixed the "Howl of Terror" problem!

But I have another issue. Whenever I use it, the game starts running veeery slowly. And it's not only my computer, I asked other people to test and they achieved the same results. Is it what people call "memory leaks"?
 
Level 2
Joined
Jan 1, 2014
Messages
14
Well, I'm not a very good programmer, I just learn by trial and error and with examples. I barely understand what I will show you next... it's what's needed to run the examples triggers I've been given. Should I ever learn how to code, I can mess with then. Else, I will just change a few values on the examples.

Code:
[HIDDEN="MCS"]library MCS initializer init

globals
    private constant integer MCSDummy = 'e002'
    private unit CASTING_UNIT = null
    private group AOE_Units
endglobals

private function init takes nothing returns nothing
    set AOE_Units = CreateGroup()
endfunction

private function IsEnemy takes nothing returns boolean
    return IsPlayerEnemy(GetOwningPlayer(CASTING_UNIT),GetOwningPlayer(GetFilterUnit()))
endfunction

private function IsAlly takes nothing returns boolean
    return IsPlayerAlly(GetOwningPlayer(CASTING_UNIT),GetOwningPlayer(GetFilterUnit()))
endfunction


function Cast takes unit caster, integer abilid, integer level, string order, real x, real y, real expire returns nothing
    local unit u = CreateUnit(GetOwningPlayer(caster),MCSDummy,x,y,0)
    call UnitAddAbility(u,abilid)
    call SetUnitAbilityLevel(u,abilid,level)
    call IssueImmediateOrder(u,order)
    call UnitApplyTimedLife(u,'BTLF',expire)
    set caster = null
    set u = null
endfunction

function CastPoint takes unit caster, integer abilid, integer level, string order, real sx, real sy,real cx, real cy, real scale, real expire returns nothing
    local unit u = CreateUnit(GetOwningPlayer(caster),MCSDummy,sx,sy,0)
    call SetUnitScale(u,scale,scale,scale)
    call UnitAddAbility(u,abilid)
    call SetUnitAbilityLevel(u,abilid,level)
    call IssuePointOrder(u,order,cx,cy)
    call UnitApplyTimedLife(u,'BTLF',expire)
    set caster = null
    set u = null
endfunction

function CastUnit takes unit caster, integer abilid, integer level, string order, real sx, real sy, widget target, real expire returns nothing
    local unit u = CreateUnit(GetOwningPlayer(caster),MCSDummy,sx,sy,0)
    call UnitAddAbility(u,abilid)
    call SetUnitAbilityLevel(u,abilid,level)
    call IssueTargetOrder(u,order,target)
    call UnitApplyTimedLife(u,'BTLF',expire)
    set caster = null
    set u = null
    set target = null
endfunction

function CastAreaEnemy takes unit caster, integer abilid, integer level, string order, real sx, real sy, real area, real expire returns nothing
    local unit u
    set CASTING_UNIT = caster
    call GroupEnumUnitsInRange(AOE_Units,sx,sy,area,Condition(function IsEnemy))
    loop
        set u = FirstOfGroup(AOE_Units)
        call CastUnit(caster,abilid,level,order,sx,sy,u,expire)
        call GroupRemoveUnit(AOE_Units,u)
        exitwhen FirstOfGroup(AOE_Units) == null
    endloop
    set u = null
endfunction

function CastAreaAlly takes unit caster, integer abilid, integer level, string order, real sx, real sy, real area, real expire returns nothing
    local unit u
    set CASTING_UNIT = caster
    call GroupEnumUnitsInRange(AOE_Units,sx,sy,area,Condition(function IsAlly))
    loop
        set u = FirstOfGroup(AOE_Units)
        call CastUnit(caster,abilid,level,order,sx,sy,u,expire)
        call GroupRemoveUnit(AOE_Units,u)
        exitwhen FirstOfGroup(AOE_Units) == null
    endloop
    set u = null
endfunction

function HealAreaAlly takes unit caster, real Damage, real sx, real sy, real Area returns nothing
    local unit u
    set CASTING_UNIT = caster
    call GroupEnumUnitsInRange(AOE_Units,sx,sy,Area,Condition(function IsAlly))
    loop
        set u = FirstOfGroup(AOE_Units)
        call SetUnitState(u,UNIT_STATE_LIFE,GetUnitState(u,UNIT_STATE_LIFE)+Damage)
        call GroupRemoveUnit(AOE_Units,u)
        exitwhen FirstOfGroup(AOE_Units) == null
    endloop
    set caster = null
    set u = null
endfunction 

function DamageAreaEnemy takes unit caster, real Damage, real sx, real sy, real Area returns nothing
    local unit u
    set CASTING_UNIT = caster
    call GroupEnumUnitsInRange(AOE_Units,sx,sy,Area,Condition(function IsEnemy))
    loop
        set u = FirstOfGroup(AOE_Units)
        call UnitDamageTarget(caster,u,Damage,true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
        call GroupRemoveUnit(AOE_Units,u)
        exitwhen FirstOfGroup(AOE_Units) == null
    endloop
    set caster = null
    set u = null
endfunction    
    
endlibrary[/HIDDEN]

This one I just found that I don't need on my map (yet), but you can look if you want:

Code:
[HIDDEN="MainLib (Copy)"]library MainLib

function HasItem takes unit u, integer it returns boolean
    local integer i = 0
        loop
            if GetItemTypeId(UnitItemInSlot(u,i)) == it then
                return true
            endif
            set i = i+1
            exitwhen i>5
        endloop
        return false
endfunction

function GoldText takes unit whichUnit,integer bounty, player whichPlayer returns nothing
    local texttag tt = CreateTextTag()
    local string text = "+" + I2S(bounty)
    call SetTextTagText(tt, text,0.024)
    call SetTextTagPos(tt, GetUnitX(whichUnit)-16.0, GetUnitY(whichUnit), 0.0)
    call SetTextTagColor(tt, 255, 220, 0, 255)
    call SetTextTagVelocity(tt, 0.0, 0.03)
    call SetTextTagVisibility(tt,GetLocalPlayer()==whichPlayer)
    call SetTextTagFadepoint(tt, 2.0)
    call SetTextTagLifespan(tt, 3.0)
    call SetTextTagPermanent(tt, false)
    set text = null
    set tt = null
endfunction

function GetRandomX takes rect rec returns real
    local real r = GetRandomReal(GetRectMinX(rec),GetRectMaxX(rec))
    set rec = null
    return r
endfunction

function GetRandomY takes rect rec returns real
    local real r = GetRandomReal(GetRectMinY(rec),GetRectMaxY(rec))
    set rec = null
    return r
endfunction

function SetMbItemWidth takes multiboard mb,integer col,integer row,real width returns nothing
    local multiboarditem mbitem = MultiboardGetItem( mb, row, col )
    call MultiboardSetItemWidth( mbitem, width/100.0 )
    call MultiboardReleaseItem( mbitem )
    
    set mbitem = null
endfunction

function SetMbItemStyle takes multiboard mb,integer col,integer row,boolean showValue,boolean showIcon returns nothing
    local multiboarditem mbitem = MultiboardGetItem( mb, row, col )
    call MultiboardSetItemStyle( mbitem, showValue, showIcon )
    call MultiboardReleaseItem( mbitem )
     
    set mbitem = null                
endfunction

function SetMbItemColor takes multiboard mb,integer col,integer row,real red,real green,real blue,real transparency returns nothing
    local multiboarditem mbitem = MultiboardGetItem(mb, row, col)
    call MultiboardSetItemValueColor( mbitem, PercentToInt(red, 255), PercentToInt(green, 255), PercentToInt(blue, 255), PercentToInt(100-transparency, 255) )
    call MultiboardReleaseItem( mbitem )

    set mbitem = null
endfunction

// Content
function SetMbItemValue takes multiboard mb,integer col,integer row,string val returns nothing
    local multiboarditem mbitem = MultiboardGetItem( mb, row, col )
    call MultiboardSetItemValue( mbitem, val )
    call MultiboardReleaseItem( mbitem )
    
    set mbitem = null
endfunction

function SetMbItemIcon takes multiboard mb,integer col,integer row,string iconFileName returns nothing
    local multiboarditem mbitem = MultiboardGetItem( mb, row, col )
    call MultiboardSetItemIcon( mbitem, iconFileName )
    call MultiboardReleaseItem( mbitem )

    set mbitem=null
endfunction


endlibrary[/HIDDEN]
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,543
In the future please use jass tags instead of code ones.

This is your problem:

JASS:
function CastUnit takes unit caster, integer abilid, integer level, string order, real sx, real sy, widget target, real expire returns nothing
    local unit u = CreateUnit(GetOwningPlayer(caster),MCSDummy,sx,sy,0)
    call UnitAddAbility(u,abilid)
    call SetUnitAbilityLevel(u,abilid,level)
    call IssueTargetOrder(u,order,target)
    call UnitApplyTimedLife(u,'BTLF',expire)
    set caster = null
    set u = null
    set target = null
endfunction

You're creating a very large number of units = lag

Edit: You can use a global dummy unit to cast the ability on all targets, like this:

JASS:
call UnitAddAbility(dummy,ABIL)
call IssueTargetOrder(dummy,"order",target)
call UnitRemoveAbility(dummy,ABIL)

But this doesn't work with all abilities. Let me know if you need a second method and I'll help you out.
 
Level 2
Joined
Jan 1, 2014
Messages
14
This is how it ended. Remember how I trial and error stuff.

JASS:
function CastUnit takes unit caster, integer abilid, integer level, string order, real sx, real sy, widget target, real expire returns nothing
    local unit u = CreateUnit(GetOwningPlayer(caster),MCSDummy,sx,sy,0)
 call UnitAddAbility(MCSDummy,abilid)
 call IssueTargetOrder(MCSDummy,"order",target)
 call UnitRemoveAbility(MCSDummy,abilid)
endfunction

Instead of ABIL I put abilid because that's how it is in my map (I suppose...).
It says it cannot convert integer to unit. (MCSDummy line 89, 90, 91.)
I don't get if " "order" " is something I should edit, is it? Or something in the other trigger? Not having english as the main language sucks -_-
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
you removed the 7 lines that were fine, you kept the one line that is totally wrong

The biggest problem of that function persist, the CreateUnit function call

edit: the "order" should just be order, the local function argument of type string that is passed to the function
 
Level 2
Joined
Jan 1, 2014
Messages
14
Because u needs to be a global variable.

at the top:

JASS:
globals
    private unit u
endglobals

and in an initializer function:

JASS:
set u = CreateUnit(...)

So, instead of

JASS:
Public function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition( function Conditions ) )
    call TriggerAddAction(t, function Actions )
    set t = null
endfunction


It goes


JASS:
Public function InitTrig takes nothing returns nothing
    set trigger u = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(u,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(u, Condition( function Conditions ) )
    call TriggerAddAction(u, function Actions )
    set u = null
endfunction

????
I'm just too dumb to understand what you say sometimes ^^u But I'm glad there's somebody to help me :D
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,543
Nope, we're just adding something extra to the InitTrig:

JASS:
public function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition( function Conditions ) )
    call TriggerAddAction(t, function Actions )
    
    //Create the GLOBAL dummy caster:
    set u = CreateUnit(Player(13),MCSDummy,0.,0.,0.)

    //Do etc. nulling last
    set t = null
endfunction
 
Level 2
Joined
Jan 1, 2014
Messages
14
I give, I give. Everytime I fix something, another thing breaks... this time, line 69, syntax error, something with MCS_Dummy.

I attached my map on this post. You can see there what I did wrong. Even fix if it you want to.

Btw, I use this NewGen WE, without it I can't open my maps.
 

Attachments

  • Fourhorsemen Showdown v1.0.1.w3x
    955.6 KB · Views: 78

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,543
There were issues all over the place. I suggest you read the MCS and Cripple scripts line by line to see all the differences.

Some notes:

  • Always name CONSTANTS_LIKE_THIS
  • Always name nonConstantsLikeThis
  • Inside scopes and librarys, initializer (InitTrig) functions will only run on initialization if you declare them like scope scopeName initializer InitTrig

https://drive.google.com/file/d/0B5p-Ruo7uA87b08yX0pBbVRaNVE/edit?usp=sharing
 
Level 2
Joined
Jan 1, 2014
Messages
14
Thanks bro! Now I can save the map and rest again o/

Now back to the main issue: the map runs slowly when I cripple many targets. And it's not only my computer. And we did your solution, which DID make the game faster.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
btw your code is not recursion safe, so if you cripple, while you are crippling, you will have unexpected crippling going on :D

edit:

try this:

JASS:
	function CastAreaEnemy takes unit caster, integer abilid, integer level, string order, real sx, real sy, real area, real expire returns nothing
		local unit f = null
		local player p = GetOwningPlayer(caster)
        set castingUnit = caster
        
		call GroupEnumUnitsInRange(AOE_Units,sx,sy,area, null)
		loop
			set f = FirstOfGroup(AOE_Units)
			exitwhen f == null
            if IsUnitEnemy(f, p) then
                call CastUnit(caster,abilid,level,order,sx,sy,f,expire)
            endif
			call GroupRemoveUnit(AOE_Units,f)
		endloop
		set f = null
	endfunction
 
Level 2
Joined
Jan 1, 2014
Messages
14
Ok, I will use this trigger instead. The fault on this one is that, instead of targetting the enemy, it targets the caster instead.
Example on how it works in-game:

I use a storm bolt on the target, I get a ilusion for free (Wand of Ilusion on the target). It's instead using the ilusion on me (btw it works with evasion peps).
My final objective is to make the storm bolt do a thunder clap on the position of the target.


JASS:
scope Justapox//Magia unit target: como soltar storm bolt e de repente o alvo tomar thunder clap, e afins.

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A008'//Abilidade dummy
endfunction

private function Actions takes nothing returns nothing
    local real x = GetUnitX(GetTriggerUnit())
    local real y = GetUnitY(GetTriggerUnit())
    call CastUnit(GetTriggerUnit(),'A015',1,"curse",x,y,GetTriggerUnit(),0.5)//Abilidade que cria a sombra
endfunction



//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition( function Conditions ) )
    call TriggerAddAction(t, function Actions )
    set t = null
endfunction

endscope


The thunderclap will slow the enemy, thus working as a cripple.
 
Level 2
Joined
Jan 1, 2014
Messages
14
Haha, my bad, I did try that GetSpellTargetUnit()... indeed, I tried GetTargetUnit and it went wrong, then GetSpellTargetUnit and went well (another trigger, yesterday)... but on this one, when I did it, I didn't try to substitute both GetTriggerUnit's!

Ok, I can cripple a single target with a stormbolt. I still cant thunderclap it. And don't get me wrong, I did change the order string, mana values, cast ranges, anything that could get in my way. How do I Thunderclap on the SpellTargetUnit position?
 
Status
Not open for further replies.
Top