View Single Post
cravenge
Veteran Member
Join Date: Nov 2015
Location: Chocolate Factory
Old 10-28-2016 , 01:13   Re: [L4D2] Register extra Actions on GameME plugin
Reply With Quote #8

How about this?

PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>

#define PLUGIN_VERSION "1.2"

#define TEAM_INFECTED 3
#define CLASS_CHARGER 6

#define PROP_CAR (1<<0)
#define PROP_CAR_ALARM (1<<1)
#define PROP_CONTAINER (1<<2)
#define PROP_TRUCK (1<<3)

#define PUSH_COUNT "m_iHealth"

new Handle:g_h_CvarChargerPowerHandle:g_h_CvarChargerCarryHandle:g_h_CvarMessageTypeHandle:g_h_CvarObjectsHandle:g_h_CvarPushLimitHandle:g_h_CvarRemoveObject,
    
Handle:g_h_CvarChargerDamage,
        
i_Owner[2048+1]; // to store the entities' owner

public Plugin:myinfo 
{
    
name "[L4D2] Super Charge",
    
author "DJ_WEST, cravenge",
    
description "Provides Chargers To Move Cars With Ability.",
    
version PLUGIN_VERSION,
    
url "http://amx-x.ru"
};

public 
OnPluginStart()
{
    
decl String:s_Game[12], Handle:h_Version;
    
    
GetGameFolderName(s_Gamesizeof(s_Game));
    if (!
StrEqual(s_Game"left4dead2"))
    {
        
SetFailState("[SM] Plugin Supports L4D2 Only!");
    }
    
    
LoadTranslations("super_charge-l4d2.phrases");
    
    
h_Version CreateConVar("super_charge-l4d2_version"PLUGIN_VERSION"Super Charge Version"FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
    
g_h_CvarChargerPower CreateConVar("super_charge-l4d2""750.0""Power Applied To Super Charge"FCVAR_NOTIFYtrue0.0true5000.0);
    
g_h_CvarChargerCarry CreateConVar("super_charge-l4d2_carry""1""Enable/Disable Super Charge If Carrying"FCVAR_NOTIFYtrue0.0true1.0);
    
g_h_CvarMessageType CreateConVar("super_charge-l4d2_message_type""3""Notification Type: 0=Disable, 1=Chat Text, 2=Hint Box, 3=Instructor Hint"FCVAR_NOTIFYtrue0.0true3.0);
    
g_h_CvarObjects CreateConVar("super_charge-l4d2_objects""7""Objects: 1=Cars, 2=Car Alarms, 4=Containers, 8=Truck"FCVAR_NOTIFYtrue1.0true15.0);
    
g_h_CvarPushLimit CreateConVar("super_charge-l4d2_push_limit""10""Super Charge Push Limit"FCVAR_NOTIFYtrue1.0true100.0);
    
g_h_CvarRemoveObject CreateConVar("super_charge-l4d2_remove""30""Delay Before Charged Objects Disappear"FCVAR_NOTIFYtrue0.0true100.0);
    
g_h_CvarChargerDamage CreateConVar("super_charge-l4d2_damage""10""Damage Applied To Charger"FCVAR_NOTIFYtrue0.0true100.0);

    
HookEvent("charger_charge_end"OnChargerChargeEnd);
    
HookEvent("player_spawn"OnPlayerSpawn);
    
    
SetConVarString(h_VersionPLUGIN_VERSION);
}

public 
OnClientPostAdminCheck(client)
{
        
SDKHook(clientSDKHook_OnTakeDamageOnTakeDamage); // Gotcha, damage!!
}

public 
Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damageType)
{
    if (
victim <= || victim MaxClients || !IsClientInGame(victim) || GetClientTeam(victim) != || !IsPlayerAlive(victim))
    {
        return 
Plugin_Continue;
    }
    
    if (
inflictor <= || !IsValidEntity(inflictor) || !IsValidEdict(inflictor))
    {
        return 
Plugin_Continue;
    }
    
    
decl String:sClass[64];
    
GetEdictClassname(inflictorsClasssizeof(sClass));
    if (
StrEqual(sClass"prop_physics") || StrEqual(sClass"prop_car_alarm"))
    {
                new 
charger CheckForChargers();
        if (
i_Owner[inflictor] == charger// since the game never makes the charger the attacker, we force it to do so.
                
{
                        new 
realDmg RoundToZero(damage); // we convert the damage from float to int.
                        
                        
new Handle:OnPlayerHurt CreateEvent("player_hurt"true); // because the event we created is not being hooked so it's true, otherwise it's false
                        
SetEventInt(OnPlayerHurt"userid"GetClientUserId(victim));
                        
SetEventInt(OnPlayerHurt"attacker"GetClientUserId(charger));
                        
SetEventInt(OnPlayerHurt"dmg_health"realDmg); // record the damage
                        
SetEventString(OnPlayerHurt"weapon"inflictor); // make the entities the weapon that the charger used to attack
                        
FireEvent(OnPlayerHurtfalse);
                        
                        new 
Handle:incapFix CreateDataPack();
                        
WritePackCell(incapFixGetClientUserId(victim));
                        
WritePackCell(incapFixGetClientUserId(charger));
                        
CreateTimer(1.0CheckForIncapsincapFixTIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT|TIMER_DATA_HNDL_CLOSE); // we create a repeating timer to check the victim's state, if this returns errors, just use CreateDataTimer instead.
                        
                        
return Plugin_Changed;
                }
    }
    
    return 
Plugin_Continue;
}

public 
Action:CheckForIncaps(Handle:timerHandle:incapFix)
{
        
ResetPack(incapFix);
        
        new 
client GetClientOfUserId(ReadPackCell(incapFix));
        if (
client <= || !IsClientInGame(client) || GetClientTeam(client) != || !IsPlayerAlive(client) || !IsPlayerIncapped(client))
        {
                return 
Plugin_Continue;
        }
        
        new 
attacker GetClientOfUserId(ReadPackCell(incapFix));
        if (
attacker <= || !IsClientInGame(attacker) || GetClientTeam(attacker) != TEAM_INFECTED || GetEntProp(attackerProp_Send"m_zombieClass") != CLASS_CHARGER)
        {
                return 
Plugin_Continue;
        }
        
        new 
Handle:OnPlayerIncapacitated CreateEvent("player_incapacitated"true);
        
SetEventInt(OnPlayerIncapacitated"userid"GetClientUserId(client));
        
SetEventInt(OnPlayerIncapacitated"attacker"GetClientUserId(attacker));
        
FireEvent(OnPlayerIncapacitatedfalse);
        
        return 
Plugin_Stop;
}

CheckForChargers()
{
        new 
count 0;
        for (new 
1<= MaxClientsi++)
        {
                if (
IsClientInGame(i) && GetClientTeam(i) == TEAM_INFECTED && GetEntProp(iProp_Send"m_zombieClass") == CLASS_CHARGER)
                {
                        
count++;
                }
        }
        return 
count;
}

stock bool:IsPlayerIncapped(client)
{
        if (
GetEntProp(clientProp_Send"m_isIncapacitated"1))
        {
                return 
true;
        }
        return 
false;
}

public 
Action:OnChargerChargeEnd(Handle:h_Event, const String:s_Name[], bool:b_DontBroadcast)
{
    
decl i_UserIDi_ClientFloat:f_Origin[3], Float:f_Angles[3], Float:f_EndOrigin[3], Float:f_Velocity[3],
        
Handle:h_TraceHandle:h_Packi_TargetString:s_ClassName[16], Float:f_PowerString:s_ModelName[64],
        
i_Typei_PushCounti_Healthi_Damagei_RemoveTime;
    
    
i_UserID GetEventInt(h_Event"userid");
    
i_Client GetClientOfUserId(i_UserID);
    if (!
i_Client || !IsClientInGame(i_Client) || GetClientTeam(i_Client) != || GetInfectedClass(i_Client) != CLASS_CHARGER)
    {
        return 
Plugin_Continue;
    }
    
    if (!
GetConVarInt(g_h_CvarChargerCarry) && GetEntProp(i_ClientProp_Send"m_carryVictim") > 0)
    {
        return 
Plugin_Continue;
    }
    
    
GetClientAbsOrigin(i_Clientf_Origin);
    
GetClientAbsAngles(i_Clientf_Angles);
    
f_Origin[2] += 20.0;
    
    
h_Trace TR_TraceRayFilterEx(f_Originf_AnglesMASK_ALLRayType_InfiniteTraceFilterClientsi_Client);
    
    if (
TR_DidHit(h_Trace))
    {
        
i_Target TR_GetEntityIndex(h_Trace);
        
TR_GetEndPosition(f_EndOriginh_Trace);
        
        if (
i_Target && IsValidEdict(i_Target) && GetVectorDistance(f_Originf_EndOrigin) <= 100.0)
        {
            if (
GetEntityMoveType(i_Target) != MOVETYPE_VPHYSICS)
            {
                return 
Plugin_Continue;
            }
            
            
i_PushCount GetEntProp(i_TargetProp_DataPUSH_COUNT);
            if (
i_PushCount >= GetConVarInt(g_h_CvarPushLimit))
            {
                return 
Plugin_Continue;
            }
            
            
i_Type GetConVarInt(g_h_CvarObjects);
            
            
GetEdictClassname(i_Targets_ClassNamesizeof(s_ClassName));
            
GetEntPropString(i_TargetProp_Data"m_ModelName"s_ModelNamesizeof(s_ModelName));
            
            if(
StrEqual(s_ClassName"prop_car_alarm") && !(i_Type PROP_CAR_ALARM))
            {
                return 
Plugin_Continue;
            }
            else if (
StrEqual(s_ClassName"prop_physics"))
            {
                if ((
StrContains(s_ModelName"car") != -&& !(i_Type PROP_CAR) && !(i_Type PROP_CAR_ALARM)) || (StrContains(s_ModelName"dumpster") != -&& !(i_Type PROP_CONTAINER)) || (StrContains(s_ModelName"forklift") != -&& !(i_Type PROP_TRUCK)))
                {
                    return 
Plugin_Continue;
                }
            }
            
            
i_PushCount++;
            
SetEntProp(i_TargetProp_DataPUSH_COUNTi_PushCount);
            
            
GetAngleVectors(f_Anglesf_VelocityNULL_VECTORNULL_VECTOR);
                        
            
f_Power GetConVarFloat(g_h_CvarChargerPower);
            
f_Velocity[0] *= f_Power;
            
f_Velocity[1] *= f_Power;
            
f_Velocity[2] *= f_Power;
                        
            
TeleportEntity(i_TargetNULL_VECTORNULL_VECTORf_Velocity);
                        
                        
i_Owner[i_Target] = i_Client// make the charger the owner of the entity.
                        
CreateTimer(3.0ResetOwneri_Target); // reset the entity's owner.
            
            
h_Pack CreateDataPack();
            
WritePackCell(h_Packi_Target);
            
WritePackFloat(h_Packf_EndOrigin[0]);
            
CreateTimer(0.5CheckEntityh_Pack);
            
            
i_Damage GetConVarInt(g_h_CvarChargerDamage);
            if (
i_Damage)
            {
                
i_Health GetClientHealth(i_Client);
                
i_Health -= i_Damage;
                if (
i_Health 0
                {
                    
SetEntityHealth(i_Clienti_Health);
                }
                else
                {
                    
ForcePlayerSuicide(i_Client);
                }
            }
            
            
i_RemoveTime GetConVarInt(g_h_CvarRemoveObject);
            if (
i_RemoveTime)
            {
                
CreateTimer(float(i_RemoveTime), RemoveEntityi_TargetTIMER_FLAG_NO_MAPCHANGE);
            }
        }
    }
    
    return 
Plugin_Continue;
}

public 
Action:ResetOwner(Handle:timerany:ent)
{
        
i_Owner[ent] = 0// no matter if said entity was removed, just reset its owner to prevent bugs.
        
return Plugin_Stop;
}

public 
Action:RemoveEntity(Handle:h_Timerany:i_Ent)
{
    if (
i_Ent && IsValidEnt(i_Ent))
    {
        
RemoveEdict(i_Ent);
    }
    
    return 
Plugin_Stop;
}

public 
bool:TraceFilterClients(i_Entityi_Maskany:i_Data)
{
    if (
i_Entity == i_Data)
    {
        return 
false;
    }
    
    if (
<= i_Entity <= MaxClients)
    {
        return 
false;
    }
    
    return 
true;
}

public 
Action:CheckEntity(Handle:h_TimerHandle:h_Pack)
{
    
decl i_EntFloat:f_Origin[3], Float:f_LastOriginHandle:h_NewPack;
    
    
ResetPack(h_Packfalse);
    
i_Ent ReadPackCell(h_Pack);
    
f_LastOrigin ReadPackFloat(h_Pack);
    
CloseHandle(h_Pack);
    
    if (
i_Ent && IsValidEnt(i_Ent))
    {
        
GetEntPropVector(i_EntProp_Data"m_vecOrigin"f_Origin);
        
        if (
f_Origin[0] != f_LastOrigin)
        {
            
h_NewPack CreateDataPack();
            
WritePackCell(h_NewPacki_Ent);
            
WritePackFloat(h_NewPackf_Origin[0]);
            
CreateTimer(0.1CheckEntityh_NewPack);
        }
        else
        {
            
TeleportEntity(i_EntNULL_VECTORNULL_VECTORFloat:{0.00.00.0});
        }
    }
    
    return 
Plugin_Stop;
}

public 
Action:OnPlayerSpawn(Handle:h_Event, const String:s_Name[], bool:b_DontBroadcast)
{
    
decl i_UserIDi_ClientHandle:h_Pack;
    
    
i_UserID GetEventInt(h_Event"userid");
    
i_Client GetClientOfUserId(i_UserID);
    if (
i_Client && IsClientInGame(i_Client) && GetClientTeam(i_Client) == TEAM_INFECTED && GetInfectedClass(i_Client) == CLASS_CHARGER  && !IsFakeClient(i_Client))
    {
        
h_Pack CreateDataPack();
        
WritePackCell(h_Packi_Client);
        
WritePackString(h_Pack"Move objects");
        
WritePackString(h_Pack"+attack");
        
CreateTimer(0.1DisplayHinth_Pack);
    }
}

public 
Action:DisplayHint(Handle:h_TimerHandle:h_Pack)
{
    
decl i_Client;
    
    
ResetPack(h_Packfalse);
    
i_Client ReadPackCell(h_Pack);
    
    if (
GetConVarInt(g_h_CvarMessageType) == && IsClientInGame(i_Client))
    {
        
ClientCommand(i_Client"gameinstructor_enable 1");
    }
    
    
CreateTimer(0.3DelayDisplayHinth_Pack);
    
    return 
Plugin_Stop;
}

public 
Action:DelayDisplayHint(Handle:h_TimerHandle:h_Pack)
{
    
decl i_ClientString:s_LanguageKey[16], String:s_Message[256], String:s_Bind[10];

    
ResetPack(h_Packfalse);
    
i_Client ReadPackCell(h_Pack);
    
ReadPackString(h_Packs_LanguageKeysizeof(s_LanguageKey));
    
ReadPackString(h_Packs_Bindsizeof(s_Bind));
    
CloseHandle(h_Pack);
    
    switch (
GetConVarInt(g_h_CvarMessageType))
    {
        case 
1:
        {
            
FormatEx(s_Messagesizeof(s_Message), "\x03[%t]\x01 %t.""Information"s_LanguageKey);
            
ReplaceString(s_Messagesizeof(s_Message), "\n"" ");
            
PrintToChat(i_Clients_Message);
        }
        case 
2PrintHintText(i_Client"%t"s_LanguageKey);
        case 
3:
        {
            
FormatEx(s_Messagesizeof(s_Message), "%t"s_LanguageKey);
            
DisplayInstructorHint(i_Clients_Messages_Bind);
        }
    }
    
    return 
Plugin_Stop;
}

public 
DisplayInstructorHint(i_ClientString:s_Message[256], String:s_Bind[])
{
    
decl i_EntString:s_TargetName[32], Handle:h_RemovePack;
    
    
i_Ent CreateEntityByName("env_instructor_hint");
    
FormatEx(s_TargetNamesizeof(s_TargetName), "hint%d"i_Client);
    
ReplaceString(s_Messagesizeof(s_Message), "\n"" ");
    
DispatchKeyValue(i_Client"targetname"s_TargetName);
    
DispatchKeyValue(i_Ent"hint_target"s_TargetName);
    
DispatchKeyValue(i_Ent"hint_timeout""5");
    
DispatchKeyValue(i_Ent"hint_range""0.01");
    
DispatchKeyValue(i_Ent"hint_color""255 255 255");
    
DispatchKeyValue(i_Ent"hint_icon_onscreen""use_binding");
    
DispatchKeyValue(i_Ent"hint_caption"s_Message);
    
DispatchKeyValue(i_Ent"hint_binding"s_Bind);
    
DispatchSpawn(i_Ent);
    
AcceptEntityInput(i_Ent"ShowHint");
    
    
h_RemovePack CreateDataPack();
    
WritePackCell(h_RemovePacki_Client);
    
WritePackCell(h_RemovePacki_Ent);
    
CreateTimer(5.0RemoveInstructorHinth_RemovePack);
}
    
public 
Action:RemoveInstructorHint(Handle:h_TimerHandle:h_Pack)
{
    
decl i_Enti_Client;
    
    
ResetPack(h_Packfalse);
    
i_Client ReadPackCell(h_Pack);
    
i_Ent ReadPackCell(h_Pack);
    
CloseHandle(h_Pack);
    
    if (!
i_Client || !IsClientInGame(i_Client) || GetClientTeam(i_Client) != TEAM_INFECTED || GetInfectedClass(i_Client) != CLASS_CHARGER)
    {
        return 
Plugin_Stop;
    }
    
    if (
i_Ent && IsValidEnt(i_Ent))
    {
        
RemoveEdict(i_Ent);
    }
    
    
ClientCommand(i_Client"gameinstructor_enable 0");
    
DispatchKeyValue(i_Client"targetname""");
    
    return 
Plugin_Stop;
}

stock GetInfectedClass(i_Client)
{
    return 
GetEntProp(i_ClientProp_Send"m_zombieClass");
}
    
stock IsValidEnt(i_Ent)
{
    return (
IsValidEdict(i_Ent) && IsValidEntity(i_Ent));


Last edited by cravenge; 10-29-2016 at 00:49.
cravenge is offline