| 08-12-2008, 05:45 PM | #1 |
Hi guys, I am making a new spell for the Olympics, I hope I can enter with more than one submission. Anyway, this spell is a fire Bomber spell. To explain, when the caster casts the spell, we create a plane away from him. The plane is created invisible. After the creation we make the plane fade in, and then we move him. while the plane is being moved, we decrease it's flying height. When it's flying height is low enough, we wait a few miliseconds (or not, this is to make the middle bomb fall on the middle of the target spell location) and then the complication begins, we start dropping bombs. I am no pro with timers, but I want to add to the bombs a realistic effect, like using a parabola or something that makes the bomb fall in a realistic way. But I can't do it alone, can some one help me ? Btw, I am using TimerUtils. JASS:cope FireBomber initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A000' //rawcode of the ability private constant integer BOMBER_ID = 'h002' //rawcode of the bomber private constant integer PLANE_RED = 255 //The Red RGB color of the Plane private constant integer PLANE_GREEN = 255 //The Green RGB color of the Plane private constant integer PLANE_BLUE = 255 //The Blue RGB color of the Plane private constant integer FADE_MAX = 255 //The maximum Alpha the plane will have. This is ralated to the transparency and therefore to the fading. private constant real FADE_IN = 0.2 //the intervail of time between each time the plane either fades in or out private constant integer FADE_INCRESE = 30 private constant integer BOMBARD_HEIGHT = 400 private constant integer HEIGHT_LOSS = 50 endglobals private constant function PlaneStartDistance takes integer level returns real //the ditance that the plane will be from the caster when it is created //you can make it depend on the level like in the next example return 1400. + (level * 0) endfunction private constant function BombsNumber takes integer level returns integer return 5 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== private struct MyStruct unit caster integer level unit bomber real height integer fade timer bombFall //will make bombs fall in realistic way timer fader //will control the fade in and fade out of the plane timer mover //this timer will move the plane timer heightControler //Controls the height of the plane static method create takes unit caster, real spellX, real spellY, real angle returns MyStruct local MyStruct data = MyStruct.allocate() //set variables about the caster set data.caster = caster set data.level = GetUnitAbilityLevel(data.caster, AID) //variables about the bomber set data.bomber = CreateUnit(GetOwningPlayer(data.caster), BOMBER_ID, spellX - PlaneStartDistance(data.level) * Cos(angle * (bj_PI / 180.0)), spellY - PlaneStartDistance(data.level) * Sin(angle * (bj_PI / 180.0)), angle) set data.height = GetUnitFlyHeight(data.bomber) set data.fade = 0 set data.bombFall = NewTimer() set data.fader = NewTimer() set data.mover = NewTimer() set data.heightControler = NewTimer() call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, data.fade) return data endmethod method onDestroy takes nothing returns nothing call ReleaseTimer(.bombFall) call ReleaseTimer(.fader) call ReleaseTimer(.mover) call ReleaseTimer(.heightControler) endmethod endstruct //====================================================================================== private function DropBomb takes integer structure returns nothing local MyStruct data = structure //here we create bombs and make them fall //when a bombs falls, it dies //when it dies, we create the effect endfunction //====================================================================================== private function FadeIn takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) //if we reached our maximum fade, we pause the timer, so we start later when we //want to make the plane fade out if (data.fade >= FADE_MAX) then call PauseTimer(data.fader) //if not, we increase the fade of the plane making it less transparent else set data.fade = data.fade + FADE_INCRESE call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, data.fade) endif endfunction //====================================================================================== private function MovePlane takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) call SetUnitPosition(data.bomber, GetUnitX(data.bomber) + 6, GetUnitY(data.bomber) + 6) endfunction //====================================================================================== private function LoseHeight takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) //if the plane alreadu reached the bombarding altitude, then we drop the bombs if (data.height <= BOMBARD_HEIGHT) then call PauseTimer(data.heightControler) //else we keep diminuishing the height of the plane else set data.height = data.height - HEIGHT_LOSS call SetUnitFlyHeight(data.bomber, data.height, 80) endif endfunction //====================================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID endfunction //====================================================================================== private function Actions takes nothing returns nothing local location spellLoc = GetSpellTargetLoc() local real angle = (180.0 / bj_PI) * Atan2(GetLocationY(spellLoc) - GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc) - GetUnitX(GetTriggerUnit())) local MyStruct data = MyStruct.create(GetTriggerUnit(), GetLocationX(spellLoc), GetLocationY(spellLoc), angle) local integer i // a counter for a loop //we attach the struct to the timer and we start it, this will make the plane //fade in call SetTimerData(data.fader, integer(data)) call TimerStart(data.fader, FADE_IN, true, function FadeIn) //we attach the struct to the timer and we start it, this will make the plane //move call SetTimerData(data.mover, integer(data)) call TimerStart(data.mover, 0.03, true, function MovePlane) //we attach the struct to the timer and we start it, this will make the plane //lose height, this is for eye candy and to indicate that the bombardment will //soon start call SetTimerData(data.heightControler, integer(data)) call TimerStart(data.heightControler, 0.03, true, function LoseHeight) //now we wait a few miliseconds //call TriggerSleepAction(0.6) loop exitwhen(i == BombsNumber(data.level)) call DropBomb(data) set i = i + 1 endloop //cleaning up the mess call RemoveLocation(spellLoc) set spellLoc = null endfunction //====================================================================================== private function Init takes nothing returns nothing local trigger FireBomberTrigger = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(FireBomberTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(FireBomberTrigger, Condition( function Conditions ) ) call TriggerAddAction(FireBomberTrigger, function Actions) set FireBomberTrigger = null endfunction endscope I will surely give +rep and credits to all those who help. Some one please ? |
| 08-12-2008, 06:32 PM | #2 |
Your FADE_IN interval is too long, the fading will look choppy (like the penguin growth in your stupid penguin spell, that one was too choppy too). You should define fading in a different way; increase per interval isn't the most user friendly. Instead, users should just specify the duration for the plane to fade in, duration from when it finishes fading to when it drops the first bomb, duration between bombs, number of bombs, duration between last bomb release and when it starts fading out, fadeout duration. With that information, plus plane speed, the spell should then be able to calculate where to start moving the plane and all other details. Once you get this sorted out, we can focus on the bombs. |
| 08-12-2008, 06:49 PM | #3 | |||
Quote:
Quote:
However, I don't understand how I make things work if the user selects the duration of the fade time. Can you give some clue, tip ? Although I agree I am kinda lost =S Quote:
About the bombs, well, I must say I have to agree with you. So what can you say ? How do I start ? |
| 08-12-2008, 07:03 PM | #4 |
Since you'll have to move the plane on a fast periodic timer anyway, you might as well change it's transparency in the same function, that way you'll get a smooth fade and it won't cost you anything. The equation is simple, Alpha would be R2I(255 * (elapsedTime/fadeDuration)), when the spell starts elapsed time would be 0 and the plane would be invisible, once elapsed time reaches fadeDuration you will get 255*1 = 255 which is a fully visible plane, at that point you stop altering it's vertex colouring. As the plane continues to be moved by the spell, at one point elapsedTime reaches fadeDuration+firstBombDelay, that's when you drop the first bomb, then you continue to drop bombs every time elapsed time becomes greater than fadeDuration+firstBombDelay+bombInterval*numberOfBombsDroppedSoFar, until you drop the last bomb. |
| 08-12-2008, 07:15 PM | #5 | ||
Quote:
Quote:
does that mean I will need a timer to count how many seconds passed ? I think I am getting the idea, but I need more detail on "elapsedTime". |
| 08-12-2008, 07:29 PM | #6 | ||
Quote:
Quote:
|
| 08-12-2008, 07:32 PM | #7 |
yes, elapsedTime holds the time since the spell started. since you're using a periodic timer anyway, you only have to increase it by the timer-period each time the timer-function runs. I'm not sure, but since you only need the periodic timer for the fade-in and the fade-out, you could also restart the timer with an interval equal to bombInterval, then you could just drop a bomb each time the timer was called... E: damn, Anitarf beat me on the elapsedTime thingy.. |
| 08-13-2008, 09:26 AM | #8 | ||
Quote:
Quote:
Anyway, I already have a new version, hope I did things right =) Now I need a formula to take fade away and a formula for the flying height Mmmm JASS:scope FireBomber initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A000' //rawcode of the ability private constant integer BOMBER_ID = 'h002' //rawcode of the bomber private constant integer PLANE_RED = 255 //The Red RGB color of the Plane private constant integer PLANE_GREEN = 255 //The Green RGB color of the Plane private constant integer PLANE_BLUE = 255 //The Blue RGB color of the Plane private constant integer FADE_MAX = 255 //The maximum Alpha the plane will have. This is ralated to the transparency and therefore to the fading. private constant real FADE_IN = 0.2 //the intervail of time between each time the plane either fades in or out private constant real FADEIN_TIME = 2.5 //the amount of time the plane will take to fade in private constant integer BOMBARD_HEIGHT = 400 private constant integer HEIGHT_LOSS = 50 private constant real MOVE_TIME = 0.03 endglobals private constant function PlaneStartDistance takes integer level returns real //the ditance that the plane will be from the caster when it is created //you can make it depend on the level like in the next example return 1400. + (level * 0) endfunction private constant function BombsNumber takes integer level returns integer return 5 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== private struct MyStruct unit caster integer level unit bomber real height timer bombFall //will make bombs fall in realistic way timer fader //will control the fade in and fade out of the plane timer mover //this timer will move the plane timer heightControler //Controls the height of the plane real elapsedTime timer waits static method create takes unit caster, real spellX, real spellY, real angle returns MyStruct local MyStruct data = MyStruct.allocate() //set variables about the caster set data.caster = caster set data.level = GetUnitAbilityLevel(data.caster, AID) //variables about the bomber set data.bomber = CreateUnit(GetOwningPlayer(data.caster), BOMBER_ID, spellX - PlaneStartDistance(data.level) * Cos(angle * (bj_PI / 180.0)), spellY - PlaneStartDistance(data.level) * Sin(angle * (bj_PI / 180.0)), angle) set data.height = GetUnitFlyHeight(data.bomber) set data.bombFall = NewTimer() set data.fader = NewTimer() set data.mover = NewTimer() set data.heightControler = NewTimer() set data.elapsedTime = 0 set data.waits = NewTimer() call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADEIN_TIME))) return data endmethod method onDestroy takes nothing returns nothing call ReleaseTimer(.bombFall) call ReleaseTimer(.fader) call ReleaseTimer(.mover) call ReleaseTimer(.heightControler) endmethod endstruct //====================================================================================== private function DropBomb takes integer structure returns nothing local MyStruct data = structure //here we create bombs and make them fall //when a bombs falls, it dies //when it dies, we create the effect endfunction //====================================================================================== private function MovePlane takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) call SetUnitPosition(data.bomber, GetUnitX(data.bomber) + 6, GetUnitY(data.bomber) + 6) set data.elapsedTime = data.elapsedTime + MOVE_TIME endfunction //====================================================================================== private function FadeIn takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) //if we reached our maximum fade, we pause the timer, so we start later when we //want to make the plane fade out if (data.elapsedTime >= FADEIN_TIME) then call PauseTimer(data.fader) //if not, we increase the fade of the plane making it less transparent else call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADEIN_TIME))) endif endfunction //====================================================================================== private function FadeOut takes nothing returns nothing //here we make the plane disappear again //we also hide and kill the plane after =D endfunction //====================================================================================== private function LoseHeight takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) //if the plane alreadu reached the bombarding altitude, then we drop the bombs if (data.height <= BOMBARD_HEIGHT) then call PauseTimer(data.heightControler) //else we keep diminuishing the height of the plane else set data.height = data.height - HEIGHT_LOSS call SetUnitFlyHeight(data.bomber, data.height, 80) endif endfunction //====================================================================================== private function GainHeight takes nothing returns nothing //here we make the plane go up again endfunction //====================================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID endfunction //====================================================================================== private function Actions takes nothing returns nothing local location spellLoc = GetSpellTargetLoc() local real angle = (180.0 / bj_PI) * Atan2(GetLocationY(spellLoc) - GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc) - GetUnitX(GetTriggerUnit())) local MyStruct data = MyStruct.create(GetTriggerUnit(), GetLocationX(spellLoc), GetLocationY(spellLoc), angle) local integer i // a counter for a loop //we attach the struct to the timer and we start it, this will make the plane //move call SetTimerData(data.mover, integer(data)) call TimerStart(data.mover, MOVE_TIME, true, function MovePlane) //now we wait a few miliseconds //call data.waits(value) //we attach the struct to the timer and we start it, this will make the plane //fade in call SetTimerData(data.fader, integer(data)) call TimerStart(data.fader, FADE_IN, true, function FadeIn) //now we wait a few miliseconds //call data.waits(value) //we attach the struct to the timer and we start it, this will make the plane //lose height, this is for eye candy and to indicate that the bombardment will //soon start call SetTimerData(data.heightControler, integer(data)) call TimerStart(data.heightControler, 0.03, true, function LoseHeight) //now we wait a few miliseconds //call data.waits(value) loop exitwhen(i == BombsNumber(data.level)) call DropBomb(data) set i = i + 1 endloop //now we wait a few miliseconds //call data.waits(value) call GainHeight() //now we wait a few miliseconds //call data.waits(value) call FadeOut() //cleaning up the mess call RemoveLocation(spellLoc) set spellLoc = null endfunction //====================================================================================== private function Init takes nothing returns nothing local trigger FireBomberTrigger = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(FireBomberTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(FireBomberTrigger, Condition( function Conditions ) ) call TriggerAddAction(FireBomberTrigger, function Actions) set FireBomberTrigger = null endfunction endscope I feel I have a long road ahead ... what else do I have to change ? Btw, Also added a new Timer - data.waits which will count the time we have to wait between each thing happens. EDIT EDIT EDIT Ok guys. It seems I am not using the best approach. I don't mind starting the spell from zero again, as long as some one can help me finish it. Can some one help me then ? |
| 08-13-2008, 11:21 AM | #9 |
I told you on irc already, run the whole spell on a single timer with a single periodic function, I explained how it'd work a few posts up, I don't know how much more I can do short of writing the spell for you myself. |
| 08-13-2008, 06:45 PM | #10 | |
Quote:
I just don't understand how I am going to do the fade, lose height, drop bombs, move plane, and wait small intervals, with only 1 times, when thing run at the same time. I understand I can try to change things into one function, I'll try it with fade but I am not sure about loose height and I am completely lost with wait intervals. I will try come up with something new soon. EDIT EDIT EIDIT Ok, I tried to follow Anitarf's suggestion and this is what I got. I feel I am letting something escape but I can't find it what it is right now ... Anyway, I am kinda confused with this stuff. I don't know the best plave to increase elpasedTime and I need a formula to make the plane lose height. I already tried, but I better get a second opinion because mine is kinda crappy ... Anyway here is new version of code: JASS:scope FireBomber initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A000' //rawcode of the ability private constant integer BOMBER_ID = 'h002' //rawcode of the bomber private constant integer PLANE_RED = 255 //The Red RGB color of the Plane private constant integer PLANE_GREEN = 255 //The Green RGB color of the Plane private constant integer PLANE_BLUE = 255 //The Blue RGB color of the Plane private constant integer FADE_MAX = 255 //The maximum Alpha the plane will have. This is ralated to the transparency and therefore to the fading. private constant real FADEIN_TIME = 2.5 //the amount of time the plane will take to fade in private constant integer BOMBARD_HEIGHT = 400 private constant integer HEIGHT_LOSS = 50 private constant real MOVE_TIME = 0.03 endglobals private constant function PlaneStartDistance takes integer level returns real //the ditance that the plane will be from the caster when it is created //you can make it depend on the level like in the next example return 1400. + (level * 0) endfunction private constant function BombsNumber takes integer level returns integer return 5 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== private struct MyStruct unit caster integer level unit bomber real height timer bombFall //will make bombs fall in realistic way timer mover //this timer will move the plane real elapsedTime timer waits static method create takes unit caster, real spellX, real spellY, real angle returns MyStruct local MyStruct data = MyStruct.allocate() //set variables about the caster set data.caster = caster set data.level = GetUnitAbilityLevel(data.caster, AID) //variables about the bomber set data.bomber = CreateUnit(GetOwningPlayer(data.caster), BOMBER_ID, spellX - PlaneStartDistance(data.level) * Cos(angle * (bj_PI / 180.0)), spellY - PlaneStartDistance(data.level) * Sin(angle * (bj_PI / 180.0)), angle) set data.height = GetUnitFlyHeight(data.bomber) set data.bombFall = NewTimer() set data.mover = NewTimer() set data.elapsedTime = 0 set data.waits = NewTimer() call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADEIN_TIME))) return data endmethod method onDestroy takes nothing returns nothing call ReleaseTimer(.bombFall) call ReleaseTimer(.mover) endmethod endstruct //====================================================================================== private function DropBomb takes integer structure returns nothing local MyStruct data = structure //here we create bombs and make them fall //when a bombs falls, it dies //when it dies, we create the effect endfunction //====================================================================================== private function MovePlane takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) call SetUnitPosition(data.bomber, GetUnitX(data.bomber) + 6, GetUnitY(data.bomber) + 6) //this make the plane fade in call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADEIN_TIME))) //if the plane already reached the bombarding altitude, then we drop the bombs if (data.height <= BOMBARD_HEIGHT) then //Ye I know this is stupid, but if the plane already reached his lower height //than we want it to keep it that way right ? //Mainly this will help people understand that we actually WANT to do nothing here xD call DoNothing() //else we keep diminuishing the height of the plane else set data.height = data.height - HEIGHT_LOSS call SetUnitFlyHeight(data.bomber, data.height, 80) endif set data.elapsedTime = data.elapsedTime + MOVE_TIME endfunction //====================================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID endfunction //====================================================================================== private function Actions takes nothing returns nothing local location spellLoc = GetSpellTargetLoc() local real angle = (180.0 / bj_PI) * Atan2(GetLocationY(spellLoc) - GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc) - GetUnitX(GetTriggerUnit())) local MyStruct data = MyStruct.create(GetTriggerUnit(), GetLocationX(spellLoc), GetLocationY(spellLoc), angle) local integer i // a counter for a loop //we attach the struct to the timer and we start it, this will make the plane //move call SetTimerData(data.mover, integer(data)) call TimerStart(data.mover, MOVE_TIME, true, function MovePlane) //now we wait a few miliseconds //call data.waits(value) loop exitwhen(i == BombsNumber(data.level)) call DropBomb(data) set i = i + 1 endloop //cleaning up the mess call RemoveLocation(spellLoc) set spellLoc = null endfunction //====================================================================================== private function Init takes nothing returns nothing local trigger FireBomberTrigger = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(FireBomberTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(FireBomberTrigger, Condition( function Conditions ) ) call TriggerAddAction(FireBomberTrigger, function Actions) set FireBomberTrigger = null endfunction endscope |
| 08-14-2008, 12:45 PM | #11 |
Pseudocode: Code:
function mainLoop takes nothing returns nothing
local MyStruct s = GetTimerData(GetExpiredTimer())
set s.time=s.time+PERIOD
if s.time <= FADETIME then
do the fading in
elseif s.time >= TOTAL_FLIGHT_DURATION-FADETIME then
do the fading out
endif
if s.time <= DIVETIME then
decrease the flying height
elseif s.time >= TOTAL_FLIGHT_DURATION-DIVETIME then
increase the flying height
endif
if s.time > DELAY_BEFORE_BOMBING_START+s.numberOfBombsDropped*BOMB_INTERVAL and s.numberOfBombsDropped<BombsNumber(s.level) then
drop a bomb
set s.numberOfBombsDropped=s.numberOfBombsDropped+1
endif
call SetUnitX(s.plane, GetUnitX(s.plane)+s.dx)
//repeat for y, also you might want to check first that the point isn't outside map bounds
if s.time > TOTAL_FLIGHT_DURATION then
call s.destroy() //the onDestroy method should do all the cleanup, not just the timer but also the unit
endif
endfunctionThe bombs themselves I'd make into an independant struct, so you don't need a .bombFall timer in your main struct. |
| 08-14-2008, 01:31 PM | #12 |
Ok, the for your post Ani. It did bring some light to my head. However, I won't use SetUnitX() and SetUnitY(). I read in a tutorial they have the problem of placing the unit outside map bounds, so I use SetUnitPosistion() which does the exact same thing, but doesn't place the unit outside (cool =D ). One question though, about the plane loosing height, isn't there a formula I can use ? I was thinking of setting rate to 100, and then make a 3 simple rule, but the result will be imprecise and choppy as well... Besides I will be forcing people to use a rate of 100. What formula did you use for the other thing, the fade ? Ex. SetUnitFlyHeight(unit, newHeight, rate) Anyway, I will remake the spell, now I understand your idea. Thx really =) |
| 08-14-2008, 02:27 PM | #13 |
I didn't use any formula, I left that for you to figure out. You should know how to calculate the rate, really. You should have the start height, bomb height and dive duration all set in the calibration section, it doesn't take a rocket scientist to calculate the rate from that data. Also, you only need to call this function twice, since it changes the fly height gradualy on it's own, you don't have to change it every 0.04 seconds like you have to change the unit's position. So,you call it once at the start of the spell and once when time reaches TOTAL_FLIGHT_DURATION - DIVETIME. Total flight duration probably shouldn't be a calibration constant, you should instead calculate it from other calibration constants, it would be something like 2*DIVETIME + 2*DELAY_BEFORE_BOMBING_START + BOMB_INTERVAL*(BombsNumber(level)-1). |
| 08-14-2008, 04:47 PM | #14 | |
This post was edited Quote:
Anyway I followed all your instructions (or at least those I could) and I also decided to change the spell's core drastically. Anyway, new version is here, please tell me if I am doing something wrong. ( I know I am lol...) Here it goes =) JASS:scope FireBomber initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A000' //rawcode of the ability private constant integer BOMBER_ID = 'h002' //rawcode of the bomber private constant integer PLANE_RED = 255 //The Red RGB color of the Plane private constant integer PLANE_GREEN = 255 //The Green RGB color of the Plane private constant integer PLANE_BLUE = 255 //The Blue RGB color of the Plane private constant integer FADE_MAX = 255 //The maximum Alpha the plane will have. This is ralated to the transparency and therefore to the fading. private constant real FADE_TIME = 2.5 //the amount of time the plane will take to fade in private constant real DIVE_TIME = 1.5 private constant integer BOMBARD_HEIGHT = 400 private constant integer HEIGHT_VARIATION = 50 private constant real MOVE_TIME = 0.03 private constant real BOMBS_INTERVAL = 0.3 private constant real BOMBS_DELAY = 1. endglobals private constant function PlaneStartDistance takes integer level returns real //the ditance that the plane will be from the caster when it is created //you can make it depend on the level like in the next example return 1400. + (level * 0) endfunction private constant function BombsNumber takes integer level returns integer return 5 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== private struct MyStruct unit caster integer level unit bomber real height timer mover //this timer will move the plane real elapsedTime integer bombsDropped real totalFlightDuration static method create takes unit caster, real spellX, real spellY, real angle returns MyStruct local MyStruct data = MyStruct.allocate() //set variables about the caster set data.caster = caster set data.level = GetUnitAbilityLevel(data.caster, AID) //variables about the bomber set data.bomber = CreateUnit(GetOwningPlayer(data.caster), BOMBER_ID, spellX - PlaneStartDistance(data.level) * Cos(angle * (bj_PI / 180.0)), spellY - PlaneStartDistance(data.level) * Sin(angle * (bj_PI / 180.0)), angle) set data.height = GetUnitFlyHeight(data.bomber) set data.mover = NewTimer() set data.bombsDropped = 0 set data.elapsedTime = 0 set data.totalFlightDuration = 2 * BOMBS_DELAY + 2 * DIVE_TIME + 2 * FADE_TIME + (BombsNumber(data.level) - 1) * BOMBS_INTERVAL call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADE_TIME))) return data endmethod method onDestroy takes nothing returns nothing call ReleaseTimer(.mover) call ShowUnit(.bomber, false) call KillUnit(.bomber) endmethod endstruct //====================================================================================== private function DropBomb takes nothing returns nothing //here we create bombs and make them fall //when a bombs falls, it dies //when it dies, we create the effect endfunction //====================================================================================== private function MovePlane takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) set data.elapsedTime = data.elapsedTime + MOVE_TIME if (data.elapsedTime <= FADE_TIME) then call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADE_TIME))) elseif (data.elapsedTime >= data.totalFlightDuration - FADE_TIME) then //PS this formula is not right, it actually just hides the plane instantly, I need to fix this call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 / (data.elapsedTime * FADE_TIME))) endif if (data.elapsedTime <= DIVE_TIME) then //another thing I should fix, is this set data.height = data.height - HEIGHT_VARIATION call SetUnitFlyHeight(data.bomber, data.height, 80) elseif (data.elapsedTime >= data.totalFlightDuration - DIVE_TIME) then //and for some stupid reason my plane never stops going down ! set data.height = data.height + HEIGHT_VARIATION call SetUnitFlyHeight(data.bomber, data.height, 100) endif if (data.elapsedTime > BOMBS_DELAY + data.bombsDropped * BOMBS_INTERVAL) and (data.bombsDropped < BombsNumber(data.level)) then call DropBomb() set data.bombsDropped = data.bombsDropped + 1 endif if (data.elapsedTime > data.totalFlightDuration) then call data.destroy() endif //Advice, what do you guys think I should do here ? //Move the plane with SetUnitPosition() or //order the plane to move with IssuePointOrder() ??? call SetUnitPosition(data.bomber, GetUnitX(data.bomber) + 6, GetUnitY(data.bomber) + 6) endfunction //====================================================================================== private function Conditions takes nothing returns boolean local location spellLoc local real angle local MyStruct data if (GetSpellAbilityId() == AID) then set spellLoc = GetSpellTargetLoc() set angle = (180.0 / bj_PI) * Atan2(GetLocationY(spellLoc) - GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc) - GetUnitX(GetTriggerUnit())) set data = MyStruct.create(GetTriggerUnit(), GetLocationX(spellLoc), GetLocationY(spellLoc), angle) call SetTimerData(data.mover, integer(data)) call TimerStart(data.mover, MOVE_TIME, true, function MovePlane) call RemoveLocation(spellLoc) endif set spellLoc = null return false endfunction //====================================================================================== private function Init takes nothing returns nothing local trigger FireBomberTrigger = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(FireBomberTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(FireBomberTrigger, Condition( function Conditions ) ) set FireBomberTrigger = null endfunction endscope Also, I am not an expert at dropping bombs, but will it be that complicated that it will require two separate structs ? =S Abut the formulas I will try to figure it out mmmm again ... EDIT EDIT EDIT Ahhh, after a long chat in irc and a few hours on coding, here it is (I think) a better version of the bomber spell. Please some one correct me if I am wrong and I would also appreciate your tip on how to move the plane. JASS:scope FireBomber initializer Init //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer AID = 'A000' //rawcode of the ability private constant integer BOMBER_ID = 'h002' //rawcode of the bomber private constant integer PLANE_RED = 255 //The Red RGB color of the Plane private constant integer PLANE_GREEN = 255 //The Green RGB color of the Plane private constant integer PLANE_BLUE = 255 //The Blue RGB color of the Plane private constant integer FADE_MAX = 255 //The maximum Alpha the plane will have. This is ralated to the transparency and therefore to the fading. private constant real FADE_TIME = 3 //the amount of time the plane will take to fade in private constant real DIVE_TIME = 2.5 private constant integer BOMBARD_HEIGHT = 200 private constant real MOVE_TIME = 0.03 private constant real BOMBS_INTERVAL = 0.3 private constant real BOMBS_DELAY = 1. endglobals private constant function PlaneStartDistance takes integer level returns real //the ditance that the plane will be from the caster when it is created //you can make it depend on the level like in the next example return 1400. + (level * 0) endfunction private constant function BombsNumber takes integer level returns integer return 5 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== private struct MyStruct unit caster integer level unit bomber real height timer mover //this timer will move the plane real elapsedTime integer bombsDropped real totalFlightDuration boolean isOnBombingHeight static method create takes unit caster, real spellX, real spellY, real angle returns MyStruct local MyStruct data = MyStruct.allocate() //set variables about the caster set data.caster = caster set data.level = GetUnitAbilityLevel(data.caster, AID) //variables about the bomber set data.bomber = CreateUnit(GetOwningPlayer(data.caster), BOMBER_ID, spellX - PlaneStartDistance(data.level) * Cos(angle * (bj_PI / 180.0)), spellY - PlaneStartDistance(data.level) * Sin(angle * (bj_PI / 180.0)), angle) set data.height = GetUnitFlyHeight(data.bomber) set data.mover = NewTimer() set data.bombsDropped = 0 set data.isOnBombingHeight = false set data.elapsedTime = 0 set data.totalFlightDuration = 2 * BOMBS_DELAY + 2 * DIVE_TIME + 2 * FADE_TIME + (BombsNumber(data.level) - 1) * BOMBS_INTERVAL call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADE_TIME))) return data endmethod method onDestroy takes nothing returns nothing call ReleaseTimer(.mover) call ShowUnit(.bomber, false) call KillUnit(.bomber) endmethod endstruct //====================================================================================== private function DropBomb takes nothing returns nothing //here we create bombs and make them fall //when a bombs falls, it dies //when it dies, we create the effect endfunction //====================================================================================== private function MovePlane takes nothing returns nothing local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer())) set data.elapsedTime = data.elapsedTime + MOVE_TIME if (data.elapsedTime <= FADE_TIME) then call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * (data.elapsedTime / FADE_TIME))) elseif (data.elapsedTime >= data.totalFlightDuration - FADE_TIME) then call SetUnitVertexColor(data.bomber, PLANE_RED, PLANE_GREEN, PLANE_BLUE, R2I(255 * ((data.totalFlightDuration - data.elapsedTime) / FADE_TIME))) endif if (data.elapsedTime >= FADE_TIME) and not(data.isOnBombingHeight) then set data.isOnBombingHeight = true call SetUnitFlyHeight(data.bomber, BOMBARD_HEIGHT, (data.height - BOMBARD_HEIGHT) / DIVE_TIME) elseif (data.elapsedTime >= data.totalFlightDuration - DIVE_TIME - FADE_TIME) and (data.isOnBombingHeight) then call SetUnitFlyHeight(data.bomber, data.height, (data.height - BOMBARD_HEIGHT) / DIVE_TIME) endif if (data.elapsedTime > BOMBS_DELAY + data.bombsDropped * BOMBS_INTERVAL) and (data.bombsDropped < BombsNumber(data.level)) then call DropBomb() set data.bombsDropped = data.bombsDropped + 1 endif if (data.elapsedTime > data.totalFlightDuration) then call data.destroy() endif //Advice, what do you guys think I should do here ? //Move the plane with SetUnitPosition() or //order the plane to move with IssuePointOrder() ??? call SetUnitPosition(data.bomber, GetUnitX(data.bomber) + 6, GetUnitY(data.bomber) + 6) endfunction //====================================================================================== private function Conditions takes nothing returns boolean local location spellLoc local real angle local MyStruct data if (GetSpellAbilityId() == AID) then set spellLoc = GetSpellTargetLoc() set angle = (180.0 / bj_PI) * Atan2(GetLocationY(spellLoc) - GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc) - GetUnitX(GetTriggerUnit())) set data = MyStruct.create(GetTriggerUnit(), GetLocationX(spellLoc), GetLocationY(spellLoc), angle) call SetTimerData(data.mover, integer(data)) call TimerStart(data.mover, MOVE_TIME, true, function MovePlane) call RemoveLocation(spellLoc) endif set spellLoc = null return false endfunction //====================================================================================== private function Init takes nothing returns nothing local trigger FireBomberTrigger = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(FireBomberTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition(FireBomberTrigger, Condition( function Conditions ) ) set FireBomberTrigger = null endfunction endscope Hope you all (and Anitarf too xD ) like this new version. It is quite amazing how things start to make sense (or maybe not). |
| 08-17-2008, 11:36 AM | #15 |
Sorry for reviving, but if some one could help me or give me more tips to end this code I'd really be happy, this is something I really need to do... |
