Senior Member
Join Date: Jan 2014
Location: Puerto Rico
|
09-11-2017
, 07:58
Re: [L4D2] Incapped Crawling with Animation (1.33) [25-Jun-2017]
|
#181
|
Quote:
Originally Posted by Lux
Hi i been searching for a way to add the crawling anim directly, this is how far i came,
however the client crawling can see the crawl anim but the other clients can just see sliding not sure how to go from here.
Maybe someone else has a better way to work on it.
|
You could use the old Dynamic Hooks Survivor Animation Fix pack plugin I made a while back as a base, just grab the gamedata if it hasn't broken that is), since the plugin hijacks the m_SetSequence function meaning you can actually force the animation of your choosing, however this poses the problem that the survivor's model orientation will not match the view orientation with the crawl animations, dunno how to fix that.
Here's an example I made, a long time ago, you need to have Dynamic Hooks for this to work obv, and the gamedata from the linked plugin, also note that since this was written a long time ago it was written on sm 1.7 I believe? So I don't know how much the current compiler will like this;
Spoiler
PHP Code:
#include <sourcemod>
#include <dhooks>
#include <sdktools>
new Handle:sdkDoAnim;
new Handle:hSequenceSet;
static clienthook[MAXPLAYERS + 1] = -1;
public Plugin:myinfo =
{
name = "[L4D2] Survivor Incap Crawling",
author = "DeathChaos25",
description = "Incap crawling while actually forcing the animation onto the model",
version = "1.0",
url = ""
}
public OnPluginStart()
{
PrepSDKCall();
SetConVarInt(FindConVar("survivor_allow_crawling"), 1);
SetConVarInt(FindConVar("survivor_crawl_speed"), 35);
LoadOffset();
}
public MRESReturn:OnSequenceSet(pThis, Handle:hReturn, Handle:hParams)
{
new client = pThis;
if (IsSurvivor(client) && IsPlayerAlive(client) && !IsPlayerHeld(client)
&& GetEntProp(client, Prop_Send, "m_isHangingFromLedge") != 1
&& GetEntProp(client, Prop_Send, "m_reviveOwner") == -1)
{
//PrintToChat(client, "m_nSequence %i", sequence);
if (IsIncapacitated(client))
{
new crawl = GetCrawlSequence(client);
new buttons = GetClientButtons(client);
if (crawl != -1 && buttons & IN_FORWARD)
{
DHookSetReturn(hReturn, crawl);
GotoThirdPerson(client);
return MRES_Override;
}
}
}
GotoFirstPerson(client);
return MRES_Ignored;
}
bool:IsSurvivor(client)
{
return (client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 2);
}
LoadOffset()
{
new Handle:temp = LoadGameConfigFile("l4d2_sequence");
if (temp == INVALID_HANDLE)
{
SetFailState("Error: Gamedata not found");
}
new offset;
offset = GameConfGetOffset(temp, "CTerrorPlayer::SelectWeightedSequence");
if (offset == -1)
{
CloseHandle(temp);
LogError("Unable to get offset for CTerrorPlayer::SelectWeightedSequence");
return;
}
hSequenceSet = DHookCreate(offset, HookType_Entity, ReturnType_Int, ThisPointer_CBaseEntity, OnSequenceSet);
DHookAddParam(hSequenceSet, HookParamType_Int);
}
stock bool:IsPlayerHeld(client)
{
new jockey = GetEntPropEnt(client, Prop_Send, "m_jockeyAttacker");
new charger = GetEntPropEnt(client, Prop_Send, "m_pummelAttacker");
new hunter = GetEntPropEnt(client, Prop_Send, "m_pounceAttacker");
new smoker = GetEntPropEnt(client, Prop_Send, "m_tongueOwner");
if (jockey > 0 || charger > 0 || hunter > 0 || smoker > 0)
{
return true;
}
return false;
}
stock bool:IsIncapacitated(client)
{
if (GetEntProp(client, Prop_Send, "m_isIncapacitated", 1) > 0)
return true;
return false;
}
public OnAllPluginsLoaded() //late loading
{
for (new client = 1; client <= MaxClients; client++)
{
if (IsSurvivor(client))
{
clienthook[client] = DHookEntity(hSequenceSet, true, client);
}
}
}
public OnClientPutInServer(client)
{
clienthook[client] = DHookEntity(hSequenceSet, true, client);
}
stock GetCrawlSequence(client)
{
if (IsSurvivor(client))
{
decl String:model[64];
GetEntPropString(client, Prop_Data, "m_ModelName", model, sizeof(model));
if (StrContains(model, "gambler", false) != -1)
{
return 631;
}
else if (StrContains(model, "producer", false) != -1)
{
return 639;
}
else if (StrContains(model, "mechanic", false) != -1)
{
return 636;
}
else if (StrContains(model, "namvet", false) != -1)
{
return 539;
}
else if (StrContains(model, "teenangst", false) != -1)
{
return 529;
}
else if (StrContains(model, "biker", false) != -1)
{
return 542;
}
else if (StrContains(model, "manager", false) != -1)
{
return 539;
}
}
return -1;
}
static PrepSDKCall()
{
new Handle:config = LoadGameConfigFile("l4d2_sequence");
if (config == INVALID_HANDLE)
{
SetFailState("Error: Why do you not have this extension's gamedata file?!");
}
StartPrepSDKCall(SDKCall_Player);
if (!PrepSDKCall_SetFromConf(config, SDKConf_Virtual, "CTerrorPlayer::DoAnimationEvent"))
{
CloseHandle(config);
SetFailState("Cant find CTerrorPlayer::DoAnimationEvent Signature in gamedata file");
}
PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
CloseHandle(config);
sdkDoAnim = EndPrepSDKCall();
if (sdkDoAnim == INVALID_HANDLE)
{
SetFailState("Cant initialize CTerrorPlayer::DoAnimationEvent SDKCall, Signature broken");
}
}
GotoThirdPerson(client)
{
SetEntPropFloat(client, Prop_Send, "m_TimeForceExternalView", 99999.3);
}
GotoFirstPerson(client)
{
SetEntPropFloat(client, Prop_Send, "m_TimeForceExternalView", 0.0);
}
Here's a video example from before the Dynamic Hooks implementation (hence the survivor "falling" back down after the animation, since instead of hijacking m_nSetSequence I was freezing it), but the premise is the same, the survivor itself is playing the animation.
https://www.youtube.com/watch?v=fvLJ8ZHyqJU
__________________
Last edited by DeathChaos25; 09-11-2017 at 08:02.
|
|