• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

using "this" inside struct method

Status
Not open for further replies.
Level 20
Joined
May 16, 2012
Messages
635
I was coding the following effect:

1.png

and end up with the following code:

JASS:
scope ElementalSphere initializer Init

globals
    integer array ElementalSphereCheck
    integer array FireEssence
    integer array WaterEssence
    integer array AirEssence
    integer array LifeEssence
    integer array DarkEssence
endglobals

private struct Essence extends array
    integer essences

    static method onFinish takes Missile missile returns boolean
        if this.essences == 1 then
            set FireEssence[GetUnitUserData(missile.source)] = FireEssence[GetUnitUserData(missile.source)] + 1
            call UnitAddMaxHealth(missile.source, 100)
            call UnitAddHealthRegen(missile.source, 10)
        elseif this.essences == 2 then
            set WaterEssence[GetUnitUserData(missile.source)] = WaterEssence[GetUnitUserData(missile.source)] + 1
            call UnitAddMaxMana(missile.source, 100)
            call UnitAddManaRegen(missile.source, 10)
        elseif this.essences == 3 then
            set AirEssence[GetUnitUserData(missile.source)] = AirEssence[GetUnitUserData(missile.source)] + 1
            call UnitAddEvasionChance(missile.source, 0.5)
            call UnitAddMoveSpeedBonus(missile.source, 0, 1, 0)
        elseif this.essences == 4 then
            set LifeEssence[GetUnitUserData(missile.source)] = LifeEssence[GetUnitUserData(missile.source)] + 1
            call UnitAddSpellPowerFlat(missile.source, 20)
        elseif this.essences == 5 then
            set DarkEssence[GetUnitUserData(missile.source)] = DarkEssence[GetUnitUserData(missile.source)] + 1
            call AddUnitBonus(missile.source, BONUS_DAMAGE, 20)
        endif
        return true
    endmethod

    implement MissileStruct

    method launchEssence takes real x, real y, unit target, integer essenceType, string sfx returns nothing
        local Missile m = Missile.createXYZ(x, y, 50, GetUnitX(target), GetUnitY(target), (BlzGetUnitZ(target) + 100))

        set this.essences = essenceType
        set m.source = target
        set m.target = target
        set m.owner = GetOwningPlayer(target)
        set m.speed = 40
        set m.model = sfx
        call Essence.launch(m)
    endmethod
endstruct

private function Collector takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_HeroHash, GetHandleId(t), 1)
    local integer index = GetUnitUserData(u)
    local group g
    local unit v
    local Essence e

    if UnitHasItemOfType(u, 'I0AO') > 0 then
        set g = CreateGroup()

        call GroupEnumUnitsInRange(g, GetUnitX(u), GetUnitY(u), 800.00, null)
        loop
            set v = FirstOfGroup(g)
            exitwhen v == null
                call GroupRemoveUnit(g, v)
                if (GetUnitTypeId(v) == 'e003' and UnitAlive(v)) then
                    call e.launchEssence(GetUnitX(v), GetUnitY(v), u, 1, "Sweep_Fire_Small.mdl")
                    call RemoveUnit(v)
                elseif (GetUnitTypeId(v) == 'e004' and UnitAlive(v)) then
                    call e.launchEssence(GetUnitX(v), GetUnitY(v), u, 2, "Sweep_Black_Frost_Small.mdl")
                    call RemoveUnit(v)
                elseif (GetUnitTypeId(v) == 'e005' and UnitAlive(v)) then
                    call e.launchEssence(GetUnitX(v), GetUnitY(v), u, 4, "Sweep_Soul_Small.mdl")
                    call RemoveUnit(v)
                elseif (GetUnitTypeId(v) == 'e006' and UnitAlive(v)) then
                    call e.launchEssence(GetUnitX(v), GetUnitY(v), u, 3, "Sweep_Wind_Small.mdl")
                    call RemoveUnit(v)
                elseif (GetUnitTypeId(v) == 'e007' and UnitAlive(v)) then
                    call e.launchEssence(GetUnitX(v), GetUnitY(v), u, 5, "Sweep_Blood_Small.mdl")
                    call RemoveUnit(v)
                endif
        endloop
        call DestroyGroup(g)
    else
        set ElementalSphereCheck[index] = 0
        call FlushChildHashtable(udg_HeroHash, GetHandleId(t))
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
  
    set t = null
    set u = null
    set g = null
    set v = null
endfunction

private function CreateEssence takes nothing returns nothing
    local unit dying = GetDyingUnit()
    local integer essenceType = GetRandomInt(1, 5)
    local unit u

    if IsUnitEnemy(dying, Player(8)) then
        if IsUnitType(dying, UNIT_TYPE_HERO) then
            set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e003', GetUnitX(dying) + GetRandomInt(10, 25), GetUnitY(dying) + GetRandomInt(10, 25), 0)
            call UnitApplyTimedLife(u, 'BTLF', 20)
            set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e004', GetUnitX(dying) + GetRandomInt(10, 25), GetUnitY(dying) + GetRandomInt(10, 25), 0)
            call UnitApplyTimedLife(u, 'BTLF', 20)
            set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e006', GetUnitX(dying) + GetRandomInt(10, 25), GetUnitY(dying) + GetRandomInt(10, 25), 0)
            call UnitApplyTimedLife(u, 'BTLF', 20)
            set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e005', GetUnitX(dying) + GetRandomInt(10, 25), GetUnitY(dying) + GetRandomInt(10, 25), 0)
            call UnitApplyTimedLife(u, 'BTLF', 20)
            set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e007', GetUnitX(dying) + GetRandomInt(10, 25), GetUnitY(dying) + GetRandomInt(10, 25), 0)
            call UnitApplyTimedLife(u, 'BTLF', 20)
        else
            if essenceType == 1 then
                set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e003', GetUnitX(dying), GetUnitY(dying), 0)
                call UnitApplyTimedLife(u, 'BTLF', 20)
            elseif essenceType == 2 then
                set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e004', GetUnitX(dying), GetUnitY(dying), 0)
                call UnitApplyTimedLife(u, 'BTLF', 20)
            elseif essenceType == 3 then
                set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e006', GetUnitX(dying), GetUnitY(dying), 0)
                call UnitApplyTimedLife(u, 'BTLF', 20)
            elseif essenceType == 4 then
                set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e005', GetUnitX(dying), GetUnitY(dying), 0)
                call UnitApplyTimedLife(u, 'BTLF', 20)
            elseif essenceType == 5 then
                set u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'e007', GetUnitX(dying), GetUnitY(dying), 0)
                call UnitApplyTimedLife(u, 'BTLF', 20)
            endif
        endif
    endif

    set u = null
    set dying = null
endfunction

private function Conditions takes nothing returns nothing
    local item i = GetManipulatedItem()
    local unit u = GetManipulatingUnit()
    local integer index = GetUnitUserData(u)
    local timer t

    if GetItemTypeId(i) == 'I0AO' then
        set ElementalSphereCheck[index] = ElementalSphereCheck[index] + 1

        if ElementalSphereCheck[index] == 1 then
            set t = CreateTimer()
            call SaveUnitHandle(udg_HeroHash, GetHandleId(t), 1, u)
            call TimerStart(t, 0.25, true, function Collector)
        endif
    endif

    set i = null
    set u = null
    set t = null
endfunction
//===========================================================================
private function Init takes nothing returns nothing
    set I0AO = CreateTrigger()
    call DisableTrigger(I0AO)
    call TriggerRegisterAnyUnitEventBJ(I0AO, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(I0AO, Condition(function CreateEssence))

    call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function Conditions)
endfunction

endscope

When i save, i get a compile error saying that the property "essences" declared inside my Essence struct is not of a type that allows "." operator. I've seen and used the "this" inside struct methods already, but i dont know why i cant use this time. Anyone know whats i'm doing wrong?
 
Level 39
Joined
Feb 27, 2007
Messages
5,023
This doesn’t exist in static methods, where you are attempting to use it. A static method does not ‘happen’ on a specific instance of the struct, but rather on the struct object itself so there is no instance for this to refer to. Looks to me like you just want a regular method.
 
Level 20
Joined
May 16, 2012
Messages
635
This doesn’t exist in static methods, where you are attempting to use it. A static method does not ‘happen’ on a specific instance of the struct, but rather on the struct object itself so there is no instance for this to refer to. Looks to me like you just want a regular method.

how can this work perfectly then?

JASS:
private struct WaterSplash extends xemissile
    private unit source
    private unit target
    private real damage
    private group g
    private group damaged

    static method create takes unit source, unit target, real damage, real x, real y, real z, real tx, real ty, real tz returns WaterSplash
        local WaterSplash this = WaterSplash.allocate(x, y, z, tx, ty, tz)
       
        set this.source = source
        set this.target = target
        set this.damage = damage
        set this.g = CreateGroup()
        set this.damaged = CreateGroup()
        set this.fxpath = "WaterBreath.mdx"
        set this.scale  = 0.75
       
        call this.launch(900.0, 0)

        return this
    endmethod

    method loopControl takes nothing returns nothing
        local unit v

        call GroupEnumUnitsInRange(this.g, this.x, this.y, 100, null)
        loop
            set v = FirstOfGroup(this.g)
            exitwhen v == null
                if(IsUnitEnemy(v, GetOwningPlayer(this.source)) and UnitAlive(v) and not IsUnitType(v, UNIT_TYPE_STRUCTURE) and not IsUnitInGroup(v, this.damaged) and v != this.target) then
                    call UnitDamageTarget(this.source, v, (this.damage * 1.2), true, false, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_MAGIC, null)
                    call DestroyEffectTimed(AddSpecialEffectTarget("WaterBreathDamage.mdx", v, "chest"), 3)
                    call UnitAddMoveSpeedBonus(v, 0, -50, 3.00)
                    call GroupAddUnit(this.damaged, v)
                endif
            call GroupRemoveUnit(this.g, v)
        endloop
    endmethod
   
    method onHit takes nothing returns nothing
        call DestroyGroup(this.g)
        call DestroyGroup(this.damaged)
        set this.g = null
        set this.source = null
        set this.target = null
        set this.damaged = null
    endmethod
endstruct

create is a static method and i'm able to use "this". How can access my property then in that case?
 
Level 18
Joined
Oct 17, 2012
Messages
822
I assume you are using BPower's missile library. In your method launchEssence, replace this.essence = essenceType with Essence(m).essence = essenceType.

In the above, this doesn't work because it references nothing since it is not set.

Then in the static method onFinish, first do local thistype this = thistype(missile) then you freely use the variable essence as you see fit in the method.

For instance, you can now do if essence == 1 then and so on. Even without the usual syntax, essence is assumed to be instantiated.

For more information, take a look at BPower's Frozen Orb.

Since BPower provides a struct member called data, you could also do m.data = essenceType.
Then in the method onFinish, you can omit the lines local thistype this = thistype(missile) and integer essence. Then, simply do if missile.data == 1 and so on.

I find this way more sublime than the first. However, the first may prove to be easier to read.
 
Last edited:
Status
Not open for further replies.
Top