Add sm_gotocouch & effect intensity
This commit is contained in:
@@ -64,6 +64,7 @@ ConVar g_cvModel;
|
|||||||
ConVar g_cvPushScale;
|
ConVar g_cvPushScale;
|
||||||
ConVar g_cvPistolOnly;
|
ConVar g_cvPistolOnly;
|
||||||
ConVar g_cvEffect;
|
ConVar g_cvEffect;
|
||||||
|
ConVar g_cvEffectIntensity;
|
||||||
ConVar g_cvIgnoreClip;
|
ConVar g_cvIgnoreClip;
|
||||||
ConVar g_cvCollisionGroup;
|
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_IsPlaced", Native_IsPlaced);
|
||||||
CreateNative("Couch_Spawn", Native_Spawn);
|
CreateNative("Couch_Spawn", Native_Spawn);
|
||||||
CreateNative("Couch_Bring", Native_Bring);
|
CreateNative("Couch_Bring", Native_Bring);
|
||||||
|
CreateNative("Couch_Goto", Native_Goto);
|
||||||
CreateNative("Couch_Remove", Native_Remove);
|
CreateNative("Couch_Remove", Native_Remove);
|
||||||
CreateNative("Couch_IsEffectEnabled", Native_IsEffectEnabled);
|
CreateNative("Couch_IsEffectEnabled", Native_IsEffectEnabled);
|
||||||
CreateNative("Couch_SetEffectEnabled", Native_SetEffectEnabled);
|
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_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_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_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_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_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_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_cvModel.AddChangeHook(OnModelChanged);
|
||||||
g_cvEffect.AddChangeHook(OnEffectChanged);
|
g_cvEffect.AddChangeHook(OnEffectChanged);
|
||||||
|
g_cvEffectIntensity.AddChangeHook(OnEffectIntensityChanged);
|
||||||
|
|
||||||
AutoExecConfig(true, "Couch");
|
AutoExecConfig(true, "Couch");
|
||||||
|
|
||||||
@@ -338,6 +342,56 @@ bool TraceFilter_NotSelfOrCouch(int entity, int contentsMask, any client)
|
|||||||
return entity != client && entity != GetCouchIndex();
|
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.
|
// The only place the couch is created. Returns the entity or -1.
|
||||||
int SpawnCouchAt(const float vecOrigin[3], const float vecAngles[3])
|
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();
|
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.
|
// Brings the light and beacon in line with sm_couch_effect. Safe to call at any time.
|
||||||
void ApplyEffectState()
|
void ApplyEffectState()
|
||||||
{
|
{
|
||||||
@@ -699,7 +769,7 @@ int SpawnCouchLight(int couch)
|
|||||||
DispatchKeyValue(light, "pitch", "-90");
|
DispatchKeyValue(light, "pitch", "-90");
|
||||||
DispatchKeyValue(light, "angles", "0 0 0");
|
DispatchKeyValue(light, "angles", "0 0 0");
|
||||||
DispatchKeyValue(light, "_light", "255 255 255 255");
|
DispatchKeyValue(light, "_light", "255 255 255 255");
|
||||||
DispatchKeyValue(light, "brightness", "3");
|
DispatchKeyValueInt(light, "brightness", g_cvEffectIntensity.IntValue);
|
||||||
DispatchKeyValue(light, "distance", "130");
|
DispatchKeyValue(light, "distance", "130");
|
||||||
DispatchKeyValue(light, "spotlight_radius", "70");
|
DispatchKeyValue(light, "spotlight_radius", "70");
|
||||||
|
|
||||||
@@ -839,6 +909,26 @@ public any Native_Bring(Handle plugin, int numParams)
|
|||||||
return true;
|
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)
|
public any Native_Remove(Handle plugin, int numParams)
|
||||||
{
|
{
|
||||||
bool bHadSomething = g_bPlaced || GetCouchIndex() != -1;
|
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_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_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_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_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");
|
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;
|
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.
|
// Needs no position, so it also works from the server console.
|
||||||
public Action Command_RemoveCouch(int client, int args)
|
public Action Command_RemoveCouch(int client, int args)
|
||||||
{
|
{
|
||||||
@@ -128,7 +138,7 @@ void DoSpawn(int client)
|
|||||||
return;
|
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);
|
LogAction(client, -1, "\"%L\" spawned the couch.", client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +154,24 @@ void DoBring(int client)
|
|||||||
LogAction(client, -1, "\"%L\" brought the couch.", 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)
|
void DoRemove(int client)
|
||||||
{
|
{
|
||||||
if (!Couch_Remove())
|
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.
|
// 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("spawn", "Spawn couch at crosshair", bHasCouch ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
|
||||||
menu.AddItem("bring", "Bring couch to crosshair", bHasCouch ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
|
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)
|
if (bHasCouch)
|
||||||
menu.AddItem("remove", "Remove couch");
|
menu.AddItem("remove", "Remove couch");
|
||||||
@@ -230,6 +259,8 @@ public int MenuHandler_Couch(Menu menu, MenuAction action, int param1, int param
|
|||||||
DoSpawn(client);
|
DoSpawn(client);
|
||||||
else if (StrEqual(sInfo, "bring"))
|
else if (StrEqual(sInfo, "bring"))
|
||||||
DoBring(client);
|
DoBring(client);
|
||||||
|
else if (StrEqual(sInfo, "goto"))
|
||||||
|
DoGoto(client);
|
||||||
else if (StrEqual(sInfo, "remove"))
|
else if (StrEqual(sInfo, "remove"))
|
||||||
DoRemove(client);
|
DoRemove(client);
|
||||||
else if (StrEqual(sInfo, "effect"))
|
else if (StrEqual(sInfo, "effect"))
|
||||||
|
|||||||
@@ -67,6 +67,15 @@ native int Couch_Spawn(int client);
|
|||||||
*/
|
*/
|
||||||
native bool Couch_Bring(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.
|
* Removes the couch and forgets its placement.
|
||||||
*
|
*
|
||||||
@@ -131,6 +140,7 @@ public SharedPlugin __pl_Couch =
|
|||||||
MarkNativeAsOptional("Couch_IsPlaced");
|
MarkNativeAsOptional("Couch_IsPlaced");
|
||||||
MarkNativeAsOptional("Couch_Spawn");
|
MarkNativeAsOptional("Couch_Spawn");
|
||||||
MarkNativeAsOptional("Couch_Bring");
|
MarkNativeAsOptional("Couch_Bring");
|
||||||
|
MarkNativeAsOptional("Couch_Goto");
|
||||||
MarkNativeAsOptional("Couch_Remove");
|
MarkNativeAsOptional("Couch_Remove");
|
||||||
MarkNativeAsOptional("Couch_IsEffectEnabled");
|
MarkNativeAsOptional("Couch_IsEffectEnabled");
|
||||||
MarkNativeAsOptional("Couch_SetEffectEnabled");
|
MarkNativeAsOptional("Couch_SetEffectEnabled");
|
||||||
|
|||||||
Reference in New Issue
Block a user