| 08-12-2009, 06:53 PM | #1 |
After my first version was graveyarded (could only draw one shape at one time); I've tried to rework it, but.... now evreything is stored in a list (good), only thing is, that.... *bah* download the map and try to create more than one star....you will see Version 1.2:// TFormula is a system to draw Shapes via the Superformula // link: [url]www.en.wikipedia.org/wiki/Superformula[/url] // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+!!IF YOU USE IT GIVE CREDITS TO TOT AND VEXORIAN FOR XE AND TIMEDLOOP!!+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+!!THIS IS TOT'S SYSTEM YOU NOT ALLOWED TO CHANGE IT OR DISTRIBUTE IT TO ANYTHING WITHOUT ASKING!!+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!the boolean original determines if u use the mathematical correct formula (one Pow() more) or a modified one (mathematical not correct but looks nicer)!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // //Create: // At first Create a Shape // call TFormula.create(unitCaster, stringPROJECTILE_PATH,locationLoc,realFlyingheight, realRange, realSpeed, realPeriod, realDuration, realAoe, realDmg, realNUMBEROFDUMMIES, real_m, real_n1, real_n2, real_n3,realSize, integer_red, integer_green, integer_blue, integer_alpha, integerLevel, integerMode, booleanOriginal) // // in detail: // - unitCaster: is usually the casting unit // - stringPROJECTILE_PATH: path of the model you want to use as projectile // - locationLoc: determines the certer of the shape // - realFlyingheight: determine the flyingheight of the Projectiles // - realRange: size of the shape // - realSpeed: speed of the shape (set 0 if you dont want to move it) // - realPeriod: time between the shape is moved (lower value: faster, looks smoother but requires mor ressources; higher: other way round)# // - realDuration: time the shape lasts // - realAoe: area around each projectile in which units are damaged // - realDmg: damage dealt to all affected units // - realNUMBEROFDUMMIES: number of effects creating the shape // - real_m, real_n1, real_n2, real_n3 determine the form of hte shape (for examples look here: [url]www.en.wikipedia.org/wiki/Superformula[/url]) // - realSize: size of the dummies // - integer_red, integer_green, integer_blue, integer_alpha: detetmone color and transparency of the dummies // - integerLevel: level of the spell // - integerMode: determines movement of the shape (see later) // - booleanOriginal: determines weather mathematical correct formula is used or not (see above for more details) // // now determine what hte shape does, if a unit enters the aoe around a dummy // call getNewestTFormula().setXedamageOptions(unittypeUtype, damagetypeDtype, attacktypeAtype, stringEffectPath, stringEffectAttach , realDmgFactor, realAllyFactor, booleanDmgSelf, booleanDmgAlly, booleanDmgFoe, booleanDmgNeut, booleanRanged, booleanVisibleOnly, booleanDeadOnly, booleanAlsoDead, booleanDmgTrees) // // in detail: // - unittypeUtype: Unittype which is affected for realDmgFactor // - damagetypeDtype: damagetype of damage dealt by the shape // - attacktypeAtype: attacktype of damage dealt by the shape // - stringEffectPath: path of the special effect created at EffectAttach of the affected unit // - stringEffectAttach: position at which stringEffectPath is created // - realDmgFactor: damage*realDamageFactor is dealt to all units matching unittype of matching unit==unittypeUtype // - realAllyFactor: damage*realAllyFactor dealt to allies of caster // - booleanDmgSelf: could caster be hit by his own spell? // - booleanDmgAlly: could allies be hit by the spell? // - booleanDmgFoe: could foes be hit by the spell? // - booleanDmgNeut: could neutral units be hit by the spell // - booleanRanged: is damage dealt ranged? (determines behavior of affected units) // - booleanVisibleOnly: can only visible units be damaged by the spell? // - booleanDeadOnly: can only dead be hit by the spell // - booleanAlsoDead: can be dead hit by the spell, too? // - booleanDmgTrees: are trees damaged by the spell? // for further information check the xedamage readme // //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //functions in detail: //<still to do> // //----------------------------------------------------------------------------------------------------------------- //methods in detail: //<still to do> library TFormula requires xefx, xedamage globals private real minX= GetRectMinX(bj_mapInitialPlayableArea) private real maxX= GetRectMaxX(bj_mapInitialPlayableArea) private real minY= GetRectMinY(bj_mapInitialPlayableArea) private real maxY= GetRectMaxY(bj_mapInitialPlayableArea) private TFormula array list[8190] private integer listmax=0 endglobals private function cleanList takes nothing returns nothing local integer l=0 local integer empty=0 loop exitwhen l>listmax if list[l]==0 then set list[l]=list[l+1] set empty=empty+1 endif set l=l+1 endloop set listmax=listmax-empty endfunction function countTFormulas takes nothing returns integer return listmax endfunction function storeTFormula takes TFormula tf returns nothing set list[listmax]=tf set list[listmax].placeinlist=listmax set listmax=listmax+1 endfunction function getNewestTFormula takes nothing returns TFormula return list[listmax] endfunction function getTFormula takes integer place returns TFormula if place<=listmax then return list[place] endif return 0 endfunction function removeTFormula takes TFormula tf returns boolean local integer i=0 loop exitwhen i>listmax if list[i]==tf then call list[i].destroy() set list[i]=0 call cleanList() return true endif endloop return false endfunction function removeTFormulaPlace takes integer place returns boolean if place>listmax then call list[place].destroy() set list[place]=0 call cleanList() return true endif return false endfunction function moveTFormula takes integer mode,integer place returns nothing if place <=listmax then if mode == 0 then call list[place].moveInLine() endif if mode == 1 then call list[place].rotate() endif if mode == 2 then call list[place].rotateInLine() endif endif endfunction private function Xbounds takes real x returns real if x > GetRectMaxX(bj_mapInitialPlayableArea) then return GetRectMaxX(bj_mapInitialPlayableArea) elseif x < GetRectMinX(bj_mapInitialPlayableArea) then return GetRectMinX(bj_mapInitialPlayableArea) endif return x endfunction private function Ybounds takes real y returns real if y > GetRectMaxY(bj_mapInitialPlayableArea) then return GetRectMaxY(bj_mapInitialPlayableArea) elseif y < GetRectMinY(bj_mapInitialPlayableArea) then return GetRectMinY(bj_mapInitialPlayableArea) endif return y endfunction private function Rad takes real m, real n1, real n2, real n3, real alpha, boolean original returns real local real r if original == true then set r=Pow((Pow(RAbsBJ(Cos(m/4*(alpha))),n2)+(Pow(RAbsBJ(Sin(m/4*(alpha))),n3))),-1/n1) else set r=1/(Pow(RAbsBJ(Cos(m/4*(alpha))),n2/n1)+(Pow(RAbsBJ(Sin(m/4*(alpha))),n3/n1))) endif return r endfunction function ReturnX takes real startx, real m, real n1, real n2, real n3, real alpha1, real alpha2, real range, boolean original returns real local real x set x=startx+Cos(alpha2)*range*Rad(m,n1,n2,n3,alpha1, original) return x endfunction function ReturnY takes real starty, real m, real n1, real n2, real n3, real alpha1, real alpha2, real range, boolean original returns real local real y set y=starty+Sin(alpha2)*range*Rad(m,n1,n2,n3,alpha1, original) return y endfunction function ReturnLoc takes location start, real m, real n1, real n2, real n3, real alpha1, real alpha2, real range, boolean original returns location local location Loc set Loc = Location(ReturnX(GetLocationX(start),m,n1,n2,n3,alpha1, alpha2, range, original),ReturnY(GetLocationY(start),m,n1,n2,n3,alpha1, alpha2, range, original)) return Loc endfunction private function TFormulamove takes nothing returns nothing endfunction struct TFormula player owner xefx array projectile [8190] unit caster string PROJECTILE_PATH real sourcex real sourcey real angle real range real speed real move_period real duration real aoe real damage real livingTime real NUMBEROFDUMMIES real t real r real size real flyingheight real FORMULA_m real FORMULA_n1 real FORMULA_n2 real FORMULA_n3 integer level integer move_mode integer i integer red integer green integer blue integer alpha integer placeinlist boolean original //xedamage xedamage d unittype utype damagetype dtype attacktype atype string effectPath string effectAttach real dmgFactor real allyFactor boolean dmgSelf boolean dmgAlly boolean dmgFoe boolean dmgNeut boolean ranged boolean visibleOnly boolean deadOnly boolean alsoDead boolean dmgTrees //xedamage static method create takes unit caster, string PROJECTILE_PATH, location loc,real flyingheight, real range, real speed, real period, real duration, real aoe, real dmg, real NUMBEROFDUMMIES, real m, real n1, real n2, real n3,real size, integer red, integer green, integer blue, integer alpha, integer level, integer mode, boolean original returns TFormula local TFormula s = TFormula.allocate() local real x local real y local real a set s.caster = caster set s.owner = GetOwningPlayer(caster) set s.angle= GetUnitFacing(caster) set s.range=range set s.speed=speed set s.duration=duration set s.aoe=aoe set s.damage=dmg set s.move_period=period set s.livingTime=0.0 set s.sourcex = GetLocationX(loc) set s.sourcey = GetLocationY(loc) set s.NUMBEROFDUMMIES=NUMBEROFDUMMIES set s.flyingheight=flyingheight set s.FORMULA_m=m set s.FORMULA_n1=n1 set s.FORMULA_n2=n2 set s.FORMULA_n3=n3 set s.PROJECTILE_PATH=PROJECTILE_PATH set s.level=level set s.move_mode=mode set s.red=red set s.green=green set s.blue=blue set s.alpha=alpha set s.size=size set s.original=original set s.t = 0.0 set s.i=0 loop exitwhen s.i > s.NUMBEROFDUMMIES set a=s.angle+360/s.NUMBEROFDUMMIES*s.i set x=Xbounds(ReturnX(s.sourcex,s.sourcey, s.FORMULA_m, s.FORMULA_n1, s.FORMULA_n2, s.FORMULA_n3, a, s.range, s.original)) set y=Ybounds(ReturnY(s.sourcex,s.sourcey, s.FORMULA_m, s.FORMULA_n1, s.FORMULA_n2, s.FORMULA_n3, a, s.range, s.original)) set s.projectile[s.i] = xefx.create(x,y,s.angle) set s.projectile[s.i].fxpath = s.PROJECTILE_PATH set s.projectile[s.i].scale= s.size call s.projectile[s.i].recolor(s.red,s.green,s.blue,s.alpha) set s.projectile[s.i].z=s.flyingheight set s.i=s.i+1 endloop call s.move() call storeTFormula(s) return s endmethod method setXedamageOptions takes unittype utype, damagetype dtype, attacktype atype, string effectPath, string effectAttach , real dmgFactor, real allyFactor, boolean dmgSelf, boolean dmgAlly, boolean dmgFoe, boolean dmgNeut, boolean ranged, boolean visibleOnly, boolean deadOnly, boolean alsoDead, boolean dmgTrees returns nothing set this.utype=utype set this.dtype=dtype set this.atype=atype set this.effectPath=effectPath set this.effectAttach=effectAttach set this.dmgFactor=dmgFactor set this.allyFactor=allyFactor set this.dmgSelf=dmgSelf set this.dmgAlly=dmgAlly set this.dmgFoe=dmgFoe set this.dmgNeut=dmgNeut set this.ranged=ranged set this.visibleOnly=visibleOnly set this.deadOnly=deadOnly set this.alsoDead=alsoDead set this.dmgTrees=dmgTrees set this.d=xedamage.create() set this.d.dtype = this.dtype set this.d.atype = this.atype call this.d.factor(this.utype, this.dmgFactor) set this.d.damageSelf = this.dmgSelf set this.d.damageAllies = this.dmgAlly set this.d.damageEnemies = this.dmgFoe set this.d.damageNeutral = this.dmgNeut set this.d.ranged = this.ranged set this.d.visibleOnly = this.visibleOnly set this.d.deadOnly = this.deadOnly set this.d.alsoDead = this.alsoDead set this.d.damageTrees = this.dmgTrees set this.d.allyfactor = this.allyFactor call this.d.useSpecialEffect(this.effectPath,this.effectAttach) endmethod private method destroyShape takes nothing returns nothing set this.i=0 loop exitwhen this.i > this.NUMBEROFDUMMIES call this.projectile[this.i].destroy() set this.i=this.i+1 endloop call removeTFormula(this.placeinlist) call this.onDestroy() endmethod private method onTimedLoop takes nothing returns boolean if this.move_mode==0 then call this.moveInLine() endif if this.move_mode==1 then call this.rotate() endif if this.move_mode==2 then call this.rotateInLine() endif if this.duration< this.livingTime then call this.destroyShape() return TimedLoop_STOP endif return TimedLoop_CONTINUE endmethod implement TimedLoop method move takes nothing returns nothing call this.startTimedLoop() endmethod method moveInLine takes nothing returns nothing set this.t=this.t+this.speed set this.i=0 loop exitwhen this.i > this.NUMBEROFDUMMIES set this.projectile[this.i].x=Xbounds(ReturnX(this.sourcex, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.range, this.original)) set this.projectile[this.i].y=Ybounds(ReturnY(this.sourcey, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.range, this.original)) set this.i=this.i+1 endloop call this.affectUnits(this.caster, this.aoe, this.damage*this.move_period) set this.livingTime=this.livingTime+this.move_period endmethod method rotate takes nothing returns nothing set this.t=this.t+this.speed set this.i=0 loop exitwhen this.i > this.NUMBEROFDUMMIES set this.projectile[this.i].x=Xbounds(ReturnX(this.sourcex, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.angle+(360/this.NUMBEROFDUMMIES)*this.i, this.range, this.original)) set this.projectile[this.i].y=Ybounds(ReturnY(this.sourcey, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.angle+(360/this.NUMBEROFDUMMIES)*this.i, this.range, this.original)) set this.i=this.i+1 endloop call this.affectUnits(this.caster, this.aoe, this.damage*this.move_period) set this.livingTime=this.livingTime+this.move_period endmethod method rotateInLine takes nothing returns nothing set this.t=this.t+this.speed set this.i=0 loop exitwhen this.i > this.NUMBEROFDUMMIES set this.projectile[this.i].x=Xbounds(ReturnX(this.sourcex, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t*2, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.range, this.original)) set this.projectile[this.i].y=Ybounds(ReturnY(this.sourcey, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t*2, this.angle+(360/this.NUMBEROFDUMMIES)*this.i+this.t, this.range, this.original)) set this.i=this.i+1 endloop call this.affectUnits(this.caster, this.aoe, this.damage*this.move_period) set this.livingTime=this.livingTime+this.move_period endmethod method isUnitInShape takes unit check returns boolean local real array xcheck local real array ycheck local real unitx=GetUnitX(check) local real unity=GetUnitY(check) local integer i=0 local integer j=0 local boolean t=false loop exitwhen i>this.NUMBEROFDUMMIES set j=i-1 if j<0 then set j=R2I(this.NUMBEROFDUMMIES) endif set xcheck[0]=Xbounds(ReturnX(this.sourcex, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, 360/this.NUMBEROFDUMMIES*i, 360/this.NUMBEROFDUMMIES*i, this.range, this.original)) set ycheck[0]=Ybounds(ReturnY(this.sourcey, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, 360/this.NUMBEROFDUMMIES*i, 360/this.NUMBEROFDUMMIES*i, this.range, this.original)) set xcheck[1]=Xbounds(ReturnX(this.sourcex, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, 360/this.NUMBEROFDUMMIES*j, 360/this.NUMBEROFDUMMIES*j, this.range, this.original)) set ycheck[1]=Ybounds(ReturnY(this.sourcey, this.FORMULA_m, this.FORMULA_n1, this.FORMULA_n2, this.FORMULA_n3, 360/this.NUMBEROFDUMMIES*j, 360/this.NUMBEROFDUMMIES*j, this.range, this.original)) if xcheck[0]>=unitx and unitx>=xcheck[1] and ycheck[0]>=unity and unity>=ycheck[1] then set t=true endif if xcheck[0]<=unitx and unitx<=xcheck[1] and ycheck[0]>=unity and unity>=ycheck[1] then set t=true endif if xcheck[0]<=unitx and unitx<=xcheck[1] and ycheck[0]<=unity and unity<=ycheck[1] then set t=true endif if xcheck[0]>=unitx and unitx>=xcheck[1] and ycheck[0]<=unity and unity<=ycheck[1] then set t=true endif set i=i+1 endloop return t endmethod method changeAllProjectilePath takes string path returns nothing set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES set this.projectile[this.i].fxpath=path endloop endmethod method changeAllProjectileSize takes real size returns nothing set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES set this.projectile[this.i].scale=size endloop set this.size=size endmethod method changeAllProjectileColor takes integer r, integer g, integer b, integer a returns nothing set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES call this.projectile[this.i].recolor(r,g,b,a) endloop set this.red=r set this.green=g set this.blue=b set this.alpha=a endmethod method modifySpecificProjectile takes string path, real size, integer r, integer g, integer b, integer alpha, integer fxnumber, boolean changepath, boolean changesize, boolean changecolor returns nothing local integer nr if fxnumber>this.NUMBEROFDUMMIES then set nr=R2I(this.NUMBEROFDUMMIES) else set nr=fxnumber endif if changepath==true then set this.projectile[nr].fxpath=path endif if changesize==true then set this.projectile[nr].scale=size endif if changecolor==true then call this.projectile[nr].recolor(r,g,b,alpha) endif endmethod method getMaxRad takes nothing returns real local real r=0 local real check set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES set check=DistanceBetweenPoints(GetUnitLoc(this.caster),Location(this.projectile[this.i].x,this.projectile[this.i].y)) if check>r then set r=check endif set this.i=this.i+1 endloop return r endmethod method affectUnits takes unit caster, real area, real damage returns nothing local location l set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES set l=Location(this.projectile[this.i].x,this.projectile[this.i].y) call this.d.damageAOELoc(caster,l, area, damage) set this.i=this.i+1 endloop endmethod method changeFlyingHeight takes real newHeight returns nothing set this.i=0 loop exitwhen this.i>this.NUMBEROFDUMMIES set this.projectile[this.i].z=newHeight set this.i=this.i+1 endloop set this.flyingheight=newHeight endmethod method returnProjectile takes integer which returns xefx local integer i if which>this.NUMBEROFDUMMIES then set i=R2I(this.NUMBEROFDUMMIES) else set i=which endif return this.projectile[i] endmethod method returnProjectileLoc takes xefx projectile returns location return Location(projectile.x,projectile.y) endmethod private method onDestroy takes nothing returns nothing set this.t=0 set this.caster=null endmethod endstruct endlibrary I'm also happy about any criticism/help I get, cause I know the code is awfull @Phlame: any wishes for better compatibility to your 2d3s thx oh...I think I've to spread lots of rep+ |
| 08-13-2009, 09:18 AM | #2 |
You are using a clever solution, coding your own list. However, you struct TFormula has an arrays of projectiles, meaning you still can have more then 1 TFormula object without having problems. When I mentioned Lists I was thinking about the following: http://www.wc3c.net/showthread.php?t=106479 http://www.wc3c.net/showthread.php?t=103604 http://www.wc3c.net/showthread.php?t...highlight=List You need to give this another try. As for compatibility, 2D3S architecture is independent from any drawing system. I have the "core" and then all shapes are just lists of points, nothing else. If I want to draw something, I need to import a module. So technically, 2d3s will not be dependant on xefx, neither anything else, and so far your system is. |
| 08-13-2009, 09:23 AM | #3 |
I've tried both LinkedList and Stack, but both made it lag, even if no unit is damaged --> not good maybe I'll try grims ListModule, but first I've to fix the probleme with drawing more than one shape ... dunno why it makes stupid things |
| 08-13-2009, 10:59 AM | #4 |
Well, technically, you could separate all things - the maths, the draw, the spell. In 2D3S, if I want to draw a Line, I import the core and Line lib. Line lib does not allow me to draw a line, it gives me the maths I need to do so. Further I would need to import xefxmodule. Separating things like this is good, in many spells I will not need to make pictures of anything. Perhaps you should follow a similar pattern. |
| 08-13-2009, 02:53 PM | #5 | |
Quote:
|
| 08-13-2009, 04:55 PM | #6 | |
Quote:
ah... you're talking about the projectiles-array... second ah... got an idea to improve my list-thingy...think i should make an own small lib for it.... |
