Add sm_gotocouch & effect intensity
This commit is contained in:
@@ -64,6 +64,7 @@ ConVar g_cvModel;
|
||||
ConVar g_cvPushScale;
|
||||
ConVar g_cvPistolOnly;
|
||||
ConVar g_cvEffect;
|
||||
ConVar g_cvEffectIntensity;
|
||||
ConVar g_cvIgnoreClip;
|
||||
ConVar g_cvCollisionGroup;
|
||||
|
||||
@@ -116,6 +117,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
|
||||
CreateNative("Couch_IsPlaced", Native_IsPlaced);
|
||||
CreateNative("Couch_Spawn", Native_Spawn);
|
||||
CreateNative("Couch_Bring", Native_Bring);
|
||||
CreateNative("Couch_Goto", Native_Goto);
|
||||
CreateNative("Couch_Remove", Native_Remove);
|
||||
CreateNative("Couch_IsEffectEnabled", Native_IsEffectEnabled);
|
||||
CreateNative("Couch_SetEffectEnabled", Native_SetEffectEnabled);
|
||||
@@ -141,12 +143,14 @@ public void OnPluginStart()
|
||||
g_cvPushScale = CreateConVar("sm_couch_push_scale", "1.0", "Multiplier on the force bullets apply to the couch. 1.0 is the engine's own push.", FCVAR_NOTIFY, true, 0.0, true, 100.0);
|
||||
g_cvPistolOnly = CreateConVar("sm_couch_pistol_only", "0", "Only pistols and knives move the couch; other guns and grenades are ignored.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
|
||||
g_cvEffect = CreateConVar("sm_couch_effect", "0", "Colour cycle and pulsing light on the couch.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
|
||||
g_cvEffectIntensity = CreateConVar("sm_couch_effect_intensity", "3", "Brightness of the couch effect light. 0 is off, 3 is the default, 8 is very bright. Applies immediately.", FCVAR_NOTIFY, true, 0.0, true, 10.0);
|
||||
g_cvIgnoreClip = CreateConVar("sm_couch_ignore_clip", "1", "Let the couch pass through func_clip_vphysics brushes.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
|
||||
g_cvTierRequirement = CreateConVar("sm_couch_tier_requirement", "0", "Minimum playtime tier needed to shoot the couch.", FCVAR_NOTIFY, true, 0.0);
|
||||
g_cvCollisionGroup = CreateConVar("sm_couch_collision_group", "5", "Collision group given to the couch at spawn. 5 (player), 0 (prop)", FCVAR_NOTIFY, true, 0.0, true, 20.0);
|
||||
|
||||
g_cvModel.AddChangeHook(OnModelChanged);
|
||||
g_cvEffect.AddChangeHook(OnEffectChanged);
|
||||
g_cvEffectIntensity.AddChangeHook(OnEffectIntensityChanged);
|
||||
|
||||
AutoExecConfig(true, "Couch");
|
||||
|
||||
@@ -338,6 +342,56 @@ bool TraceFilter_NotSelfOrCouch(int entity, int contentsMask, any client)
|
||||
return entity != client && entity != GetCouchIndex();
|
||||
}
|
||||
|
||||
// Landing spot for a player sent to the couch: on top of it when it is upright, otherwise beside it.
|
||||
// The couch is kept solid in the trace so the player never arrives inside it.
|
||||
#define COUCH_GOTO_LIFT 8.0
|
||||
#define COUCH_GOTO_SIDE_GAP 24.0
|
||||
|
||||
bool FindCouchLandingSpot(int client, int couch, float vecSpot[3])
|
||||
{
|
||||
float vecOrigin[3];
|
||||
float vecMaxs[3];
|
||||
GetEntPropVector(couch, Prop_Send, "m_vecOrigin", vecOrigin);
|
||||
GetEntPropVector(couch, Prop_Send, "m_vecMaxs", vecMaxs);
|
||||
|
||||
// Tried in order: on top when upright, on top when tipped over, then each side.
|
||||
float fTop = vecMaxs[2] + COUCH_GOTO_LIFT;
|
||||
float fTipped = GetVectorLength(vecMaxs) + COUCH_GOTO_LIFT;
|
||||
float fSideX = vecMaxs[0] + COUCH_GOTO_SIDE_GAP;
|
||||
float fSideY = vecMaxs[1] + COUCH_GOTO_SIDE_GAP;
|
||||
|
||||
float vecOffsets[6][3];
|
||||
vecOffsets[0][2] = fTop;
|
||||
vecOffsets[1][2] = fTipped;
|
||||
vecOffsets[2][0] = fSideX; vecOffsets[2][2] = COUCH_GOTO_LIFT;
|
||||
vecOffsets[3][0] = -fSideX; vecOffsets[3][2] = COUCH_GOTO_LIFT;
|
||||
vecOffsets[4][1] = fSideY; vecOffsets[4][2] = COUCH_GOTO_LIFT;
|
||||
vecOffsets[5][1] = -fSideY; vecOffsets[5][2] = COUCH_GOTO_LIFT;
|
||||
|
||||
float vecMins[3];
|
||||
float vecPlayerMaxs[3];
|
||||
GetClientMins(client, vecMins);
|
||||
GetClientMaxs(client, vecPlayerMaxs);
|
||||
|
||||
for (int i = 0; i < sizeof(vecOffsets); i++)
|
||||
{
|
||||
AddVectors(vecOrigin, vecOffsets[i], vecSpot);
|
||||
|
||||
TR_TraceHullFilter(vecSpot, vecSpot, vecMins, vecPlayerMaxs, MASK_PLAYERSOLID, TraceFilter_NotSelf, client);
|
||||
if (!TR_DidHit())
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing clear; go high above the couch so the command still does something.
|
||||
AddVectors(vecOrigin, vecOffsets[1], vecSpot);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceFilter_NotSelf(int entity, int contentsMask, any client)
|
||||
{
|
||||
return entity != client;
|
||||
}
|
||||
|
||||
// The only place the couch is created. Returns the entity or -1.
|
||||
int SpawnCouchAt(const float vecOrigin[3], const float vecAngles[3])
|
||||
{
|
||||
@@ -664,6 +718,22 @@ public void OnEffectChanged(ConVar convar, const char[] oldValue, const char[] n
|
||||
ApplyEffectState();
|
||||
}
|
||||
|
||||
public void OnEffectIntensityChanged(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
ApplyLightIntensity();
|
||||
}
|
||||
|
||||
// light_dynamic takes brightness as an input, so a running light updates in place.
|
||||
void ApplyLightIntensity()
|
||||
{
|
||||
int light = GetLightIndex();
|
||||
if (light == -1)
|
||||
return;
|
||||
|
||||
SetVariantInt(g_cvEffectIntensity.IntValue);
|
||||
AcceptEntityInput(light, "brightness");
|
||||
}
|
||||
|
||||
// Brings the light and beacon in line with sm_couch_effect. Safe to call at any time.
|
||||
void ApplyEffectState()
|
||||
{
|
||||
@@ -699,7 +769,7 @@ int SpawnCouchLight(int couch)
|
||||
DispatchKeyValue(light, "pitch", "-90");
|
||||
DispatchKeyValue(light, "angles", "0 0 0");
|
||||
DispatchKeyValue(light, "_light", "255 255 255 255");
|
||||
DispatchKeyValue(light, "brightness", "3");
|
||||
DispatchKeyValueInt(light, "brightness", g_cvEffectIntensity.IntValue);
|
||||
DispatchKeyValue(light, "distance", "130");
|
||||
DispatchKeyValue(light, "spotlight_radius", "70");
|
||||
|
||||
@@ -839,6 +909,26 @@ public any Native_Bring(Handle plugin, int numParams)
|
||||
return true;
|
||||
}
|
||||
|
||||
public any Native_Goto(Handle plugin, int numParams)
|
||||
{
|
||||
int client = GetNativeCell(1);
|
||||
if (client < 1 || client > MaxClients || !IsClientInGame(client))
|
||||
return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client);
|
||||
|
||||
int couch = GetCouchIndex();
|
||||
if (couch == -1)
|
||||
return false;
|
||||
|
||||
float vecSpot[3];
|
||||
FindCouchLandingSpot(client, couch, vecSpot);
|
||||
|
||||
// Arrives still, keeps their view angles.
|
||||
float vecStill[3];
|
||||
TeleportEntity(client, vecSpot, NULL_VECTOR, vecStill);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public any Native_Remove(Handle plugin, int numParams)
|
||||
{
|
||||
bool bHadSomething = g_bPlaced || GetCouchIndex() != -1;
|
||||
|
||||
@@ -23,6 +23,7 @@ public void OnPluginStart()
|
||||
RegAdminCmd("sm_couch", Command_Couch, ADMFLAG_CHANGEMAP, "Opens the couch menu");
|
||||
RegAdminCmd("sm_spawncouch", Command_SpawnCouch, ADMFLAG_CHANGEMAP, "Spawns the couch where you are aiming");
|
||||
RegAdminCmd("sm_bringcouch", Command_BringCouch, ADMFLAG_CHANGEMAP, "Brings the couch to where you are aiming");
|
||||
RegAdminCmd("sm_gotocouch", Command_GotoCouch, ADMFLAG_CHANGEMAP, "Teleports you to the couch");
|
||||
RegAdminCmd("sm_removecouch", Command_RemoveCouch, ADMFLAG_CHANGEMAP, "Removes the couch");
|
||||
RegAdminCmd("sm_couchpistolonly", Command_PistolOnly, ADMFLAG_CHANGEMAP, "sm_couchpistolonly [0|1] - only pistols and knives move the couch; no argument toggles");
|
||||
}
|
||||
@@ -75,6 +76,15 @@ public Action Command_BringCouch(int client, int args)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_GotoCouch(int client, int args)
|
||||
{
|
||||
if (!RequireInGame(client) || !RequireCore(client))
|
||||
return Plugin_Handled;
|
||||
|
||||
DoGoto(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Needs no position, so it also works from the server console.
|
||||
public Action Command_RemoveCouch(int client, int args)
|
||||
{
|
||||
@@ -128,7 +138,7 @@ void DoSpawn(int client)
|
||||
return;
|
||||
}
|
||||
|
||||
ShowActivity2(client, PREFIX, "\x01Spawned the \x04couch\x01.");
|
||||
ShowActivity2(client, PREFIX, "\x01Spawned the \x04couch\x01, it will respawn here each round until removed.");
|
||||
LogAction(client, -1, "\"%L\" spawned the couch.", client);
|
||||
}
|
||||
|
||||
@@ -144,6 +154,24 @@ void DoBring(int client)
|
||||
LogAction(client, -1, "\"%L\" brought the couch.", client);
|
||||
}
|
||||
|
||||
void DoGoto(int client)
|
||||
{
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] You must be alive to go to the couch.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Couch_Goto(client))
|
||||
{
|
||||
ReplyToCommand(client, "[SM] There is no couch to go to. Use sm_spawncouch first.");
|
||||
return;
|
||||
}
|
||||
|
||||
ShowActivity2(client, PREFIX, "\x01Teleported to the \x04couch\x01.");
|
||||
LogAction(client, -1, "\"%L\" teleported to the couch.", client);
|
||||
}
|
||||
|
||||
void DoRemove(int client)
|
||||
{
|
||||
if (!Couch_Remove())
|
||||
@@ -190,6 +218,7 @@ void ShowCouchMenu(int client)
|
||||
// With a couch out, bring is the way to move it; without one there is nothing to bring.
|
||||
menu.AddItem("spawn", "Spawn couch at crosshair", bHasCouch ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
|
||||
menu.AddItem("bring", "Bring couch to crosshair", bHasCouch ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
|
||||
menu.AddItem("goto", "Teleport to couch", bHasCouch ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
|
||||
|
||||
if (bHasCouch)
|
||||
menu.AddItem("remove", "Remove couch");
|
||||
@@ -230,6 +259,8 @@ public int MenuHandler_Couch(Menu menu, MenuAction action, int param1, int param
|
||||
DoSpawn(client);
|
||||
else if (StrEqual(sInfo, "bring"))
|
||||
DoBring(client);
|
||||
else if (StrEqual(sInfo, "goto"))
|
||||
DoGoto(client);
|
||||
else if (StrEqual(sInfo, "remove"))
|
||||
DoRemove(client);
|
||||
else if (StrEqual(sInfo, "effect"))
|
||||
|
||||
@@ -67,6 +67,15 @@ native int Couch_Spawn(int client);
|
||||
*/
|
||||
native bool Couch_Bring(int client);
|
||||
|
||||
/**
|
||||
* Teleports the client onto the couch, or beside it when the top is blocked. The client keeps
|
||||
* their view angles and arrives with no velocity.
|
||||
*
|
||||
* @param client Client to teleport. Must be in game.
|
||||
* @return True on success, false if there is no couch.
|
||||
*/
|
||||
native bool Couch_Goto(int client);
|
||||
|
||||
/**
|
||||
* Removes the couch and forgets its placement.
|
||||
*
|
||||
@@ -131,6 +140,7 @@ public SharedPlugin __pl_Couch =
|
||||
MarkNativeAsOptional("Couch_IsPlaced");
|
||||
MarkNativeAsOptional("Couch_Spawn");
|
||||
MarkNativeAsOptional("Couch_Bring");
|
||||
MarkNativeAsOptional("Couch_Goto");
|
||||
MarkNativeAsOptional("Couch_Remove");
|
||||
MarkNativeAsOptional("Couch_IsEffectEnabled");
|
||||
MarkNativeAsOptional("Couch_SetEffectEnabled");
|
||||
|
||||
Reference in New Issue
Block a user