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

[cJass,vJass] Realistic View System

Level 3
Joined
Sep 25, 2009
Messages
18
I want to present you my new system! :cwink:
It is first system on HIVE, so be lenient =)
Here is original system's thread

The system provides the ability to create more or less realistic views for units. For example, not round, but only its segment. The main actions - the creation, modification and deletion. Immediately warn, system resource-intensive and a lot of modifiers for units is better not to impose. But it is ideal for RPG or campaigns.

REQUIREMENTS
JNGP 5C or later
cJass latest DEV version
WarCraft 1.21 or later

IMPORT
Copy rView trigger to your map.
Create unit with parameters of PEON from this map, copy his rawcode to system's config.

IMPORTANT
In the system there is no handler for dying units! Do not forget to write your own! I did not write because of the fact that the coder may want to make their own logic in the processing field of view.
Make sure that the field could not go beyond the boundaries of the map. Restrict access to it, or increase the dark boundary maps.


// I will improve the description of the system as soon as I can. Translation of available variables is in development

Sorry for my bad English, i still have some difficulties with it :smile:


JASS:
/*******************************
System: Realistic View 1.06
Author: Artte
Distribution: free, with author's nickname.
Credits: XGM.RU, VD, Adic, MF
Date: 4.11.09
********************************/

/**************************
REQUIREMENTS:
    JNGP 5C or later 
    cJass latest DEV version 
    WarCraft 1.21 or later
**************************/

/****************
IMPORT:
    Copy rView trigger to your map.
    Create unit with parameters of PEON from this map, copy his rawcode to system's config.
****************/

/*
++++++_Base functions and usage_++++++


rView.AddView takes

    ### required ###
    unit un, (unit, which will be beginning point of view region)
    player ownp, (player, which will see all in modified region)
    int r, (radius of modified region)
    real a, (angle of view, starts from unit facing [0,360])
    bool h, (unit would not change his position and facing angle ?)
    bool cd, (check destructibles ?)
    bool cc, (check cliffs and ground height ?)
    bool ft, (make full view verification ?)
    ### end of required ###
    ### optional ###
    int vsw, real dvr, int drv, real dpr, int ex, int mhd
    ### end of optional ###

returns bool


rView.ChangeParams takes 

    ### required ###
    unit un, (unit, which have attached view modifier)
    int r, (radius of modified region)
    real a, (angle of view, starts from unit facing [0,360])
    bool h, (unit would not change his position and facing angle ?)
    bool cd, (check destructibles ?)
    bool cc, (check cliffs and ground height ?)
    bool ft, (make full view verification ?)
    ### end of required ###
    ### optional ###
    int vsw, real dvr, int drv, real dpr, int ex, int mhd
    ### end of optional ###

returns bool



***********OPTIONAL PARAMETERS****************
(...,vsw,dvr,drv,dpr,ex)
If this variables aren't set - default values will be used(look below).

    vsw=view_start_wave
    dvr=dummyVRad
    drv=dummyravcode
    dpr=dummy_phys_radius
    ex=exactness
    mhd=maximal_height_difference

You can see variable's descripitions in ++++++_Main variables_++++++
**********************************************



rView.DestroyView takes

    unit un (unit, which have attached view modifier)

returns bool

###
This function can change parameters with different speed and time
###
rView.SChangeParams takes
 
    unit un (unit, which have attached view modifier)
    int r, (radius of modified region)
    real a, (angle of view, starts from unit facing [0,360])
    real time (time, which needed to change parameters)

returns bool


All functions returns TRUE if attempt successful or FALSE

*/

/*

++++++_Main variables_++++++

real RV_TPeriod

real RV_STPeriod

bool RV_display_errors

real RV_distInc


bool RV_dynamic_illumination

    bool RV_lantern_illumination
    
    int RV_lanternRad
    
    int RV_lanternRav

    
int RV_maximal_height_difference 

int RV_viewstartwave 

real RV_DummyVRad

int RV_dummyravcode

bool RV_CheckDestructibles

bool RV_CheckCliffs

bool RV_full_treatment

real RV_dummy_phys_radius

int RV_exactness
*/

include "cj_print.j"
include "cj_antibj_base.j"

library rView initializer Init {


/* BEGINNING OF EDIT BOX */

define {
// Global parameters
RV_TPeriod=0.15
RV_STPeriod=0.3
RV_display_errors=true
RV_distInc=1.4
// Dynamic illumination
RV_dynamic_illumination=true
    // Lantern
    RV_lantern_illumination=true
    RV_lanternRad=500
    RV_lanternRav='n000'
// Parameters, which can be set manually for each unit
RV_maximal_height_difference=150
RV_viewstartwave=1              
RV_dummyravcode='hpea'          
RV_CheckDestructibles=true      
RV_CheckCliffs=true             
RV_full_treatment=true          
RV_dummy_phys_radius=140.00     
RV_exactness=13   
RV_DummyRadius=350.00
}       

/* END OF EDIT BOX */



/* A further change is FORBIDDEN, if you do not have an absolute concept of system working! */


/*================================================================
==================================================================
                            SYSTEM
==================================================================
=================================================================*/



include "cj_types_priv.j"
include "cj_typesEX_priv.j"
define {
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,RV_viewstartwave,RV_DummyVRad,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft,vsw)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,vsw,RV_DummyVRad,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft,vsw,dvr)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,RV_exactness,RV_maximal_height_difference)
    <rView.AddView>(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,ex,mhd)=rView.##AddView(un,ownp,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,ex,mhd)
    
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,RV_viewstartwave,RV_DummyVRad,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft,vsw)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,vsw,RV_DummyVRad,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft,vsw,dvr)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,vsw,dvr,RV_dummyravcode,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft,vsw,dvr,drv)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,vsw,dvr,drv,RV_dummy_phys_radius,RV_exactness,RV_maximal_height_difference)
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,RV_exactness,RV_maximal_height_difference)
    <rView.ChangeParams>(un,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,ex,mhd)=rView.##ChangeParams(un,r,a,h,cd,cc,ft,vsw,dvr,drv,dpr,ex,mhd)
    
    private REFRESH_BLOCK1={            
            f.dummy[ind]=CreateUnit(f.plr,RV_dummyravcode,cx,cy,0)
            f.angle[ind]=a-GetUnitFacing(f.mUnit)
            f.dist[ind]=SquareRoot(dx * dx + dy * dy)
            f.dummy_count++
            PauseUnit(f.dummy[ind],true)
            ShowUnit(f.dummy[ind],false)
            ind++ 
        }
        
    private RV_FT={
            if (RV_full_treatment) {
                .dists[i]=R2I(.dist[j])
            }
        }
        
     private HIDE_DUMMY={
                if (!IsUnitHidden(.dummy[j])) {
                    ShowUnit(.dummy[j], false)
                }
        } 
    private sqr(x)=((x)*(x))
    
    private Round(r,x)={
            ROUND_TMP=R2I(r)
            if ((r)-ROUND_TMP<0.5) {
                x=ROUND_TMP
            } else {
                x=ROUND_TMP+1
            }
        }
    private Normalize_Angle(n,nz)={
            if (n<0) {
                nz=n+360
            } elseif (n>360) {
                nz=n-360
            } else {
                nz=n
            }
        }        
    private Normalize_Angle2(n,nz)={
            if (n<-180) {
                nz=mod(n+360)
            } elseif (n>180) {
                nz=mod(n-360)
            } else {
                nz=mod(n)
            }
        }   
    private REPORTIT=BJDebugMsg("please, report to [email][email protected][/email] [jabber]")
        
    private NOT_CONTROLLED={
        if (RV_display_errors) {
            BJDebugMsg("Unit isn't under rView system's control")
        }
        return false
    }
    
    private NOT_FOUND={
        if (RV_display_errors) {
            BJDebugMsg("Unit is under rView system's control, but cannot be found")
            REPORTIT
        }
        return false
    }
    
    private MAXIMAL_MODIFIERS={
        if (RV_display_errors) {
            BJDebugMsg("Error  happened, when trying add new view modifier: count of modifiers>8000")
            BJDebugMsg("If you sure, than you created less 8000 modifiers and error happened - ")
            REPORTIT
        }
        return false
    }
}

/*Some needed variables*/
real MAP_MaxX,MAP_MaxY,MAP_MinX,MAP_MinY
real RV_DummyVRad=RV_DummyRadius

private real Count_R=0,Count_X=0,Count_Y=0
private real RV_DummyVRadius=0
private int CountedD=0,ROUND_TMP, tmpint
private location ccloc = Location(0,0)
private player tmppl


/*Auxiliary functions*/
private void Init() {
    MAP_MaxX=GetRectMaxX(bj_mapInitialPlayableArea)
    MAP_MaxY=GetRectMaxY(bj_mapInitialPlayableArea)
    MAP_MinX=GetRectMinX(bj_mapInitialPlayableArea)
    MAP_MinY=GetRectMinY(bj_mapInitialPlayableArea)
    RV_DummyVRad*=0.9
    RV_DummyVRadius=RV_DummyVRad*0.5
}

private void Wait(real duration){
    timer t
    real  timeRemaining
    if (duration > 0) {
        t = CreateTimer()
        TimerStart(t, duration, false, null)
        loop {
            timeRemaining = TimerGetRemaining(t)
            exitwhen (timeRemaining <= 0)
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) {
                TriggerSleepAction(0.1 * timeRemaining)
            } else {
                TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            }
        }
        DestroyTimer(t)
        t=null
    }
}

private real mod(real x) {
    if x<0 {        
        return -x
    } else {
        return x
    }
}

private real map_bound(real x, bool y) {
    if (y) {
        if (x>MAP_MaxY) {
            return MAP_MaxY
        }
        if (x<MAP_MinY) {
            return MAP_MinY
        }
        return x
   } else {
        if (x>MAP_MaxX) {
            return MAP_MaxX
        }
        if (x<MAP_MinX) {
            return MAP_MinX
        }
        return x
    }
}

void rView__Count_Destructibles() {
    CountedD++
}

void rView__CountDestructibles() {
    rect r=Rect(Count_X - Count_R, Count_Y - Count_R, Count_X + Count_R, Count_Y + Count_R)
    CountedD=0
    EnumDestructablesInRect(r, null, function rView__Count_Destructibles)
    RemoveRect(r)
    r=null
}

private int GetTerrainCliffLevelRect(real x,real y,real r) {
    int l=GetTerrainCliffLevel(x,y),cl
    cl=GetTerrainCliffLevel(x+r,y+r)
    if (cl>l) {
        l=cl
    }
    cl=GetTerrainCliffLevel(x+r,y-r)
    if (cl>l) {
        l=cl
    }
    cl=GetTerrainCliffLevel(x-r,y+r)
    if (cl>l) {
        l=cl
    }
    cl=GetTerrainCliffLevel(x-r,y-r)
    if (cl>l) {
        l=cl
    }
    return l

}


/*Timer's function*/
private void RV_refresh() {
    int i=0,j=0,k=1,ind=1,c,n
    real a=0,cy,cx,n2,angle,dx,dy,mina,maxa,tmp
    location l
    bool nn=false
    unit uu
    rView f
    whilenot(i++ > rView.count) {
        f=rView.list[i]
        if (f.created==false) {
            f.created=true
            tmp=GetUnitFacing(f.mUnit)-f.angle_of_view/2
            Normalize_Angle(tmp,mina)
            if (tmp!=mina) {
                nn=true
            }
            tmp=GetUnitFacing(f.mUnit)+f.angle_of_view/2
            Normalize_Angle(tmp,maxa)
            if (tmp!=maxa) {
                nn=true
            }
            if (maxa<mina) {
                tmp=mina
                mina=maxa
                maxa=tmp
            }
            l=GetUnitLoc(f.mUnit)
            do{
                RemoveUnit(f.dummy[j])
                f.dummy[j]=null
            }whilenot(++j>f.dummy_count) 
            f.dummy_count=0
            Round(f.rad/f.DummyVRadius,c)
            j=f.viewstartwave       
            do {
                n2=3.14159/Asin(f.DummyVRad/(2*f.DummyVRadius*j+0.00001))
                Round(n2,n)
                do {
                    cx=GetUnitX(f.mUnit)+(j*f.DummyVRadius+f.DummyVRadius*RV_distInc)*Cos(a*bj_DEGTORAD)
                    cy=GetUnitY(f.mUnit)+(j*f.DummyVRadius+f.DummyVRadius*RV_distInc)*Sin(a*bj_DEGTORAD)
                    dx = cx - GetUnitX(f.mUnit)
                    dy = cy - GetUnitY(f.mUnit)
                    angle= bj_RADTODEG * Atan2(cy - GetUnitY(f.mUnit), cx - GetUnitX(f.mUnit))                 
                    if (nn) {
                        if (!(maxa>a and a>mina)) {
                            REFRESH_BLOCK1                            
                        }
                    } else {
                        if ((maxa>a and a>mina)) {
                            REFRESH_BLOCK1
                        }
                    }
                    a=a+360/n2                        
                } whilenot (++k > n)
                a=0
                k=1
            } whilenot (++j > c)
            k=1
            a=0
            j=0
            ind=1
            RemoveLocation(l)
            f.posX=GetUnitX(f.mUnit)
            f.posY=GetUnitY(f.mUnit)
            f.quick=false
            do{
                f.dists[j]=f.rad
            }whilenot(++j>360)
            MoveLocation(ccloc,GetUnitX(f.mUnit),GetUnitY(f.mUnit))
            f.absUHeight=GetLocationZ(ccloc)+GetUnitFlyHeight(f.mUnit)
            f.reset()
            j=0
        } elseif (!f.hold) { 
            if (not(mod(GetUnitX(f.mUnit)-f.posX) < 2) or not(mod(GetUnitY(f.mUnit)-f.posY) < 2) or f.quick) {         
                do{
                    f.dists[j]=f.rad
                }whilenot(++j>360)
                MoveLocation(ccloc,GetUnitX(f.mUnit),GetUnitY(f.mUnit))
                f.absUHeight=GetLocationZ(ccloc)+GetUnitFlyHeight(f.mUnit)
                f.reset()
            }   
            f.posX=GetUnitX(f.mUnit)
            f.posY=GetUnitY(f.mUnit)    
            j=0
        }
        nn=false
    } 
    l=null
    uu=null
}

integer CountUnitsInGr(group grr){
    integer i=0
    group ggg=CreateGroup()
    GroupAddGroup(grr,ggg)
    loop {
    exitwhen FirstOfGroup(ggg)==null
        GroupRemoveUnit(ggg,FirstOfGroup(ggg))
        i++
    }
    DestroyGroup(ggg)
    ggg=null
    return i
}

/*Struct for data saving*/

struct rView {
    int viewstartwave           
    real DummyVRad                     
    int dummyravcode      
    bool CheckDestructibles  
    bool CheckCliffs          
    bool full_treatment       
    real dummy_phys_radius  
    real DummyVRadius
    int exactness
    int maximal_height_difference
    real absUHeight
    unit mUnit
    int rad
    bool created
    bool after_change
    bool quick
    bool hold
    real posX
    real posY
    unit dummy[512]
    real angle[512]
    real dist[512]
    int dists[361]
    unit lanterns[256]
    int ln_count
    int dummy_count
    real angle_of_view
    player plr
    static int count=0
    static timer t=new timer
    static rView array list
    static group allunits=new group
    
        
    static boolean Lantern_filter() {
        return GetUnitTypeId(GetFilterUnit())==RV_lanternRav
    }
    
        
    static void Lantern_create() {
        unit u=GetEnumUnit()
        if  GetUnitUserData(u)==0 {
            rView.AddView(u,tmppl,RV_lanternRad,360,true,true,true,true)
            rView.list[tmpint].lanterns[rView.list[tmpint].ln_count]=u
            rView.list[tmpint].ln_count++
            SetUnitUserData(u,-1)
        }
        u=null
    }

    void onDestroy() {
        .mUnit=null
        int j=0
        do{
            RemoveUnit(.dummy[j])
            .dummy[j]=null
        }whilenot(++j>.dummy_count) 
    }
    
    void reset() {
        real f=GetUnitFacing(.mUnit),ux=GetUnitX(.mUnit),uy=GetUnitY(.mUnit),nx,ny,a,aD,reNormalized 
        group g=CreateGroup(),gr=CreateGroup()
        int i,j=0
        bool continue=false
        tmppl=GetOwningPlayer(.mUnit)
        tmpint=this
        do{
            aD=-100.
            a=(f+.angle[j])*bj_DEGTORAD
            nx=ux+.dist[j]*Cos(a)
            ny=uy+.dist[j]*Sin(a)
            if (.quick) {
                Normalize_Angle2(.angle[j],reNormalized)
                if (.angle_of_view/2<=reNormalized || .rad<=.dist[j]) {           
                    HIDE_DUMMY                
                    SetUnitUserData(.dummy[j],-1)
                    continue=true
                }
            }     
            if (!continue) {
                if (.full_treatment) {
                    Normalize_Angle(f+.angle[j],aD)
                    Round(aD/.exactness,i) 
                    i*=.exactness
                    if (.dist[j]>.dists[i]) {
                        HIDE_DUMMY
                        continue=true
                    }
                }  
                if (!continue) {
                    SetUnitUserData(.dummy[j],0)
                    if (.CheckCliffs) {
                    MoveLocation(ccloc,nx,ny)
                        if (GetTerrainCliffLevelRect(nx,ny,.dummy_phys_radius*2)>GetTerrainCliffLevel(ux,uy) || GetLocationZ(ccloc)-.absUHeight>RV_maximal_height_difference) {
                            HIDE_DUMMY
                            RV_FT
                            continue=true
                        }
                    }
                    if (!continue) {
                        Count_X=nx
                        Count_Y=ny
                        Count_R=.dummy_phys_radius
                        ExecuteFunc("rView__CountDestructibles")
                        if (.CheckDestructibles && CountedD>0) {
                            HIDE_DUMMY
                            RV_FT
                            continue=true
                        } 
                        if (!continue) {
                            if (IsUnitHidden(.dummy[j]) && GetUnitUserData(.dummy[j])!=-1) {
                                ShowUnit(.dummy[j], true)
                            }
                            SetUnitX(.dummy[j],nx)
                            SetUnitY(.dummy[j],ny) 
                            if RV_dynamic_illumination {
                                if RV_lantern_illumination and GetUnitTypeId(.mUnit)!=RV_lanternRav{
                                    GroupEnumUnitsInRange(g, nx, ny, .DummyVRad, Condition(function rView.Lantern_filter))
                                    if (CountUnitsInGr(g)>0) {                                
                                        ForGroup(g,function rView.Lantern_create)
                                        GroupAddGroup(g,gr)
                                    }             
                                }
                            }                            
            }}}}
            continue=false
        } whilenot(++j>.dummy_count)
        j=0
        while(j<.ln_count){
            if (!IsUnitInGroup(.lanterns[j],gr)) and  GetUnitUserData(.lanterns[j])==-1 {
                rView.DestroyView(.lanterns[j])
                SetUnitUserData(.lanterns[j],0)
                .lanterns[j]=.lanterns[.ln_count-1]
                .lanterns[.ln_count-1]=null
                j--
                .ln_count--
            }
            j++
        }
        .after_change=false
        DestroyGroup(g)
        g=null
        DestroyGroup(gr)
        gr=null
    }
    
    /*================================================================
    ==================================================================
                    Functions for system management
    ==================================================================
    =================================================================*/
    
    static bool AddView (unit un, player ownp, int r, real a, bool h, bool cd, bool cc, bool ft, /*end of required*/ int vsw, real dvr, int drv, real dpr, int ex, int mhd) {
        rView f              
        if rView.count>=8000 {
            MAXIMAL_MODIFIERS
        } 
        rView.count++ 
        f=rView.create()
        rView.list[rView.count] = f
        
        GroupAddUnit(rView.allunits,un)
        if (rView.count==1) {
            TimerStart(rView.t,RV_TPeriod,true, function RV_refresh) 
        }
        f.viewstartwave=vsw      
        f.maximal_height_difference=mhd
        f.DummyVRad=dvr                     
        f.dummyravcode=drv     
        f.CheckDestructibles=cd
        f.CheckCliffs=cc
        f.full_treatment=ft     
        f.dummy_phys_radius=dpr  
        f.DummyVRad*=0.9
        f.DummyVRadius=f.DummyVRad*0.5
        f.exactness=ex
        f.mUnit=un
        f.rad=r
        f.dummy_count=0 
        f.angle_of_view=a
        f.quick=false
        f.hold=h
        f.created=false
        f.plr=ownp
        f.ln_count=0
         return true
    }
        
    static bool DestroyView(unit un) {
        int i=1
        bool f=false
        if (!IsUnitInGroup(un,.allunits)) {
            NOT_CONTROLLED
        }
        GroupRemoveUnit(.allunits,un)
        loop {
            if (.list[i].mUnit==un) {
                f=true
            }          
            exitwhen (i>.count or f)      
            i++        
        }
        if (!f) {
            NOT_FOUND
        }
        .destroy(.list[i])
        if (.count>1) {
            .list[i]=.list[.count]
        }
        .count--
        if .count<1 {
            PauseTimer(.t)
        }
        return true
    }
    
    static bool ChangeParams(unit un, int r,real a, bool h, bool cd, bool cc, bool ft, /*end of required*/ int vsw, real dvr, int drv, real dpr, int ex, int mhd) {
        int i=1
        bool f=false
        if (!IsUnitInGroup(un,.allunits)) {
            NOT_CONTROLLED
        }
        loop {   
            if .list[i].mUnit==un {
                f=true
            }
        exitwhen f or i>=8000
        i=i+1
        }
        if (!f) {
            NOT_FOUND
        }
        if (r>.list[i].rad || a>.list[i].angle_of_view){
            .list[i].quick=false
            .list[i].created=false
        } else {
            .list[i].quick=true
        }    
        .list[i].viewstartwave=vsw           
        .list[i].DummyVRad=dvr                     
        .list[i].dummyravcode=drv     
        .list[i].CheckDestructibles=cd
        .list[i].CheckCliffs=cc
        .list[i].full_treatment=ft     
        .list[i].dummy_phys_radius=dpr  
        .list[i].DummyVRad*=0.9
        .list[i].DummyVRadius=.list[i].DummyVRad*0.5
        .list[i].exactness=ex
        .list[i].rad=r
        .list[i].maximal_height_difference=mhd
        .list[i].angle_of_view=a
        .list[i].after_change=true
        .list[i].hold=h
        return true
    }

    static bool SChangeParams(unit un, int r, real a, real time) {
        int i=1,nr,olr
        real na,t=0.0,ola
        bool f=false
        if (!IsUnitInGroup(un,.allunits)) {
            NOT_CONTROLLED
        }
        loop {   
            if .list[i].mUnit==un {
                f=true
            }
        exitwhen f or i>=8000
        i=i+1
        }
        if (!f) {
            NOT_FOUND
        }
        if (time<RV_STPeriod*2) {
            time=RV_STPeriod*2
        }
        olr=.list[i].rad
        ola=.list[i].angle_of_view
        if (r>olr || a>ola){
            .list[i].quick=false
        } else {
            .list[i].quick=true
        }
        nr=R2I((r-.list[i].rad)/time*RV_STPeriod)
        na=(a-.list[i].angle_of_view)/time*RV_STPeriod
        loop {
        exitwhen t>time
            if (r>olr || a>ola){
                .list[i].created=false
            }
            .list[i].after_change=true
            .list[i].rad+=nr
            .list[i].angle_of_view+=na
            Wait(RV_STPeriod)       
        t+=RV_STPeriod
        }
        return true
    }

}
}


vJass code was automatically generated by cJass parser.
JASS:
library_once cjsprintf initializer cj_sprintf_updatePlayers
globals
string array cj_sprintf_p
string array cj_sprintf_pc
endglobals
function cj_sprintf_updatePlayers takes nothing returns nothing
set cj_sprintf_p[0x00]=GetPlayerName(Player(0x00))
set cj_sprintf_p[0x01]=GetPlayerName(Player(0x01))
set cj_sprintf_p[0x02]=GetPlayerName(Player(0x02))
set cj_sprintf_p[0x03]=GetPlayerName(Player(0x03))
set cj_sprintf_p[0x04]=GetPlayerName(Player(0x04))
set cj_sprintf_p[0x05]=GetPlayerName(Player(0x05))
set cj_sprintf_p[0x06]=GetPlayerName(Player(0x06))
set cj_sprintf_p[0x07]=GetPlayerName(Player(0x07))
set cj_sprintf_p[0x08]=GetPlayerName(Player(0x08))
set cj_sprintf_p[0x09]=GetPlayerName(Player(0x09))
set cj_sprintf_p[0x0a]=GetPlayerName(Player(0x0a))
set cj_sprintf_p[0x0b]=GetPlayerName(Player(0x0b))
set cj_sprintf_p[0x0c]=GetPlayerName(Player(0x0c))
set cj_sprintf_p[0x0d]=GetPlayerName(Player(0x0d))
set cj_sprintf_p[0x0e]=GetPlayerName(Player(0x0e))
set cj_sprintf_p[0x0f]=GetPlayerName(Player(0x0f))
set cj_sprintf_pc[0x00]="|cffff0303"+GetPlayerName(Player(0x00))+"|r"
set cj_sprintf_pc[0x01]="|cff0042ff"+GetPlayerName(Player(0x01))+"|r"
set cj_sprintf_pc[0x02]="|cff1ce6b9"+GetPlayerName(Player(0x02))+"|r"
set cj_sprintf_pc[0x03]="|cff540081"+GetPlayerName(Player(0x03))+"|r"
set cj_sprintf_pc[0x04]="|cffffff01"+GetPlayerName(Player(0x04))+"|r"
set cj_sprintf_pc[0x05]="|cfffe8a0e"+GetPlayerName(Player(0x05))+"|r"
set cj_sprintf_pc[0x06]="|cff20c000"+GetPlayerName(Player(0x06))+"|r"
set cj_sprintf_pc[0x07]="|cffe55bb0"+GetPlayerName(Player(0x07))+"|r"
set cj_sprintf_pc[0x08]="|cff959697"+GetPlayerName(Player(0x08))+"|r"
set cj_sprintf_pc[0x09]="|cff7ebff1"+GetPlayerName(Player(0x09))+"|r"
set cj_sprintf_pc[0x0a]="|cff106246"+GetPlayerName(Player(0x0a))+"|r"
set cj_sprintf_pc[0x0b]="|cff4e2a04"+GetPlayerName(Player(0x0b))+"|r"
set cj_sprintf_pc[0x0c]="|cff282828"+GetPlayerName(Player(0x0c))+"|r"
set cj_sprintf_pc[0x0d]="|cff282828"+GetPlayerName(Player(0x0d))+"|r"
set cj_sprintf_pc[0x0e]="|cff282828"+GetPlayerName(Player(0x0e))+"|r"
set cj_sprintf_pc[0x0f]="|cff282828"+GetPlayerName(Player(0x0f))+"|r"
endfunction
function cj_sprintf_b2s takes boolean b returns string
if             b then
return        "true"
endif
return        "false"
endfunction
endlibrary
library rView initializer Init
globals
real MAP_MaxX
real MAP_MaxY
real MAP_MinX
real MAP_MinY
endglobals
globals
real RV_DummyVRad=350.00
endglobals
globals
private real Count_R=0
private real Count_X=0
private real Count_Y=0
endglobals
globals
private real RV_DummyVRadius=0
endglobals
globals
private integer CountedD=0
private integer ROUND_TMP
private integer tmpint
endglobals
globals
private location ccloc=Location(0,0)
endglobals
globals
private player tmppl
endglobals
private function Init takes nothing returns nothing
set MAP_MaxX=GetRectMaxX(bj_mapInitialPlayableArea)
set MAP_MaxY=GetRectMaxY(bj_mapInitialPlayableArea)
set MAP_MinX=GetRectMinX(bj_mapInitialPlayableArea)
set MAP_MinY=GetRectMinY(bj_mapInitialPlayableArea)
set RV_DummyVRad=RV_DummyVRad*(0.9)
set RV_DummyVRadius=RV_DummyVRad*0.5
endfunction
private function Wait takes real duration returns nothing
local timer t
local real timeRemaining
if            (duration>0) then
set t=CreateTimer()
call TimerStart(t,duration,false,null)
loop
set timeRemaining=TimerGetRemaining(t)
exitwhen      (timeRemaining<=0)
if            (timeRemaining>2.) then
call TriggerSleepAction(0.1*timeRemaining)
else
call TriggerSleepAction(.1)
endif
endloop
call DestroyTimer(t)
set t=null
endif
endfunction
private function mod takes real x returns real
if             x<0 then
return        -x
else
return         x
endif
endfunction
private function map_bound takes real x,boolean y returns real
if            (y) then
if            (x>MAP_MaxY) then
return         MAP_MaxY
endif
if            (x<MAP_MinY) then
return         MAP_MinY
endif
return         x
else
if            (x>MAP_MaxX) then
return         MAP_MaxX
endif
if            (x<MAP_MinX) then
return         MAP_MinX
endif
return         x
endif
endfunction
function rView__Count_Destructibles takes nothing returns nothing
set CountedD=CountedD+1
endfunction
function rView__CountDestructibles takes nothing returns nothing
local rect r=Rect(Count_X-Count_R,Count_Y-Count_R,Count_X+Count_R,Count_Y+Count_R)
set CountedD=0
call EnumDestructablesInRect(r,null,function rView__Count_Destructibles)
call RemoveRect(r)
set r=null
endfunction
private function GetTerrainCliffLevelRect takes real x,real y,real r returns integer
local integer l=GetTerrainCliffLevel(x,y)
local integer cl
set cl=GetTerrainCliffLevel(x+r,y+r)
if            (cl>l) then
set l=cl
endif
set cl=GetTerrainCliffLevel(x+r,y-r)
if            (cl>l) then
set l=cl
endif
set cl=GetTerrainCliffLevel(x-r,y+r)
if            (cl>l) then
set l=cl
endif
set cl=GetTerrainCliffLevel(x-r,y-r)
if            (cl>l) then
set l=cl
endif
return         l
endfunction
private function RV_refresh takes nothing returns nothing
local integer i=0
local integer j=0
local integer k=1
local integer ind=1
local integer c
local integer n
local real a=0
local real cy
local real cx
local real n2
local real angle
local real dx
local real dy
local real mina
local real maxa
local real tmp
local location l
local boolean nn=false
local unit uu
local rView f
loop
exitwhen (i>rView.count)
set i=i+1
set f=rView.list[i]
if            (f.created==false) then
set f.created=true
set tmp=GetUnitFacing(f.mUnit)-f.angle_of_view/2
if            (tmp<0) then
set mina=tmp+360
elseif(tmp>360) then
set mina=tmp-360
else
set mina=tmp
endif
if            (tmp!=mina) then
set nn=true
endif
set tmp=GetUnitFacing(f.mUnit)+f.angle_of_view/2
if            (tmp<0) then
set maxa=tmp+360
elseif(tmp>360) then
set maxa=tmp-360
else
set maxa=tmp
endif
if            (tmp!=maxa) then
set nn=true
endif
if            (maxa<mina) then
set tmp=mina
set mina=maxa
set maxa=tmp
endif
set l=GetUnitLoc(f.mUnit)
loop

call RemoveUnit(f.dummy[j])
set f.dummy[j]=null

set j=j+1
exitwhen      (j>f.dummy_count)

endloop
set f.dummy_count=0
set ROUND_TMP=R2I(f.rad/f.DummyVRadius)
if            ((f.rad/f.DummyVRadius)-ROUND_TMP<0.5) then
set c=ROUND_TMP
else
set c=ROUND_TMP+1
endif
set j=f.viewstartwave
loop

set n2=3.14159/Asin(f.DummyVRad/(2*f.DummyVRadius*j+0.00001))
set ROUND_TMP=R2I(n2)
if            ((n2)-ROUND_TMP<0.5) then
set n=ROUND_TMP
else
set n=ROUND_TMP+1
endif
loop

set cx=GetUnitX(f.mUnit)+(j*f.DummyVRadius+f.DummyVRadius*1.4)*Cos(a*.0174532)
set cy=GetUnitY(f.mUnit)+(j*f.DummyVRadius+f.DummyVRadius*1.4)*Sin(a*.0174532)
set dx=cx-GetUnitX(f.mUnit)
set dy=cy-GetUnitY(f.mUnit)
set angle=57.2958*Atan2(cy-GetUnitY(f.mUnit),cx-GetUnitX(f.mUnit))
if            (nn) then
if            ( not (maxa>a and a>mina)) then
set f.dummy[ind]=CreateUnit(f.plr,0x68706561,cx,cy,0)
set f.angle[ind]=a-GetUnitFacing(f.mUnit)
set f.dist[ind]=SquareRoot(dx*dx+dy*dy)
set f.dummy_count=f.dummy_count+1
call PauseUnit(f.dummy[ind],true)
call ShowUnit(f.dummy[ind],false)
set ind=ind+1
endif
else
if            ((maxa>a and a>mina)) then
set f.dummy[ind]=CreateUnit(f.plr,0x68706561,cx,cy,0)
set f.angle[ind]=a-GetUnitFacing(f.mUnit)
set f.dist[ind]=SquareRoot(dx*dx+dy*dy)
set f.dummy_count=f.dummy_count+1
call PauseUnit(f.dummy[ind],true)
call ShowUnit(f.dummy[ind],false)
set ind=ind+1
endif
endif
set a=a+360/n2

set k=k+1
exitwhen      (k>n)

endloop
set a=0
set k=1

set j=j+1
exitwhen      (j>c)

endloop
set k=1
set a=0
set j=0
set ind=1
call RemoveLocation(l)
set f.posX=GetUnitX(f.mUnit)
set f.posY=GetUnitY(f.mUnit)
set f.quick=false
loop

set f.dists[j]=f.rad

set j=j+1
exitwhen      (j>360)

endloop
call MoveLocation(ccloc,GetUnitX(f.mUnit),GetUnitY(f.mUnit))
set f.absUHeight=GetLocationZ(ccloc)+GetUnitFlyHeight(f.mUnit)
call f.reset()
set j=0
elseif( not f.hold) then
if            (not(mod(GetUnitX(f.mUnit)-f.posX)<2)or not(mod(GetUnitY(f.mUnit)-f.posY)<2)or f.quick) then
loop

set f.dists[j]=f.rad

set j=j+1
exitwhen      (j>360)

endloop
call MoveLocation(ccloc,GetUnitX(f.mUnit),GetUnitY(f.mUnit))
set f.absUHeight=GetLocationZ(ccloc)+GetUnitFlyHeight(f.mUnit)
call f.reset()
endif
set f.posX=GetUnitX(f.mUnit)
set f.posY=GetUnitY(f.mUnit)
set j=0
endif
set nn=false
endloop
set l=null
set uu=null
endfunction
function CountUnitsInGr takes group grr returns integer
local integer i=0
local group ggg=CreateGroup()
call GroupAddGroup(grr,ggg)
loop
exitwhen       FirstOfGroup(ggg)==null
call GroupRemoveUnit(ggg,FirstOfGroup(ggg))
set i=i+1
endloop
call DestroyGroup(ggg)
set ggg=null
return         i
endfunction
struct rView
integer viewstartwave
real DummyVRad
integer dummyravcode
boolean CheckDestructibles
boolean CheckCliffs
boolean full_treatment
real dummy_phys_radius
real DummyVRadius
integer exactness
integer maximal_height_difference
real absUHeight
unit mUnit
integer rad
boolean created
boolean after_change
boolean quick
boolean hold
real posX
real posY
unit array dummy[512]
real array angle[512]
real array dist[512]
integer array dists[361]
unit array lanterns[256]
integer ln_count
integer dummy_count
real angle_of_view
player plr
static integer count=0
static timer t=CreateTimer()
static rView array list
static group allunits=CreateGroup()
static method Lantern_filter takes nothing returns boolean
return         GetUnitTypeId(GetFilterUnit())==0x6E303030
endmethod
static method Lantern_create takes nothing returns nothing
local unit u=GetEnumUnit()
if             GetUnitUserData(u)==0 then
call rView.AddView(u,tmppl,500,360,true,true,true,true,1,RV_DummyVRad,0x68706561,140.00,13,150)
set rView.list[tmpint].lanterns[rView.list[tmpint].ln_count]=u
set rView.list[tmpint].ln_count=rView.list[tmpint].ln_count+1
call SetUnitUserData(u,-1)
endif
set u=null
endmethod
method onDestroy takes nothing returns nothing
local integer j=0
set .mUnit=null
loop

call RemoveUnit(.dummy[j])
set .dummy[j]=null

set j=j+1
exitwhen      (j>.dummy_count)

endloop
endmethod
method reset takes nothing returns nothing
local real f=GetUnitFacing(.mUnit)
local real ux=GetUnitX(.mUnit)
local real uy=GetUnitY(.mUnit)
local real nx
local real ny
local real a
local real aD
local real reNormalized
local group g=CreateGroup()
local group gr=CreateGroup()
local integer i
local integer j=0
local boolean continue=false
set tmppl=GetOwningPlayer(.mUnit)
set tmpint=this
loop

set aD=-100.
set a=(f+.angle[j])*.0174532
set nx=ux+.dist[j]*Cos(a)
set ny=uy+.dist[j]*Sin(a)
if            (.quick) then
if            (.angle[j]<-180) then
set reNormalized=mod(.angle[j]+360)
elseif(.angle[j]>180) then
set reNormalized=mod(.angle[j]-360)
else
set reNormalized=mod(.angle[j])
endif
if            (.angle_of_view/2<=reNormalized or .rad<=.dist[j]) then
if            ( not IsUnitHidden(.dummy[j])) then
call ShowUnit(.dummy[j],false)
endif
call SetUnitUserData(.dummy[j],-1)
set continue=true
endif
endif
if            ( not continue) then
if            (.full_treatment) then
if            (f+.angle[j]<0) then
set aD=f+.angle[j]+360
elseif(f+.angle[j]>360) then
set aD=f+.angle[j]-360
else
set aD=f+.angle[j]
endif
set ROUND_TMP=R2I(aD/.exactness)
if            ((aD/.exactness)-ROUND_TMP<0.5) then
set i=ROUND_TMP
else
set i=ROUND_TMP+1
endif
set i=i*(.exactness)
if            (.dist[j]>.dists[i]) then
if            ( not IsUnitHidden(.dummy[j])) then
call ShowUnit(.dummy[j],false)
endif
set continue=true
endif
endif
if            ( not continue) then
call SetUnitUserData(.dummy[j],0)
if            (.CheckCliffs) then
call MoveLocation(ccloc,nx,ny)
if            (GetTerrainCliffLevelRect(nx,ny,.dummy_phys_radius*2)>GetTerrainCliffLevel(ux,uy) or GetLocationZ(ccloc)-.absUHeight>150) then
if            ( not IsUnitHidden(.dummy[j])) then
call ShowUnit(.dummy[j],false)
endif
if            (true) then
set .dists[i]=R2I(.dist[j])
endif
set continue=true
endif
endif
if            ( not continue) then
set Count_X=nx
set Count_Y=ny
set Count_R=.dummy_phys_radius
call ExecuteFunc("rView__CountDestructibles")
if            (.CheckDestructibles and CountedD>0) then
if            ( not IsUnitHidden(.dummy[j])) then
call ShowUnit(.dummy[j],false)
endif
if            (true) then
set .dists[i]=R2I(.dist[j])
endif
set continue=true
endif
if            ( not continue) then
if            (IsUnitHidden(.dummy[j]) and GetUnitUserData(.dummy[j])!=-1) then
call ShowUnit(.dummy[j],true)
endif
call SetUnitX(.dummy[j],nx)
call SetUnitY(.dummy[j],ny)
if             true then
if             true and GetUnitTypeId(.mUnit)!=0x6E303030 then
call GroupEnumUnitsInRange(g,nx,ny,.DummyVRad,Condition(function rView.Lantern_filter))
if            (CountUnitsInGr(g)>0) then
call ForGroup(g,function rView.Lantern_create)
call GroupAddGroup(g,gr)
endif
endif
endif
endif
endif
endif
endif
set continue=false

set j=j+1
exitwhen      (j>.dummy_count)

endloop
set j=0
loop
exitwhen  not(j<.ln_count)
if            ( not IsUnitInGroup(.lanterns[j],gr))and GetUnitUserData(.lanterns[j])==-1 then
call rView.DestroyView(.lanterns[j])
call SetUnitUserData(.lanterns[j],0)
set .lanterns[j]=.lanterns[.ln_count-1]
set .lanterns[.ln_count-1]=null
set j=j-1
set .ln_count=.ln_count-1
endif
set j=j+1
endloop
set .after_change=false
call DestroyGroup(g)
set g=null
call DestroyGroup(gr)
set gr=null
endmethod
static method AddView takes unit un,player ownp,integer r,real a,boolean h,boolean cd,boolean cc,boolean ft,integer vsw,real dvr,integer drv,real dpr,integer ex,integer mhd returns boolean
local rView f
if             rView.count>=8000 then
if            (true) then
call BJDebugMsg("Error  happened, when trying add new view modifier: count of modifiers>8000")
call BJDebugMsg("If you sure, than you created less 8000 modifiers and error happened - ")
call BJDebugMsg("please, report to [email][email protected][/email] [jabber]")
endif
return         false
endif
set rView.count=rView.count+1
set f=rView.create()
set rView.list[rView.count]=f
call GroupAddUnit(rView.allunits,un)
if            (rView.count==1) then
call TimerStart(rView.t,0.15,true,function RV_refresh)
endif
set f.viewstartwave=vsw
set f.maximal_height_difference=mhd
set f.DummyVRad=dvr
set f.dummyravcode=drv
set f.CheckDestructibles=cd
set f.CheckCliffs=cc
set f.full_treatment=ft
set f.dummy_phys_radius=dpr
set f.DummyVRad=f.DummyVRad*(0.9)
set f.DummyVRadius=f.DummyVRad*0.5
set f.exactness=ex
set f.mUnit=un
set f.rad=r
set f.dummy_count=0
set f.angle_of_view=a
set f.quick=false
set f.hold=h
set f.created=false
set f.plr=ownp
set f.ln_count=0
return         true
endmethod
static method DestroyView takes unit un returns boolean
local integer i=1
local boolean f=false
if            ( not IsUnitInGroup(un,.allunits)) then
if            (true) then
call BJDebugMsg("Unit isn't under rView system's control")
endif
return         false
endif
call GroupRemoveUnit(.allunits,un)
loop
if            (.list[i].mUnit==un) then
set f=true
endif
exitwhen      (i>.count or f)
set i=i+1
endloop
if            ( not f) then
if            (true) then
call BJDebugMsg("Unit is under rView system's control, but cannot be found")
call BJDebugMsg("please, report to [email][email protected][/email] [jabber]")
endif
return         false
endif
call .destroy(.list[i])
if            (.count>1) then
set .list[i]=.list[.count]
endif
set .count=.count-1
if             .count<1 then
call PauseTimer(.t)
endif
return         true
endmethod
static method ChangeParams takes unit un,integer r,real a,boolean h,boolean cd,boolean cc,boolean ft,integer vsw,real dvr,integer drv,real dpr,integer ex,integer mhd returns boolean
local integer i=1
local boolean f=false
if            ( not IsUnitInGroup(un,.allunits)) then
if            (true) then
call BJDebugMsg("Unit isn't under rView system's control")
endif
return         false
endif
loop
if             .list[i].mUnit==un then
set f=true
endif
exitwhen       f or i>=8000
set i=i+1
endloop
if            ( not f) then
if            (true) then
call BJDebugMsg("Unit is under rView system's control, but cannot be found")
call BJDebugMsg("please, report to [email][email protected][/email] [jabber]")
endif
return         false
endif
if            (r>.list[i].rad or a>.list[i].angle_of_view) then
set .list[i].quick=false
set .list[i].created=false
else
set .list[i].quick=true
endif
set .list[i].viewstartwave=vsw
set .list[i].DummyVRad=dvr
set .list[i].dummyravcode=drv
set .list[i].CheckDestructibles=cd
set .list[i].CheckCliffs=cc
set .list[i].full_treatment=ft
set .list[i].dummy_phys_radius=dpr
set .list[i].DummyVRad=.list[i].DummyVRad*(0.9)
set .list[i].DummyVRadius=.list[i].DummyVRad*0.5
set .list[i].exactness=ex
set .list[i].rad=r
set .list[i].maximal_height_difference=mhd
set .list[i].angle_of_view=a
set .list[i].after_change=true
set .list[i].hold=h
return         true
endmethod
static method SChangeParams takes unit un,integer r,real a,real time returns boolean
local integer i=1
local integer nr
local integer olr
local real na
local real t=0.0
local real ola
local boolean f=false
if            ( not IsUnitInGroup(un,.allunits)) then
if            (true) then
call BJDebugMsg("Unit isn't under rView system's control")
endif
return         false
endif
loop
if             .list[i].mUnit==un then
set f=true
endif
exitwhen       f or i>=8000
set i=i+1
endloop
if            ( not f) then
if            (true) then
call BJDebugMsg("Unit is under rView system's control, but cannot be found")
call BJDebugMsg("please, report to [email][email protected][/email] [jabber]")
endif
return         false
endif
if            (time<0.3*2) then
set time=0.3*2
endif
set olr=.list[i].rad
set ola=.list[i].angle_of_view
if            (r>olr or a>ola) then
set .list[i].quick=false
else
set .list[i].quick=true
endif
set nr=R2I((r-.list[i].rad)/time*0.3)
set na=(a-.list[i].angle_of_view)/time*0.3
loop
exitwhen       t>time
if            (r>olr or a>ola) then
set .list[i].created=false
endif
set .list[i].after_change=true
set .list[i].rad=.list[i].rad+(nr)
set .list[i].angle_of_view=.list[i].angle_of_view+(na)
call Wait(0.3)
set t=t+(0.3)
endloop
return         true
endmethod
endstruct
endlibrary
 

Attachments

  • rview_sys1.06_demo.w3x
    58.2 KB · Views: 85
Last edited:
Level 8
Joined
Aug 4, 2006
Messages
357
Wow that's a cool idea to only allow units to see in front of them. You should keep working on it, optimize it, make it smoother, and make it work better with objects. Sometimes my footman would blink out of sight when I was walking through the woods, which doesn't really make sense; try to fix that. Would this work with more than one unit at a time?
 
Level 3
Joined
Sep 25, 2009
Messages
18
Wow that's a cool idea to only allow units to see in front of them. You should keep working on it, optimize it, make it smoother, and make it work better with objects. Sometimes my footman would blink out of sight when I was walking through the woods, which doesn't really make sense; try to fix that. Would this work with more than one unit at a time?
Yes, it can work with big amount of units, but only if u have good PC. It's better to make a small locator, which will add views to all units in 1000 range(RPG, for example). I have new version, which have best set of parameters, but it is optimized for project. I can put it here if people need it.
 
I honestly believe that this should be submitted to the spells section.
Since the demo map is a big part of the system and to understand what the effect is, the demo map is needed.

Not to mention this will get more attention there.

I'm going to graveyard this, and I hope you consider submitting it to the spells section.
If you do not agree with me, send me a PM containing a valid reason that this should remain here.
 
Top