#pragma semicolon 1 #pragma newdecls required #include #include #include #include #include public Plugin myinfo = { name = "ZItemKnockback", author = "BotoX", description = "", version = "0.0", url = "" }; Handle hFireBulletDetour; int g_LastAttacker = 0; int g_LastVictim = 0; public void OnPluginStart() { Handle hGameData = LoadGameConfigFile("ZItemKnockback.games"); if(!hGameData) SetFailState("Failed to load ZItemKnockback gamedata."); hFireBulletDetour = DHookCreateFromConf(hGameData, "CCSPlayer__FireBullet"); if(!hFireBulletDetour) SetFailState("Failed to setup detour for CCSPlayer__FireBullet"); delete hGameData; if(!DHookEnableDetour(hFireBulletDetour, false, Detour_OnFireBullet)) SetFailState("Failed to detour CCSPlayer__FireBullet."); for(int client = 1; client <= MaxClients; client++) { if(IsClientInGame(client)) OnClientPutInServer(client); } } public void OnClientPutInServer(int client) { SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponEquip); } public Action OnWeaponEquip(int client, int entity) { if(!IsValidEntity(entity)) return; char sClassname[64]; GetEntityClassname(entity, sClassname, sizeof(sClassname)); if(strcmp(sClassname, "weapon_knife", false) != 0) return; int HammerID = GetEntProp(entity, Prop_Data, "m_iHammerID"); if(!HammerID) return; CheckChildren(client, entity); } void CheckChildren(int client, int parent) { int entity = INVALID_ENT_REFERENCE; while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) { if(GetEntPropEnt(entity, Prop_Data, "m_pParent") != parent) continue; char sClassname[64]; GetEntityClassname(entity, sClassname, sizeof(sClassname)); char sTargetname[64]; GetEntPropString(entity, Prop_Data, "m_iName", sTargetname, sizeof(sTargetname)); PrintToChatAll("%d child: \"%s\" %d (%s)", client, sClassname, entity, sTargetname); if(!strncmp(sClassname, "func_physbox", 12, false) || !strcmp(sClassname, "func_breakable", false)) { SDKHook(entity, SDKHook_OnTakeDamage, OnTakeDamage); PrintToChatAll("Hooking \"%s\" %d (%s) OnTakeDamage", sClassname, entity, sTargetname); } else if(!strcmp(sClassname, "trigger_push", false)) { AcceptEntityInput(entity, "Kill"); PrintToChatAll("Killing \"%s\" %d (%s)", sClassname, entity, sTargetname); } else { CheckChildren(client, entity); } } } public MRESReturn Detour_OnFireBullet(int pThis, Handle hParams) { PrintToServer("OnFireBullet called on entity %d!", pThis); g_LastAttacker = 0; g_LastVictim = 0; return MRES_Handled; } public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3]) { PrintToChatAll("OnTakeDamage(%d, %d, %d, %f, %d, %d)", victim, attacker, inflictor, damage, damagetype, weapon); if(attacker <= 0 || attacker > MAXPLAYERS) return Plugin_Continue; int client = victim; while((client = GetEntPropEnt(client, Prop_Data, "m_pParent")) != INVALID_ENT_REFERENCE) { if(client >= 1 && client <= MAXPLAYERS) break; } PrintToChatAll("\tclient = %d", client); if(client <= 0) return Plugin_Handled; // TODO: Fix for knife if(g_LastAttacker == attacker && g_LastVictim == client) return Plugin_Handled; g_LastAttacker = attacker; g_LastVictim = client; victim = client; PrintToChatAll("\tvictim = %d", victim); SDKHooks_TakeDamage(victim, inflictor, attacker, damage, damagetype, weapon, damageForce, damagePosition); return Plugin_Handled; }