Skip to content

Commit 268fac1

Browse files
authored
Create rustlerFireFix.pwn
Initial commit
1 parent e1eb926 commit 268fac1

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed

filterscripts/rustlerFireFix.pwn

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
#include <a_samp>
2+
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
You can use mobile.inc to distinguish mobile
4+
players from PC and not to use this script
5+
with PC players. This include by default
6+
is avaliable only for servers that bought
7+
"Hosted" tab, but maybe there is free ones
8+
on the github.
9+
10+
#include "mobile.inc" // Needs Pawn.RakNet plugin
11+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12+
*/
13+
14+
/*
15+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16+
Have 13 warnings from rotation include.
17+
If it is a big problem, then you can
18+
use your own functions for calculating
19+
plane's offset coordinates instead.
20+
*/
21+
#include <rotation>
22+
#include <rotation_misc>
23+
#include <rotation_extra>
24+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
#include <colandreas> // For collisions
26+
27+
#include <Pawn.RakNet> // For bulletSync packets
28+
#define FILTERSCRIPT // For Pawn.RakNet :D
29+
30+
#define DEBUG_MODE false // To have extra prints in log
31+
#define COLLISION_SEARCH_MIN_RADIUS 1 // Radius near plane
32+
#define COLLISION_SEARCH_RADIUS_STEP 1 // Step increasing radius
33+
#define COLLISION_SEARCH_MAX_RADIUS 5 // Radius far away from plane
34+
#define COLLISION_MINIMAL_DISTANCE 10 // Distance from plane to start search
35+
#define COLLISION_MAXIMAL_DISTANCE 200 // Maximal search distance
36+
#define COLLISION_DISTANCE_STEP 10 // Search for every 10 metres
37+
#define RUSTLER_DAMAGE_PLAYERS 10 // Plane's damage to players
38+
#define RUSTLER_DAMAGE_VEHICLES 10 // Damage to vehicles
39+
#define RUSTLER_DAMAGE_BODYPART 3 // Bodypart to damage to (not used)
40+
#define RUSTLER_MODEL_ID 476 // ModelID of Rustler plane
41+
#define RUSTLER_WEAPON_ID 31 // WeaponID for killing messages / damage sync
42+
#define NOTSET -1
43+
44+
#define BULLET_SYNC_ENABLE true // Set true if you want to send BulletSync packet when damaging player
45+
#define BULLET_SYNC_STREAM_ENABLE true // Set true if you want to send BulletSync to all players in victim's stream area
46+
#if BULLET_SYNC_ENABLE == true
47+
#define BULLET_SYNC 206
48+
#define BULLET_HIT_TYPE_NONE 0
49+
#define BULLET_HIT_TYPE_PLAYER 1
50+
#define BULLET_HIT_TYPE_VEHICLE 2
51+
#define BULLET_HIT_TYPE_OBJECT 3
52+
#define BULLET_HIT_TYPE_PLAYER_OBJECT 4
53+
#endif
54+
55+
forward OnCheckFireUpdate();
56+
forward OnRustlerFiring(playerid, vehicleid);
57+
forward GetNearestPlayer(Float:x, Float:y, Float:z, Float:radius, playerid);
58+
59+
new firingTimer[MAX_PLAYERS];
60+
new playerDeath[MAX_PLAYERS];
61+
62+
63+
public OnFilterScriptInit()
64+
{
65+
print("----------------------------\n|-[rustlerFireFix script by d7.KrEoL loaded]");
66+
print("| 15.12.24");
67+
print("|->Discord:https://discord.gg/QSKkNhZrTh");
68+
print("|->VK:https://vk.com/d7kreol\n----------------------------");
69+
70+
for (new i = 0; i < MAX_PLAYERS; i++)
71+
{
72+
firingTimer[i] = NOTSET;
73+
playerDeath[i] = NOTSET;
74+
}
75+
if (!CA_Init())
76+
printf("[rustlerFireFix]: cannot create raycast world. Script may not work well.");
77+
return 1;
78+
}
79+
80+
public OnFilterScriptExit()
81+
{
82+
print("\n--dlink Test Unloaded.\n------------------");
83+
return 1;
84+
}
85+
86+
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
87+
{
88+
if ((newkeys & KEY_ACTION) && !(oldkeys & KEY_ACTION) && IsPlayerInAnyVehicle(playerid))
89+
{
90+
new vehicleid = GetPlayerVehicleID(playerid);
91+
if (GetVehicleModel(vehicleid) != RUSTLER_MODEL_ID)
92+
return 0;
93+
AddPlayerFiringTimer(playerid, vehicleid);
94+
}
95+
if ((oldkeys & KEY_ACTION) && !(newkeys & KEY_ACTION))
96+
{
97+
if (firingTimer[playerid] != NOTSET)
98+
KillFiringTimer(playerid);
99+
}
100+
return 0;
101+
}
102+
103+
public GetNearestPlayer(Float:x, Float:y, Float:z, Float:radius, playerid)
104+
{
105+
new result = NOTSET;
106+
new Float:distance = radius;
107+
new Float:playerDistance = radius * 2;
108+
for(new i = 0; i < MAX_PLAYERS; i++)
109+
{
110+
if(!IsPlayerConnected(i) || !IsPlayerSpawned(i) || i == playerid)
111+
continue;
112+
playerDistance = GetPlayerDistanceFromPoint(i, x, y, z);
113+
if (playerDistance < distance)
114+
{
115+
result = i;
116+
distance = playerDistance;
117+
}
118+
}
119+
return int:result;
120+
}
121+
122+
public OnRustlerFiring(playerid, vehicleid)
123+
{
124+
if (!IsPlayerConnected(playerid) || !IsPlayerSpawned(playerid) || !IsPlayerInAnyVehicle(playerid))
125+
{
126+
KillFiringTimer(playerid);
127+
return;
128+
}
129+
#if DEBUG_MODE == true
130+
printf("\n------------\n\n\nRustler fire from id: %d", playerid);
131+
#endif
132+
if (!IsPlayerInAnyVehicle(playerid))
133+
KillFiringTimer(playerid);
134+
new Float:positionX, Float:positionY, Float:positionZ;
135+
GetVehiclePos(vehicleid, positionX, positionY, positionZ);
136+
new Float:offsetX, Float:offsetY, Float:offsetZ;
137+
new Float:castX, Float:castY, Float:castZ;
138+
new targetid = NOTSET;
139+
new searchRadius = COLLISION_SEARCH_MIN_RADIUS;
140+
141+
for (new i = COLLISION_MINIMAL_DISTANCE; i < COLLISION_MAXIMAL_DISTANCE; i += COLLISION_DISTANCE_STEP)
142+
{
143+
GetVehicleRelativePos(vehicleid, 0, i, 0, offsetX, offsetY, offsetZ);
144+
targetid = GetNearestPlayer(offsetX, offsetY, offsetZ, searchRadius, playerid);
145+
146+
if (searchRadius < COLLISION_SEARCH_MAX_RADIUS)
147+
searchRadius += COLLISION_SEARCH_RADIUS_STEP;
148+
if (targetid == NOTSET)
149+
continue;
150+
151+
new Float:targetX, Float:targetY, Float:targetZ;
152+
if (!GetPlayerPos(targetid, targetX, targetY, targetZ))
153+
{
154+
#if DEBUG_MODE == true
155+
printf("bad target %d", targetid);
156+
#endif
157+
158+
break;
159+
}
160+
161+
if (CA_RayCastLine(positionX, positionY, positionZ, targetX, targetY, targetZ, castX, castY, castZ) != 0)
162+
{
163+
#if DEBUG_MODE == true
164+
printf("!!![COLLISION FOUND: %.2f %.2f %.2f] (Player %d is behind the object)", castX, castY, castZ, targetid);
165+
#endif
166+
167+
break;
168+
}
169+
// Uncomment if you're using mobile.inc to recognize mobile clients
170+
/*if (!IsPlayerMobile(targetid)) //#include "mobile.inc" above
171+
{
172+
printf("player %d is not mobile player", targetid);
173+
break;
174+
}*/
175+
#if BULLET_SYNC_ENABLE == true
176+
new bulletData[PR_BulletSync]; //To send bulletData
177+
bulletData[PR_hitId] = targetid;
178+
bulletData[PR_origin][0] = positionX;
179+
bulletData[PR_origin][1] = positionY;
180+
bulletData[PR_origin][2] = positionZ;
181+
bulletData[PR_hitPos][0] = targetX;
182+
bulletData[PR_hitPos][1] = targetY;
183+
bulletData[PR_hitPos][2] = targetZ;
184+
bulletData[PR_offsets][0] = 0;
185+
bulletData[PR_offsets][1] = 0;
186+
bulletData[PR_offsets][2] = 0;
187+
bulletData[PR_weaponId] = RUSTLER_WEAPON_ID;
188+
#endif
189+
190+
if (IsPlayerInAnyVehicle(targetid))
191+
{
192+
new targetvehicleid = GetPlayerVehicleID(targetid);
193+
#if DEBUG_MODE == true
194+
printf("%d damaged vehicle: %d(player: %d)", playerid, targetvehicleid, targetid);
195+
#endif
196+
new Float:vehiclehealth = 1000;
197+
if (!GetVehicleHealth(targetvehicleid, vehiclehealth))
198+
continue;
199+
SetVehicleHealth(targetvehicleid, vehiclehealth - RUSTLER_DAMAGE_VEHICLES); // Can rewrite with you GiveVehicleDamage logic here
200+
#if BULLET_SYNC_ENABLE == true
201+
bulletData[PR_hitType] = BULLET_HIT_TYPE_VEHICLE;
202+
SendBulletSync(playerid, targetvehicleid, bulletData);
203+
#endif
204+
205+
break;
206+
}
207+
else
208+
{
209+
#if DEBUG_MODE == true
210+
printf("%d damaged player: %d", playerid, targetid);
211+
#endif
212+
new Float:playerhealth = 100;
213+
if (!GetPlayerHealth(targetid, playerhealth))
214+
continue;
215+
GivePlayerDamage(targetid, playerid, RUSTLER_DAMAGE_PLAYERS);
216+
#if BULLET_SYNC_ENABLE == true
217+
bulletData[PR_hitType] = BULLET_HIT_TYPE_PLAYER;
218+
SendBulletSync(playerid, targetid, bulletData);
219+
#endif
220+
221+
break;
222+
}
223+
}
224+
#if DEBUG_MODE == true
225+
printf("---------");
226+
#endif
227+
}
228+
229+
public OnPlayerDeath(playerid, killerid, reason)
230+
{
231+
if (playerDeath[playerid] > NOTSET)
232+
{
233+
SendDeathMessage(playerDeath[playerid], playerid, RUSTLER_WEAPON_ID);
234+
playerDeath[playerid] = NOTSET;
235+
return 0;
236+
}
237+
return 1;
238+
}
239+
240+
#if BULLET_SYNC_ENABLE == true
241+
stock SendBulletSync(playerid, victimid, data[PR_BulletSync])
242+
{
243+
new BitStream:bs = BS_New();
244+
BS_WriteValue(bs,
245+
PR_UINT8, BULLET_SYNC,
246+
PR_UINT16, playerid
247+
);
248+
BS_WriteBulletSync(bs, data);
249+
#if BULLET_SYNC_STREAM_ENABLE == true
250+
for (new i = 0; i < MAX_PLAYERS; i++)
251+
{
252+
if (IsPlayerStreamedIn(i, victimid))
253+
PR_SendPacket(bs, i);
254+
}
255+
#else
256+
PR_SendPacket(bs, victimid);
257+
#endif
258+
BS_Delete(bs);
259+
}
260+
#endif
261+
262+
stock AddPlayerFiringTimer(playerid, vehicleid)
263+
{
264+
if (firingTimer[playerid] != NOTSET)
265+
KillFiringTimer(playerid);
266+
new FuncName[16] = "OnRustlerFiring";
267+
firingTimer[playerid] = SetTimerEx(FuncName, 100, true, "ii", playerid, vehicleid);
268+
}
269+
270+
stock GivePlayerDamage(playerid, damagerid, Float:damage) // Can rewrite with your GivePlayerDamage (OnFoot) logic here
271+
{
272+
new Float:health, Float:armour;
273+
if (!GetPlayerHealth(playerid, health))
274+
return;
275+
if (!GetPlayerArmour(playerid, armour))
276+
return;
277+
if (armour > 0)
278+
{
279+
SetPlayerArmour(playerid, armour - damage);
280+
damage = damage - armour;
281+
if (damage <= 0)
282+
return;
283+
}
284+
if (health - damage <= 0) // Do "player kill" logic
285+
{
286+
//SendDeathMessage(damagerid, playerid, RUSTLER_WEAPON_ID);
287+
playerDeath[playerid] = damagerid;
288+
}
289+
SetPlayerHealth(playerid, health - damage);
290+
#if DEBUG_MODE == true
291+
printf("Damage has given to %d", playerid);
292+
#endif
293+
}
294+
295+
stock KillFiringTimer(playerid)
296+
{
297+
KillTimer(firingTimer[playerid]);
298+
firingTimer[playerid] = NOTSET;
299+
}
300+
301+
stock IsPlayerSpawned(playerid)
302+
{
303+
new pState = GetPlayerState(playerid);
304+
return 0 <= playerid <= MAX_PLAYERS && pState != PLAYER_STATE_NONE && pState != PLAYER_STATE_WASTED && pState != PLAYER_STATE_SPECTATING;
305+
}

0 commit comments

Comments
 (0)