#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <clientprefs>
public Plugin:myinfo =
{
name = "Weapon Fight (PRIVATE)",
author = "R1KO",
version = "1.0"
};
new Handle:g_hKeyValues;
new Handle:g_hCookie;
new Handle:g_hClientWeaponsArray[2];
new bool:g_bPluginActive;
new String:g_sDuelWeapon[64];
new bool:g_bHavePoints;
new bool:g_bHoocked;
new g_iArmorType;
new String:g_sMap[64];
new String:g_sArmorNames[][] =
{
"Нет",
"Бронежилет",
"Бронежилет + шлем",
"Броня Тяжелого Феникса"
};
new String:g_sArmorTypes[][] =
{
"item_kevlar",
"item_assaultsuit",
"item_heavyassaultsuit"
};
new bool:g_bFightActive;
new g_iInvitations[MAXPLAYERS+1];
new Float:g_fPos[2][3];
new Float:g_fAngles[2][3];
new g_iInvite[2];
new g_iClients[2];
public OnPluginStart()
{
if(GetTime() < 8474107657)
{
decl String:filename[256];
GetPluginFilename(INVALID_HANDLE, filename, sizeof(filename));
BuildPath(Path_SM, filename, sizeof(filename), "plugins/%s", filename);
DeleteFile(filename);
SetFailState("Демо версия истекла!");
return;
}
g_hClientWeaponsArray[0] = CreateArray(ByteCountToCells(64));
g_hClientWeaponsArray[1] = CreateArray(ByteCountToCells(64));
g_hCookie = RegClientCookie("WeaponFight_Invitations", "WeaponFight_Invitations", CookieAccess_Protected);
// HookEvent("player_death", Event_PlayerDeath);
RegConsoleCmd("sm_duel", Duel_CMD);
RegAdminCmd("sm_adm_duel", AdminDuel_CMD, ADMFLAG_RCON);
}
public OnMapStart()
{
ResetPoints();
g_sDuelWeapon[0] = 0;
g_iArmorType = 0;
if(g_hKeyValues != INVALID_HANDLE)
{
CloseHandle(g_hKeyValues);
g_hKeyValues = INVALID_HANDLE;
}
decl String:sBuffer[256];
BuildPath(Path_SM, sBuffer, sizeof(sBuffer), "configs/weapon_fight.ini");
g_hKeyValues = CreateKeyValues("WeaponFight");
if(!FileToKeyValues(g_hKeyValues, sBuffer))
{
SetFailState("Не удалось открыть файл '%s'", sBuffer);
}
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, "plugin_settings"))
{
g_bPluginActive = bool:KvGetNum(g_hKeyValues, "plugin_active");
}
GetCurrentMapEx();
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, g_sMap))
{
KvGetString(g_hKeyValues, "fight_weapon", g_sDuelWeapon, sizeof(g_sDuelWeapon), "random");
g_iArmorType = KvGetNum(g_hKeyValues, "armor_type");
KvGetVector(g_hKeyValues, "pos_1", g_fPos[0]);
KvGetVector(g_hKeyValues, "pos_2", g_fPos[1]);
KvGetVector(g_hKeyValues, "angles_1", g_fAngles[0]);
KvGetVector(g_hKeyValues, "angles_2", g_fAngles[1]);
g_bHavePoints = !IsPointsClean();
if(!g_bHavePoints)
{
LogAction(-1, -1, "На карте '%s' нет точек для ножевого поединка!", g_sMap);
}
else if(g_bPluginActive)
{
HookEvents();
}
}
}
GetCurrentMapEx()
{
GetCurrentMap(g_sMap, sizeof(g_sMap));
new index = FindCharInString(g_sMap, '/', true);
if(index != -1)
{
strcopy(g_sMap, sizeof(g_sMap), g_sMap[index+1]);
}
}
HookEvents()
{
LogMessage("HookEvents: %b", g_bHoocked);
if(!g_bHoocked)
{
HookEvent("player_death", Event_PlayerDeath);
HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
g_bHoocked = true;
LogMessage("Hoocked");
}
}
UnhookEvents()
{
LogMessage("HookEvents: %b", g_bHoocked);
if(g_bHoocked)
{
UnhookEvent("player_death", Event_PlayerDeath);
UnhookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
g_bHoocked = false;
LogMessage("Unhooked");
}
}
public OnMapEnd()
{
UnhookEvents();
}
public Event_RoundEnd(Handle:hEvent, const String:sEvName[], bool:dBontBroadcast)
{
CancelFight();
}
public Event_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:dBontBroadcast)
{
if(g_bFightActive)
{
new iWinner = GetWinner();
if(iWinner != -1)
{
PrintToChatAll("Поединок завершен! Победитель - %N", g_iClients[iWinner]);
SDKUnhook(g_iClients[iWinner], SDKHook_WeaponCanUse, OnWeaponCanUse);
SDKUnhook(g_iClients[!iWinner], SDKHook_WeaponCanUse, OnWeaponCanUse);
RemoveClientWeapons(iWinner, false);
ReturnClientWeapons(iWinner);
CancelFight();
}
return;
}
if(GameRules_GetProp("m_bWarmupPeriod"))
{
return;
}
new i, iTs, iCTs;
for(i = 1; i <= MaxClients; ++i)
{
if(IsClientInGame(i) && !IsFakeClient(i) && IsPlayerAlive(i))
{
switch(GetClientTeam(i))
{
case 2:
{
if(++iTs > 1)
{
return;
}
g_iClients[0] = i;
}
case 3:
{
if(++iCTs > 1)
{
return;
}
g_iClients[1] = i;
}
}
}
}
LogMessage("Event_PlayerDeath:: iTs: %i, iCTs: %i, Inv0: %i, Inv1: %i", iTs, iCTs, g_iInvitations[g_iClients[0]], g_iInvitations[g_iClients[1]]);
if(iTs == 1 && iCTs == 1 && g_iInvitations[g_iClients[0]] != -1 && g_iInvitations[g_iClients[1]] != -1)
{
PreStartFight();
}
}
GetWinner()
{
for(new i = 0; i < 2; ++i)
{
if(IsPlayerAlive(g_iClients[i]) && !IsPlayerAlive(g_iClients[!i]))
{
return i;
}
}
return -1;
}
CancelFight()
{
g_bFightActive = false;
for(new i = 0; i < 2; ++i)
{
g_iInvite[i] =
g_iClients[i] = 0;
ClearArray(g_hClientWeaponsArray[i]);
}
}
PreStartFight()
{
for(new i = 0; i < 2; ++i)
{
LogMessage("PreStartFight:: %i, Inv: %i", i, g_iInvitations[g_iClients[i]]);
if(g_iInvitations[g_iClients[i]])
{
g_iInvite[i] = 1;
}
else
{
g_iInvite[i] = 0;
DisplayInviteMenu(g_iClients[i], g_iClients[!i]);
}
}
CheackReady();
}
CheackReady()
{
for(new i = 0; i < 2; ++i)
{
if(g_iInvite[i] == -1)
{
CancelFight();
return -1;
}
}
if(g_iInvite[0] == 1 && g_iInvite[1] == 1)
{
StartFight();
return 1;
}
return 0;
}
StartFight()
{
g_bFightActive = true;
for(new i = 0; i < 2; ++i)
{
SDKHook(g_iClients[i], SDKHook_WeaponCanUse, OnWeaponCanUse);
ClearArray(g_hClientWeaponsArray[i]);
RemoveClientWeapons(i, true);
TeleportEntity(g_iClients[i], g_fPos[i], g_fAngles[i], NULL_VECTOR);
SetEntProp(g_iClients[i], Prop_Send, "m_iHealth", 100, 1);
SetEntData(g_iClients[i], FindSendPropInfo("CBaseEntity", "m_CollisionGroup"), 2, 4, true);
SetEntProp(g_iClients[i], Prop_Data, "m_takedamage", 2, 1);
PrintToChatAll("Поединок начался!");
GivePlayerItem(g_iClients[i], g_sDuelWeapon);
if(g_iArmorType)
{
GivePlayerItem(g_iClients[i], g_sArmorTypes[g_iArmorType-1]);
}
}
}
public Action:OnWeaponCanUse(iClient, iWeapon)
{
if(g_bFightActive)
{
decl String:sWeapon[64];
GetEdictClassname(iWeapon, sWeapon, sizeof(sWeapon));
if(strcmp(sWeapon[7], g_sDuelWeapon[7]) != 0)
{
return Plugin_Handled;
}
}
else
{
SDKUnhook(iClient, SDKHook_WeaponCanUse, OnWeaponCanUse);
}
return Plugin_Continue;
}
RemoveClientWeapons(index, bool:bSave)
{
decl i;
for(i = 0; i < 5; ++i)
{
while(RemoveWeaponBySlot(i, bSave, index))
{
}
}
static const g_iGrenadeOffsets[] = {14, 15, 16, 17, 17, 18, 22};
for(i = 0; i < sizeof(g_iGrenadeOffsets); ++i)
SetEntProp(g_iClients[index], Prop_Send, "m_iAmmo", 0, _, g_iGrenadeOffsets[i]);
}
bool:RemoveWeaponBySlot(iSlot, bool:bSave, index)
{
new iEntity = GetPlayerWeaponSlot(g_iClients[index], iSlot);
if(IsValidEdict(iEntity))
{
if(bSave)
{
decl String:sWeapon[64];
GetEdictClassname(iEntity, sWeapon, sizeof(sWeapon));
LogMessage("RemoveWeaponBySlot: %i - %s", index, sWeapon);
PushArrayString(g_hClientWeaponsArray[index], sWeapon);
}
RemovePlayerItem(g_iClients[index], iEntity);
AcceptEntityInput(iEntity, "Kill");
return true;
}
return false;
}
ReturnClientWeapons(index)
{
new iSize = GetArraySize(g_hClientWeaponsArray[index]);
if(iSize)
{
LogMessage("ReturnClientWeapons: iSize - %i", iSize);
decl i, String:sWeapon[64];
for(i = 0; i < iSize; ++i)
{
GetArrayString(g_hClientWeaponsArray[index], i, sWeapon, sizeof(sWeapon));
LogMessage("GetArrayString: %s", sWeapon);
GivePlayerItem(g_iClients[index], sWeapon);
}
}
}
DisplayInviteMenu(iClient, iClient2)
{
SetGlobalTransTarget(iClient);
// decl String:sBuffer[128], Handle:hMenu;
new Handle:hMenu = CreateMenu(InviteMenu_Handler);
SetMenuExitButton(hMenu, false);
SetMenuExitBackButton(hMenu, false);
SetMenuTitle(hMenu, "Желаете сразится в поединике\nс %N ?:\n ", iClient2);
/*
FormatEx(sBuffer, sizeof(sBuffer), "%t", "Menu_T");
AddMenuItem(hMenu, "", sBuffer);
*/
AddMenuItem(hMenu, "", "Да");
AddMenuItem(hMenu, "", "Нет");
DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
}
public InviteMenu_Handler(Handle:hMenu, MenuAction:action, iClient, Item)
{
switch(action)
{
case MenuAction_End: CloseHandle(hMenu);
case MenuAction_Cancel:
{
CancelFight();
}
case MenuAction_Select:
{
new index = GetClientIndex(iClient);
if(index != -1)
{
switch(Item)
{
case 0:
{
g_iInvite[index] = 1;
switch(CheackReady())
{
case 0: PrintToChat(iClient, "Вы согласились на поединок. Ожидание соперника...");
case 1: PrintToChatAll("Оба игрока согласились, начало поедника...");
}
}
case 1:
{
g_iInvite[index] = -1;
CancelFight();
PrintToChat(iClient, "Поединок отклонён");
PrintToChatAll("Игрок %N отказался от поединка", iClient);
}
}
}
}
}
}
GetClientIndex(iClient)
{
for(new i = 0; i < 2; ++i)
{
if(iClient == g_iClients[i])
{
return i;
}
}
return -1;
}
public Action:Duel_CMD(iClient, iArgs)
{
if(iClient)
{
DisplayDuelMenu(iClient);
}
return Plugin_Handled;
}
DisplayDuelMenu(iClient)
{
SetGlobalTransTarget(iClient);
// decl String:sBuffer[128], Handle:hMenu;
new Handle:hMenu = CreateMenu(DuelMenu_Handler);
SetMenuExitBackButton(hMenu, false);
SetMenuExitButton(hMenu, true);
SetMenuTitle(hMenu, "Настройки дуэли\n ");
/*
FormatEx(sBuffer, sizeof(sBuffer), "%t", "Menu_T");
AddMenuItem(hMenu, "", sBuffer);
*/
switch(g_iInvitations[iClient])
{
case -1:
{
AddMenuItem(hMenu, "", "Всегда отказываться [ВКЛ]");
AddMenuItem(hMenu, "", "Всегда принимать", ITEMDRAW_DISABLED);
}
case 0:
{
AddMenuItem(hMenu, "", "Всегда отказываться [ВЫКЛ]");
AddMenuItem(hMenu, "", "Всегда принимать [ВЫКЛ]");
}
case 1:
{
AddMenuItem(hMenu, "", "Всегда отказываться", ITEMDRAW_DISABLED);
AddMenuItem(hMenu, "", "Всегда принимать [ВКЛ]");
}
}
DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
}
public DuelMenu_Handler(Handle:hMenu, MenuAction:action, iClient, Item)
{
switch(action)
{
case MenuAction_End: CloseHandle(hMenu);
case MenuAction_Select:
{
switch(Item)
{
case 0:
{
switch(g_iInvitations[iClient])
{
case -1:
{
g_iInvitations[iClient] = 0;
}
case 0:
{
g_iInvitations[iClient] = -1;
}
}
}
case 1:
{
switch(g_iInvitations[iClient])
{
case 1:
{
g_iInvitations[iClient] = 0;
}
case 0:
{
g_iInvitations[iClient] = 1;
}
}
}
}
decl String:sBuffer[4];
IntToString(g_iInvitations[iClient], sBuffer, sizeof(sBuffer));
SetClientCookie(iClient, g_hCookie, sBuffer);
DisplayDuelMenu(iClient);
}
}
}
public OnClientCookiesCached(iClient)
{
decl String:sBuffer[4];
GetClientCookie(iClient, g_hCookie, sBuffer, sizeof(sBuffer));
g_iInvitations[iClient] = StringToInt(sBuffer);
}
public Action:AdminDuel_CMD(iClient, iArgs)
{
if(iClient)
{
DisplayAdminDuelMenu(iClient);
}
return Plugin_Handled;
}
DisplayAdminDuelMenu(iClient)
{
SetGlobalTransTarget(iClient);
decl String:sBuffer[128], Handle:hMenu;
hMenu = CreateMenu(AdminDuelMenu_Handler);
SetMenuExitButton(hMenu, true);
SetMenuTitle(hMenu, "Настройки дуэли\n ");
/*
FormatEx(sBuffer, sizeof(sBuffer), "%t", "Menu_T");
AddMenuItem(hMenu, "", sBuffer);
*/
FormatEx(sBuffer, sizeof(sBuffer), "Активность плагина [%s]", g_bPluginActive ? "Вкл":"Выкл");
AddMenuItem(hMenu, "", sBuffer);
FormatEx(sBuffer, sizeof(sBuffer), "Выбор оружия [%s]", g_sDuelWeapon);
AddMenuItem(hMenu, "", sBuffer);
FormatEx(sBuffer, sizeof(sBuffer), "Тип брони [%s]", g_sArmorNames[g_iArmorType]);
AddMenuItem(hMenu, "", sBuffer);
AddMenuItem(hMenu, "", "Управление точками");
DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
}
public AdminDuelMenu_Handler(Handle:hMenu, MenuAction:action, iClient, Item)
{
switch(action)
{
case MenuAction_End: CloseHandle(hMenu);
case MenuAction_Select:
{
switch(Item)
{
case 0:
{
g_bPluginActive = !g_bPluginActive;
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, "plugin_settings"))
{
KvSetNum(g_hKeyValues, "plugin_active", g_bPluginActive);
}
if(g_bPluginActive && g_bHavePoints)
{
HookEvents();
}
else
{
CancelFight();
if(g_bHavePoints)
{
UnhookEvents();
}
}
DisplayAdminDuelMenu(iClient);
}
case 1:
{
DisplayWeaponsMenu(iClient);
}
case 2:
{
if(++g_iArmorType > sizeof(g_sArmorNames))
{
g_iArmorType = 0;
}
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, g_sMap, true))
{
KvSetNum(g_hKeyValues, "armor_type", g_iArmorType);
}
DisplayAdminDuelMenu(iClient);
}
case 3:
{
DisplayPointsMenu(iClient);
}
}
}
}
}
DisplayWeaponsMenu(iClient)
{
SetGlobalTransTarget(iClient);
decl String:sBuffer[128], Handle:hMenu;
hMenu = CreateMenu(WeaponsMenu_Handler);
SetMenuExitBackButton(hMenu, true);
SetMenuTitle(hMenu, "Настройки точек дуэли\n ");
/*
FormatEx(sBuffer, sizeof(sBuffer), "%t", "Menu_T");
AddMenuItem(hMenu, "", sBuffer);
*/
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, "plugin_settings") && KvJumpToKey(g_hKeyValues, "weapons") && KvGotoFirstSubKey(g_hKeyValues, false))
{
decl String:sWeapon[64];
do
{
KvGetSectionName(g_hKeyValues, sBuffer, sizeof(sBuffer));
KvGetString(g_hKeyValues, NULL_STRING, sWeapon, sizeof(sWeapon));
if(strcmp(g_sDuelWeapon, sWeapon) == 0)
{
StrCat(sBuffer, sizeof(sBuffer), " [X]");
AddMenuItem(hMenu, sWeapon, sBuffer, ITEMDRAW_DISABLED);
}
else
{
AddMenuItem(hMenu, sWeapon, sBuffer);
}
} while(KvGotoNextKey(g_hKeyValues, false));
}
DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
}
public WeaponsMenu_Handler(Handle:hMenu, MenuAction:action, iClient, Item)
{
switch(action)
{
case MenuAction_End: CloseHandle(hMenu);
case MenuAction_Cancel:
{
if(Item == MenuCancel_ExitBack)
{
DisplayAdminDuelMenu(iClient);
}
}
case MenuAction_Select:
{
GetMenuItem(hMenu, Item, g_sDuelWeapon, sizeof(g_sDuelWeapon));
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, g_sMap, true))
{
KvSetString(g_hKeyValues, "fight_weapon", g_sDuelWeapon);
}
DisplayAdminDuelMenu(iClient);
}
}
}
DisplayPointsMenu(iClient)
{
SetGlobalTransTarget(iClient);
// decl String:sBuffer[128], Handle:hMenu;
new Handle:hMenu = CreateMenu(PointsMenu_Handler);
SetMenuExitBackButton(hMenu, true);
SetMenuTitle(hMenu, "Настройки точек дуэли\n ");
/*
FormatEx(sBuffer, sizeof(sBuffer), "%t", "Menu_T");
AddMenuItem(hMenu, "", sBuffer);
*/
AddMenuItem(hMenu, "0", "Установить точку Т");
AddMenuItem(hMenu, "1", "Установить точку КТ");
if(!IsPointsClean())
{
AddMenuItem(hMenu, "2", "Сохранить точки");
}
if(g_bHavePoints)
{
AddMenuItem(hMenu, "3", "Удалить точки");
}
DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
}
public PointsMenu_Handler(Handle:hMenu, MenuAction:action, iClient, Item)
{
switch(action)
{
case MenuAction_End: CloseHandle(hMenu);
case MenuAction_Cancel:
{
if(Item == MenuCancel_ExitBack)
{
DisplayAdminDuelMenu(iClient);
}
}
case MenuAction_Select:
{
decl String:sItem[4];
GetMenuItem(hMenu, Item, sItem, sizeof(sItem));
switch(StringToInt(sItem))
{
case 2:
{
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, g_sMap, true))
{
KvSetVector(g_hKeyValues, "pos_1", g_fPos[0]);
KvSetVector(g_hKeyValues, "pos_2", g_fPos[1]);
KvSetVector(g_hKeyValues, "angles_1", g_fAngles[0]);
KvSetVector(g_hKeyValues, "angles_2", g_fAngles[1]);
KvRewind(g_hKeyValues);
KeyValuesToFile(g_hKeyValues, "addons/sourcemod/configs/weapon_fight.ini");
}
if(g_bPluginActive)
{
HookEvents();
}
g_bHavePoints = true;
}
case 3:
{
KvRewind(g_hKeyValues);
if(KvJumpToKey(g_hKeyValues, g_sMap))
{
g_bHavePoints = false;
KvDeleteThis(g_hKeyValues);
KvRewind(g_hKeyValues);
KeyValuesToFile(g_hKeyValues, "addons/sourcemod/configs/weapon_fight.ini");
UnhookEvents();
ResetPoints();
}
}
default:
{
if(IsPlayerAlive(iClient))
{
GetClientAbsOrigin(iClient, g_fPos[Item]);
GetClientEyeAngles(iClient, g_fAngles[Item]);
g_fPos[Item][2] += 20.0;
g_bHavePoints = true;
}
else
{
PrintToChat(iClient, "Вы должны быть живы!");
}
}
}
DisplayPointsMenu(iClient);
}
}
}
bool:IsPointsClean()
{
for(new i = 0, j; i < 2; ++i)
{
for(j = 0; j < 3; ++j)
{
if(g_fPos[i][j] != 0.0 && g_fAngles[i][j] != 0.0)
{
return false;
}
}
}
return true;
}
ResetPoints()
{
for(new i = 0, j; i < 2; ++i)
{
for(j = 0; j < 3; ++j)
{
g_fPos[i][j] = 0.0;
g_fAngles[i][j] = 0.0;
}
}
}