| 04-29-2009, 03:58 PM | #1 |
Hey guys, I'm having some trouble with a grenade that should be bouncing on the ground. This doesn't work (surprise) so I need some help. This is what I have: JASS:if (xp.groundBounce==true) then if (xp.state==1) then set p=(GetUnitFlyHeight(e)+xp.addZ) set xp.addZ=(xp.addZ/2) elseif (xp.state==0) then set p=(GetUnitFlyHeight(e)-xp.addZ) set xp.addZ=(xp.addZ*2) endif call SetUnitFlyHeight(e,p,0) if (p>=xp.maxBounceZ) then set xp.state=0 elseif (p<=xp.minBounceZ) then set xp.state=1 set xp.bounces=(xp.bounces+1) endif endif This is where I call it: JASS:private function Actions takes nothing returns boolean local projsetup x local unit u local location l if (GetSpellAbilityId()==RAW_CODE) then set u=GetTriggerUnit() set l=GetSpellTargetLoc() set x=projsetup.create() set x.tx=GetLocationX(l) set x.ty=GetLocationY(l) set x.sx=GetUnitX(u) set x.sy=GetUnitY(u) set x.sz=0 set x.tz=0 set x.speed=400 set x.zspeed=0 set x.scale=100 set x.model="Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl" set x.attach="origin" set x.owner=GetOwningPlayer(u) set x.useZ=false set x.groundBounce=true set x.minBounceZ=1 set x.maxBounceZ=100 set x.maxBounces=GetRandomInt(10,15) set x.f=0 set x.proj=VPM_CreateProjectile(x,function MoveAct,function FinishAct) call RemoveLocation(l) set u=null set l=null endif return false endfunction And this is the full code: JASS:library VPM initializer Init globals //* Conf private constant integer DUMMY_CODE = 'h000' public constant real PERIOD = 0.04 endglobals struct projsetup unit proj real sx real sy real sz real tx real ty real tz real f real speed real zspeed real scale real minBounceZ real maxBounceZ string model string attach player owner boolean useZ boolean groundBounce integer maxBounces endstruct public struct mainproj extends projsetup real cos real sin real max real t real count effect e projsetup x boolean finish boolean stopWhenExceeded integer bounces trigger trg1 trigger trg2 //* bouncing real addZ integer state //* (1==up) (0==down) endstruct globals private timer xt=CreateTimer() private group xgrp=CreateGroup() private unit temp public real Game_maxX public real Game_maxY public real Game_minX public real Game_minY private location ZLoc=Location(0,0) endglobals public function GetUnitZ takes unit which returns real local real x=GetUnitX(which) local real y=GetUnitY(which) call MoveLocation(ZLoc,x,y) return (GetUnitFlyHeight(which)+GetLocationZ(ZLoc)) endfunction public function SetUnitZ takes unit which, real z returns nothing local real x=GetUnitX(which) local real y=GetUnitY(which) local real h call MoveLocation(ZLoc,x,y) set h=GetLocationZ(ZLoc) if (z>h) then call SetUnitFlyHeight(which,(z-h),0) endif call SetUnitFlyHeight(which,h,0) endfunction private function HandleProjs_Callback takes nothing returns nothing local unit e=GetEnumUnit() local mainproj xp=GetUnitUserData(e) local real x=GetUnitX(e) local real y=GetUnitY(e) local real z local real px=(x+xp.speed*xp.cos) local real py=(y+xp.speed*xp.sin) local real pz local real p local boolean b=false call TriggerEvaluate(xp.trg1) set xp.t=(xp.t+xp.speed) set temp=xp.proj if (xp.maxBounces!=0) then set b=(xp.bounces>=xp.maxBounces) endif if (x<Game_minX) then set px=Game_minX elseif (x>Game_maxX) then set px=Game_maxX endif if (py<Game_minY) then set py=Game_minY elseif (y>Game_maxY) then set py=Game_maxY endif call SetUnitX(e,px) call SetUnitY(e,py) if (xp.useZ==true) then set z=GetUnitZ(e) set pz=(z+xp.zspeed) call SetUnitZ(e,pz) endif if (xp.groundBounce==true) then if (xp.state==1) then set p=(GetUnitFlyHeight(e)+xp.addZ) set xp.addZ=(xp.addZ/2) elseif (xp.state==0) then set p=(GetUnitFlyHeight(e)-xp.addZ) set xp.addZ=(xp.addZ*2) endif call SetUnitFlyHeight(e,p,0) if (p>=xp.maxBounceZ) then set xp.state=0 elseif (p<=xp.minBounceZ) then set xp.state=1 set xp.bounces=(xp.bounces+1) endif endif if ((xp.t>=xp.max) and (xp.stopWhenExceeded==true)) or (xp.finish==true) or (b==true) then call GroupRemoveUnit(xgrp,e) call KillUnit(xp.proj) call DestroyEffect(xp.e) call TriggerEvaluate(xp.trg2) call DestroyTrigger(xp.trg1) call DestroyTrigger(xp.trg2) call xp.x.destroy() call xp.destroy() endif set e=null endfunction private function HandleProjs takes nothing returns nothing call ForGroup(xgrp,function HandleProjs_Callback) endfunction public function KillProjectile takes unit proj returns nothing set mainproj(GetUnitUserData(proj)).finish=true endfunction public function CreateProjectile takes projsetup x, code moveCode, code finishCode returns unit local mainproj xp=mainproj.create() local real angle local real dx local real dy set xp.proj=CreateUnit(x.owner,DUMMY_CODE,x.sx,x.sy,x.f) set xp.e=AddSpecialEffectTarget(x.model,xp.proj,x.attach) set xp.speed=(x.speed*PERIOD) set xp.zspeed=(x.zspeed*PERIOD) set xp.tx=x.tx set xp.ty=x.ty set xp.useZ=x.useZ set xp.count=0 set xp.stopWhenExceeded=true set xp.bounces=0 set xp.addZ=(x.maxBounceZ-xp.minBounceZ/2) set xp.state=1 set xp.minBounceZ=x.minBounceZ set xp.maxBounceZ=x.maxBounceZ if (x.groundBounce==true) then set xp.useZ=false set xp.stopWhenExceeded=false endif set xp.groundBounce=x.groundBounce set xp.x=x set xp.finish=false set xp.t=0 set dx=(x.tx-x.sx) set dy=(x.ty-x.sy) set xp.max=SquareRoot(dx*dx+dy*dy) set angle=Atan2(x.ty-x.sy,x.tx-x.sx) set xp.cos=Cos(angle) set xp.sin=Sin(angle) set xp.trg1=CreateTrigger() set xp.trg2=CreateTrigger() call TriggerAddCondition(xp.trg1,Condition(moveCode)) call TriggerAddCondition(xp.trg2,Condition(finishCode)) call SetUnitScale(xp.proj,(x.scale*0.01),(x.scale*0.01),(x.scale*0.01)) call UnitAddAbility(xp.proj,'Amrf') call UnitRemoveAbility(xp.proj,'Amrf') call SetUnitUserData(xp.proj,xp) call GroupAddUnit(xgrp,xp.proj) return xp.proj endfunction public function GetProj takes nothing returns unit return temp endfunction private function Init takes nothing returns nothing set Game_maxX=(GetRectMaxX(bj_mapInitialPlayableArea)-64.00) set Game_maxY=(GetRectMaxY(bj_mapInitialPlayableArea)-64.00) set Game_minX=(GetRectMinX(bj_mapInitialPlayableArea)+64.00) set Game_minY=(GetRectMinY(bj_mapInitialPlayableArea)+64.00) call TimerStart(xt,PERIOD,true,function HandleProjs) endfunction endlibrary The grenade should be having a realistic bounce, like when it has just hit the ground it is at its fastest point, where it basically is increasing in height medium fast, and then the higher up is goes the slower it becomes. When it then has hit the maximum, it should be doing the same thing except the other way around. |
| 04-29-2009, 04:20 PM | #2 |
So, what does the code do now? Isn't it doing anything at all? Doesn't the projectile height change? Or is it simply that the movement isn't realistic? If the answer to the last question is yes: To make the height change look realistic, the acceleration in the z direction has to be constant JASS:if xp.groundBounce then if xp.state == 1 then set p = GetUnitFlyHeight(e) + xp.addZ set xp.addZ = xp.addZ - VAR elseif xp.state == 0 then set p = GetUnitFlyHeight(e) - xp.addZ set xp.addZ = xp.addZ + VAR endif call SetUnitFlyHeight(e, p, 0) if p >= xp.maxBounceZ then set xp.state = 0 elseif p <= xp.minBounceZ then set xp.state = 1 set xp.bounces = xp.bounces + 1 endif endif And you deserve a comment about your post count, so here it is. |
| 04-29-2009, 04:25 PM | #3 |
The code makes the height change so much that you sometimes can't even see the proj. I just need a new way to do it. |
| 04-29-2009, 09:28 PM | #4 |
I'd say you should use vectors for stuff like this. |
| 04-30-2009, 03:58 PM | #5 |
> I'd say you should use vectors for stuff like this. Hnnng. I'd prefer it not to. Bumpy. |
| 04-30-2009, 04:18 PM | #6 |
Use 2 variables, a current height and a current velocity. You will constantly be adding to the velocity by some constant acceleration. You will subtract the velocity from the height, causing it to go downward. On a bounce, you multiply your velocity by some negative factor, to shrink and flip the direction of the ball. Since you are adding the velocity, it will cause the ball to slow down going up, and then speed up going down. JASS:if (xp.groundBounce==true) then set xp.vel = xp.vel + xp.acc set xp.height = xp.height - xp.vel if xp.height <= 0 then set xp.vel = xp.vel * -0.75 // flips and reduces the velocity (75% bounce) set xp.height = 0 // to make sure it doesn't stay under on the next iteration. endif call SetUnitFlyHeight(e, xp.height, 0) endif hopefully you get the idea. |
| 04-30-2009, 05:42 PM | #7 |
Thanks for helping Ammorth, but I am experiencing problems. I'm sure I'm just failing. My code: JASS:library VPM initializer Init requires DummyUtils globals //* Conf public constant real PERIOD = 0.04 endglobals struct projsetup unit proj real sx real sy real sz real tx real ty real tz real f real speed real zspeed real scale real minBounceZ real maxBounceZ real accZ real vel string model string attach player owner boolean useZ boolean groundBounce integer maxBounces endstruct public struct mainproj extends projsetup real cos real sin real max real t real count effect e projsetup x boolean finish boolean stopWhenExceeded integer bounces trigger trg1 trigger trg2 real height endstruct globals private timer xt=CreateTimer() private group xgrp=CreateGroup() private unit temp public real Game_maxX public real Game_maxY public real Game_minX public real Game_minY private location ZLoc=Location(0,0) endglobals public function GetUnitZ takes unit which returns real local real x=GetUnitX(which) local real y=GetUnitY(which) call MoveLocation(ZLoc,x,y) return (GetUnitFlyHeight(which)+GetLocationZ(ZLoc)) endfunction public function SetUnitZ takes unit which, real z returns nothing local real x=GetUnitX(which) local real y=GetUnitY(which) local real h call MoveLocation(ZLoc,x,y) set h=GetLocationZ(ZLoc) if (z>h) then call SetUnitFlyHeight(which,(z-h),0) endif call SetUnitFlyHeight(which,h,0) endfunction private function HandleProjs_Callback takes nothing returns nothing local unit e=GetEnumUnit() local mainproj xp=GetUnitUserData(e) local real x=GetUnitX(e) local real y=GetUnitY(e) local real z local real px=(x+xp.speed*xp.cos) local real py=(y+xp.speed*xp.sin) local real pz local real p local boolean b=false set temp=xp.proj call TriggerEvaluate(xp.trg1) set xp.t=(xp.t+xp.speed) if (x<Game_minX) then set px=Game_minX elseif (x>Game_maxX) then set px=Game_maxX endif if (py<Game_minY) then set py=Game_minY elseif (y>Game_maxY) then set py=Game_maxY endif call SetUnitX(e,px) call SetUnitY(e,py) if (xp.useZ==true) then set z=GetUnitZ(e) set pz=(z+xp.zspeed) call SetUnitZ(e,pz) endif if (xp.groundBounce==true) then set xp.vel=(xp.vel+xp.accZ) set xp.height=(xp.height-xp.vel) if (xp.height<=0) then set xp.vel=(xp.vel*-0.75) set xp.height=0 set xp.bounces=(xp.bounces+1) endif call BJDebugMsg(R2S(xp.height)) call SetUnitFlyHeight(e,xp.height,0) endif if (xp.maxBounces!=0) then set b=(xp.bounces>=xp.maxBounces) endif if ((xp.t>=xp.max) and (xp.stopWhenExceeded==true)) or (xp.finish==true) or (b==true) then call GroupRemoveUnit(xgrp,e) call DestroyEffect(xp.e) call TriggerEvaluate(xp.trg2) call DestroyTrigger(xp.trg1) call DestroyTrigger(xp.trg2) call ReleaseDummy(xp.proj) call xp.x.destroy() call xp.destroy() endif set e=null endfunction private function HandleProjs takes nothing returns nothing call ForGroup(xgrp,function HandleProjs_Callback) endfunction public function KillProjectile takes unit proj returns nothing set mainproj(GetUnitUserData(proj)).finish=true endfunction public function CreateProjectile takes projsetup x, code moveCode, code finishCode returns unit local mainproj xp=mainproj.create() local real angle local real dx local real dy set xp.proj=NewDummy(x.owner,x.sx,x.sy,x.f) set xp.e=AddSpecialEffectTarget(x.model,xp.proj,x.attach) set xp.speed=(x.speed*PERIOD) set xp.zspeed=(x.zspeed*PERIOD) set xp.tx=x.tx set xp.ty=x.ty set xp.useZ=x.useZ set xp.count=0 set xp.stopWhenExceeded=true set xp.bounces=0 set xp.height=GetUnitFlyHeight(xp.proj) set xp.minBounceZ=x.minBounceZ set xp.maxBounceZ=x.maxBounceZ if (x.groundBounce==true) then set xp.useZ=false set xp.stopWhenExceeded=false endif set xp.groundBounce=x.groundBounce set xp.x=x set xp.finish=false set xp.t=0 set dx=(x.tx-x.sx) set dy=(x.ty-x.sy) set xp.max=SquareRoot(dx*dx+dy*dy) set angle=Atan2(x.ty-x.sy,x.tx-x.sx) set xp.cos=Cos(angle) set xp.sin=Sin(angle) set xp.trg1=CreateTrigger() set xp.trg2=CreateTrigger() call TriggerAddCondition(xp.trg1,Condition(moveCode)) call TriggerAddCondition(xp.trg2,Condition(finishCode)) call SetUnitScale(xp.proj,(x.scale*0.01),(x.scale*0.01),(x.scale*0.01)) call UnitAddAbility(xp.proj,'Amrf') call UnitRemoveAbility(xp.proj,'Amrf') call SetUnitUserData(xp.proj,xp) call GroupAddUnit(xgrp,xp.proj) return xp.proj endfunction public function GetProj takes nothing returns unit return temp endfunction private function Init takes nothing returns nothing set Game_maxX=(GetRectMaxX(bj_mapInitialPlayableArea)-64.00) set Game_maxY=(GetRectMaxY(bj_mapInitialPlayableArea)-64.00) set Game_minX=(GetRectMinX(bj_mapInitialPlayableArea)+64.00) set Game_minY=(GetRectMinY(bj_mapInitialPlayableArea)+64.00) call TimerStart(xt,PERIOD,true,function HandleProjs) endfunction endlibrary JASS:library Grenade initializer Init requires VPM globals private constant integer RAW_CODE = 'A002' //* Raw code of the spell private constant real RADIUS = 200 //* Radius of the check/damage private constant real DAMAGE = 75 //* Damage done to units //* Don't touch private trigger Trg=CreateTrigger() private group Grp=CreateGroup() private unit Temp endglobals private function EnumAct takes nothing returns boolean local unit f=GetFilterUnit() if ((IsUnitEnemy(f,GetOwningPlayer(Temp))) and (IsUnitType(f,UNIT_TYPE_STRUCTURE)==false) and (GetWidgetLife(f)>.405)) then set VPM_mainproj(GetUnitUserData(Temp)).finish=true call UnitDamageTarget(Temp,f,DAMAGE,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS) endif set f=null return false endfunction private function MoveAct takes nothing returns boolean local unit u=VPM_GetProj() local real x=GetUnitX(u) local real y=GetUnitY(u) set Temp=u call GroupEnumUnitsInRange(Grp,x,y,RADIUS,Filter(function EnumAct)) set u=null return false endfunction private function FinishAct takes nothing returns boolean local unit u=VPM_GetProj() call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl",GetUnitX(u),GetUnitY(u))) set u=null return false endfunction private function Actions takes nothing returns boolean local projsetup x local unit u local location l if (GetSpellAbilityId()==RAW_CODE) then set u=GetTriggerUnit() set l=GetSpellTargetLoc() set x=projsetup.create() set x.tx=GetLocationX(l) set x.ty=GetLocationY(l) set x.sx=GetUnitX(u) set x.sy=GetUnitY(u) set x.sz=0 set x.tz=0 set x.speed=400 set x.zspeed=0 set x.scale=100 set x.model="Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl" set x.attach="origin" set x.owner=GetOwningPlayer(u) set x.useZ=false set x.groundBounce=true set x.minBounceZ=1 set x.maxBounceZ=100 set x.maxBounces=GetRandomInt(10,15) set x.accZ=5 set x.vel=50 set x.f=0 set x.proj=VPM_CreateProjectile(x,function MoveAct,function FinishAct) call RemoveLocation(l) set u=null set l=null endif return false endfunction private function Init takes nothing returns nothing call TriggerRegisterAnyUnitEventBJ(Trg,EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(Trg,Condition(function Actions)) endfunction endlibrary The debug msg displays 50 all the way and the height doesn't change. |
| 04-30-2009, 06:58 PM | #8 |
use vector will do the trick fast easy and fast |
| 05-01-2009, 12:57 AM | #9 |
Add Crow Form to the unit u wan to bounce |
