HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Will this work for more than one person?

05-07-2008, 03:01 AM#1
dhobby
Hello, I don't know any Jass but I found this spell online written in Jass and I would like to add it to one of my heros. The problem is that I'm not sure if it would work if two people were using the same typed hero.
Spell found at http://www.hiveworkshop.com/resources_new/spells/735/

The following piece of code probably means that it won't work for heros that people choose from a tavern right? or if there was more than one hero running around? The return value is too specific right?
Collapse JASS:
function GetHero takes nothing returns unit
    return gg_unit_H000_0001
endfunction

Full code below
Collapse JASS:
function GetConstant takes integer i returns integer
    if i==1 then
        return 'AHfa'    //abilityid of constant 1
    elseif i==2 then
        return 'e001'    //unitid of constant 2
    elseif i==3 then
        return 'A000'    //abilityid of constant 3
    elseif i==4 then
        return 'A001'    //abilityid of constant 4
    elseif i==5 then
        return 'ewsp'    //unitid of constant 5
    elseif i==6 then
        return 'A003'    //abilityid of constant 6
    elseif i==7 then
        return 15        //percent damage increased per level
    elseif i==8 then
        return 50        //equal to mana cost per arrow
    elseif i==9 then
        return 3         //basic number of targets
    elseif i==10 then
        return 1         //number of targets increased each level
    endif
    return 0
endfunction

function GetHero takes nothing returns unit
    return gg_unit_H000_0001
endfunction
//************************************************************

function GetGameCache takes nothing returns gamecache
    return udg_gamecache
endfunction

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

function SetHandleInt takes handle subject,string name,integer value returns nothing
    if value==0 then
        call FlushStoredInteger(GetGameCache(),I2S(H2I(subject)),name)
    else
        call StoreInteger(GetGameCache(),I2S(H2I(subject)),name,value)
    endif
endfunction

function SetHandleHandle takes handle subject,string name,handle value returns nothing
    call SetHandleInt(subject,name,H2I(value))
endfunction

function GetHandleHandle takes handle subject,string name returns handle
    return GetStoredInteger(GetGameCache(),I2S(H2I(subject)),name)
    return null
endfunction

function GetHandleUnit takes handle subject,string name returns unit
    return GetHandleHandle(subject,name)
endfunction

function GetHandleTimer takes handle subject,string name returns timer
    return GetHandleHandle(subject,name)
endfunction

function GetHandleTrigger takes handle subject,string name returns trigger
    return GetHandleHandle(subject,name)
endfunction

function GetHandleInt takes handle subject,string name returns integer
    return GetStoredInteger(GetGameCache(),I2S(H2I(subject)),name)
endfunction

function FlushHandleLocals takes handle subject returns nothing
    call FlushStoredMission(GetGameCache(),I2S(H2I(subject)))
endfunction

function ColdArrowDamage_Conditions takes nothing returns boolean
    return GetEventDamageSource()==GetHero()
endfunction

function ColdArrowDamage_Actions takes nothing returns nothing
    local integer loopindex=1
    local unit caster=GetTriggerUnit()
    local unit target=GetHandleUnit(caster,"target")
    local integer i=GetUnitAbilityLevel(GetHero(),GetConstant(1))
    if Pow(GetUnitX(target)-GetUnitX(caster),2)+Pow(GetUnitY(target)-GetUnitY(caster),2)>10000 then
        return  
    endif
    if GetHandleInt(caster,"maintarget")==0 then
        call UnitDamageTarget(caster,target,(1+0.01*GetConstant(7)*i)*GetEventDamage(),true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
    else   
        call UnitDamageTarget(caster,target,0.01*GetConstant(7)*i*GetEventDamage(),true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
    endif
    call SetHandleInt(caster,"timercount",20)
    set caster=CreateUnit(GetOwningPlayer(caster),GetConstant(2),GetUnitX(target),GetUnitY(target),0)
    call ShowUnit(caster,false)
    call UnitApplyTimedLife(caster,0,0.5)
    call SetUnitAbilityLevel(caster,GetConstant(6),i)
    call IssueTargetOrder(caster,"coldarrowstarg",target)
    set caster=null
    set target=null
endfunction

function SetCasterPosition takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local unit caster=GetHandleUnit(t,"caster")
    local unit target=GetHandleUnit(caster,"target")
    local integer timercount=GetHandleInt(caster,"timercount")
    call IssuePointOrder(caster,"smart",GetUnitX(target),GetUnitY(target))  
    call SetHandleInt(caster,"timercount",timercount+1)
    if timercount>=24 or GetUnitState(target,UNIT_STATE_LIFE)<=0 then
        call FlushHandleLocals(caster)
        call DestroyTrigger(GetHandleTrigger(t,"trigger"))
        call RemoveUnit(caster)
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    set t=null
    set caster=null
    set target=null
endfunction

function UnitTypeFilter takes unit u returns boolean
    return IsUnitEnemy(u,GetOwningPlayer(GetTriggerUnit())) and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)==false and IsUnitType(u,UNIT_TYPE_STRUCTURE)==false
endfunction

function Filter_Conditions takes nothing returns boolean
    return GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0 and UnitTypeFilter(GetFilterUnit())
endfunction

function CreateCasters takes unit trigunit,unit targetunit returns nothing
    local integer loopindex=1
    local integer loopend=GetConstant(9)+GetConstant(10)*GetUnitAbilityLevel(GetHero(),GetConstant(1))-1
    local unit caster
    local unit pickedunit
    local timer t
    local trigger trig
    local group g=CreateGroup()
    local boolexpr filter=Condition(function Filter_Conditions)
    call GroupEnumUnitsInRange(g,GetUnitX(trigunit),GetUnitY(trigunit),700,filter)
    call DestroyBoolExpr(filter)
    set filter=null
    set pickedunit=targetunit
    loop
        set caster=CreateUnit(GetOwningPlayer(trigunit),GetConstant(5),GetUnitX(pickedunit),GetUnitY(pickedunit),0)
        call SetUnitFlyHeight(caster,GetUnitFlyHeight(pickedunit),0)
        call SetHandleHandle(caster,"target",pickedunit)
        if loopindex==1 then
            call SetHandleInt(caster,"maintarget",1)        
        endif
        call UnitRemoveType(GetHandleUnit(trigunit,"caster"+I2S(loopindex)),UNIT_TYPE_MECHANICAL)
        call SetHandleHandle(trigunit,"caster"+I2S(loopindex),caster)
        set t=CreateTimer()
        call SetHandleHandle(t,"caster",caster)
        call TimerStart(t,0.15,true,function SetCasterPosition)
        set trig=CreateTrigger()
        call TriggerRegisterUnitEvent(trig,caster,EVENT_UNIT_DAMAGED)
        call TriggerAddCondition(trig,Condition(function ColdArrowDamage_Conditions))
        call TriggerAddAction(trig,function ColdArrowDamage_Actions)
        call SetHandleHandle(t,"trigger",trig)
        call GroupRemoveUnit(g,pickedunit)
        set pickedunit=FirstOfGroup(g)
        exitwhen loopindex==loopend or pickedunit==null
        set loopindex=loopindex+1  
    endloop
    call DestroyGroup(g)
    set caster=null
    set pickedunit=null
    set t=null
    set trig=null
    set g=null
endfunction

function ManualCast_Conditions takes nothing returns boolean
    return GetSpellAbilityId()==GetConstant(1)
endfunction

function ManualCast_Actions takes nothing returns nothing
    local unit trigunit=GetTriggerUnit()
    call SetPlayerAbilityAvailable(GetOwningPlayer(trigunit),GetConstant(3),true)
    call CreateCasters(trigunit,GetSpellTargetUnit())
    call SetHandleHandle(trigunit,"target",GetSpellTargetUnit())
    set trigunit=null
endfunction

function AutoCast_Actions takes nothing returns nothing
    local unit trigunit=GetTriggerUnit()
    local player p=GetOwningPlayer(trigunit)
    if GetHandleInt(trigunit,"ColdArrowOn")==1 and UnitTypeFilter(GetEventTargetUnit()) then
        if GetUnitState(trigunit,UNIT_STATE_MANA)>=I2R(GetConstant(8)) then
            call SetPlayerAbilityAvailable(p,GetConstant(3),true)
        else
            call SetPlayerAbilityAvailable(p,GetConstant(3),false)
        endif
        call CreateCasters(trigunit,GetEventTargetUnit())
    else
        call SetPlayerAbilityAvailable(p,GetConstant(3),false)
    endif
    call SetHandleHandle(trigunit,"target",GetEventTargetUnit())
    set trigunit=null
    set p=null
endfunction

function ColdArrowSwitch_Conditions takes nothing returns boolean
    return GetIssuedOrderId()==OrderId("flamingarrows") or GetIssuedOrderId()==OrderId("unflamingarrows")
endfunction

function ColdArrowSwitch_Actions takes nothing returns nothing
    local unit trigunit=GetTriggerUnit()
    local player p=GetOwningPlayer(trigunit)
    if GetIssuedOrderId()==OrderId("flamingarrows") then
        call SetHandleInt(trigunit,"ColdArrowOn",1)
        if GetUnitState(trigunit,UNIT_STATE_MANA)>=I2R(GetConstant(8)) and UnitTypeFilter(GetHandleUnit(trigunit,"target")) then
            call SetPlayerAbilityAvailable(p,GetConstant(3),true)
            call CreateCasters(trigunit,GetHandleUnit(trigunit,"target"))
        endif
    else
        call SetPlayerAbilityAvailable(p,GetConstant(3),false)
        call SetHandleInt(trigunit,"ColdArrowOn",0)
    endif
    set trigunit=null
    set p=null
endfunction

function ManaUseUp_Actions takes nothing returns nothing
    local unit trigunit=GetTriggerUnit()
    if GetHandleInt(trigunit,"ColdArrowOn")==1 and UnitTypeFilter(GetHandleUnit(trigunit,"target")) then
        call SetPlayerAbilityAvailable(GetOwningPlayer(trigunit),GetConstant(3),true)
    endif
    set trigunit=null
endfunction

function InitTrig_MultiColdArrow takes nothing returns nothing
    set udg_gamecache=InitGameCache("GameCache.w3v")
    call SetPlayerAbilityAvailable(GetOwningPlayer(GetHero()),GetConstant(3),false)
    call SetPlayerAbilityAvailable(GetOwningPlayer(GetHero()),GetConstant(4),false)
    set gg_trg_MultiColdArrow=CreateTrigger()
    call TriggerRegisterUnitEvent(gg_trg_MultiColdArrow,GetHero(),EVENT_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(gg_trg_MultiColdArrow,Condition(function ColdArrowSwitch_Conditions))
    call TriggerAddAction(gg_trg_MultiColdArrow,function ColdArrowSwitch_Actions)
    set gg_trg_MultiColdArrow=CreateTrigger()
    call TriggerRegisterUnitManaEvent(gg_trg_MultiColdArrow,GetHero(),GREATER_THAN_OR_EQUAL,I2R(GetConstant(8)))
    call TriggerAddAction(gg_trg_MultiColdArrow,function ManaUseUp_Actions)
    set gg_trg_MultiColdArrow=CreateTrigger()
    call TriggerRegisterUnitEvent(gg_trg_MultiColdArrow,GetHero(),EVENT_UNIT_SPELL_CAST)
    call TriggerAddCondition(gg_trg_MultiColdArrow,Condition(function ManualCast_Conditions))
    call TriggerAddAction(gg_trg_MultiColdArrow,function ManualCast_Actions)
    set gg_trg_MultiColdArrow=CreateTrigger()
    call TriggerRegisterUnitEvent(gg_trg_MultiColdArrow,GetHero(),EVENT_UNIT_TARGET_IN_RANGE)
    call TriggerAddAction(gg_trg_MultiColdArrow,function AutoCast_Actions)
endfunction
05-07-2008, 05:56 AM#2
Strilanc
Ok, the 'GetConstant' function is hilarious.

It's so obvious now. Instead of just using constants, put them in a function and access them using arbitrary indexes. Then we could have constants for the indexes! Of course, then we need to put those in a function...
05-07-2008, 01:25 PM#3
ProFeT
What Strilanc want to tell you, is you could just use constant variables instead of your function, somethink like this:
Collapse JASS:
globals
    constant integer ABILITYID_CONSTANT1 =  'AHfa'
    constant integer UNITID_CONSTANT2 = 'e001'
    etc...
endglobals

It's more efficient in term of performance ;)
05-07-2008, 01:41 PM#4
Vexorian
Quote:
Originally Posted by Strilanc
Ok, the 'GetConstant' function is hilarious.

It's so obvious now. Instead of just using constants, put them in a function and access them using arbitrary indexes. Then we could have constants for the indexes! Of course, then we need to put those in a function...
You got to put it in context of a pre vJass era, I once used that instead of multiple constant functions, cause if you do the later it ends up generating a bunch of code.


This piece of code looks way too familiar to me.
05-07-2008, 02:51 PM#5
Strilanc
Quote:
Originally Posted by Vexorian
You got to put it in context of a pre vJass era, I once used that instead of multiple constant functions, cause if you do the later it ends up generating a bunch of code.


This piece of code looks way too familiar to me.

I'm sorry, but using a function like that is not appropriate, even without vJass. It introduces magic numbers (eg. '1' means 'attack damage') everywhere, and is less efficient than just using a function per value.
05-07-2008, 03:29 PM#6
Captain Griffen
Quote:
Originally Posted by Strilanc
I'm sorry, but using a function like that is not appropriate, even without vJass. It introduces magic numbers (eg. '1' means 'attack damage') everywhere, and is less efficient than just using a function per value.

Tell me how the efficiency matters. You can do MILLIONS of accessing of local variables a second before it starts to lag. That was tested on an old 1.7 GHz Celeron. So, really...the efficiency argument is meaningless (particularly given that more functions => slower function calling in the whole map). Also, magic numbers in this context don't matter much, since they are commented in the configuration function.
05-07-2008, 04:52 PM#7
Vexorian
Quote:
is less efficient than just using a function per value.
There just isn't a big advantage in using one function per constant over this, I think both things are equally bad.
05-07-2008, 05:42 PM#8
Strilanc
Quote:
Originally Posted by Captain Griffen
Tell me how the efficiency matters. You can do MILLIONS of accessing of local variables a second before it starts to lag. That was tested on an old 1.7 GHz Celeron. So, really...the efficiency argument is meaningless (particularly given that more functions => slower function calling in the whole map). Also, magic numbers in this context don't matter much, since they are commented in the configuration function.

It might make a difference if you're asking for the last value repeatedly. In any case I agree with you: the difference should not be significant. The point is that you're sacrificing readability, and not even getting efficiency out of it.

Magic numbers always matter. I shouldn't have to jump to the function to see what '1' means.

Quote:
Originally Posted by Vexorian
There just isn't a big advantage in using one function per constant over this, I think both things are equally bad.

Readability is the big advantage.
05-07-2008, 05:46 PM#9
Vexorian
Using a single function makes it easier for people to change it. So they cancel it out both are equally lame.
05-07-2008, 06:17 PM#10
Strilanc
Quote:
Originally Posted by Vexorian
Using a single function makes it easier for people to change it. So they cancel it out both are equally lame.

What do you mean by 'easier to change'?
- Changing the constants themselves requires equivalent amounts of work for either style (eg. replace 'A000' with 'A001').
- Changing the number of constants is easier with an amalgamated function because you have fewer lines to add.
- Changing the code using the constants is easier with a separated style because you don't need to know the magic numbers.
05-07-2008, 06:19 PM#11
Captain Griffen
*applies cattle-prod of on-topic-ness*
05-08-2008, 08:13 PM#12
dhobby
lol thanks guys I think I will try my best to implement the suggestions :)