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

CS:GO Z:R fixes and workarounds


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Morell
AlliedModders Donor
Join Date: Jun 2010
Location: World
Old 07-22-2014 , 11:31   CS:GO Z:R fixes and workarounds
Reply With Quote #1

After dropping our CS:GO server months ago, we decided to move back to it. We have been trying to find a fix/workaround that lets us have a decent knockback for CS:GO. The workaround isn't equal to what you'd be expecting if you had only played CS:S' zombie mods, but it is enough to be enjoyable. It is based (we cooperated with mappers to get it) on setting the basevelocity field when hit, which lets you have a subtle knockback/push while on the ground (it lets a player hold a zombie by himself alone, which is enough for us). As seen on CS:GO, you'll get a normal knockback while on the air.

knockback.inc
Code:
/**
 * Minimum upwards boost that is required to push zombies off the ground.
 */
#define CSGO_KNOCKBACK_BOOST        251.0
#define CSGO_KNOCKBACK_BOOST_MAX    350.0

/** Client has been hurt.
 *
 * @param client        The client index. (zombie)
 * @param attacker      The attacker index. (human)
 * @param weapon        The weapon used.
 * @param hitgroup      Hitgroup attacker has damaged. 
 * @param dmg_health    Damage done.
 */
KnockbackOnClientHurt(client, attacker, const String:weapon[], hitgroup, dmg_health)
{
    // If attacker is invalid, then stop.
    if (!ZRIsClientValid(attacker))
    {
        return;
    }
    
    // Client is a human, then stop.
    if (InfectIsClientHuman(client))
    {
        return;
    }
    
    // If attacker is a zombie, then stop.
    if (InfectIsClientInfected(attacker))
    {
        return;
    }
    
    // Block knock back if an immunity mode is handling this.
    if (ImmunityOnClientKnockBack(client))
    {
        return;
    }
    
    // Get zombie knockback value.
    new Float:knockback = ClassGetKnockback(client);
    
    new Float:clientloc[3];
    new Float:attackerloc[3];
    
    GetClientAbsOrigin(client, clientloc);
    
    // Check if a grenade was thrown.
    if (StrEqual(weapon, "hegrenade"))
    {
        // Get the location of the grenade.
        if (KnockbackFindExplodingGrenade(attackerloc) == -1)
        {
            // If the grenade wasn't found, then stop.
            return;
        }
    }
    else
    {
        // Get attackers eye position.
        GetClientEyePosition(attacker, attackerloc);
        
        // Get attackers eye angles.
        new Float:attackerang[3];
        GetClientEyeAngles(attacker, attackerang);
        
        // Calculate knockback end-vector.
        TR_TraceRayFilter(attackerloc, attackerang, MASK_ALL, RayType_Infinite, KnockbackTRFilter);
        TR_GetEndPosition(clientloc);
    }
    
    new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]);
    if (weapons)
    {
        new weaponindex = WeaponsNameToIndex(weapon);
        if (weaponindex != -1)
        {
            // Apply weapon knockback multiplier.
            knockback *= WeaponsGetKnockback(weaponindex);
        }
    }
    
    new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
    if (hitgroups)
    {
        new hitgroupindex = HitgroupToIndex(hitgroup);
        if (hitgroupindex != -1)
        {
            // Apply hitgroup knockback multiplier.
            knockback *= HitgroupsGetKnockback(hitgroupindex);
        }
    }
    
    // Apply damage knockback multiplier.
    knockback *= float(dmg_health);
	
	knockback *= 7.5;
    
    // Apply knockback.
    KnockbackSetVelocity(client, attackerloc, clientloc, knockback);
}

/**
 * Sets velocity on a player.
 *  
 * @param client        The client index.
 * @param startpoint    The starting coordinate to push from.
 * @param endpoint      The ending coordinate to push towards.
 * @param magnitude     Magnitude of the push.
 */  
KnockbackSetVelocity(client, const Float:startpoint[3], const Float:endpoint[3], Float:magnitude)
{
    // Create vector from the given starting and ending points.
    new Float:vector[3];
    MakeVectorFromPoints(startpoint, endpoint, vector);
 
    // Normalize the vector
    new Float:normal = GetVectorLength(vector);
    vector[0] /= normal;
    vector[1] /= normal;
    vector[2] /= normal;
 
    // Only apply knockback if the vector has a reasonable length (this avoids null vectors)
    if(normal>0.001)
    {
        // If we are touching the ground (with a threshold) we get a weaker Z-knockback
        // Perhaps this could be removed to suit your needs...
        if((GetClientDistanceToGround(client) > -1.0) && (GetClientDistanceToGround(client) < 1.0))
        {
                // This reduces the obnoxiousness of knockback on zombies that try to jump a crate
                // I'd recommend each server owner to tune to their specific needs.
                // It converges pretty fast, so it shouldn't be troublesome at all.
                while(vector[2]*magnitude > 64)
                {
                        magnitude/=2;
                }
        }
        // Otherwise we apply knockback with a cap
        // (256 is a good value because it's the breaking point for basevelocity to have an effect vertically, so it will push but not too much)
        else
        {
                if(magnitude > 256.0)
                {
                        magnitude = 256.0;
                }
        }
        // Apply the magnitude by scaling the vector (multiplying each of its components).
        ScaleVector(vector, magnitude);
                 
        // Add the given vector to the client's current velocity.
        // We use the basevelocity (velocity for movement in vehicles/given by other forces) for that
        new g_iBaseVelocityOffset = FindSendPropOffs("CBasePlayer","m_vecBaseVelocity");
        SetEntDataVector(client, g_iBaseVelocityOffset, vector, true);
    }
}

/**
 * Trace Ray forward, used as a filter to continue tracing if told so. (See sdktools_trace.inc)
 *  
 * @param entity        The entity index.
 * @param contentsMask  The contents mask.
 * @return              True to allow hit, false to continue tracing. 
 */ 
public bool:KnockbackTRFilter(entity, contentsMask)
{
    // If entity is a player, continue tracing.
    if (entity > 0 && entity < MAXPLAYERS)
    {
        return false;
    }
    
    // Allow hit.
    return true;
}

/**
 * Find the location of an exploding grenade (currently inflicting damage in player_hurt).
 *  
 * @param heLoc     The location of the exploding grenade.
 * @return          The entity index of the grenade. 
 */  
KnockbackFindExplodingGrenade(Float:heLoc[3])
{
    decl String:classname[64];
    
    // Find max entities and loop through all of them.
    new maxentities = GetMaxEntities();
    for (new x = MaxClients; x <= maxentities; x++)
    {
        // If entity is invalid, then stop.
        if (!IsValidEdict(x))
        {
            continue;
        }
        
        // If entity isn't a grenade, then stop.
        GetEdictClassname(x, classname, sizeof(classname));
        if (!StrEqual(classname, "hegrenade_projectile", false))
        {
            continue;
        }
        
        // If m_takedamage is set to 0, we found our grenade.
        new takedamage = GetEntProp(x, Prop_Data, "m_takedamage");
        if (takedamage == 0)
        {
            // Return its location.
            GetEntPropVector(x, Prop_Send, "m_vecOrigin", heLoc);
            
            // Return its entity index.
            return x;
        }
    }
    
    // Didn't find the grenade.
    return -1;
}

stock Float:GetClientDistanceToGround(client)
{
	new Float:distance = 0.0;
    // Player is already standing on the ground?
    if(GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") == 0)
	{
		distance = 0.0;
		return distance;
	}
	
    new Float:fOrigin[3], Float:fGround[3];
    GetClientAbsOrigin(client, fOrigin);
    
    fOrigin[2] += 10.0;
    
    TR_TraceRayFilter(fOrigin, Float:{90.0,0.0,0.0}, MASK_PLAYERSOLID, RayType_Infinite, TraceRayNoPlayers, client);
    if (TR_DidHit())
    {
        TR_GetEndPosition(fGround);
        fOrigin[2] -= 10.0;
		
	distance = GetVectorDistance(fOrigin, fGround);
        return distance;
    }
    return distance;
}

public bool:TraceRayNoPlayers(entity, mask, any:data)
{
    if(entity == data || (entity >= 1 && entity <= MaxClients))
    {
        return false;
    }
    return true;
}
To handle this and make it more enjoyable, we figured out we could depend on subtle ground knockback plus extra vertical knockback (to produce 'jumps') provided by some weapons. We are publishing our vertical knockback for grenades too in case anyone wants a similar system. On the server, we have extended it for a few other weapons (knives, for example, and the awp). We thought about forcing a vertical knockback if on the ground (as you can see on the code), but we found that to be annoying (despite other communities using it).

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

new Handle:g_Cvar_MaxZKnock = INVALID_HANDLE;
new Handle:g_Cvar_HeKnock = INVALID_HANDLE;

public Plugin:myinfo ={
	name = "Z:R Grenade Boost",
	author = "Marica Stevens",
	description = "Pushes zombies upwards when hit by a grenade.",
	version = "1.0.0",
	url = "http://maricascripters.com"
};

public OnPluginStart()
{
	g_Cvar_MaxZKnock = CreateConVar("sm_max_zknock", "32.0", "Knock in Z");
	g_Cvar_HeKnock = CreateConVar("sm_he_knock", "320.0", "Max Knock in Z");
	HookEvent("player_hurt", Event_HandleNadeDamage); 
}

public OnPluginEnd()
{ 	
	UnhookEvent("player_hurt", Event_HandleNadeDamage); 
}

public Event_HandleNadeDamage(Handle:event, const String:name[], bool:dontBroadcast)
{ 
	new clientid = GetEventInt(event, "userid");
	new client = GetClientOfUserId(clientid);
	new damage = GetEventInt(event,"dmg_health");
	decl String:weapon[32];
	GetEventString(event, "weapon", weapon, sizeof(weapon));
	if(GetClientTeam(client)==2 && StrEqual("hegrenade", weapon))
	{
		new Float:vector[3];
		vector[0] = 0.0;
		vector[1] = 0.0;
		vector[2] = GetConVarFloat(g_Cvar_HeKnock)*damage;
		
		if(vector[2]> GetConVarFloat(g_Cvar_MaxZKnock))
		{
			vector[2] = GetConVarFloat(g_Cvar_MaxZKnock);
		}
		new g_iBaseVelocityOffset = FindSendPropOffs("CBasePlayer","m_vecBaseVelocity");
		SetEntDataVector(client, g_iBaseVelocityOffset, vector, true);
	}
}
Finally, to address the problem with zombies spawning as classes, we've tried to perfect the 'fix' (which didn't feel like enough to us) that Franc1sco made. We're sure that he probably updated his own, but seeing how it wasn't updated we're publishing ours.

Code:
#include <sourcemod>
#include <sdktools>
#undef REQUIRE_PLUGIN
#include <zombiereloaded>

new zombie1, zombie2, zombie3;

public Plugin:myinfo =
{
	name = "ZR Class Fix",
	author = "Mapeadores",
	description = "Class Fix (Franug plugin modification)",
	version = "1.5",
	url = "http://Mapeadores.com/"
};

public OnPluginStart()
{
	//Edit this with your zombie classes
	zombie1 = ZR_GetClassByName("Clasico");
	zombie2 = ZR_GetClassByName("Zombie Rapido");
	zombie3 = ZR_GetClassByName("Zombie Resistente");
}

public ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn)
{
	new vida = GetClientHealth(client);
	if(vida < 300)
	{
		CreateTimer(0.5, TimerAsegurarClase, client, TIMER_FLAG_NO_MAPCHANGE);
	}
}

public Action:TimerAsegurarClase(Handle:timer, any:client)
{
	AsegurarClaseDefault(client);
}

public AsegurarClaseDefault(client)
{
	SetEntityHealth(client, 5000);
	new randomnum = GetRandomInt(0, 2);
	switch(randomnum)
	{
		case 0:
		{
			SetEntityModel(client, "models/player/mapeadores/morell/zh/zh3fix.mdl");
			ZR_SelectClientClass(client, zombie3, true, true);
		}
		case 1:
		{
			SetEntityModel(client, "models/player/mapeadores/kaem/zh/zh1fix.mdl");
			ZR_SelectClientClass(client, zombie1, true, true);
		}
		case 2:
		{
			SetEntityModel(client, "models/player/mapeadores/kaem/zh/zh2fix.mdl");
			ZR_SelectClientClass(client, zombie2, true, true);
		}
	}
}
This plugin is a sample from our server. If you have seen Franc1sco's plugin you'll notice that it hasn't changed much, the only difference is that the plugin selects a valid class for a player so that this round (if possible) or next he gets a real zombie class. You'd need to adjust it to your settings by adding more classes following the style (we thought of making a nicer plugin but ended up slacking, sorry about that).

Those plugins, fixes and workarounds aren't optimal, probably, but seeing how the community doesn't seem to help, we thought that by adding our little grain of sand perhaps others will eventually join us and help the mod develop as a whole with interests aside.

On a different matter, some mappers have been porting maps with us being the test subjects. The mappers will eventually publish their ports in some sort of way, as they're following a set of porting rules to ensure that the ports have a minimal filesize while adapting the looks of the maps to the new engine. We have seen that some communities (shockingly, those that seem to rarely contribute or, rather, try to mock others whilst saying they've addressed issues) have 'stolen' those maps while they are still in the process of being perfected (and some even said they ported the maps themselves, which is rather bothersome). We'd value that, for some time, you stepped out and didn't use '_p' map ports until we have a big enough batch for everybody to use.

ATTACHED FIX WITH JARGON ZR FIXES: https://forums.alliedmods.net/showthread.php?t=200527
Attached Files
File Type: zip ZR 3.1 [KNOCKBACK FIX].zip (608.7 KB, 723 views)
File Type: sp Get Plugin or Get Source (zr_classfix.sp - 435 views - 1.4 KB)
File Type: sp Get Plugin or Get Source (zr_grenadeboost.sp - 925 views - 1.5 KB)
__________________

Last edited by Morell; 07-23-2014 at 02:57.
Morell is offline
Pan32
Member
Join Date: Dec 2010
Location: ?
Old 07-22-2014 , 11:58   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #2

Since class fixes requires zr to compile, ill just leave the compiled smx here. Please take note that this compile is using Morell's playerclasses config.

Thank you Morell!
Attached Files
File Type: smx zr_classfix.smx (4.4 KB, 438 views)

Last edited by Pan32; 07-22-2014 at 13:08.
Pan32 is offline
Cook13s
Junior Member
Join Date: Jul 2009
Old 07-22-2014 , 12:14   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #3

As for the mappers thing, that sucks, not cool. It should be the author porting, or the guys trying to port re-making it themselves and crediting the original author. A veteran zombie mod mapper and I will be trying to port (his own) and create new maps, of course that is if we manage to get our server running.
Cook13s is offline
bebe9b
Veteran Member
Join Date: May 2009
Location: Romania
Old 07-22-2014 , 12:51   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #4

Hi, how can I make the icon appear knife??
thx
bebe9b is offline
Franc1sco
Veteran Member
Join Date: Oct 2010
Location: Spain (Madrid)
Old 07-22-2014 , 14:56   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #5

The class bug is a thing that now rarely occur so I dont update it more because I thought that are already fixed, I dont update the plugin, I dont know why you say that yes

Anyway, if bug continue I will make a new version more advanced because your code have errors like dont check if the player are ingame after CreateTimer and I can do more improvements

Btw, I currently have vacations, this weekend I will see it
__________________
Veteran Coder -> Activity channel
Coding on CS2 and taking paid and free jobs.

Contact: Steam, Telegram or discord ( franug ).

You like my work? +Rep in my steam profile comments or donate.


Last edited by Franc1sco; 07-22-2014 at 15:34.
Franc1sco is offline
Send a message via MSN to Franc1sco
Morell
AlliedModders Donor
Join Date: Jun 2010
Location: World
Old 07-22-2014 , 15:57   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #6

Quote:
Originally Posted by bebe9b View Post
Hi, how can I make the icon appear knife??
thx
Change this in zr/infect.inc:
Code:
SetEventString(event, "weapon", "zombie_claws_of_death");
for:
Code:
SetEventString(event, "weapon", "knife"); (or other knife)
__________________

Last edited by Morell; 07-22-2014 at 16:18.
Morell is offline
bebe9b
Veteran Member
Join Date: May 2009
Location: Romania
Old 07-22-2014 , 16:17   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #7

Why are players out after the server? Please fix if you can
thx man

Last edited by bebe9b; 07-22-2014 at 16:20.
bebe9b is offline
Morell
AlliedModders Donor
Join Date: Jun 2010
Location: World
Old 07-22-2014 , 16:24   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #8

Quote:
Originally Posted by bebe9b View Post
Why are players out after the server? Please fix if you can
thx man
Sorry, I don't know what you mean. Could you be more clear?
__________________
Morell is offline
bebe9b
Veteran Member
Join Date: May 2009
Location: Romania
Old 07-22-2014 , 16:38   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #9

Some players are disconnected from the zombie server and I don`t know why
The game crashes because of the server
bebe9b is offline
Jargon
SourceMod Donor
Join Date: Jun 2012
Location: Sydney, Australia
Old 07-22-2014 , 17:04   Re: CS:GO Z:R fixes and workarounds
Reply With Quote #10

Hey Morell, does this include all of the previous changes as well or just knockback?

If it includes all, do you mind if I merge the knockback.inc with my sticky post (crediting you of course) to keep things easy to find? I've been working on some other fixes for a few months now that I should be adding soon, so it'd be silly to have two posts to keep track of.
Jargon is offline
Reply



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 09:13.


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