HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[System] TerrainZ

08-17-2008, 06:26 PM#1
Vestras
This is a system I use mostly for registering when units bounces on walls and such, thought that some might could use it.

Collapse JASS:
library TerrainZ

globals
   constant integer TDID                  = 'h000'
  // These two types shouldn't be edited
   constant integer TERRAINZ_TYPE_RAISE   = 1
   constant integer TERRAINZ_TYPE_LOWER   = 2
endglobals

// These globals shouldn't be edited

// These two functions are currently disabled because if bugs.

//globals
//   private terraindeformation td
//   private real st
//endglobals

//private function StopTerrainZ takes nothing returns nothing
//    call TerrainDeformStop(td,R2I(st))
//    call DestroyTimer(GetExpiredTimer())
//endfunction

//function CreateTerrainZ takes integer Type,real x,real y,real height,real radius,boolean perm,real createtime,real shrinktime returns nothing
//   if(Type==TERRAINZ_TYPE_LOWER)then
//     set td=TerrainDeformCrater(x,y,radius,height,R2I(createtime),perm)
//   else
//     set td=TerrainDeformCrater(x,y,radius,height/3,R2I(createtime),perm)
//   endif
//   call TriggerSleepAction(createtime+0.5)
//       if(perm==true)then
//          set td=null
//       else
//          set st=shrinktime
//          call TimerStart(CreateTimer(),0.,false,function StopTerrainZ)
//       endif
//endfunction

function IsHigherThan takes real x1,real y1,real x2,real y2 returns boolean
 local location l1=Location(x1,y1)
 local location l2=Location(x2,y2)
  if(GetLocationZ(l1)<=GetLocationZ(l2))then
    call RemoveLocation(l1)
      call RemoveLocation(l2)
      set l1=null
    set l2=null
    return true
  else
    call RemoveLocation(l1)
      call RemoveLocation(l2)
      set l1=null
    set l2=null
    return false
  endif
endfunction

function IsHigherThanMax takes real x,real y,real max returns boolean
 local location l=Location(x,y)
  if(GetLocationZ(l)>max)then
    call RemoveLocation(l)
      set l=null
    return true
  else
    call RemoveLocation(l)
      set l=null
    return false
  endif
endfunction

function CompareXYZ takes real x1,real y1,real x2,real y2 returns real
 return ModuloReal(GetLocationZ(Location(x1,y1)),GetLocationZ(Location(x2,y2)))
endfunction

function GetTerrainHeightLine takes real fromx,real fromy,real tox,real toy,real range,real time,real speed,real maximum returns boolean
 local real x=fromx
 local real y=fromy
 local real px
 local real py
 local real tr=0
 local real a=Atan2(toy-y,tox-x)
 local real r=time*speed
 local boolean b=false
 
   loop
    exitwhen tr>=range
      set px=x+speed*Cos(a)
      set py=y+speed*Sin(a)
        if IsHigherThanMax(px,py,maximum)==true then
          set b=true
        else
          set b=false
        endif
      set x=px
      set y=py
    set tr=tr+r
   endloop
   
 return b
endfunction

// These globals isn't for user use.

globals
   group SlideGroup=CreateGroup()
   private timer SlideTimer
   private real length
   private real speed
   private real range
   private real angle
   private real fromx
   private real fromy
   private real tox
   private real toy
   private real tr
   private real er
   private unit u
   // and now the triggeregister stuff;
   private trigger SlideTrig=CreateTrigger()
   private unit dummy
   private real t
   private real sr
endglobals

//! textmacro MakeUnitSlideable takes UNIT
  call GroupAddUnit(SlideGroup,$UNIT$)
//! endtextmacro

private function TimerSlide takes nothing returns nothing
  local real px=GetUnitX(u)+length*Cos(angle*bj_DEGTORAD)
  local real py=GetUnitY(u)+length*Sin(angle*bj_DEGTORAD)
    if IsUnitInRange(u,dummy,er)==false then
      call DestroyTimer(SlideTimer)
      return
    else
      call SetUnitX(u,px)
      call SetUnitY(u,py)
    endif
endfunction

private function SlideUnit takes unit whichUnit,real time,real sliderange returns nothing
  // The unit MUST be in the SlideGroup, use //! runtextmacro("YourUnit") to add your unit to the slide group
  set speed=GetUnitMoveSpeed(whichUnit)
  set length=speed*time
    if speed>100 then
      set speed=(GetUnitMoveSpeed(whichUnit)/100)+10
    elseif speed<=100 then
      set speed=(GetUnitMoveSpeed(whichUnit)/10)+1
    endif
  set range=sliderange
  set fromx=GetUnitX(whichUnit)
  set fromy=GetUnitY(whichUnit)
  set tox=fromx+length*Cos(GetUnitFacing(whichUnit)-180*bj_DEGTORAD)
  set toy=fromy+length*Sin(GetUnitFacing(whichUnit)-180*bj_DEGTORAD)
  set u=whichUnit
  set angle=Atan2(toy-fromy,tox-fromx)
  set SlideTimer=CreateTimer()
  
    if IsUnitInGroup(whichUnit,SlideGroup)==true then
        call TimerStart(SlideTimer,time,true,function TimerSlide)
      else
        call BJDebugMsg("|cffAD0821SlideUnit function: |r the unit you specified isn't in SlideGroup. You can add the unit to SlideGroup by doing //! runtextmacro(YourUnit). The YourUnit should be inside quotes.")
  endif
endfunction

private function RunSliding takes nothing returns boolean
  if GetTriggerUnit()==u then
    call SlideUnit.execute(u,t,sr)
  endif
 return false
endfunction

function TriggerRegisterEnterTerrainZ takes unit whichUnit,real time,real range,real entrange,real x,real y returns nothing
  set dummy=CreateUnit(GetOwningPlayer(whichUnit),TDID,x,y,0)
  set u=whichUnit
  set t=time
  set sr=range
  set er=entrange
    
    call TriggerRegisterUnitInRange(SlideTrig,dummy,entrange,null)
    call TriggerAddCondition(SlideTrig,Condition(function RunSliding))
endfunction

endlibrary

Screenshots:
Sorry, right now I'm in a hurry, I'll get one as fast as I can.
Attached Files
File type: w3x[System] TerrainZ.w3x (21.2 KB)
08-17-2008, 07:13 PM#2
Tukki
Other people will certainly have more opinions but then I only check the script briefly. What made me confused was the usage of the textmacro.

Collapse JASS:
//! textmacro MakeUnitSlideable takes UNIT
  call GroupAddUnit(SlideGroup,$UNIT$)
//! endtextmacro

Why not make a simple function for adding the unit. Like;
Collapse JASS:
function MakeUnitSlideable takes unit whichUnit returns nothing
   call GroupAddUnit(SlideGroup, whichUnit)
endfunction

as textmacros are used to create multiple instances of things.
08-17-2008, 07:13 PM#3
Anitarf
These functions are just terrible. My favourite:
Collapse JASS:
function CompareXYZ takes real x1,real y1,real x2,real y2 returns real
 return ModuloReal(GetLocationZ(Location(x1,y1)),GetLocationZ(Location(x2,y2)))
endfunction
Not only does it leak two locations, I have no idea what the hell it's supposed to do.

This is not what a TerrainZ library should be at all. I'm movig this crap out of resource submissions.
08-17-2008, 08:28 PM#4
the-thingy
Quote:
I have no idea what the hell it's supposed to do.

I think it's supposed to get the height difference between XY1 and XY2, even though it would fail if XY1 is lower than XY2 (I think it'd just return the height value of XY1 in that situation, which would more than likely be incorrect unless the Z of XY1 was exactly half the Z of XY2) e.g.

60Mod100 - 100 doesn't divide into 60 fully, so the remainder is 60, and the difference between 100 and 60 is definitely not 60 :P You could just do subtraction instead, and return the absolute value i.e.
return RAbsBJ (GetLocationZ (l1) - GetLocationZ (l2))
Also, the indentation here is a bit... freaky (use Tab to indent, it'll be about 4-5 spaces, and keeps everything in line with everything above/below it)
Collapse JASS:
function IsHigherThan takes real x1,real y1,real x2,real y2 returns boolean
 local location l1=Location(x1,y1)
 local location l2=Location(x2,y2)
  if(GetLocationZ(l1)<=GetLocationZ(l2))then
    call RemoveLocation(l1)
      call RemoveLocation(l2)
      set l1=null
    set l2=null
    return true
  else
    call RemoveLocation(l1)
      call RemoveLocation(l2)
      set l1=null
    set l2=null
    return false
  endif
endfunction
and you could shorten the code a bit

Collapse JASS:
function IsHigherThan takes real x1,real y1,real x2,real y2 returns boolean
 local location l1=Location(x1,y1)
 local location l2=Location(x2,y2)
 local boolean b
//Instead of destroying and nulling the locations within the if (which is extra coding work), use a boolean and return that after you've cleaned up?
  if(GetLocationZ(l1)<=GetLocationZ(l2))then
    set b = true
  else
    set b = false
  endif
 call RemoveLocation (l1)
 call RemoveLocation (l2)
 set l1 = null
 set l2 = null
 return b
endfunction

EDIT:
call SlideUnit.execute(u,t,sr)
Any particular reason for using .execute? Probably doesn't make a difference, but you can just do call SlideUnit (...)

Also, if you call TriggerRegisterEnterTerrainZ (...) multiple times, only the last unit to be registered will be capable of running SlideUnit (since you're overwriting u everytime you call that event registration function, and SlideUnit () is only called when GetTriggerUnit == u, you could replace that with an IsUnitInGroup (...) check, and add all registered units to a global group)


MORE EDIT:
Ahm... why are you using a global timer? If a unit is sliding, and another unit initiates a slide from this system, you have a leak (since you are overwriting the existing SlideTimer with CreateTimer (), and you're not pausing SlideTimer before destroying it, I've pointed it out numerous times over at TH (like here), I even quoted Rising_Dusk's tutorial) but the message doesn't appear to be sinking in)

And you should say that the 'system' isn't MUI since (1) the TimerSlide function is only capable of handling one unit, and (2) the TriggerRegisterEnterTerrainZ function is also only capable of supporting one unit

Quote:
call TriggerRegisterUnitInRange(SlideTrig,dummy,entrange,null)
Doesn't a null boolexpr argument result in a leak?