| 11-03-2006, 01:12 AM | #1 |
Mainly because of a question from a friend, I've spent the last couple days making a system that will have an artillery attack the spot where a unit will be when the projectile lands. (supposing that the unit walks in a straight line.) This tool takes in to account: - Projectile and unit speed. - Firing Delay. - Rotation speed. - Projectile window. In what I hope is a bugfree version, I can kill every target with a 25 diameter attack ground anywhere from 100-1000 units away. The timing is off by less that 0.1 seconds every time. Heres the code! JASS:function convert takes real input returns real //this fixes a bug where the angle between two units can return a negative value. if (input < 0 ) then return (input + 360) else return input endif endfunction function check2 takes real input returns real if (input < 0 ) then return 0 else return input endif endfunction function check1 takes real input returns real if (input > 180) then return (360 - input) else return input endif endfunction function Trig_atk_prediction_Actions takes nothing returns nothing local location attackedLoc = GetUnitLoc(GetTriggerUnit()) local location attackedLocV = GetUnitLoc(GetTriggerUnit()) local location attackerLoc = GetUnitLoc(GetAttacker()) local real attackerA = GetUnitFacing(GetAttacker()) local real attackedA = GetUnitFacing(GetTriggerUnit()) local real timeTilHit local real travelAngle local integer i = 0 call IssueImmediateOrderBJ( gg_unit_ebal_0000, "stop" ) loop set i = i+1 set travelAngle = check2( check1((RAbsBJ(attackerA - convert(AngleBetweenPoints(attackerLoc, attackedLocV))))) -GetUnitPropWindowBJ(GetAttacker()) ) set timeTilHit = ( (DistanceBetweenPoints(attackedLocV, attackerLoc) / 1000.00 ) + (0.25) + (0.30) + ( travelAngle * (GetUnitTurnSpeed(GetAttacker()) / 360.00) )) //1000 is projectile speed, 0.25 is fire delay, and 0.30 is an arbitrary constant. set attackedLocV = PolarProjectionBJ(attackedLoc, GetUnitMoveSpeed(GetTriggerUnit()) * timeTilHit, attackedA) call AddSpecialEffectLocBJ( attackedLocV, "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" ) exitwhen (i==4) endloop call DisplayTextToForce(GetPlayersAll(), "rotation needed: " + R2S(travelAngle)) //this is often 0 because of the 30 degree propulsion window. call StartTimerBJ( udg_tempTimer, false, 30 ) if (DistanceBetweenPoints(attackedLocV, attackerLoc) < 1151 ) then //dont atk if not in range call TriggerSleepAction( 0.01 ) //needed to make the thing actually fire call IssuePointOrderLocBJ( gg_unit_ebal_0000, "attackground", attackedLocV ) endif call TriggerRegisterUnitEvent( gg_trg_find_lista_delay_2, GetAttackedUnitBJ(), EVENT_UNIT_DAMAGED ) //detect projectile impact time set udg_flightTime = timeTilHit //for comparison in other trigger call TriggerSleepAction( 0.40 ) call IssueImmediateOrderBJ( gg_unit_ebal_0000, "stop" ) call RemoveLocation(attackedLoc) call RemoveLocation(attackedLocV) call RemoveLocation(attackerLoc) endfunction Does it leak? I am considering submitting it to the demo maps section. Is there anything to change first? I hope someone can dream up a use for this. ![]() |
| 11-03-2006, 02:12 AM | #2 |
You have some leaks in there; such as a special effect not destroyed. You should also learn to indent your code for easier reading. If you are planning on submitting this map, I would also get rid of all the blizzard.j calls and use the natives. You have tons of them that are really easily removed such as GetAttackedUnitBJ(), which just translates to GetTriggerUnit(). There are also plenty more of them. Get the blizzard.j file and search for anything in your code that has BJ in it first. You can see what a lot of these codes are calling. |
| 11-03-2006, 02:25 AM | #3 |
you have a lot of location leaks. |
| 11-03-2006, 02:26 AM | #4 |
JASS:function convert takes real input returns real //this fixes a bug where the angle between two units can return a negative value. if (input < 0 ) then return (input + 360) else return input endif endfunction function check2 takes real input returns real if (input < 0 ) then return 0 else return input endif endfunction function check1 takes real input returns real if (input > 180) then return (360 - input) else return input endif endfunction function Trig_atk_prediction_Actions takes nothing returns nothing local location attackedLoc = GetUnitLoc(GetTriggerUnit()) local location attackedLocV = GetUnitLoc(GetTriggerUnit()) local location attackerLoc = GetUnitLoc(GetAttacker()) local real attackerA = GetUnitFacing(GetAttacker()) local real attackedA = GetUnitFacing(GetTriggerUnit()) local real timeTilHit local real travelAngle local integer i = 0 call IssueImmediateOrder( gg_unit_ebal_0000, "stop" ) loop set i = i+1 set travelAngle = check2( check1((RAbsBJ(attackerA - convert(AngleBetweenPoints(attackerLoc, attackedLocV))))) -GetUnitPropWindowBJ(GetAttacker()) ) set timeTilHit = ( (DistanceBetweenPoints(attackedLocV, attackerLoc) / 1000.00 ) + (0.25) + (0.30) + ( travelAngle * (GetUnitTurnSpeed(GetAttacker()) / 360.00) )) set attackedLocV = PolarProjectionBJ(attackedLoc, GetUnitMoveSpeed(GetTriggerUnit()) * timeTilHit, attackedA) call AddSpecialEffectLocBJ( attackedLocV, "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" ) call DestroyEffect( bj_lastCreatedEffect ) exitwhen (i==4) endloop call DisplayTextToForce(GetPlayersAll(), "rotation needed: " + R2S(travelAngle)) //this is often 0 because of the 30 degree propulsion window. call StartTimerBJ( udg_tempTimer, false, 30 ) if (DistanceBetweenPoints(attackedLocV, attackerLoc) < 1151 ) then //dont atk if not in range call TriggerSleepAction( 0.01 ) //needed to make the thing actually fire call IssuePointOrderLoc( gg_unit_ebal_0000, "attackground", attackedLocV ) endif call TriggerRegisterUnitEvent( gg_trg_find_lista_delay_2, GetTriggerUnit(), EVENT_UNIT_DAMAGED ) //detect projectile impact time set udg_flightTime = timeTilHit //for comparison in other trigger call TriggerSleepAction( 0.40 ) call IssueImmediateOrder( gg_unit_ebal_0000, "stop" ) call RemoveLocation(attackedLoc) call RemoveLocation(attackedLocV) call RemoveLocation(attackerLoc) set attackedLoc = null set attackedLocV = null set attackerLoc = null endfunction function InitTrig_atk_prediction takes nothing returns nothing set gg_trg_atk_prediction = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_atk_prediction, EVENT_PLAYER_UNIT_ATTACKED ) call TriggerAddAction( gg_trg_atk_prediction, function Trig_atk_prediction_Actions ) endfunction fixed location leaks (I think.) Thanks to this post by PipeDream |
| 11-03-2006, 02:59 AM | #6 |
there are still many useless bj JASS:call AddSpecialEffectLocBJ( attackedLocV, "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" ) call DestroyEffect( bj_lastCreatedEffect ) replace with JASS:call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl",attackedLocV)) and JASS:call StartTimerBJ( udg_tempTimer, false, 30 ) JASS:call TimerStart( udg_tempTimer, 30, false, null) and JASS:call TriggerSleepAction( 0.01 ) //needed to make the thing actually fire |
| 11-03-2006, 04:01 AM | #7 |
TriggerSleepAction is a native and for a .01 wait does not need to be accurate at all. I wouldn't use a timer for something like that. |
| 11-04-2006, 12:33 AM | #8 |
Thanks. Will fix the above BJs. JASS:call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl",attackedLocV)) Best option would the wait would be to find out why I need it. Comment out that line, the ballista will just face the target, not shooting anything. |
| 11-04-2006, 12:58 AM | #9 |
basically it creates a thunderclap effect and instantly destroy it at the certain location so only its death animation are played, i did this alot untill i'm tired to typing it over and over again and make a function for it lol JASS:function CreateEffectEx takes string e, real x, real y returns nothing call DestroyEffect(AddSpecialEffect(e,x,y)) endfunction function CreateEffectExLoc takes string e, location l returns nothing call CreateEffectEx(e,GetLocationX(l),GetLocationY(l)) endfunction |
