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

[General] Problem with calculus

Status
Not open for further replies.
Level 24
Joined
Jun 26, 2020
Messages
1,852
Why I will ask is a bit complicated, so I'll try to explain myself as best I can.
I made a spell to push a unit to a point (like force staff) but if there is a wall of height 2 in the middle of the road then the unit stops, I wanna aplicate this also with platforms, if in the middle of the road is a plataform with a height of 3 then the unit stops, and I also wanna consider if the platform is on top of ground at least 1 high and with contiguous platforms, can you help me? This is the code:
JASS:
scope ImpulseBoots initializer Init

struct ImpulseBoots
   
    static integer temp
    static integer temp2
    static integer temp3
    unit caster
    real distance
    real reacheddistance
    real act_x
    real act_y
    real var_x
    real var_y
    timer t
   
    static method create takes unit caster, location l returns thistype
        local thistype this=thistype.allocate()
        local real x=GetUnitX(caster)
        local real y=GetUnitY(caster)
        local real dx=GetLocationX(l)-x
        local real dy=GetLocationY(l)-y
        local real angle=Atan2(dy,dx)
        call RemoveLocation(l)
        set this.caster=caster
        set this.distance=SquareRoot(dx*dx+dy*dy)
        set this.reacheddistance=0.00
        set this.act_x=x
        set this.act_y=y
        set this.var_x=25*Cos(angle)
        set this.var_y=25*Sin(angle)
        if this.distance>1200 then
            set this.distance=1200
        endif
        call SetUnitPathing(caster,false)
        call GroupAddUnit(udg_Impulse_boots_casters,caster)
        set this.t=NewTimerEx(this)
        call TimerStart(this.t,0.01,true,function thistype.callperiodic)
        return this
    endmethod
   
    static method destructable1 takes nothing returns nothing
        if GetDestructableTypeId(GetEnumDestructable())=='B00E' and IsDestructableAliveBJ(GetEnumDestructable()) then
            set thistype.temp=1
        endif
    endmethod
   
    static method destructable2 takes nothing returns nothing
        local thistype this=thistype.temp2
        local real x=GetDestructableX(GetEnumDestructable())
        local real y=GetDestructableY(GetEnumDestructable())
        local real dx=x-this.act_x
        local real dy=y-this.act_y
        if SquareRoot(dx*dx+dy*dy)>=160 and GetElevatorHeight(GetEnumDestructable())+GetTerrainCliffLevel(x,y)-(GetTerrainCliffLevel(this.act_x,this.act_y)+thistype.temp3-1)>=1 then
            set thistype.temp=1
        endif
    endmethod
   
    static method destructable3 takes nothing returns nothing
        if thistype.temp3<GetElevatorHeight(GetEnumDestructable()) then
            set thistype.temp3=GetElevatorHeight(GetEnumDestructable())
        endif
    endmethod
   
    method pointcondition takes nothing returns boolean
        local real x=this.act_x+6*this.var_x
        local real y=this.act_y+6*this.var_y
        local location l=null
        if GetTerrainCliffLevel(x,y)-GetTerrainCliffLevel(this.act_x,this.act_y)>1 then
            return true
        elseif IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY)==false and GetTerrainCliffLevel(x,y)==0 then
            return true
        else
            set l=Location(x,y)
            set thistype.temp=0
            call EnumDestructablesInCircleBJ(64.00,l,function thistype.destructable1)
            if thistype.temp==1 then
                call RemoveLocation(l)
                set l=null
                return true
            endif
            set thistype.temp2=this
            call RemoveLocation(l)
            set l=Location(this.act_x,this.act_y)
            set thistype.temp3=0
            call EnumDestructablesInCircleBJ(16.00,l,function thistype.destructable3)
            call RemoveLocation(l)
            set l=Location(x,y)
            call EnumDestructablesInCircleBJ(160.00,l,function thistype.destructable2)
            if thistype.temp==1 then
                call RemoveLocation(l)
                set l=null
                return true
            endif
            call RemoveLocation(l)
            set l=null
        endif
        return false
    endmethod
   
    method period takes nothing returns nothing
        set this.act_x=this.act_x+this.var_x
        set this.act_y=this.act_y+this.var_y
        call SetUnitPosition(this.caster,this.act_x,this.act_y)
        if GetRandomInt(1,5)==1 then
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\Defend\\DefendCaster.mdl",this.caster,"chest"))
        endif
    endmethod
   
    static method callperiodic takes nothing returns nothing
        local ImpulseBoots this=GetTimerData(GetExpiredTimer())
        set this.reacheddistance=this.reacheddistance+25.00
        if this.reacheddistance>this.distance or IsUnitHidden(this.caster) or this.pointcondition() then
            call this.destroy()
        else
            call this.period()
        endif
    endmethod
   
    method destroy takes nothing returns nothing
        call ReleaseTimer(this.t)
        call GroupRemoveUnit(udg_Impulse_boots_casters,this.caster)
        call OnColision(this.caster)
        set this.caster=null
        set this.t=null
        call this.deallocate()
    endmethod
endstruct

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

private function Actions takes nothing returns nothing
    local location l=GetSpellTargetLoc()
    call ImpulseBoots.create(GetSpellAbilityUnit(),l)
    set l=null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    set gg_trg_Impulse_boots=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Impulse_boots,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Impulse_boots,Condition(function Conditions))
    call TriggerAddAction(gg_trg_Impulse_boots,function Actions)
endfunction
endscope
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Depends how platforms are implemented. You cannot sample the height of destructable ones for logic purposes as that is the result of a local animation.

What you could do is store the height that each platform is set. This could be done by mapping the height to the platform using a hashtable or Lua table. Then when you are moving you can pick all destructables nearby to check for platforms. If a platform is found you overlay its shape in your collision logic using the height you stored for it.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Yes, you can see in the code I'm using the
GetElevatorHeight
function.

Which seems to be based on the occulder height of the destructable.
JASS:
function GetElevatorHeight takes destructable d returns integer
    local integer height
    set height = 1 + R2I(GetDestructableOccluderHeight(d) / bj_CLIFFHEIGHT)
    if (height < 1) or (height > 3) then
        set height = 1
    endif
    return height
endfunction
You could use it to skip the mapping. However the rest of what I said still applies in that you can look for nearby destructables and then factor them in to your collision logic. The computed height for the platform is likely only accurate for the origin point of the platform. As such you will need to project that to nearby sample points if appropriate. The logic might be implemented like first computing the sample point cliff height, then finding all nearby destructables and if the platform would overlap the sample point then calculate the effective cliff height of the platform at its origin and then use the maximum of all those and the sample point as the resulting height of the point for collision logic.
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
Which seems to be based on the occulder height of the destructable.
JASS:
function GetElevatorHeight takes destructable d returns integer
    local integer height
    set height = 1 + R2I(GetDestructableOccluderHeight(d) / bj_CLIFFHEIGHT)
    if (height < 1) or (height > 3) then
        set height = 1
    endif
    return height
endfunction
You could use it to skip the mapping. However the rest of what I said still applies in that you can look for nearby destructables and then factor them in to your collision logic. The computed height for the platform is likely only accurate for the origin point of the platform. As such you will need to project that to nearby sample points if appropriate. The logic might be implemented like first computing the sample point cliff height, then finding all nearby destructables and if the platform would overlap the sample point then calculate the effective cliff height of the platform at its origin and then use the maximum of all those and the sample point as the resulting height of the point for collision logic.
I have an idea of what to do, but my problem is why any of my calculus didn't work?, I think I should write in the title that my problem is the calculus and that is what I going to do.
 
Status
Not open for further replies.
Top