1------------------------------------
2-- TUMBLER
3-- v.0.8.0
4------------------------------------
5
6--[[
7SCRIPT PARAMETER
8The script is configured with the script parameter.
9
10Additional configuration in the game scheme is permitted.
11
12The script parameter is a comma-separated list of key=value pairs.
13
14The values are always whole numbers, the keys are listed below.
15
16Key			Default	Description
17----------------------------------------------------------------------
18spawnbarrels		2	Number of barrels that spawn per turn
19spawnmines		4	Number of mines that spawn per turn
20ammoflamer		50	Initial fuel/ammo of Flamer
21ammobarrel		2	Initial ammo of Barrel Launcher
22ammomine		1	Initial ammo of Mine Deployer
23minetimerplaced		1000	Mine timer of mines dropped from Mine Deployer (!) in milliseconds
24bonustime		25	Bonus time in utility crates, in seconds
25bonusflames		800	Flamer fuel bonus in ammo crates
26chanceammo		30	Chance (in %) that an ammo crate will drop before a turn
27chancetime		50	Chance (in %) that an utility crate (extra time) will drop before a turn
28
29
30EXAMPLES:
31
32ammoflamer=800, ammomine=5
33--> Starts the game with 800 Flamer fuel and 5 Mine Deployer mines.
34
35chancetime=0
36--> No clock crates.
37
38
39GAME SCHEME CONFIGURATION
40The script recognizes most game modifiers and settings, but changing the following game modifiers
41will have no effect:
42- Artillery
43- Tag Team
44- Shared ammo
45- Per-hog ammo
46- Place hogs
47- Invulnerable
48- Reset weapons
49]]
50
51
52HedgewarsScriptLoad("/Scripts/Locale.lua")
53HedgewarsScriptLoad("/Scripts/Tracker.lua")
54HedgewarsScriptLoad("/Scripts/Params.lua")
55
56local fMod = 1000000 -- use this for dev and .16+ games
57
58local leftOn = false
59local rightOn = false
60local upOn = false
61local downOn = false
62local preciseOn = false
63
64local wep = {}
65local wepAmmo = {}
66local wepCol = {}
67local wepIndex = 0
68local wepCount = 0
69local fGears = 0
70
71local mineSpawn
72local barrelSpawn
73
74local roundKills = 0
75
76local moveTimer = 0
77local fireTimer = 0
78local TimeLeftCounter = 0
79local TimeLeft = 0
80local stopMovement = false
81local tumbleStarted = false
82
83local vTag = {}
84
85local barrelSpawn = 2
86local mineSpawn = 4
87local initAmmoFlamer = 50
88local initAmmoBarrel = 2
89local initAmmoMine = 1
90local placedMineTime = 1000
91local bonusTime = 25
92local bonusFlames = 800
93local chanceAmmo = 30
94local chanceTime = 50
95
96
97------------------------
98-- version 0.4
99------------------------
100
101-- removed some old code/comments
102-- removed both shell and mortar as the primary and secondary weapons
103-- the primary weapon is now an explosive(barrel)
104
105-- added support for picking up barrels scattered about the map (backspace)
106-- added support for dragging around mines (enter toggles on/off)
107-- added support for primary fire being onAttackUp
108-- added a trail to indicate when the player has 5s or less left to tumble
109-- updated showmission to reflect changed controls and options
110
111------------------------
112-- version 0.5
113------------------------
114
115-- changed some of the user feedback
116-- i can't remember??
117-- substituted onAttackUp for onPrecise()
118-- brought in line with new velocity changes
119
120------------------------
121-- version 0.6
122------------------------
123
124-- reduced starting "ammo"
125-- randomly spawn new barrels/mines on new turn
126-- updated user feedback
127-- better locs and coloured addcaptions
128-- added tag for turntime
129-- removed tractor beam
130-- added two new weapons and changed ammo handling
131-- health crates now give tumbler time, and wep/utility give flamer ammo
132-- explosives AND mines can be picked up to increase their relative ammo
133-- replaced "no weapon" selected message that hw serves
134-- modified crate frequencies a bit
135-- added some simple kill-based achievements, i think
136
137------------------------
138-- version 0.7
139------------------------
140
141-- a few code optimisations/performance tweaks
142-- removed some deprecated code
143-- fix a potential spawn bug
144
145-- improved HUD (now shows ammo counts)
146-- improved user feedback (less generic messages)
147-- colour-coded addcaptions to match hud :)
148
149-- base tumbling time now equals scheme turntime
150-- tumbling time extension is now based on the amount of health contained in crate
151-- new mines per turn based on minesnum
152-- new barrels per turn based on explosives
153
154-- added 2 more achievements: barrel eater and mine eater (like kills, don't do anything atm)
155-- slightly increased grab distance for explosives/mines
156-- slightly increased flamer velocity
157-- slightly decreased flamer volume
158-- added a flame vaporiser (based on number of flame gears?)
159-- give tumblers an extra 47 health on the start of their tumble to counter the grenade (exp)
160-- refocus camera on tumbler on newturn (not on crates, barrels etc)
161-- increase delay: yes, yes, eat your hearts out
162
163-- commit log
164-- Better HUD
165-- Allow more user customization
166-- Bugfix for new gear spawns
167-- Performance tweaks
168-- Variety of small gameplay changes
169
170------------------------
171-- version 0.7.1
172------------------------
173
174-- redraw HUD on screen resolution change
175
176------------------------
177-- version 0.8.0
178------------------------
179-- Allow detailed configuration with script parameter (see above)
180-- Alternative weapon selection with slot keys
181--- Slot 1: Barrel Launcher
182--- Slot 2: Mine Deployer
183--- Slot 3: Flamer
184-- Add mine/barrel launch sounds
185-- Improved ammo display
186-- Denied sound + message when trying to fire empty ammo weapon
187-- Slightly better mission description
188--- The old hacks by (ab)using MinesNum, Explosives and HealthCaseAmount have been removed
189-- Permanently disable some gameflags which currently won't work together with this script (see above)
190-- Show flamer ammo as fuel everywhere (no more percentage confusion)
191
192---------------------------
193-- some other ideas/things
194---------------------------
195--[[
196-- allow invulnerability mode (currently broken, thus disabled)
197-- better barrel/minespawn effects
198-- separate grab distance for mines/barrels
199-- bug: message color for remaining ammo does not change if two times the same message
200   (but in different desired color) is shown in quick succession (i.e. "Out of ammo!" for all weapons)
201-- [probably not] make barrels always explode?
202-- [probably not] persistent ammo?
203-- [probably not] dont hurt tumblers and restore their health at turn end?
204]]
205
206
207----------------------------------------------------------------
208----------------------------------------------------------------
209
210local flames = {}
211local fGearValues = {}
212
213function runOnflames(func)
214    for k, gear in ipairs(flames) do
215        func(gear)
216    end
217end
218
219function trackFGear(gear)
220    table.insert(flames, gear)
221end
222
223function trackFGearDeletion(gear)
224    fGearValues[gear] = nil
225    for k, g in ipairs(flames) do
226        if g == gear then
227            table.remove(flames, k)
228            break
229        end
230    end
231end
232
233function getFGearValue(gear, key)
234    if fGearValues[gear] ~= nil then
235        return fGearValues[gear][key]
236    end
237    return nil
238end
239
240function setFGearValue(gear, key, value)
241    found = false
242    for id, values in pairs(fGearValues) do
243        if id == gear then
244            values[key] = value
245            found = true
246        end
247    end
248    if not found then
249        fGearValues[gear] = { [key] = value }
250    end
251end
252
253function decreaseFGearValue(gear, key)
254    for id, values in pairs(fGearValues) do
255        if id == gear then
256            values[key] = values[key] - 1
257        end
258    end
259end
260
261function HandleLife(gear)
262
263	decreaseFGearValue(gear, "L")
264	if getFGearValue(gear, "L") == 0 then
265		AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false)
266		DeleteGear(gear)
267	end
268
269end
270
271----------------------------------------------------------------
272----------------------------------------------------------------
273
274function HideTags()
275
276	for i = 0, 3 do
277		SetVisualGearValues(vTag[i],0,0,0,0,0,1,0, 0, 240000, 0xffffff00)
278	end
279
280end
281
282function DrawTag(i)
283
284	local zoomL = 1.3
285
286	local xOffset, yOffset, tValue, tCol
287
288	if i == 0 then
289		if INTERFACE == "touch" then
290			xOffset = 60
291			yOffset = ScreenHeight - 35
292		else
293			xOffset = 40
294			yOffset = 40
295		end
296		tCol = 0xffee00ff
297		tValue = TimeLeft
298	elseif i == 1 then
299		zoomL = 1.1
300		if INTERFACE == "touch" then
301			xOffset = 126
302			yOffset = ScreenHeight - 37
303		else
304			xOffset = 40
305			yOffset = 70
306		end
307		tCol = wepCol[0]
308		tValue = wepAmmo[0]
309	elseif i == 2 then
310		zoomL = 1.1
311		if INTERFACE == "touch" then
312			xOffset = 126 + 35
313			yOffset = ScreenHeight - 37
314		else
315			xOffset = 40 + 35
316			yOffset = 70
317		end
318		tCol = wepCol[1]
319		tValue = wepAmmo[1]
320	elseif i == 3 then
321		zoomL = 1.1
322		if INTERFACE == "touch" then
323			xOffset = 126 + 70
324			yOffset = ScreenHeight - 37
325		else
326			xOffset = 40 + 70
327			yOffset = 70
328		end
329		tCol = wepCol[2]
330		tValue = wepAmmo[2]
331	end
332
333	DeleteVisualGear(vTag[i])
334	vTag[i] = AddVisualGear(0, 0, vgtHealthTag, 0, false)
335	SetVisualGearValues	(
336				vTag[i], 		--id
337				-(ScreenWidth/2) + xOffset,	--xoffset
338				ScreenHeight - yOffset, --yoffset
339				0, 			--dx
340				0, 			--dy
341				zoomL, 			--zoom
342				1, 			--~= 0 means align to screen
343				nil, 			--frameticks
344				tValue, 		--value
345				240000, 		--timer
346				tCol		--GetClanColor( GetHogClan(CurrentHedgehog) )
347				)
348
349end
350
351function GetGearDistance(gear)
352
353	g1X, g1Y = GetGearPosition(gear)
354	g2X, g2Y = GetGearPosition(CurrentHedgehog)
355
356	q = g1X - g2X
357	w = g1Y - g2Y
358	return( (q*q) + (w*w) )
359
360end
361
362-- add to your ammo ***WHEN YOU PUSH A KEY*** near them
363-- yes that was my justification for a non generic method
364function CheckProximityToExplosives(gear)
365
366	if (GetGearDistance(gear) < 1400) then
367
368		if (GetGearType(gear) == gtExplosives) then
369
370			wepAmmo[0] = wepAmmo[0] + 1
371			PlaySound(sndShotgunReload)
372			DeleteGear(gear)
373			AddCaption(loc("+1 barrel!"), wepCol[0], capgrpAmmoinfo )
374			DrawTag(1)
375
376		elseif (GetGearType(gear) == gtMine) then
377			wepAmmo[1] = wepAmmo[1] + 1
378			PlaySound(sndShotgunReload)
379			DeleteGear(gear)
380			AddCaption(loc("+1 mine!"), wepCol[1], capgrpAmmoinfo )
381			DrawTag(2)
382
383		end
384
385	end
386
387end
388
389-- check proximity on crates
390function CheckProximity(gear)
391
392	dist = GetGearDistance(gear)
393
394	if (dist < 1600) and (GetGearType(gear) == gtCase) then
395
396		if band(GetGearPos(gear), 0x4) ~= 0 then
397
398			AddCaption(string.format(loc("+%d seconds!"), bonusTime), 0xffee00ff, capgrpMessage2 )
399
400			TimeLeft = TimeLeft + bonusTime
401			DrawTag(0)
402			PlaySound(sndExtraTime)
403		elseif band(GetGearPos(gear), 0x1) ~= 0 then
404			wepAmmo[2] = wepAmmo[2] + bonusFlames
405			PlaySound(sndShotgunReload)
406			AddCaption(string.format(loc("+%d flamer fuel!"), bonusFlames), wepCol[2], capgrpAmmoinfo )
407			DrawTag(3)
408		end
409
410		DeleteGear(gear)
411
412	end
413
414end
415
416function shotsRemainingMessage()
417	local shotsMsg
418	if wepAmmo[wepIndex] <= 0 then
419		shotsMsg = loc("Out of ammo!")
420	else
421		if wepIndex == 2 then
422			shotsMsg = loc("Fuel: %d")
423		else
424			shotsMsg = loc("Ammo: %d")
425		end
426	end
427	AddCaption(string.format(shotsMsg, wepAmmo[wepIndex]), wepCol[wepIndex],capgrpAmmostate)
428end
429
430function ChangeWeapon(newIndex)
431	if newIndex == nil then
432		wepIndex = wepIndex + 1
433		if wepIndex == wepCount then
434			wepIndex = 0
435		end
436	else
437		wepIndex = newIndex
438	end
439
440	local selText
441	if wepIndex == 0 then
442		selText = loc("Barrel Launcher")
443	elseif wepIndex == 1 then
444		selText = loc("Mine Deployer")
445	else
446		selText = loc("Flamer")
447	end
448	AddCaption(selText, wepCol[wepIndex],capgrpAmmoinfo )
449
450	shotsRemainingMessage()
451end
452
453---------------
454-- Parse parameters
455---------------
456
457function parseNum(key, default, min, max)
458	local num = tonumber(params[key])
459	if type(num) ~= "number" then
460		if default ~= nil then
461			return default
462		else
463			return nil
464		end
465	end
466
467	if min ~= nil then
468		num = math.max(min, num)
469	end
470	if max ~= nil then
471		num = math.min(max, num)
472	end
473	return num
474end
475
476function onParameters()
477	parseParams()
478
479	barrelSpawn = parseNum("spawnbarrels", barrelSpawn, 0)
480	mineSpawn = parseNum("spawnmines", mineSpawn, 0)
481
482	initAmmoFlamer = parseNum("ammoflamer", initAmmoFlamer, 0)
483	initAmmoBarrel = parseNum("ammobarrel", initAmmoBarrel, 0)
484	initAmmoMine = parseNum("ammomine", initAmmoMine, 0)
485
486	placedMineTime = parseNum("minetimeplaced", placedMineTime, 0, 5000)
487
488	bonusTime = parseNum("bonustime", bonusTime, 0)
489	bonusFlames = parseNum("bonusflames", bonusFlames, 0)
490
491	chanceAmmo = parseNum("chanceammo", chanceAmmo, 0, 100)
492	chanceTime = parseNum("chancetime", chanceTime, 0, 100)
493end
494
495---------------
496-- action keys
497---------------
498
499function onPrecise()
500
501	if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
502
503		if wepAmmo[wepIndex] <= 0 then
504			PlaySound(sndDenied)
505			shotsRemainingMessage()
506		else
507
508			wepAmmo[wepIndex] = wepAmmo[wepIndex] - 1
509			shotsRemainingMessage()
510
511			if wep[wepIndex] == loc("Barrel Launcher") then
512				morte = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtExplosives, 0, 0, 0, 1)
513				CopyPV(CurrentHedgehog, morte) -- new addition
514				x,y = GetGearVelocity(morte)
515				x = x*2
516				y = y*2
517				SetGearVelocity(morte, x, y)
518				DrawTag(1)
519				PlaySound(sndThrowRelease)
520
521			elseif wep[wepIndex] == loc("Mine Deployer") then
522				morte = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtMine, 0, 0, 0, 0)
523				SetTimer(morte, placedMineTime)
524				DrawTag(2)
525				PlaySound(sndThrowRelease)
526
527			end
528		end
529
530	end
531
532	preciseOn = true
533
534end
535
536function onPreciseUp()
537	preciseOn = false
538end
539
540onAttack = onPrecise
541onAttackUp = onPreciseUp
542
543function onHJump()
544	-- pick up explosives/mines if nearby them
545	if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
546		runOnGears(CheckProximityToExplosives)
547	end
548end
549
550-------------------
551-- Weapon selection
552-------------------
553
554function onLJump()
555	if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
556		ChangeWeapon()
557	end
558end
559
560function onSlot(slot)
561	if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
562		if slot >= 0 and slot <= 2 then
563			ChangeWeapon(slot)
564		end
565	end
566end
567
568-----------------
569-- movement keys
570-----------------
571
572function onLeft()
573	if (CurrentHedgehog ~= nil) and (stopMovement == false) then
574		leftOn = true
575	end
576end
577
578function onRight()
579	if (CurrentHedgehog ~= nil) and (stopMovement == false) then
580		rightOn = true
581	end
582end
583
584function onUp()
585	if (CurrentHedgehog ~= nil) and (stopMovement == false) then
586		upOn = true
587	end
588end
589
590function onDown()
591	if (CurrentHedgehog ~= nil) and (stopMovement == false) then
592		downOn = true
593	end
594end
595
596function onDownUp()
597	downOn = false
598end
599function onUpUp()
600	upOn = false
601end
602function onLeftUp()
603	leftOn = false
604end
605function onRightUp()
606	rightOn = false
607end
608
609--------------------------
610-- other event handlers
611--------------------------
612
613function onGameInit()
614	CaseFreq = 0
615	HealthCaseProb = 0
616	Delay = 1000
617
618	for i = 0, 3 do
619		vTag[i] = AddVisualGear(0, 0, vgtHealthTag, 0, false)
620	end
621
622	HideTags()
623
624	wep[0] = loc("Barrel Launcher")
625	wep[1] = loc("Mine Deployer")
626	wep[2] = loc("Flamer")
627
628	wepCol[0] = 0x78818eff
629	wepCol[1] = 0xa12a77ff
630	wepCol[2] = 0xf49318ff
631
632	wepCount = 3
633
634	DisableGameFlags(gfArtillery + gfSharedAmmo + gfPerHogAmmo + gfTagTeam + gfPlaceHog + gfInvulnerable)
635	SetSoundMask(sndFlyAway, true)
636
637end
638
639function onGameStart()
640
641	local clockStr
642	local timeStr
643
644	if chanceTime > 0 then
645		clockStr = loc("Utility crates extend your time.") .. "|"
646		timeStr = string.format(loc("Time extension: %ds"), bonusTime) .. "|"
647	else
648		clockStr = ""
649		timeStr = ""
650	end
651
652	ShowMission	(
653			loc("Tumbler"),
654			loc("A Hedgewars mini-game"),
655			loc("Fly around and hurl explosives to your enemies.") .."|"..
656			loc("Eliminate the enemy hogs to win.") .. "|" ..
657			" " .. "|" ..
658
659			string.format(loc("New mines per turn: %d"), mineSpawn) .. "|" ..
660			string.format(loc("New barrels per turn: %d"), barrelSpawn) .. "|" ..
661			timeStr ..
662			" " .. "|" ..
663
664			loc("Movement: [Up], [Down], [Left], [Right]") .. "|" ..
665			loc("Fire: [Precise]") .. "|" ..
666			loc("Change weapon: [Long jump] or [Slot 1]-[Slot 3]") .. "|" ..
667			loc("Grab mines/barrels: [High jump]") .. "|" ..
668
669			" " .. "|" ..
670
671			clockStr ..
672			loc("Ammo is reset at the end of your turn.") .. "|" ..
673
674			"", -amMine, 4000
675			)
676
677end
678
679function onScreenResize()
680
681	-- redraw Tags so that their screen locations are updated
682	if (CurrentHedgehog ~= nil) and (tumbleStarted == true) then
683		for i = 0, 3 do
684			DrawTag(i)
685		end
686	end
687
688end
689
690function onAmmoStoreInit()
691	-- Remove all conventional weapons
692	for a=0, 56 do
693		SetAmmo(a, 0, 0, 0, 0)
694	end
695end
696
697function onNewTurn()
698
699	stopMovement = false
700	tumbleStarted = false
701
702	-- randomly create new barrels mines on the map every turn (can be disabled by setting mine/barrels to 0 in scheme)
703	for i = 0, barrelSpawn-1 do
704		gear = AddGear(100, 100, gtExplosives, 0, 0, 0, 0)
705		SetHealth(gear, 100)
706		if FindPlace(gear, false, 0, LAND_WIDTH, false) ~= nil then
707			AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
708		end
709	end
710	for i = 0, mineSpawn-1 do
711		gear = AddGear(100, 100, gtMine, 0, 0, 0, 0)
712		if FindPlace(gear, false, 0, LAND_WIDTH, false) ~= nil then
713			AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
714		end
715	end
716
717	-- randomly spawn time extension crates / flamer fuel on the map
718	r = GetRandom(100)
719	if r > 100-chanceTime then
720		gear = SpawnFakeUtilityCrate(0, 0, false, false)
721	end
722	r = GetRandom(100)
723	if r > 100-chanceAmmo then
724		gear = SpawnFakeAmmoCrate(0, 0, false, false)
725	end
726
727	HideTags()
728
729	--reset ammo counts
730	wepAmmo[0] = 2
731	wepAmmo[1] = 1
732	wepAmmo[2] = 50 -- 50000 -- 50
733	wepIndex = 2
734	ChangeWeapon()
735
736	roundKills = 0
737
738	FollowGear(CurrentHedgehog)
739
740end
741
742
743function DisableTumbler()
744	stopMovement = true
745	upOn = false
746	down = false
747	leftOn = false
748	rightOn = false
749	HideTags()
750end
751
752function onGameTick()
753
754	-- start the player tumbling with a boom once their turn has actually begun
755	if tumbleStarted == false then
756		if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then
757			tumbleStarted = true
758			TimeLeft = (TurnTime/1000)
759			AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1)
760			SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog) + 47) -- new
761			for i = 0, 3 do
762				DrawTag(i)
763			end
764		end
765	end
766
767	if (CurrentHedgehog ~= nil) and (tumbleStarted == true) then
768
769		runOnGears(CheckProximity) -- crates
770
771		-- Calculate and display turn time
772		TimeLeftCounter = TimeLeftCounter + 1
773		if TimeLeftCounter == 1000 then
774			TimeLeftCounter = 0
775			TimeLeft = TimeLeft - 1
776
777			-- Countdown sounds
778			if TimeLeft == 5 then
779				PlaySound(sndHurry, CurrentHedgehog)
780			elseif TimeLeft <= 4 and TimeLeft >= 1 then
781				PlaySound(_G["sndCountdown"..TimeLeft])
782			end
783
784			if TimeLeft >= 0 then
785				DrawTag(0)
786			end
787
788		end
789
790		if TimeLeft == 0 then
791			DisableTumbler()
792		end
793
794		-- handle movement based on IO
795		moveTimer = moveTimer + 1
796		if moveTimer == 100 then -- 100
797			moveTimer = 0
798
799			runOnflames(HandleLife)
800
801			---------------
802			-- new trail code
803			---------------
804			-- the trail lets you know you have 5s left to pilot, akin to birdy feathers
805			if (TimeLeft <= 5) and (TimeLeft > 0) then
806				local tempE = AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmoke, 0, false)
807				SetVisualGearValues(tempE, nil, nil, nil, nil, nil, nil, nil, nil, nil, GetClanColor(GetHogClan(CurrentHedgehog)) )
808			end
809			--------------
810
811			dx, dy = GetGearVelocity(CurrentHedgehog)
812
813			dxlimit = 0.4*fMod
814			dylimit = 0.4*fMod
815
816			if dx > dxlimit then
817				dx = dxlimit
818			end
819			if dy > dylimit then
820				dy = dylimit
821			end
822			if dx < -dxlimit then
823				dx = -dxlimit
824			end
825			if dy < -dylimit then
826				dy = -dylimit
827			end
828
829
830			if leftOn == true then
831				dx = dx - 0.1*fMod
832			end
833			if rightOn == true then
834				dx = dx + 0.1*fMod
835			end
836
837			if upOn == true then
838				dy = dy - 0.1*fMod
839			end
840			if downOn == true then
841				dy = dy + 0.1*fMod
842			end
843
844			SetGearVelocity(CurrentHedgehog, dx, dy)
845
846		end
847
848		--
849		--flamer
850		--
851		fireTimer = fireTimer + 1
852		if fireTimer == 6 then	-- 5 --10
853			fireTimer = 0
854
855			if (wep[wepIndex] == loc("Flamer") ) and (preciseOn == true) and (wepAmmo[wepIndex] > 0) and (stopMovement == false) and (tumbleStarted == true) then
856
857				wepAmmo[wepIndex] = wepAmmo[wepIndex] - 1
858				shotsRemainingMessage()
859				DrawTag(3)
860
861				dx, dy = GetGearVelocity(CurrentHedgehog)
862				shell = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtFlame, 0, 0, 0, 0)
863
864				xdev = 1 + GetRandom(25)	--15
865				xdev = xdev / 100
866
867				r = GetRandom(2)
868				if r == 1 then
869					xdev = xdev*-1
870				end
871
872				ydev = 1 + GetRandom(25)	--15
873				ydev = ydev / 100
874
875				r = GetRandom(2)
876				if r == 1 then
877					ydev = ydev*-1
878				end
879
880				--*13	--8	*-4
881				SetGearVelocity(shell, (dx*4.5)+(xdev*fMod), (dy*4.5)+(ydev*fMod))	--10
882
883			end
884
885		end
886		--
887
888	end
889
890
891end
892
893function isATrackedGear(gear)
894	if 	(GetGearType(gear) == gtExplosives) or
895		(GetGearType(gear) == gtMine) or
896		(GetGearType(gear) == gtCase)
897	then
898		return(true)
899	else
900		return(false)
901	end
902end
903
904function onGearAdd(gear)
905
906	if GetGearType(gear) == gtFlame then
907
908		trackFGear(gear)
909
910		fGears = fGears +1
911
912		if fGears < 80 then
913			setFGearValue(gear,"L",30)
914		else
915			setFGearValue(gear,"L",5) --3
916		end
917
918	elseif isATrackedGear(gear) then
919		trackGear(gear)
920	end
921
922end
923
924function onGearDelete(gear)
925
926	if GetGearType(gear) == gtFlame then
927		trackFGearDeletion(gear)
928		fGears = fGears -1
929
930	elseif isATrackedGear(gear) then
931		trackDeletion(gear)
932
933	-- achievements? prototype
934	elseif GetGearType(gear) == gtHedgehog then
935
936		if GetHogTeamName(gear) ~= GetHogTeamName(CurrentHedgehog) then
937
938			roundKills = roundKills + 1
939			if roundKills == 2 then
940				AddCaption(loc("Double Kill!"),capcolDefault,capgrpMessage2)
941			elseif roundKills == 3 then
942				AddCaption(loc("Killing spree!"),capcolDefault,capgrpMessage2)
943			elseif roundKills >= 4 then
944				AddCaption(loc("Unstoppable!"),capcolDefault,capgrpMessage2)
945			end
946
947		elseif gear == CurrentHedgehog then
948			DisableTumbler()
949
950		elseif gear ~= CurrentHedgehog then
951			AddCaption(loc("Friendly Fire!"),capcolDefault,capgrpMessage2)
952		end
953
954	end
955
956	if CurrentHedgehog ~= nil then
957		FollowGear(CurrentHedgehog)
958	end
959
960end
961
962
963