Files
SMScripts/scripting/temp/fusrodah.sp

398 lines
12 KiB
SourcePawn
Raw Normal View History

2025-04-15 22:27:20 -04:00
// base grab code taken from http://forums.alliedmods.net/showthread.php?t=157075 and https://forums.alliedmods.net/showthread.php?p=1946774
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <morecolors>
#define DRAGONBORN "shout/dragonborn.wav" // grab
#define FUSRODAH "shout/fusrodah.wav" // throw
#define THROW_FORCE 10000.0
#define GRAB_DISTANCE 250.0
#define PLUGIN_NAME "Dovah Shout!"
#define PLUGIN_AUTHOR "DovahkiinYT / TheXeon"
#define PLUGIN_VERSION "2.0.2"
#define PLUGIN_DESCRIP "Allows Dovah to Grab Stuff"
#define PLUGIN_CONTACT "http://steamcommunity.com/groups/FireHostv2"
public Plugin myinfo = {
name = PLUGIN_NAME,
author = PLUGIN_AUTHOR,
description = PLUGIN_DESCRIP,
version = PLUGIN_VERSION,
url = PLUGIN_CONTACT
}
int g_grabbed[MAXPLAYERS+10]; // track client's grabbed object
float gDistance[MAXPLAYERS+10]; // track distance of grabbed object
//////////////////////////////////////////////////////////////////////
///////////// Setup /////////////
//////////////////////////////////////////////////////////////////////
public void OnPluginStart()
{
CreateConVar("tf_dovahgrab_version", PLUGIN_VERSION, PLUGIN_NAME, FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_SPONLY);
PrecacheSound(FUSRODAH, true);
PrecacheSound(DRAGONBORN, true);
AddFileToDownloadsTable("sound/shout/fusrodah.wav");
AddFileToDownloadsTable("sound/shout/dragonborn.wav");
RegConsoleCmd("sm_SetTarget", Command_Dragonborn, "Attempt to be the Dragonborn");
RegConsoleCmd("sm_FusRoDah", Command_FusRoDah, "The Dragonborn's Words");
RegConsoleCmd("sm_Disarm", Command_Disarm, "Disarm the pursuing");
HookEvent("player_death", OnPlayerSpawn);
HookEvent("player_spawn", OnPlayerSpawn);
HookEvent("player_team", OnPlayerSpawn);
//Some code was here, but it was marked as unnecessary and removed.
}
stock bool:IsTargetInSightRange(client, target, Float:angle=90.0, Float:distance=0.0, bool:heightcheck=true, bool:negativeangle=false)
{
if(angle > 360.0 || angle < 0.0)
ThrowError("Angle Max : 360 & Min : 0. %d isn't proper angle.", angle);
if(!IsValidClient(client))
ThrowError("Client is not Alive.");
if(!IsValidClient(target))
ThrowError("Target is not Alive.");
decl Float:clientpos[3], Float:targetpos[3], Float:anglevector[3], Float:targetvector[3], Float:resultangle, Float:resultdistance;
GetClientEyeAngles(client, anglevector);
anglevector[0] = anglevector[2] = 0.0;
GetAngleVectors(anglevector, anglevector, NULL_VECTOR, NULL_VECTOR);
NormalizeVector(anglevector, anglevector);
if(negativeangle)
NegateVector(anglevector);
GetClientAbsOrigin(client, clientpos);
GetClientAbsOrigin(target, targetpos);
if(heightcheck && distance > 0)
resultdistance = GetVectorDistance(clientpos, targetpos);
clientpos[2] = targetpos[2] = 0.0;
MakeVectorFromPoints(clientpos, targetpos, targetvector);
NormalizeVector(targetvector, targetvector);
resultangle = RadToDeg(ArcCosine(GetVectorDotProduct(targetvector, anglevector)));
if(resultangle <= angle/2)
{
if(distance > 0)
{
if(!heightcheck)
resultdistance = GetVectorDistance(clientpos, targetpos);
if(distance >= resultdistance)
return true;
else
return false;
}
else
return true;
}
else
return false;
}
public void OnMapStart()
{
for (int client = 1; client <= MaxClients; client++)
{
g_grabbed[client] = INVALID_ENT_REFERENCE;
PrecacheSound(FUSRODAH, true);
PrecacheSound(DRAGONBORN, true);
AddFileToDownloadsTable("sound/shout/fusrodah.wav");
AddFileToDownloadsTable("sound/shout/dragonborn.wav");
}
}
public void OnClientPutInServer(int client)
{
g_grabbed[client] = INVALID_ENT_REFERENCE;
}
//////////////////////////////////////////////////////////////////////
///////////// Commands /////////////
//////////////////////////////////////////////////////////////////////
public Action Command_Dragonborn(int client, int target)
{
char player_authid[32];
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
if IsTargetInSightRange(client, target) *then
{
SDKHook(target, SDKHook_PreThink, OnPreThink);
GrabObject(target);
int grabbed = EntRefToEntIndex(g_grabbed[client]);
if(grabbed != INVALID_ENT_REFERENCE)
{
CPrintToChat(client, "{orange}Arngeir: {green}You now have an entity in your sights! Now, type !FusRoDah to use the power of the Voice.");
EmitSoundToClient(client, DRAGONBORN);
EmitSoundToClient(client, DRAGONBORN);
return Plugin_Handled;
}
else
{
CPrintToChat(client, "{orange}Arngeir: {red}My dear Dragonborn, you have done something wrong! Were you not aimed at a valid target?");
return Plugin_Handled;
}
}
else
{
CPrintToChat(client, "{orange}Arngeir: {red}You don't understand the power of the Voice.");
return Plugin_Handled;
}
}
public Action Command_FusRoDah(int client, int args)
{
if (!IsValidClient(client))
{
return Plugin_Handled;
}
char player_authid[32];
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
if (!StrEqual(player_authid, "STEAM_0:1:69132908", false))
{
CPrintToChat(client, "{orange}Arngeir: {red}Only the true Dragonborn can speak these words!");
return Plugin_Handled;
}
if(IsValidClient(client))
{
int grabbed = EntRefToEntIndex(g_grabbed[client]);
if(grabbed != INVALID_ENT_REFERENCE)
{
ThrowObject(client, grabbed, true);
EmitSoundToAll(FUSRODAH);
CPrintToChatAll("{fullred}Dovahkiin: {aqua}FUS RO DAH!!!!");
}
else
{
CPrintToChat(client, "{orange}Arngeir: {red}I'm sorry Dragonborn, but you must first prepare this shout. Aim at something, and then try !SetTarget.");
return Plugin_Handled;
}
}
return Plugin_Handled;
}
public Action Command_Disarm(int client, int args)
{
if (!IsValidClient(client))
{
return Plugin_Handled;
}
char player_authid[32];
GetClientAuthId(client, AuthId_Steam2, player_authid, sizeof(player_authid));
if (!StrEqual(player_authid, "STEAM_0:1:69132908", false))
{
CPrintToChat(client, "{orange}Arngeir: {red}I'm sorry, but only the true Dragonborn may release an entity.");
return Plugin_Handled;
}
if(IsValidClient(client))
{
int grabbed = EntRefToEntIndex(g_grabbed[client]);
if(grabbed != INVALID_ENT_REFERENCE)
{
ThrowObject(client, grabbed, false);
CPrintToChat(client, "{orange}Arngeir: {green}You have stopped pursuing your target! Use !SetTarget to choose a new target.");
return Plugin_Handled;
}
}
return Plugin_Handled;
}
void GrabObject(int client)
{
int grabbed = TraceToObject(client); // -1 for no collision, 0 for world
if (grabbed > 0)
{
if(grabbed > MaxClients)
{
char classname[13];
GetEntityClassname(grabbed, classname, 13);
if(StrEqual(classname, "prop_physics"))
{
int grabber = GetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker");
if(grabber > 0 && grabber <= MaxClients && IsClientInGame(grabber))
{
return; // another client is grabbing this object
}
SetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker", client);
AcceptEntityInput(grabbed, "EnableMotion");
}
SetEntityMoveType(grabbed, MOVETYPE_VPHYSICS);
}
else
{
SetEntityMoveType(grabbed, MOVETYPE_WALK);
PrintHintText(client,"Compelling %N",grabbed);
PrintHintText(grabbed,"%N is about to FUS RO DAH you!",client);
}
if(GetClientButtons(client) & IN_ATTACK2) // Store and maintain distance
{
float VecPos_grabbed[3], VecPos_client[3];
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", VecPos_grabbed);
GetClientEyePosition(client, VecPos_client);
gDistance[client] = GetVectorDistance(VecPos_grabbed, VecPos_client);
}
else
{
gDistance[client] = GRAB_DISTANCE; // Use prefab distance
}
float fVelocity[3] = { 0.0, 0.0, 0.0 };
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, fVelocity);
g_grabbed[client] = EntIndexToEntRef(grabbed);
}
}
void ThrowObject(int client, int grabbed, bool fusrodah)
{
if(fusrodah)
{
float vecView[3], vecFwd[3], vecPos[3], vecVel[3];
GetClientEyeAngles(client, vecView);
GetAngleVectors(vecView, vecFwd, NULL_VECTOR, NULL_VECTOR);
GetClientEyePosition(client, vecPos);
vecPos[0]+=vecFwd[0]*THROW_FORCE;
vecPos[1]+=vecFwd[1]*THROW_FORCE;
vecPos[2]+=vecFwd[2]*THROW_FORCE;
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", vecFwd);
SubtractVectors(vecPos, vecFwd, vecVel);
ScaleVector(vecVel, 10.0);
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, vecVel);
}
g_grabbed[client] = INVALID_ENT_REFERENCE;
if(grabbed > MaxClients)
{
char classname[13];
GetEntityClassname(grabbed, classname, 13);
if(StrEqual(classname, "prop_physics"))
{
SetEntPropEnt(grabbed, Prop_Data, "m_hPhysicsAttacker", 0);
}
}
}
//////////////////////////////////////////////////////////////////////
///////////// Prethink /////////////
//////////////////////////////////////////////////////////////////////
public void OnPreThink(int client)
{
int grabbed = EntRefToEntIndex(g_grabbed[client]);
if (grabbed != INVALID_ENT_REFERENCE)
{
float vecView[3], vecFwd[3], vecPos[3], vecVel[3];
GetClientEyeAngles(client, vecView);
GetAngleVectors(vecView, vecFwd, NULL_VECTOR, NULL_VECTOR);
GetClientEyePosition(client, vecPos);
vecPos[0]+=vecFwd[0]*gDistance[client];
vecPos[1]+=vecFwd[1]*gDistance[client];
vecPos[2]+=vecFwd[2]*gDistance[client];
GetEntPropVector(grabbed, Prop_Send, "m_vecOrigin", vecFwd);
SubtractVectors(vecPos, vecFwd, vecVel);
ScaleVector(vecVel, 10.0);
TeleportEntity(grabbed, NULL_VECTOR, NULL_VECTOR, vecVel);
}
}
//////////////////////////////////////////////////////////////////////
///////////// Events /////////////
//////////////////////////////////////////////////////////////////////
public void OnPlayerSpawn(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(IsValidClient(client))
{
for(int i = 1; i <= MaxClients; i++)
{
if(EntRefToEntIndex(g_grabbed[i]) == client)
{
g_grabbed[i] = INVALID_ENT_REFERENCE; // Clear grabs on them
}
}
}
return;
}
//////////////////////////////////////////////////////////////////////
///////////// Trace /////////////
//////////////////////////////////////////////////////////////////////
public int TraceToObject(int client)
{
float vecClientEyePos[3], vecClientEyeAng[3];
GetClientEyePosition(client, vecClientEyePos);
GetClientEyeAngles(client, vecClientEyeAng);
TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_PLAYERSOLID, RayType_Infinite, TraceRayGrab, client);
return TR_GetEntityIndex(INVALID_HANDLE);
}
public bool TraceRayGrab(int entityhit, int mask, any self)
{
if(entityhit > 0 && entityhit <= MaxClients)
{
if(IsPlayerAlive(entityhit) && entityhit != self)
{
return true;
}
else
{
return false;
}
}
else
{
char classname[13];
if(GetEntityClassname(entityhit, classname, 13) && (StrEqual(classname, "prop_physics") || StrEqual(classname, "tf_ammo_pack") || StrContains(classname, "tf_projectile") || StrContains(classname, "prop_") || StrContains(classname, "func_tracktrain") || StrEqual(classname, "prop_physics_override")))
{
return true;
}
}
return false;
}
public bool IsValidClient (int target)
{
if(target > 4096) target = EntRefToEntIndex(target);
if(target < 1 || target > MaxClients) return false;
if(!IsClientInGame(target)) return false;
if(IsFakeClient(target)) return false;
if(GetEntProp(target, Prop_Send, "m_bIsCoaching")) return false;
return true;
}