Raised This Month: $207 Target: $400
 51% 

Solved [L4D2] Witch target override in better way?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
HarryPotter
Senior Member
Join Date: Sep 2017
Location: TW
Old 12-27-2020 , 23:00   [L4D2] Witch target override in better way?
Reply With Quote #1

As the title says, I need a function like this
PHP Code:

//entitiy: witch
//client: a target that witch will chase 
//return true if succeed, return false if can't change witch target

bool WitchAttackTargetint entityint client
Change target when the witch incapacitates or kills victim,
I know some plugins already did this before, but there are still some problems.

Example:
1. [L4D & L4D2] Evil Witch
Spawns a new witch and give a hurt point. I think that is not good.

2. [L4D2] Relentless Witch
He uses signature "@_ZN8Infected15OnHitByVomitJarEP20CBaseComba tCharacter" on witch, but the director will call a horde.

Edit:
Thanks BHaType, xZk, cravenge and silvers, I write code here for myself
__________________

Last edited by HarryPotter; 01-10-2021 at 10:53. Reason: see solution
HarryPotter is offline
Marttt
Veteran Member
Join Date: Jan 2019
Location: Brazil
Old 12-28-2020 , 01:23   Re: [L4D2] Witch target override in better way?
Reply With Quote #2

Is not exactly what you asked...

Maybe you can force the target with CommandABot

Usually, we use that for bots (clients) (Scavenge Bots use this, I think).

I have never seen a plugin to common infected/witch.

Didn't test but here are some examples.

https://gist.github.com/Rectus/8d760...c5ce378ed09264 (steamworkshop source)

https://github.com/search?q=commanda...3Asp&type=code
__________________

Last edited by Marttt; 12-28-2020 at 01:26.
Marttt is online now
BHaType
Great Tester of Whatever
Join Date: Jun 2018
Location: Methamphetamine
Old 12-28-2020 , 04:27   Re: [L4D2] Witch target override in better way?
Reply With Quote #3

My old practices, they work but as far as I remember the server will crash if you change the target when the witch is not scared yet

You can also literally change the target to any entity and patch the WitchAttack::IsValidEnemy function so the witch can run after anyone and not just survivors

Spoiler


Note:
If this still works then I might try to make a more advanced version and this is for windows only
__________________
Heart
cry

Last edited by BHaType; 12-28-2020 at 04:29.
BHaType is offline
Send a message via AIM to BHaType
HarryPotter
Senior Member
Join Date: Sep 2017
Location: TW
Old 12-28-2020 , 05:27   Re: [L4D2] Witch target override in better way?
Reply With Quote #4

I will give a try and report
__________________
HarryPotter is offline
HarryPotter
Senior Member
Join Date: Sep 2017
Location: TW
Old 12-28-2020 , 08:45   Re: [L4D2] Witch target override in better way?
Reply With Quote #5

Quote:
Originally Posted by BHaType View Post
Note:
If this still works then I might try to make a more advanced version and this is for windows only
I just tested,
Everything works fine in windows server,
no crash, no wired behavior.

I just have a little wish,
It could be better if we can force witch to attack another target again even after witch had lost her target or killed survivor already.
__________________

Last edited by HarryPotter; 12-28-2020 at 09:27.
HarryPotter is offline
larrybrains
Senior Member
Join Date: May 2017
Old 12-29-2020 , 23:47   Re: [L4D2] Witch target override in better way?
Reply With Quote #6

Quote:
Originally Posted by BHaType View Post
If this still works then I might try to make a more advanced version and this is for windows only
Would love to see a Linux version of this.
larrybrains is offline
xZk
Senior Member
Join Date: Nov 2017
Location: cl
Old 01-02-2021 , 21:15   Re: [L4D2] Witch target override in better way?
Reply With Quote #7

ago I was looking for something like that, and maybe this can be useful when the witch loses her objective, but I think it only works for survivors :/:
PHP Code:
stock void WitchChangeTarget(int witchint target)
{
    
//PrintToChatAll("attacking target %N", target);
    
if(GetEntProp(witchProp_Send"m_bIsBurning") == 1){
        
ExtinguishEntity(witch);
        
SDKHooks_TakeDamage(witchtargettarget0.0DMG_BURN);
    }else{
        
int anim GetEntProp(witchProp_Send"m_nSequence");
        
SDKHooks_TakeDamage(witchtargettarget0.0DMG_BURN);
        
SetEntProp(witchProp_Send"m_nSequence"anim);
        
SetVariantFloat(0.0);
        
AcceptEntityInput(witch"IgniteLifetime");
        
//ExtinguishEntity(witch);// no works
        
SetEntProp(witchProp_Send"m_bIsBurning"0);
        
int ent GetEntPropEnt(witchProp_Data"m_hMoveChild");
        if(
IsValidEnt(ent)){
            
char classname[32];
            
GetEntityClassname(entclassnamesizeof(classname));
            if(
strcmp(classname"entityflame") == 0){
                
SDKHook(entSDKHook_SetTransmitSetTransmit_Fire);
            }
        }
    }
}

public 
Action SetTransmit_Fire(int entityint client)
{
    return 
Plugin_Handled;

xZk is offline
HarryPotter
Senior Member
Join Date: Sep 2017
Location: TW
Old 01-04-2021 , 22:30   Re: [L4D2] Witch target override in better way?
Reply With Quote #8

Quote:
Originally Posted by xZk View Post
ago I was looking for something like that, and maybe this can be useful when the witch loses her objective, but I think it only works for survivors :/:
Working for survivors is enough to me, I will give a try
__________________
HarryPotter is offline
HarryPotter
Senior Member
Join Date: Sep 2017
Location: TW
Old 01-10-2021 , 08:21   Re: [L4D2] Witch target override in better way?
Reply With Quote #9

Thanks BHaType, xZk, cravenge and silvers, I write a script for myself

Witch target override Improved version 1.1 [2021/1/10]
Change target when the witch incapacitates or kills victim

apply to:
L4D1/2

-ConVar-
Spoiler


Code:
PHP Code:
#pragma newdecls required
#define PLUGIN_VERSION "1.1"

#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#define DEBUG 0
#define L4D_TEAM_SPECTATOR        1
#define L4D_TEAM_SURVIVORS         2
#define L4D_TEAM_INFECTED         3

public Plugin myinfo 
{
    
name "Witch Target Override",
    
author "xZk, BHaType, HarryPotter",
    
description "witch target override in better way.",
    
version PLUGIN_VERSION,
    
url "https://steamcommunity.com/id/HarryPotter_TW/"
};

ConVar g_hCvarAllowg_hCvarIncapOverrideg_hCvarKillOverride,
    
g_hCvarIncapOverrideHealthg_hCvarKillOverrideHealthg_hRequiredRange;
int g_iCvarIncapOverrideHealthg_iCvarKillOverrideHealth;
bool g_bCvarAllowg_bCvarIncapOverrideg_bCvarKillOverride;
float g_fRequiredRange;

public 
void OnPluginStart()
{
    
g_hCvarAllow CreateConVar("witch_target_override_on""1""1=Plugin On. 0=Plugin Off"FCVAR_NOTIFYtrue0.0true1.0);
    
g_hCvarIncapOverride CreateConVar("witch_target_override_incap""1""If 1, allow witch to chased another target after she incapacitated a survivor."FCVAR_NOTIFYtrue0.0true1.0);
    
g_hCvarKillOverride CreateConVar("witch_target_override_kill""1""If 1, allow witch to chased another target after she killed a survivor."FCVAR_NOTIFYtrue0.0true1.0);
    
g_hCvarIncapOverrideHealth CreateConVar("witch_target_override_incap_health""0""Set witch health if she is allowed to chased another target after she incapacitated a survivor. (0=Off)"FCVAR_NOTIFYtrue0.0true9999.0);
    
g_hCvarKillOverrideHealth CreateConVar("witch_target_override_kill_health""1000""Set witch health if she is allowed to chased chased another target after she killed a survivor. (0=Off)"FCVAR_NOTIFYtrue0.0true9999.0);
    
g_hRequiredRange CreateConVar("witch_target_override_range""9999""This controls the range for witch to reacquire another target. (If no targets within range, witch default behavior)"FCVAR_NOTIFYtrue0.0true9999.0);

    
GetCvars();
    
g_hCvarAllow.AddChangeHook(ConVarChanged_Cvars);
    
g_hCvarIncapOverride.AddChangeHook(ConVarChanged_Cvars);
    
g_hCvarKillOverride.AddChangeHook(ConVarChanged_Cvars);
    
g_hCvarIncapOverrideHealth.AddChangeHook(ConVarChanged_Cvars);
    
g_hCvarKillOverrideHealth.AddChangeHook(ConVarChanged_Cvars);
    
g_hRequiredRange.AddChangeHook(ConVarChanged_Cvars);

    
#if DEBUG
        
RegConsoleCmd("sm_test"sm_insult);
    
#endif

    
HookEvent("player_incapacitated"Player_Incapacitated);
    
HookEvent("player_death"Player_Death);

    
//Autoconfig for plugin
    
AutoExecConfig(true"witch_target_override");
}

public 
void ConVarChanged_Cvars(ConVar convar, const char[] oldValue, const char[] newValue)
{
    
GetCvars();
}

void GetCvars()
{
    
g_bCvarAllow g_hCvarAllow.BoolValue;
    
g_bCvarIncapOverride g_hCvarIncapOverride.BoolValue;
    
g_bCvarKillOverride g_hCvarKillOverride.BoolValue;
    
g_iCvarIncapOverrideHealth g_hCvarIncapOverrideHealth.IntValue;
    
g_iCvarKillOverrideHealth g_hCvarKillOverrideHealth.IntValue;
    
g_fRequiredRange g_hRequiredRange.FloatValue;
}

public 
Action sm_insult int clientint args )
{
    if(
client == || g_bCvarAllow == false) return Plugin_Handled;

    
int target GetClientAimTarget(client);
    
    if ( 
target == -)
        return 
Plugin_Handled;

    
int witch MaxClients 1;

    while ( (
witch FindEntityByClassname(witch"witch")) && IsValidEntity(witch) )
    {
        
WitchAttackTarget(witchtarget0);
    }

    return 
Plugin_Handled;
}

public 
Action Player_Incapacitated(Event event, const char[] event_namebool dontBroadcast)
{
    if(
g_bCvarAllow == false || g_bCvarIncapOverride == false) return;

    
int victim GetClientOfUserId(event.GetInt("userid"));
    
int entity event.GetInt("attackerentid");
    if (
IsWitch(entity) && victim && victim <= MaxClients && IsSurvivor(victim))
    {
        
int target GetNearestSurvivorDist(entity);
        if(
target == 0) return;

        
WitchAttackTarget(entitytargetg_iCvarIncapOverrideHealth);
    }
}

public 
Action Player_Death(Event event, const char[] event_namebool dontBroadcast)
{
    if(
g_bCvarAllow == false || g_bCvarKillOverride == false ) return;

    
int victim GetClientOfUserId(event.GetInt("userid"));
    
int entity event.GetInt("attackerentid");
    if (
IsWitch(entity) && victim && victim <= MaxClients && IsSurvivor(victim))
    {
        
int target GetNearestSurvivorDist(entity);
        if(
target == 0) return;

        
WitchAttackTarget(entitytargetg_iCvarKillOverrideHealth);
    }
}

stock void WitchAttackTarget(int witchint targetint newHealth)
{

    if(
GetEntProp(witchProp_Data"m_iHealth") < 0) return;
    
#if DEBUG
        
PrintToChatAll("witch attacking new target %N, her max health: %d, now health: %d"targetGetEntProp(witchProp_Data"m_iMaxHealth"), GetEntProp(witchProp_Data"m_iHealth"));
    
#endif

    
if(newHealth 0SetEntProp(witchProp_Data"m_iHealth"newHealth);

    if(
GetEntProp(witchProp_Send"m_bIsBurning") == 1)
    {
        
ExtinguishEntity(witch);
        
int flame GetEntPropEnt(witchProp_Send"m_hEffectEntity");
        if( 
flame != -)
        {
            
AcceptEntityInput(flame"Kill");
        }

        
SDKHooks_TakeDamage(witchtargettarget0.0DMG_BURN);
    }
    else
    {
        
int anim GetEntProp(witchProp_Send"m_nSequence");
        
SDKHooks_TakeDamage(witchtargettarget0.0DMG_BURN);
        
SetEntProp(witchProp_Send"m_nSequence"anim);
        
SetEntProp(witchProp_Send"m_bIsBurning"0);
        
SDKHook(witchSDKHook_ThinkPostPostThink);
    }
}

public 
void PostThink(int witch)
{
    
SDKUnhook(witchSDKHook_ThinkPostPostThink);

    
ExtinguishEntity(witch);

    
int flame GetEntPropEnt(witchProp_Send"m_hEffectEntity");
    if( 
flame != -)
    {
        
AcceptEntityInput(flame"Kill");
    }
}

int GetNearestSurvivorDist(int entity)
{
    
int target 0IncapTarget0;
    
float s_fRequiredRange Pow (g_fRequiredRange2.0);
    
float Origin[3], TOrigin[3], distance 0.0;
    
float fMinDistance 0.0fMinIncapDistance 0.0;
    
GetEntPropVector(entityProp_Send"m_vecOrigin"Origin);
    for (
int i 1<= MaxClientsi++)
    {
        if (
IsSurvivor(i) && IsPlayerAlive(i))
        {
            
GetEntPropVector(iProp_Send"m_vecOrigin"TOrigin);
            
distance GetVectorDistance(OriginTOrigintrue);
            if (
s_fRequiredRange >= distance)
            {
                if(
IsPlayerIncapOrHanging(i))
                {
                    if (
fMinIncapDistance == 0.0 || fMinIncapDistance distance)
                    {
                        
fMinIncapDistance distance;
                        
IncapTarget i;
                    } 
                }
                else
                {
                    if (
fMinDistance == 0.0 || fMinDistance distance)
                    {
                        
fMinDistance distance;
                        
target i;
                    } 
                }
            }
        }
    }

    if(
target == 0) return IncapTarget;

    return 
target;
}

bool IsWitch(int entity)
{
    if (
entity MaxClients && IsValidEntity(entity))
    {
        static 
char classname[16];
        
GetEdictClassname(entityclassnamesizeof(classname));
        if (
strcmp(classname"witch"false) == 0)
            return 
true;
    }
    return 
false;
}

bool IsSurvivor(int client)
{
    if (
IsClientInGame(client) && GetClientTeam(client) == L4D_TEAM_SURVIVORS)
    {
        return 
true;
    }
    return 
false;   
}


bool IsPlayerIncapOrHanging(int client)
{
    if (
GetEntProp(clientProp_Send"m_isIncapacitated")) 
        return 
true;
    if (
GetEntProp(clientProp_Send"m_isHangingFromLedge"))
        return 
true;

    return 
false;

__________________

Last edited by HarryPotter; 01-10-2021 at 10:55.
HarryPotter is offline
cravenge
Veteran Member
Join Date: Nov 2015
Location: Middle of Nowhere
Old 01-10-2021 , 09:47   Re: [L4D2] Witch target override in better way?
Reply With Quote #10

You might improve the method on completely removing the fire from the Witch. You could take a look at the Bots Trigger Witch plugin by Silvers.
__________________
cravenge is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:53.


Powered by vBulletin®
Copyright ©2000 - 2021, vBulletin Solutions, Inc.
Theme made by Freecode