| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- /*
- About: FCNPC Bodyguard System
- Author: ziggi
- */
- #define FILTERSCRIPT
- #include <a_samp>
- #if !defined _FCNPC_included
- #tryinclude <FCNPC>
- #endif
- #if !defined _FCNPC_included
- #tryinclude "FCNPC"
- #endif
- #if !defined _FCNPC_included
- #tryinclude "../FCNPC"
- #endif
- #if !defined _FCNPC_included
- #error Add FCNPC.inc to your scripts directory
- #endif
- /*
- Defines
- */
- #define MAX_BODYGUARDS 6
- #define DEBUG
- #define MAX_BODYPART_NAME 10
- #define BG_INVALID_SLOT_ID -1
- /*
- Vars
- */
- static
- gPlayerNpc[MAX_PLAYERS][MAX_BODYGUARDS],
- gNpcSlot[MAX_PLAYERS],
- gNpcPlayer[MAX_PLAYERS],
- gFollowTimer[MAX_PLAYERS],
- gFollowTarget[MAX_PLAYERS],
- PlayerText3D:gNpcText3D[MAX_PLAYERS];
- /*
- Publics
- */
- public OnFilterScriptInit()
- {
- for (new playerid; playerid < MAX_PLAYERS; playerid++) {
- for (new slot; slot < MAX_BODYGUARDS; slot++) {
- gPlayerNpc[playerid][slot] = INVALID_PLAYER_ID;
- }
- gNpcSlot[playerid] = BG_INVALID_SLOT_ID;
- gNpcPlayer[playerid] = INVALID_PLAYER_ID;
- gFollowTimer[playerid] = 0;
- gFollowTarget[playerid] = INVALID_PLAYER_ID;
- }
- printf("\n-------------------------------");
- printf(" FCNPC Bodyguard System");
- printf(" Author: ziggi");
- printf("-------------------------------\n");
- return 1;
- }
- public OnFilterScriptExit()
- {
- for (new playerid; playerid < MAX_PLAYERS; playerid++) {
- if (BG_IsValid(playerid)) {
- BG_DeleteByID(playerid);
- }
- }
- }
- public OnPlayerDisconnect(playerid, reason)
- {
- if (!BG_IsValid(playerid)) {
- for (new slot; slot < MAX_BODYGUARDS; slot++) {
- if (BG_IsValidSlot(playerid, slot)) {
- BG_Delete(playerid, slot);
- }
- }
- }
- return 1;
- }
- public FCNPC_OnReachDestination(npcid)
- {
- BG_SetFollowTimer(npcid);
- }
- public FCNPC_OnTakeDamage(npcid, damagerid, weaponid, bodypart, Float:health_loss)
- {
- if (!IsPlayerConnected(damagerid) || !BG_IsValid(npcid)) {
- return 1;
- }
- #if defined DEBUG
- new
- string[44 + 3 + MAX_PLAYER_NAME + 3 + 2 + MAX_BODYPART_NAME + 16],
- player_name[MAX_PLAYER_NAME + 1],
- bodypart_name[MAX_BODYPART_NAME],
- weapon_name[16];
- GetPlayerName(damagerid, player_name, sizeof(player_name));
- GetBodypartName(bodypart, bodypart_name);
- GetWeaponName(weaponid, weapon_name, sizeof(weapon_name));
- format(string, sizeof(string),
- "NPC(%d) was damaged by %s(%d) with %s(%d) in the %s (hp: %f)",
- npcid, player_name, damagerid, weapon_name, weaponid, bodypart_name, health_loss);
- SendClientMessageToAll(0xFF0000FF, string);
- #endif
- return 1;
- }
- public FCNPC_OnVehicleEntryComplete(npcid, vehicleid, seat)
- {
- #if defined DEBUG
- new string[27 + 3 + 1];
- format(string, sizeof(string), "NPC %d finished vehicle entry", npcid);
- SendClientMessageToAll(0xFF0000FF, string);
- #endif
- return 1;
- }
- public FCNPC_OnVehicleExitComplete(npcid)
- {
- #if defined DEBUG
- new string[26 + 3 + 1];
- format(string, sizeof(string), "NPC %d finished vehicle exit", npcid);
- SendClientMessageToAll(0xFF0000FF, string);
- #endif
- return 1;
- }
- public OnPlayerCommandText(playerid, cmdtext[])
- {
- new
- cmd[20],
- subcmd[20],
- param[20],
- idx;
- cmd = strcharsplit(cmdtext, idx);
- if (!strcmp(cmd, "/bg", true)) {
- subcmd = strcharsplit(cmdtext, idx);
- if (strlen(subcmd) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg [option]");
- SendClientMessage(playerid, -1, "{8470FF}Options: {FFFFFF}add, delete, follow, unfollow, enter, exit");
- SendClientMessage(playerid, -1, "{8470FF}Options: {FFFFFF}shoot, aim, reset");
- return 1;
- }
- if (!strcmp(subcmd, "add", true)) {
- new npcid = BG_Add(playerid);
- if (npcid < 0) {
- if (npcid == -1) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Maximum bodyguards allowed per player is reached.");
- } else if (npcid == -2) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}No slots available.");
- } else {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Unknown error.");
- }
- return 1;
- }
- new
- Float:player_x,
- Float:player_y,
- Float:player_z,
- Float:player_angle;
- GetPlayerPos(playerid, player_x, player_y, player_z);
- GetPlayerFacingAngle(playerid, player_angle);
- new
- Float:pos_x,
- Float:pos_y;
- GetCoordsInFront(player_x, player_y, player_angle, 2.0, pos_x, pos_y);
- FCNPC_Spawn(npcid, random(4) + 163, pos_x, pos_y, player_z);
- FCNPC_SetAngleToPlayer(npcid, playerid);
- FCNPC_SetVirtualWorld(npcid, GetPlayerVirtualWorld(playerid));
- FCNPC_SetInterior(npcid, GetPlayerInterior(playerid));
- FCNPC_SetWeapon(npcid, random(3) + 22);
- FCNPC_ToggleInfiniteAmmo(npcid, true);
- FCNPC_SetArmour(npcid, 80);
- FCNPC_SetFightingStyle(npcid, random(4) + 3);
- new label_text[2 + 3 + 1];
- format(label_text, sizeof(label_text), "[%d]", BG_GetSlotByID(npcid));
- gNpcText3D[npcid] = CreatePlayer3DTextLabel(playerid, label_text, 0xFFFFFFFF, 0.0, 0.0, 0.0, 5.0, npcid);
- #if defined DEBUG
- new
- string[38 + MAX_PLAYER_NAME + 3 + 1],
- playername[MAX_PLAYER_NAME + 1];
- GetPlayerName(playerid, playername, sizeof(playername));
- format(string, sizeof(string), "Player %s (ID: %d) has created a bodyguard", playername, playerid);
- SendClientMessageToAll(0xFF0000FF, string);
- #endif
- return 1;
- }
- if (!strcmp(subcmd, "delete", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg delete [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_Delete(playerid, slot);
- return 1;
- }
- if (!strcmp(subcmd, "follow", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg follow [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_FollowPlayer(playerid, slot, playerid);
- return 1;
- }
- if (!strcmp(subcmd, "unfollow", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg unfollow [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_UnFollowPlayer(playerid, slot);
- return 1;
- }
- if (!strcmp(subcmd, "aim", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg aim [slot] [targetid]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg aim [slot] [targetid]");
- return 1;
- }
- new targetid = strval(param);
- if (!IsPlayerConnected(targetid)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid target.");
- return 1;
- }
- BG_Aim(playerid, slot, targetid);
- return 1;
- }
- if (!strcmp(subcmd, "shoot", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg shoot [slot] [targetid]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg shoot [slot] [targetid]");
- return 1;
- }
- new targetid = strval(param);
- if (!IsPlayerConnected(targetid)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid target.");
- return 1;
- }
- BG_Shoot(playerid, slot, targetid);
- return 1;
- }
- if (!strcmp(subcmd, "reset", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg reset [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_AimReset(playerid, slot);
- return 1;
- }
- if (!strcmp(subcmd, "enter", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg enter [slot] [vehicleid] [seat]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg enter [slot] [vehicleid] [seat]");
- return 1;
- }
- new vehicleid = strval(param);
- if (!GetVehicleModel(vehicleid)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid target.");
- return 1;
- }
- param = strcharsplit(cmdtext, idx);
- new seat = strval(param);
- BG_UnFollowPlayer(playerid, slot);
- BG_EnterVehicle(playerid, slot, vehicleid, seat);
- return 1;
- }
- if (!strcmp(subcmd, "exit", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg exit [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_ExitVehicle(playerid, slot);
- return 1;
- }
- if (!strcmp(subcmd, "melee", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg melee [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_Melee(playerid, slot);
- return 1;
- }
- if (!strcmp(subcmd, "stopmelee", true)) {
- param = strcharsplit(cmdtext, idx);
- if (strlen(param) == 0) {
- SendClientMessage(playerid, -1, "{8470FF}Use: {FFFFFF}/bg stopmelee [slot]");
- return 1;
- }
- new slot = strval(param);
- if (!BG_IsValidSlot(playerid, slot)) {
- SendClientMessage(playerid, -1, "{CC0000}Error: {FFFFFF}Invalid bodyguard.");
- return 1;
- }
- BG_MeleeStop(playerid, slot);
- return 1;
- }
- }
- return 0;
- }
- /*
- Vehicle functions
- */
- stock BG_EnterVehicle(playerid, slot, vehicleid, seat)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_EnterVehicle(npcid, vehicleid, seat, MOVE_TYPE_RUN);
- }
- stock BG_ExitVehicle(playerid, slot)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_ExitVehicle(npcid);
- }
- /*
- Aim functions
- */
- stock BG_Aim(playerid, slot, targetid)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_AimAtPlayer(npcid, targetid);
- }
- stock BG_Shoot(playerid, slot, targetid)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_AimAtPlayer(npcid, targetid, .shoot = true);
- }
- stock BG_AimReset(playerid, slot)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_StopAim(npcid);
- }
- /*
- Melee functions
- */
- stock BG_Melee(playerid, slot)
- {
- BG_MeleeStop(playerid, slot);
- new npcid = gPlayerNpc[playerid][slot];
- SetPVarInt(npcid, "bg_last_weapon", FCNPC_GetWeapon(npcid));
- FCNPC_SetWeapon(npcid, 0);
- FCNPC_MeleeAttack(npcid, .fightstyle = true);
- }
- stock BG_MeleeStop(playerid, slot)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_SetWeapon(npcid, GetPVarInt(npcid, "bg_last_weapon"));
- FCNPC_StopAttack(npcid);
- }
- /*
- Follow functions
- */
- stock BG_SetFollowTimer(npcid)
- {
- if (gFollowTarget[npcid] != INVALID_PLAYER_ID) {
- gFollowTimer[npcid] = SetTimerEx("BG_SetFollowPosition", 300, true, "ii", npcid, gFollowTarget[npcid]);
- }
- }
- stock BG_FollowPlayer(playerid, slot, targetid)
- {
- BG_UnFollowPlayer(playerid, slot);
- new npcid = gPlayerNpc[playerid][slot];
- gFollowTarget[npcid] = targetid;
- new isgo = BG_SetFollowPosition(npcid, targetid);
- if (!isgo) {
- BG_SetFollowTimer(npcid);
- }
- }
- stock BG_UnFollowPlayer(playerid, slot)
- {
- new npcid = gPlayerNpc[playerid][slot];
- if (gFollowTimer[npcid] != 0) {
- KillTimer(gFollowTimer[npcid]);
- gFollowTimer[npcid] = 0;
- }
- if (gFollowTarget[npcid] == INVALID_PLAYER_ID) {
- return 0;
- }
- gFollowTarget[npcid] = INVALID_PLAYER_ID;
- return 1;
- }
- forward BG_SetFollowPosition(npcid, playerid);
- public BG_SetFollowPosition(npcid, playerid)
- {
- new
- Float:pos_x,
- Float:pos_y,
- Float:pos_z,
- Float:dist_offset,
- Float:range,
- Float:speed;
- GetPlayerPos(playerid, pos_x, pos_y, pos_z);
- if (FCNPC_GetVehicleID(npcid) != INVALID_VEHICLE_ID) {
- dist_offset = -3.0;
- range = -dist_offset + 1.0;
- speed = 0.8;
- } else {
- dist_offset = -1.0;
- range = -dist_offset + 0.5;
- speed = MOVE_SPEED_AUTO;
- }
- if (!IsPlayerInRangeOfPoint(npcid, range, pos_x, pos_y, pos_z)) {
- FCNPC_GoToPlayer(npcid, playerid, .speed = speed, .dist_offset = dist_offset);
- KillTimer(gFollowTimer[npcid]);
- gFollowTimer[npcid] = 0;
- return 1;
- }
- return 0;
- }
- /*
- Add/Delete functions
- */
- stock BG_Add(playerid)
- {
- new slot = BG_GetFreeSlot(playerid);
- if (slot == BG_INVALID_SLOT_ID) {
- return -1;
- }
- new name[MAX_PLAYER_NAME + 1];
- format(name, sizeof(name), "Guard_%d_%d", playerid, slot);
- new npcid = FCNPC_Create(name);
- if (npcid == INVALID_PLAYER_ID) {
- return -2;
- }
- gPlayerNpc[playerid][slot] = npcid;
- gNpcPlayer[npcid] = playerid;
- gNpcSlot[npcid] = slot;
- return npcid;
- }
- stock BG_Delete(playerid, slot)
- {
- new npcid = gPlayerNpc[playerid][slot];
- FCNPC_Destroy(npcid);
- BG_UnFollowPlayer(playerid, slot);
- DeletePlayer3DTextLabel(playerid, gNpcText3D[npcid]);
- gPlayerNpc[playerid][slot] = INVALID_PLAYER_ID;
- gNpcPlayer[npcid] = INVALID_PLAYER_ID;
- gNpcSlot[npcid] = BG_INVALID_SLOT_ID;
- }
- stock BG_DeleteByID(npcid)
- {
- new playerid = gNpcPlayer[npcid];
- new slot = gNpcSlot[npcid];
- BG_Delete(playerid, slot);
- }
- /*
- Slot functions
- */
- stock BG_IsValidSlot(playerid, slot)
- {
- if (slot < 0 || slot > sizeof(gPlayerNpc[])) {
- return false;
- }
- return gPlayerNpc[playerid][slot] != INVALID_PLAYER_ID;
- }
- stock BG_IsValid(npcid)
- {
- return FCNPC_IsValid(npcid) && gNpcSlot[npcid] != BG_INVALID_SLOT_ID;
- }
- stock BG_GetFreeSlot(playerid)
- {
- for (new slot; slot < sizeof(gPlayerNpc[]); slot++) {
- if (gPlayerNpc[playerid][slot] == INVALID_PLAYER_ID) {
- return slot;
- }
- }
- return BG_INVALID_SLOT_ID;
- }
- stock BG_GetSlotByID(npcid)
- {
- return gNpcSlot[npcid];
- }
- /*
- Other functions
- */
- stock strcharsplit(const string[], &index, seperator = ' ')
- {
- new
- result[20],
- i;
- if (index != 0 && string[index] != '\0') {
- index++;
- }
- while (string[index] && string[index] != seperator && string[index] != '\r' && string[index] != '\n') {
- result[i++] = string[index++];
- }
- return result;
- }
- stock GetCoordsInFront(Float:x, Float:y, Float:a, Float:distance, &Float:res_x, &Float:res_y)
- {
- res_x = x + (distance * floatsin(-a, degrees));
- res_y = y + (distance * floatcos(-a, degrees));
- }
- stock GetBodypartName(bodypart, name[], const size = sizeof(name))
- {
- static const
- names[][] = {
- !"torso",
- !"groin",
- !"left arm",
- !"right arm",
- !"left leg",
- !"right leg",
- !"head"
- };
- if (9 < bodypart < 3) {
- return 0;
- }
- return strunpack(name, names[bodypart - 3], size);
- }
|