Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove pipes spread #84

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion gamedata/tf2-comp-fixes.games.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,42 @@
}
}

"CTFGrenadePipebombProjectile::Create" {
/* CTFGrenadePipebombProjectile* CTFGrenadePipebombProjectile::Create( const Vector &position, const QAngle &angles,
const Vector &velocity, const AngularImpulse &angVelocity,
CBaseCombatCharacter *pOwner, const CTFWeaponInfo &weaponInfo,
int iPipeBombType, float flMultDmg ) */
"signature" "CTFGrenadePipebombProjectile::Create"
"callconv" "cdecl"
"return" "cbaseentity"
"arguments" {
"position" {
"type" "vectorptr"
}
"angles" {
"type" "vectorptr"
}
"velocity" {
"type" "vectorptr"
}
"angVelocity" {
"type" "vectorptr"
}
"pOwner" {
"type" "objectptr"
}
"weaponInfo" {
"type" "objectptr"
}
"iPipeBombType" {
"type" "int"
}
"flMultDmg" {
"type" "float"
}
}
}

"CTFFlameThrower::DeflectEntity" {
// virtual bool DeflectEntity( CBaseEntity *pTarget, CTFPlayer *pOwner, Vector &vecForward, Vector &vecCenter, Vector &vecSize )
"signature" "CTFFlameThrower::DeflectEntity"
Expand Down Expand Up @@ -178,7 +214,7 @@
"signature" "CTFWeaponBaseGun::FirePipeBomb"
"callconv" "thiscall"
"return" "cbaseentity"
"this" "ignore"
"this" "entity"
"arguments" {
"player" {
"type" "objectptr"
Expand All @@ -189,6 +225,19 @@
}
}

"CTFWeaponBaseGun::FireProjectile" {
// CBaseEntity *CTFWeaponBaseGun::FireProjectile( CTFPlayer *pPlayer )
"signature" "CTFWeaponBaseGun::FireProjectile"
"callconv" "thiscall"
"return" "cbaseentity"
"this" "ignore"
"arguments" {
"player" {
"type" "objectptr"
}
}
}

"PassServerEntityFilter" {
// bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass )
"signature" "PassServerEntityFilter"
Expand Down Expand Up @@ -321,6 +370,15 @@
"windows" "\x55\x8B\xEC\x83\xEC\x0C\x56\x6A\x00\x8D\x45\x2A"
}


"CTFGrenadeLauncher::GetProjectileSpeed" {
"linux" "@_ZN18CTFGrenadeLauncher18GetProjectileSpeedEv"
}

"CTFGrenadePipebombProjectile::Create" {
"linux" "@_ZN28CTFGrenadePipebombProjectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacterRK13CTFWeaponInfoif"
}

"CTFPlayer::OnTakeDamage_Alive" {
"linux" "@_ZN9CTFPlayer18OnTakeDamage_AliveERK15CTakeDamageInfo"
}
Expand All @@ -337,6 +395,10 @@
"windows" "\x53\x8B\xDC\x83\xEC\x08\x83\xE4\xF0\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x81\xEC\x58\x01\x00\x00\x56\x8B\xF1\x57\x8B\x06"
}

"CTFWeaponBaseGun::FireProjectile" {
"linux" "@_ZN16CTFWeaponBaseGun14FireProjectileEP9CTFPlayer"
}

"GEconItemSchema" {
"linux" "@_Z15GEconItemSchemav"
"windows" "\xE8\x2A\x2A\x2A\x2A\x83\xC0\x04\xC3"
Expand Down
8 changes: 7 additions & 1 deletion scripting/tf2-comp-fixes.sp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "tf2-comp-fixes/remove-halloween-souls.sp"
#include "tf2-comp-fixes/remove-medic-attach-speed.sp"
#include "tf2-comp-fixes/remove-pipe-spin.sp"
#include "tf2-comp-fixes/remove-pipes-spread.sp"
#include "tf2-comp-fixes/solid-buildings.sp"
#include "tf2-comp-fixes/tournament-end-ignores-whitelist.sp"
#include "tf2-comp-fixes/winger-jump-bonus-when-fully-deployed.sp"
Expand Down Expand Up @@ -79,7 +80,7 @@ void OnPluginStart() {
RegConsoleCmd("sm_cf", Command_Cf, "Batch update of TF2 Competitive Fixes cvars");

Common_Setup(game_config);
Debug_Setup();
Debug_Setup(game_config);

// Here
Concede_Setup();
Expand All @@ -101,6 +102,7 @@ void OnPluginStart() {
RemoveHalloweenSouls_Setup(game_config);
RemoveMedicAttachSpeed_Setup(game_config);
RemovePipeSpin_Setup();
RemovePipesSpread_Setup(game_config);
SolidBuildings_Setup();
TournamentEndIgnoresWhitelist_Setup(game_config);
WingerJumpBonusWhenFullyDeployed_Setup(game_config);
Expand Down Expand Up @@ -173,6 +175,7 @@ Action Command_Cf(int client, int args) {
ReplyDiffConVar(client, "sm_gunboats_always_apply");
ReplyDiffConVar(client, "sm_prevent_respawning");
ReplyDiffConVar(client, "sm_remove_medic_attach_speed");
ReplyDiffConVar(client, "sm_remove_pipes_spread");
ReplyDiffConVar(client, "sm_solid_buildings");
ReplyDiffConVar(client, "sm_winger_jump_bonus_when_fully_deployed");

Expand Down Expand Up @@ -245,6 +248,9 @@ Action Command_Cf(int client, int args) {
FindConVar("sm_remove_pipe_spin")
.SetBool(all);

FindConVar("sm_remove_pipes_spread")
.SetBool(all);

FindConVar("sm_rest_in_peace_rick_may")
.SetInt(all || fixes || rgl ? 128 : ozf ? 255 : 0);

Expand Down
4 changes: 4 additions & 0 deletions scripting/tf2-comp-fixes/common.sp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ stock int GetEntityFromAddress(Address entity_ptr) {
return entity_handle & 0xFFF;
}

stock void GetEntityPosition(int entity, float position[3]) {
GetEntPropVector(entity, Prop_Data, "m_vecOrigin", position);
}

stock void ScaleVectorTo(const float vec[3], float scale, float result[3]) {
result[0] = vec[0] * scale;
result[1] = vec[1] * scale;
Expand Down
63 changes: 62 additions & 1 deletion scripting/tf2-comp-fixes/debug.sp
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
static ConVar g_cvar;

void Debug_Setup() {
static StringMap g_projectiles_positions;
static int g_laser;

static Handle g_detour_CTFWeaponBaseGun_FireProjectile;

void Debug_Setup(Handle game_config) {
g_laser = PrecacheModel("sprites/laser.vmt");
g_projectiles_positions = new StringMap();

g_detour_CTFWeaponBaseGun_FireProjectile =
CheckedDHookCreateFromConf(game_config, "CTFWeaponBaseGun::FireProjectile");

g_cvar = CreateConVar("sm_cf_debug", "0", "Print debug statements in chat", FCVAR_NOTIFY, true,
0.0, true, 2.0);
CreateBoolConVar("sm_cf_show_projectiles_traces", OnConVarChange);
}

void LogDebug(const char[] format, any...) {
Expand All @@ -22,3 +34,52 @@ void LogDebug(const char[] format, any...) {
PrintToChatAll("[TF2 Competitive Fixes] Debug: %s", message);
}
}

static void OnConVarChange(ConVar cvar, const char[] before, const char[] after) {
if (cvar.BoolValue == TruthyConVar(before)) {
return;
}

if (!DHookToggleDetour(g_detour_CTFWeaponBaseGun_FireProjectile, HOOK_POST,
Detour_CTFWeaponBaseGun_FireProjectile, true)) {
SetFailState("Failed to toggle detour on CCTFWeaponBaseGun::FireProjectile");
}
}

static MRESReturn Detour_CTFWeaponBaseGun_FireProjectile(Handle hReturn, Handle hParams) {
if (g_cvar.IntValue < 2) {
return MRES_Ignored;
}

int entity = DHookGetReturn(hReturn);

if (entity == -1) {
return MRES_Ignored;
}

float position[3];
char entity_id[5];

GetEntityPosition(entity, position);
IntToString(entity, entity_id, sizeof(entity_id));

g_projectiles_positions.SetArray(entity_id, position, 3);
SDKHook(entity, SDKHook_SetTransmit, DrawProjectilePath);

return MRES_Handled;
}

static void DrawProjectilePath(int entity) {
float position[3], last_position[3];
char entity_id[5];

GetEntityPosition(entity, position);
IntToString(entity, entity_id, sizeof(entity_id));

g_projectiles_positions.GetArray(entity_id, last_position, 3);

TE_SetupBeamPoints(last_position, position, g_laser, 0, 0, 66, 20.0, 1.0, 1.0, 1, 0.1, {255, 0, 0, 255}, 0);
TE_SendToAll();

g_projectiles_positions.SetArray(entity_id, position, 3);
}
120 changes: 120 additions & 0 deletions scripting/tf2-comp-fixes/remove-pipes-spread.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#define PIPEBOMB_REMOTE 4 //sticky bomb launcher
#define PIPEBOMB_REMOTE_PRACTICE 14 //sticky jumper

#define MASK 31 //0b11111
#define MASK_SIZE 5

#define ANGULAR_VELOCITY_Y -1125.89

static Handle g_call_CTFGrenadeLauncher_GetProjectileSpeed;

static Handle g_detour_CTFWeaponBaseGun_FirePipeBomb;
static Handle g_detour_CTFGrenadePipebombProjectile_Create;

void RemovePipesSpread_Setup(Handle game_config) {
StartPrepSDKCall(SDKCall_Entity);

if (!PrepSDKCall_SetFromConf(game_config, SDKConf_Signature,
"CTFGrenadeLauncher::GetProjectileSpeed")) {
SetFailState("Failed to finalize SDK call to CTFGrenadeLauncher::GetProjectileSpeed");
}

PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain);
g_call_CTFGrenadeLauncher_GetProjectileSpeed = EndPrepSDKCall();

g_detour_CTFWeaponBaseGun_FirePipeBomb =
CheckedDHookCreateFromConf(game_config, "CTFWeaponBaseGun::FirePipeBomb");
g_detour_CTFGrenadePipebombProjectile_Create =
CheckedDHookCreateFromConf(game_config, "CTFGrenadePipebombProjectile::Create");

CreateBoolConVar("sm_remove_pipes_spread", OnConVarChange);
}

static void OnConVarChange(ConVar cvar, const char[] before, const char[] after) {
if (cvar.BoolValue == TruthyConVar(before)) {
return;
}

if (!DHookToggleDetour(g_detour_CTFWeaponBaseGun_FirePipeBomb, HOOK_PRE,
Detour_CTFWeaponBaseGun_FirePipeBomb, cvar.BoolValue)) {
SetFailState("Failed to toggle detour on CTFWeaponBaseGun::FirePipeBomb");
}

if (!DHookToggleDetour(g_detour_CTFGrenadePipebombProjectile_Create, HOOK_PRE,
Detour_CTFGrenadePipebombProjectile_Create, cvar.BoolValue)) {
SetFailState("Failed to toggle detour on CTFGrenadePipebombProjectile::Create");
}
}

static MRESReturn Detour_CTFWeaponBaseGun_FirePipeBomb(int weapon, Handle hReturn, DHookParam hParams) {
int projectile_type = hParams.Get(2);

if (IsStickyBomb(projectile_type)) {
return MRES_Ignored;
}

//The fractional part of the speed is always zero, so we don't lose anything by using RoundToFloor
int speed = RoundToFloor(SDKCall(g_call_CTFGrenadeLauncher_GetProjectileSpeed, weapon));

LogDebug("Projectile speed: %d, type: %d", speed, projectile_type);

/*
We use iPipeBombType parameter to store two values:
- projectile speed
- projectile type
Since the max value of iPipeBombType is 17 (Cannonball), we only need 5 bits to store the projectile type
The remaining bits are used to store the speed value
*/
speed = speed << MASK_SIZE;
hParams.Set(2, speed | projectile_type);

return MRES_ChangedHandled;
}

static MRESReturn Detour_CTFGrenadePipebombProjectile_Create(Handle hReturn, DHookParam hParams) {
//now we need to "unpack" the projectile speed and type from iPipeBombType
int param = hParams.Get(7);
int projectile_type = param & MASK;

if (IsStickyBomb(projectile_type)) {
return MRES_Ignored;
}

hParams.Set(7, projectile_type);

int speed = (param & ~MASK) >> MASK_SIZE;
float launchSpeed = float(speed);

LogDebug("Pipe launch speed: %.2f", launchSpeed);

float eye_angles[3], velocity[3], fwd[3], up[3];

hParams.GetVector(2, eye_angles);
GetAngleVectors(eye_angles, fwd, NULL_VECTOR, up);

//velocity: launchSpeed * forward + 200 * up;
ScaleVector(fwd, launchSpeed);
ScaleVector(up, 200.0);
AddVectors(fwd, up, velocity);

hParams.SetVector(3, velocity);

float ang_velocity[3];
hParams.GetVector(4, ang_velocity);

LogDebug("Angular velocity before: { %.2f, %.2f, %.2f }", ang_velocity[0], ang_velocity[1], ang_velocity[2]);

//if the x-component is nonzero, then the y-component is randomized
if (ang_velocity[0] != 0) {
ang_velocity[1] = ANGULAR_VELOCITY_Y;
hParams.SetVector(4, ang_velocity);
}

LogDebug("Angular velocity after: { %.2f, %.2f, %.2f }", ang_velocity[0], ang_velocity[1], ang_velocity[2]);

return MRES_ChangedHandled;
}

static bool IsStickyBomb(int projectile_type) {
return projectile_type == PIPEBOMB_REMOTE || projectile_type == PIPEBOMB_REMOTE_PRACTICE;
}