View difference between Paste ID: Y2bWsntk and 8brDNZup
SHOW: | | - or go back to the newest paste.
1
/*
2
GTA: SA-MP
3
BOMBER FILTERSCRIPT 0.97
4
created by Mauzen (MSoll (at) web.de) 2008-2010
5
This code represents my own work and must not be released without my credits
6
You are allowed to change the code, you may release your own bombtypes and explosions,
7
but not other codechanges without my permission
8
And of course you can use this filterscript on your server, giving some credits to me
9
then would be nice, I spent lots of time for this...
10
11
12
Add this to the top of your gamemodes OnPlayerDeath to assign bombkills to players:
13
14
	if(GetPVarInt(playerid, "nearExp") > -1 && killerid == INVALID_PLAYER_ID) {
15
		killerid = GetPVarInt(playerid, "nearExp");
16
		if(killerid == playerid) killerid = INVALID_PLAYER_ID;
17
		reason = 51;
18
	}
19
*/
20
21
#include <a_samp>
22
#include <mapandreas>
23
24
#define COLOR_RED 0xAA3333AA
25
#define COLOR_YELLOW 0xFFFF00AA
26
27
#define MAX_BOMBS 32			//Max bombs at once per player
28
#define UPDATE_TIME 100			//Collisioncheck updatetime in ms, increase it if your server is slow
29
30
#define KEY_DROP_BOMB KEY_HANDBRAKE
31
#define KEY_NEXT_BOMBTYPE KEY_ANALOG_DOWN
32
#define KEY_PREV_BOMBTYPE KEY_ANALOG_UP
33
34
#define USE_TEXTDRAWS 1			//See the SA-MP.com forum topic and the screenshots for info about this, or try 0, 1 and 2
35
36
#define FILTERSCRIPT
37
38
forward DropBomb(playerid);
39
forward BombTimer(playerid, num, Float:targetz);
40
forward DetonateBomb(playerid, num);
41
forward CreateSpecialExplosion(explosionid, num, playerid);
42
forward ReactivateBomb(playerid, bombnum);
43
forward CreateRadialExplosion(Float:x, Float:y, Float:z, round, max);
44
forward ReleaseBomb(playerid, bid);
45
forward OnBombExplode(playerid, num, Float:x, Float:y, Float:z);
46
forward ResetNearExp(playerid);
47
forward RemoveTextDraw(playerid);
48
forward ShowTextDraw(playerid, vehicleid, count);
49
50
// Free changeable stuff -------------
51
52
enum bombEnum {
53
	bombName[32],                       //Name of the bomb (plural for correct grammar ;)
54
	expID,                              //ExplosionID of the bomb (the same as in CreateExplosion)
55
	Float:expRadius,                    //Explosion radius (the same as in CreateExplosion)
56
	Float:accuracy,                     //Drop accuracy, higher is better (Height / this value = max x,y tolerance)
57
	bombModel,                          //Object model of the bomb
58
	bombModelRot,                       //Object model rotation of the bomb
59
	expDelay,                           //Explosion delay after reaching the ground (ms)
60
	reloadTime,                         //Reload time (ms)
61
	dropAtOnce,                         //Number of bombs beeing dropped with one click
62
	dropAtOnceDelay                     //Delay between the bombs beeing dropped at once (ms)
63
}
64
	
65
new gBombTypes[][bombEnum] = {
66
{"Nothing", 0, 0.0, 0.0, 0, 0, 0, 0, 0, 0},
67
{"Normal bombs", 11, 2.8, 6.0, 1636, 270, 500, 150, 1, 0},
68
{"Fire bombs", 1, 4.0, 8.0, 1636, 270, 0, 200, 1, 0},
69
{"Big bombs", 7, 4.5, 10.0, 3790, 270, 0, 750, 1, 0},
70
{"Laser-guided Bombs", 6, 5.0, 25.0, 1636, 270, 0, 1500, 1, 0},
71
{"Heavy bombs", -1, 5.0, 15.0, 345, 270, 0, 10000, 1, 0},                    	//Negative Explosion IDs can be used for self-created explosions, for more info check CreateSpecialExplosion
72
{"Anti-Missile Flares", -2, 150.0, 35.0, 354, 0, 5000, 10000, 1, 0},         	//Only has an effect together with my (act. unreleased) missile FS
73
{"Nuclear Bombs", -3, 4.0, 10.0, 3790, 270, 0, 10000, 1, 0},
74
{"Clusterbombs", 11, 2.5, 3.0, 1636, 270, 0, 15000, 12, 0},
75
{"Carpetbombs", 11, 2.5, 5.5, 1636, 270, 0, 15000, 12, 100}
76
};
77
78
//{Vehicle model ID, bombtype 1 allowed, bombtype 2 allowed, ..., bombtype n allowed}
79
//needs to be expanded, when more bombtypes are added
80
new gVehicleBombs[][] = {
81
	{476, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},      //Rustler
82
	{593, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Dodo
83
	{553, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1},      //Nevada
84
	{513, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Stuntplane
85
	{512, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Cropdust
86
	{577, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1},      //At-400
87
	{511, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0},      //Beagle
88
	{460, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Skimmer
89
	{519, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1},      //Shamal
90
	{548, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0},      //Cargobob
91
	{417, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1},      //Leviathan
92
	{487, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},      //Maverick
93
	{497, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},      //Police Maverick
94
	{563, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0},      //Raindance
95
	{447, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Seasparrow
96
	{469, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},      //Sparrow
97
	{425, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0},      //Hunter
98
	{592, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1}       //Andromeda
99
};
100
101
new Float:gBombSpeed = 20.0;        //Bomb-falling speed (constant, non-accelerated)
102
// Global variables ---------------
103
new bombid[MAX_PLAYERS][MAX_BOMBS];
104
new bombtime[MAX_PLAYERS][MAX_BOMBS];
105
new bombcount[MAX_PLAYERS];
106
new boti[MAX_PLAYERS][MAX_BOMBS];
107
new bfree[MAX_PLAYERS];
108
new btype[MAX_PLAYERS][MAX_BOMBS];
109
new bptype[MAX_PLAYERS] = 0;
110
new vmid[MAX_PLAYERS] = -1;
111
#if(USE_TEXTDRAWS)
112
new Text:bombtext[MAX_PLAYERS];
113
new removetimer[MAX_PLAYERS];
114
#endif
115
// ----------------------------------
116
117
#if defined FILTERSCRIPT
118
119
public OnFilterScriptInit()
120
{
121
        print("\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
122
        print("X         Bombing filterscript  V0.97       X");
123
        print("X        created by Mauzen 7/2008-2010      X");
124
        print("XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX");
125
		new size = sizeof gBombTypes;
126
		if(size != (sizeof gVehicleBombs[] - 1)) print("WARNING: NUMBER OF BOMBS DOES NOT MATCH THE VEHICLECONFIGERATIONS");
127
        MapAndreas_Init(MAP_ANDREAS_MODE_FULL);     //This FS requires the MapAndres-plugin
128
        return 1;
129
}
130
131
public OnFilterScriptExit()
132
{
133
		return 1;
134
}
135
#endif
136
137
public OnPlayerEnterVehicle(playerid, vehicleid, ispassenger)
138
{
139
		vmid[playerid] = GetVehicleStatID(GetVehicleModel(vehicleid));
140
        if(vmid[playerid] > -1) {
141
			bptype[playerid] = 0;
142
			#if(USE_TEXTDRAWS)
143
                TextDrawHideForPlayer(playerid, bombtext[playerid]);
144
			    TextDrawDestroy(bombtext[playerid]);
145
			    KillTimer(removetimer[playerid]);
146
				SetTimerEx("ShowTextDraw", 500, 0, "iii", playerid, vehicleid, 0);
147
			#endif
148
		}
149
		return 1;
150
}
151
152
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
153
{
154
		if(IsPlayerInAnyVehicle(playerid) && (vmid[playerid] > -1)) {
155
			new old[MAX_PLAYERS];
156
			if((newkeys & KEY_NEXT_BOMBTYPE) && !(oldkeys & KEY_NEXT_BOMBTYPE)) {
157
				old[playerid] = bptype[playerid];
158
				bptype[playerid] ++;
159
                if(bptype[playerid] >= sizeof gBombTypes) bptype[playerid] = old[playerid];
160
				while(gVehicleBombs[vmid[playerid]][bptype[playerid] + 1] <= 0) {
161
					bptype[playerid] ++;
162
			        if(bptype[playerid] >= sizeof gBombTypes) {
163
						bptype[playerid] = old[playerid];
164
						return 1;
165
					}
166
				}
167
				#if(USE_TEXTDRAWS)
168
					UpdateTextDraw(playerid);
169
				#else
170
                    new str[40];
171
					format(str, 40, "You have armed %s", gBombTypes[bptype[playerid]][bombName]);
172
			    	SendClientMessage(playerid, COLOR_YELLOW, str);
173
				#endif
174
		    }
175
		    if((newkeys & KEY_PREV_BOMBTYPE) && !(oldkeys & KEY_PREV_BOMBTYPE)) {
176
                old[playerid] = bptype[playerid];
177
				bptype[playerid] --;
178
	        	if(bptype[playerid] < 0) bptype[playerid] = old[playerid];
179
				while(gVehicleBombs[vmid[playerid]][bptype[playerid] + 1] <= 0) {
180
					bptype[playerid] --;
181
		        	if(bptype[playerid] < 0) {
182
						bptype[playerid] = old[playerid];
183
						return 1;
184
					}
185
				}
186
				#if(USE_TEXTDRAWS)
187
					UpdateTextDraw(playerid);
188
				#else
189
                    new str[40];
190
					format(str, 40, "You have armed %s", gBombTypes[bptype[playerid]][bombName]);
191
			    	SendClientMessage(playerid, COLOR_YELLOW, str);
192
				#endif
193
		    }
194
			if((newkeys & KEY_DROP_BOMB) && !(oldkeys & KEY_DROP_BOMB)) {
195
				if(IsPlayerAllowedToDropBomb(playerid)) DropBomb(playerid);
196
					else SendClientMessage(playerid, COLOR_RED, "You can't use that bomb now!");
197
                #if(USE_TEXTDRAWS)
198
					UpdateTextDraw(playerid);
199
				#endif
200
			}
201
		}
202
		return 1;
203
}
204
205
// -----------------------------------------------------------------------------
206
stock Float:floatrandom(Float:max)
207
{
208
		new Float:rand;
209
		max = max * 100000;
210
		rand = floatdiv(float(random(floatround(max))), 100000.0);
211
		return rand;
212
}
213
214
stock Float:GetPlayerDistanceToPoint(playerid, Float:x, Float:y, Float:z)
215
{
216
		new Float:px;
217
		new Float:py;
218
		new Float:pz;
219
		if(!IsPlayerInAnyVehicle(playerid)) GetPlayerPos(playerid, px, py, pz);
220
		    else GetVehiclePos(GetPlayerVehicleID(playerid), px, py, pz);
221
		return floatsqroot( floatadd( floatadd( floatpower(floatsub(x, px), 2), floatpower(floatsub(y, py), 2) ), floatpower(floatsub(z, pz), 2) ) );
222
}
223
224
stock Float:GetGroundZ(Float:x, Float:y)
225
{
226
		new Float:gz;
227
		MapAndreas_FindZ_For2DCoord(x, y, gz);
228
		return gz;
229
}
230
231
stock GetVehicleStatID(modelid)
232
{
233
		for(new i = 0; i < sizeof gVehicleBombs; i ++)
234
		    if(gVehicleBombs[i][0] == modelid)
235
		        return i;
236
		return -1;
237
}
238
239
// -----------------------------------------------------------------------------
240
241
public DropBomb(playerid)
242
{
243
		if(bptype[playerid] != 0) {
244
			if(bfree[playerid] == 0) {
245
				if(bombcount[playerid] < MAX_BOMBS) {
246
                    bfree[playerid] = 1;
247
					new bid = bptype[playerid];
248
					for(new drops = 0; drops < gBombTypes[bptype[playerid]][dropAtOnce] && bombcount[playerid] < MAX_BOMBS; drops ++) {
249
						if(gBombTypes[bid][dropAtOnceDelay] > 0) SetTimerEx("ReleaseBomb", gBombTypes[bid][dropAtOnceDelay] * drops, 0, "ii", playerid, bid);
250
						    else ReleaseBomb(playerid, bid);
251
					}
252
					SetTimerEx("ReactivateBomb", gBombTypes[bptype[playerid]][reloadTime], 0, "ii", playerid, bptype[playerid]);
253
				} else SendClientMessage(playerid, COLOR_RED, "Too many falling bombs, you cannot drop more at once!");
254
            } else {
255
				#if(!USE_TEXTDRAWS)
256
					SendClientMessage(playerid, COLOR_RED, "The bomb needs to be loaded! Wait a moment...");
257
				#endif
258
			}
259
        }
260
}
261
public ReleaseBomb(playerid, bid)
262
{
263
	    bombcount[playerid] ++;
264
	    new Float:x, Float:y, Float:z, Float:tz;
265
		new sel = -1;
266
		new Float:tolerancex, Float:tolerancey;
267
		for(new i = 0; i < MAX_BOMBS; i++) {
268
		    if(bombid[playerid][i] <= 0) {
269
		        sel = i;
270
		        bombid[playerid][i] = 1;
271
		        break;
272
			}
273
		}
274
		if(sel == -1) return;
275
		btype[playerid][sel] = bid;
276
		GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);
277
278
		tz = floatdiv(z - GetGroundZ(x, y), gBombTypes[bid][accuracy]);
279
		tolerancex = floatsub( floatrandom( tz ), floatdiv(tz, 2.0));
280
		tolerancey = floatsub( floatrandom( tz ), floatdiv(tz, 2.0));
281
		tz = GetGroundZ(x + tolerancex, y + tolerancey);
282
		bombid[playerid][sel] = CreateObject(gBombTypes[bid][bombModel], x, y, z - 1, gBombTypes[bid][bombModelRot], 0, 0);
283
		MoveObject(bombid[playerid][sel], x + tolerancex, y + tolerancey, tz - 1, gBombSpeed);
284
	    boti[playerid][sel] = 0;
285
		bombtime[playerid][sel] = SetTimerEx("BombTimer", UPDATE_TIME, 1, "iif", playerid, sel, tz);
286
		if(bptype[playerid] == 6) {
287
			CallRemoteFunction("LaunchAntiRocketFlare", "iff", bombid[playerid][sel], gBombTypes[6][expRadius], gBombTypes[6][accuracy]);
288
		}
289
}
290
291
public BombTimer(playerid, num, Float:targetz)
292
{
293
	    new Float:x;
294
		new Float:y;
295
		new Float:z;
296
		GetObjectPos(bombid[playerid][num], x, y, z);
297
		boti[playerid][num] += UPDATE_TIME;
298
299
		for(new i = 0; i < MAX_PLAYERS; i ++) {                                 //Check, if the bombs hits a player
300
		    if(IsPlayerConnected(i))
301
		        if(GetPlayerDistanceToPoint(i, x, y, z) < 7.5 && boti[playerid][num] >= 400) DetonateBomb(playerid, num);
302
		}
303
		if((floatsub(z, targetz) < 1)) {  										//bomb reached ground
304
			if(gBombTypes[btype[playerid][num]][expDelay] > 0) {
305
				SetTimerEx("DetonateBomb", gBombTypes[btype[playerid][num]][expDelay], 0, "ii", playerid, num);
306
				KillTimer(bombtime[playerid][num]);
307
			} else {
308
			    DetonateBomb(playerid, num);
309
			}
310
		}
311
}
312
313
public DetonateBomb(playerid, num)
314
{
315
	    new Float:x;
316
		new Float:y;
317
		new Float:z;
318
		GetObjectPos(bombid[playerid][num], x, y, z);
319
		OnBombExplode(playerid, num, x, y, z);
320
		KillTimer(bombtime[playerid][num]);
321
		if(gBombTypes[btype[playerid][num]][expID] > -1) {
322
			CreateExplosion(x, y, z, gBombTypes[btype[playerid][num]][expID], gBombTypes[btype[playerid][num]][expRadius]);
323
		} else {
324
			CreateSpecialExplosion(gBombTypes[btype[playerid][num]][expID], num, playerid);
325
		}
326
		DestroyObject(bombid[playerid][num]);
327
	    bombid[playerid][num] = -1;
328
		bombcount[playerid] --;
329
}
330
331
public CreateSpecialExplosion(explosionid, num, playerid)
332
{            												//Every explosion with a negative explosion ID is created here
333
	    new Float:x;                                        //You may add a check for your own bombs like the one already existing
334
		new Float:y;
335
		new Float:z;
336
		GetObjectPos(bombid[playerid][num], x, y, z);
337
		if(explosionid == -1) {     				        //btype[playerid][num] is the index of the exploding bomb
338
		    CreateExplosion(x, y, z, 7, 4.0);               //x, y and z are the coordinates of the bomb
339
		    CreateExplosion(x, y, z + 5.0, 1, 4.0);
340
		    CreateExplosion(x, y, z + 9.0, 1, 3.0);
341
		    CreateExplosion(x, y, z + 12.5, 1, 3.0);
342
		    CreateExplosion(x + 4.0, y, z, 0, 2.0);
343
		    CreateExplosion(x - 4.0, y, z, 0, 2.0);
344
		    CreateExplosion(x, y + 4.0, z, 0, 2.0);
345
		    CreateExplosion(x, y - 4.0, z, 0, 2.0);
346
		    CreateExplosion(x, y - 7.0, z, 1, 3.0);
347
		    CreateExplosion(x, y + 7.0, z, 1, 3.0);
348
		    CreateExplosion(x + 7.0, y, z, 1, 3.0);
349
		    CreateExplosion(x - 7.0, y, z, 1, 3.0);
350
		    CreateExplosion(x + 4.0, y + 4.0, z, 1, 4.0);
351
		    CreateExplosion(x - 4.0, y - 4.0, z, 1, 4.0);
352
		    CreateExplosion(x - 4.0, y + 4.0, z, 1, 4.0);
353
		    CreateExplosion(x + 4.0, y - 4.0, z, 1, 4.0);
354
		} else if(explosionid == -2) {
355
		    CallRemoteFunction("StopAntiRocketFlare", "i", bombid[playerid][num]);
356
		} else if(explosionid == -3) {
357
			CreateExplosion(x, y, z, 7, 4.0);
358
		    SetTimerEx("CreateRadialExplosion", 200, 0, "fffii", x, y, z, 0, 4);
359
		}
360
		//To add an own explosion create a new check like this:
361
		/*if(btype[playerid][num] == YOUR_BOMB_INDEX) {
362
		    ...your explosion...
363
		}*/
364
}
365
366
public CreateRadialExplosion(Float:x, Float:y, Float:z, round, max)
367
{
368
	for(new i = 0; i < 1 + 6 * round; i ++) {
369
		CreateExplosion(x + round * 10 * floatcos(6.28318 * (float(i) / (1.0 + 6.0*float(round)))),  y + round * 10 * floatsin(6.28318 * (float(i) / (1.0 + 6.0*float(round)))), z, 2, 3.0);
370
	}
371
	round ++;
372
	if(round <= max) SetTimerEx("CreateRadialExplosion", 200, 0, "fffii", x, y, z, round, max);
373
	return 1;
374
}
375
376
public ReactivateBomb(playerid)
377
{
378
		bfree[playerid] = 0;
379
		#if(USE_TEXTDRAWS)
380
			UpdateTextDraw(playerid);
381
		#endif
382
}
383
384
public OnBombExplode(playerid, num, Float:x, Float:y, Float:z)
385
{
386
	    //is called everytime a bomb explodes
387
		for(new i = 0; i < MAX_PLAYERS; i ++) {
388
		    if(GetPlayerDistanceToPoint(i, x, y, z) < 2 * gBombTypes[btype[playerid][num]][2]) {
389
				SetPVarInt(i, "nearExp", playerid);
390
				SetTimerEx("ResetNearExp", 15000, 0, "i", i);
391
			}
392
		}
393
		return 1;
394
}
395
396
public ShowTextDraw(playerid, vehicleid, count)
397
{
398
    	if(IsPlayerInVehicle(playerid, vehicleid)) {
399
			bombtext[playerid] = TextDrawCreate(480, 200, " ");                 //Change the Textdraw position for both styles here
400
			TextDrawUseBox(bombtext[playerid], 1);
401
			TextDrawBoxColor(bombtext[playerid], 0x00000066);
402
			TextDrawFont(bombtext[playerid], 1);
403
			UpdateTextDraw(playerid);
404
			removetimer[playerid] = SetTimerEx("RemoveTextDraw", 2000, 1, "i", playerid);
405
			TextDrawShowForPlayer(playerid, bombtext[playerid]);
406
		} else {
407
			count ++;
408
			if(count < 20) SetTimerEx("ShowTextDraw", 500, 0, "iii", playerid, vehicleid, count);
409
		}
410
}
411
public RemoveTextDraw(playerid)
412
{
413
		if(!IsPlayerInAnyVehicle(playerid)) {
414
		    TextDrawHideForPlayer(playerid, bombtext[playerid]);
415
		    TextDrawDestroy(bombtext[playerid]);
416
		    KillTimer(removetimer[playerid]);
417
		}
418
}
419
stock UpdateTextDraw(playerid)
420
{
421
		new text[160] = " ";
422
		#if(USE_TEXTDRAWS == 1)
423
			if(bptype[playerid] == 0) text = "~r~Nothing~w~";
424
			    else text = "Nothing";
425
			for(new i = 1; i < sizeof gBombTypes; i ++)
426
			    if(gVehicleBombs[vmid[playerid]][i + 1] == 1) {
427
			        if(bptype[playerid] == i) {
428
						if(bfree[playerid] || !IsPlayerAllowedToDropBomb(playerid)) format(text, 160, "%s~n~~r~%s~w~", text, gBombTypes[i][bombName]);
429
							else format(text, 160, "%s~n~~g~%s~w~", text, gBombTypes[i][bombName]);
430
	     			} else format(text, 160, "%s~n~%s", text, gBombTypes[i][bombName]);
431
				}
432
		#elseif(USE_TEXTDRAWS == 2)
433
		    if(bfree[playerid] || bptype[playerid] == 0 || !IsPlayerAllowedToDropBomb(playerid)) format(text, 160, "~r~%s", gBombTypes[bptype[playerid]][bombName]);
434
				else format(text, 160, "~g~%s", gBombTypes[bptype[playerid]][bombName]);
435
		#endif
436
		TextDrawSetString(bombtext[playerid], text);
437
}
438
439
public ResetNearExp(playerid)
440
{
441
    SetPVarInt(playerid, "nearExp", -1);
442
}
443
444
IsPlayerAllowedToDropBomb(playerid)
445
{
446
	#pragma unused playerid
447
	// This is used to restrict the use of bombs for single players
448
	// For example to make them available for special teams only, ...
449
	// bptype[playerid] is the index of the selected bomb
450
	return 1;
451
}