AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Snippets and Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=112)
-   -   [TF2] Player-Following Annotations Snippet (https://forums.alliedmods.net/showthread.php?t=232383)

404UserNotFound 12-29-2013 17:59

[TF2] Player-Following Annotations Snippet
 
So I started working on something I was calling Admin Anno-tags (combination of Annotation and Tags). Then I ran into an issue where the annotations were visible through walls, and at any distance, so I gave up on it.

I also originally had some code in there to hide the annotations when a player died, but I didn't do it properly, so if a player died, all annotations would disappear for them. Once an admin respawned, the annotations would re-appear to that player. It was incredibly glitchy. So I commented it out.

Luckily, I was smart enough to keep the code, so I've decided to post it here. I know that Geit's Annotations plugin was unapproved, and people are wanting that to be fixed, so hopefully my code can be of some use.

NOTE 1: Some code was taken from that excellent Gravestone Markers plugin made by Friagram, in regards to the Bitstring stuff, that I was having trouble with.

NOTE 2: If you do make a plugin using any of this code, you do NOT have to give me credit. You can if you want to, but I don't find it necessary. Do give credit to Friagram though, he deserves it!

PHP Code:

// Massive credit to Friagram for his Gravestone Markers plugin. Without that, I wouldn't have gotten this far!

#include <sourcemod>
#include <sdktools>
#include <tf2_stocks>

#pragma semicolon 1

#define PLUGIN_VERSION "1.0"
#define SOUND_NULL    "vo/null.wav"

public Plugin:myinfo =
{
    
name "[WIP] Annotation Admin Tags",
    
author "abrandnewday",
    
description "Adds neat little annotation tags for admins",
    
version PLUGIN_VERSION,
}

public 
OnPluginStart()
{
    
HookEvent("player_spawn"Event_PlayerSpawn);
//    HookEvent("player_death", Event_PlayerDeath);
}

/*
// Event: Plugin has been unloaded, hide annotations.
public OnPluginEnd()
{
    for (new i=1; i <= MaxClients; i++)
    {
        HideAnnotation(i);
    }
}
*/

// Event: Player has spawned, check if they're an admin, and if so, assign the annotation.
public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast
{
    new 
user GetEventInt(event"userid");
    new 
client GetClientOfUserId(user);
    
    if(
GetUserFlagBits(client) && ADMFLAG_GENERIC
    {
        
ShowAnnotation(client);
    }
    return 
Plugin_Continue;
}

/*
// Event: Player has died, hide the annotation.
public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
    new user = GetEventInt(event, "userid");
    new client = GetClientOfUserId(user);

    if(GetUserFlagBits(client) && ADMFLAG_GENERIC)
    {
        HideAnnotation(client);
    }
    return Plugin_Continue;
}
*/

// Function: Show the annotation!
ShowAnnotation(client)
{
    for (new 
i=1<= MaxClientsi++)
    {
        new 
bitstring RoundFloat(Pow(2.0float(i)));
        if (
bitstring 1)
        {
            new 
Handle:event CreateEvent("show_annotation");
            if (
event != INVALID_HANDLE)
            {
                
SetEventFloat(event"lifetime"999999.0); // Long-ass lifetime.
                
SetEventInt(event"id"i);
                
SetEventString(event"text""Admin"); // Displays "Admin" in the annotation
                
SetEventInt(event"visibilityBitfield"bitstring);
                
SetEventInt(event"follow_entindex"client); // Follow the player
                
SetEventString(event"play_sound"SOUND_NULL);
                
SetEventBool(event"show_distance"100); // Not sure what the distance is measured in
                
FireEvent(event);
            }
        }
    }
}

/*
// Function: Hide Annotation
HideAnnotation(client)
{
    new Handle:event = CreateEvent("hide_annotation");
    if(event == INVALID_HANDLE) return;
    SetEventInt(event, "id", client);
    FireEvent(event);
}
*/

// Function: Build Bitstring for visibility
public BuildBitString(Float:position[3])
{
    new 
bitstring 1;
    for (new 
client=1client <= MaxClientsclient++)
    {
        if (
IsClientInGame(client))
        {
            
decl Float:EyePos[3];
            
GetClientEyePosition(clientEyePos);
            if (
GetVectorDistance(positionEyePos) < 400)
            {
                
bitstring |= RoundFloat(Pow(2.0float(client)));
            }
        }
    }
    return 
bitstring;
}

/*
// Old bitstring code I used to use.
DoFilter(client)
{
    new bitstring;
    for(new viewer = 1; viewer <= MaxClients; viewer++)
    {
        if(client == viewer) continue;
        if(IsClientInGame(viewer) && IsPlayerAlive(viewer) && IsWithinRange(client, viewer))
        {
            bitstring |= (1 << viewer);
        }
    }
    return bitstring;
}

bool:IsWithinRange(client, viewer)
{
    new Float:clientpos[3], Float:viewerpos[3];
    GetClientAbsOrigin(client, clientpos);
    GetClientAbsOrigin(viewer, viewerpos);
    if(GetVectorDistance(clientpos, viewerpos) <= 500.0) return true;
    else return false;

*/ 


friagram 12-30-2013 06:06

Re: [TF2] Player-Following Annotations Snippet
 
...
You need to do something like what I did here to make these work properly: https://forums.alliedmods.net/showthread.php?p=1946768

404UserNotFound 12-30-2013 10:49

Re: [TF2] Player-Following Annotations Snippet
 
Quote:

Originally Posted by friagram (Post 2078379)
...
You need to do something like what I did here to make these work properly: https://forums.alliedmods.net/showthread.php?p=1946768

I used snippets from your plugin. Everything works correctly except for the visibility bitfield.

But hey, it's not my problem anymore. Hooray for public access!

Mitchell 12-30-2013 11:58

Re: [TF2] Player-Following Annotations Snippet
 
Mind explaining how the visibility Field works?

404UserNotFound 12-30-2013 12:31

Re: [TF2] Player-Following Annotations Snippet
 
Quote:

Originally Posted by Mitchell (Post 2078567)
Mind explaining how the visibility Field works?

I'm not really sure how, that's more or less Friagram's area of expertise. The code was taken from his gravestone plugin, and modified so it didn't use a convar. For some reason though, the annotations would stay visible even if you were to noclip WAY out into the void of a map.

The original visibility bitstring code that is commented out at the bottom, I believe that worked.

I'm no expert in this annotation and bitstring stuff, but I just love the idea of it. I mean, it could be used in plugins like VS Saxton Hale/Freak Fortress 2 (i.e. when the boss is visible to a player, have an annotation follow the boss that says the bosses name, such as "Saxton Hale!" or "Horsemann Jr!")

EDIT: Oh, and as mentioned in the main post, my code is a tad wonky, so if an admin spawns, the tag becomes visible to people. But if an admin dies (with the player_death code uncommented) all the annotations on every admin disappear. From there, an admin has to respawn for the tag to become visible. I have no clue how to make annotations with differential IDs so that if Admin A dies, the annotations on Admin B/C/etc don't disappear from everyone's view.

Mitchell 12-30-2013 13:30

Re: [TF2] Player-Following Annotations Snippet
 
I was asking because i want to make an annotation that only certain players can see over another player's head.

404UserNotFound 12-30-2013 13:33

Re: [TF2] Player-Following Annotations Snippet
 
Quote:

Originally Posted by Mitchell (Post 2078607)
I was asking because i want to make an annotation that only certain players can see over another player's head.

Hmm....yeah, I'm not exactly sure. Sorry :cry:

EDIT: Actually, I think I may have an idea. Gimme a mo!

PHP Code:

public BuildBitString(Float:position[3])
{
    new 
bitstring 1;
    for (new 
client=1client <= MaxClientsclient++)
    {
        
// Check if client is ingame, and is a donator. Not sure if this'd work though.
        
if (IsClientInGame(client) && GetUserFlagBits(client) && ADMFLAG_CUSTOM1)
        {
            
decl Float:EyePos[3];
            
GetClientEyePosition(clientEyePos);
            if (
GetVectorDistance(positionEyePos) < 400)
            {
                
bitstring |= RoundFloat(Pow(2.0float(client)));
            }
        }
    }
    return 
bitstring;



Mitchell 12-30-2013 13:52

Re: [TF2] Player-Following Annotations Snippet
 
Just making sure, ill have to test this at a later moment but say if i want to show it to only one player i would just make the bitstring: "2^(clientindex)" correct?

404UserNotFound 12-30-2013 14:51

Re: [TF2] Player-Following Annotations Snippet
 
Quote:

Originally Posted by Mitchell (Post 2078622)
Just making sure, ill have to test this at a later moment but say if i want to show it to only one player i would just make the bitstring: "2^(clientindex)" correct?

Uh.....I don't know.....I'm not at that level of coding :cry:

Powerlord 12-30-2013 16:34

Re: [TF2] Player-Following Annotations Snippet
 
Quote:

Originally Posted by Mitchell (Post 2078622)
Just making sure, ill have to test this at a later moment but say if i want to show it to only one player i would just make the bitstring: "2^(clientindex)" correct?

For bitfields, why not just use (left) bitshifting? That's what it exists for.

The only catch is that I'm not sure if it counts from 0 or not.

So, here's both versions... try both and see if they work.
PHP Code:

new bitfield 0;

// Iterating through all clients to build a visibility bitfield of all alive players
for (new client 1client <= MaxClientsi++)
{
    if (
IsClientInGame(client) && IsPlayerAlive(client))
    {
         
// 1-based
        
bitfield |= (<< client);
        
// 0-based
        //bitfield |= (1 << (client - 1));
    
}
}

// or for a single client

new bitfield = (<< client); 

(I'm assuming 1-based is correct based on glancing at the gravestone plugin's BuildBitString)

Edit: For those of you who don't know what bitshifting does, I'll give a quick example.

Pretend this is a series of 8 bits: 0b00000000 (0b is used to denote it's binary... it's a GCC thing)
Like a standard decimal, the lowest number is the one at the far right. What (1 << client) does is tell it to take the number 1 and move it to the left client bits. So:

Code:

(1 << 0) = 0b00000001
(1 << 1) = 0b00000010
(1 << 2) = 0b00000100

and there are 32-bits to a cell in Pawn.

It's a cheap way of storing a bunch of bools as a single value.


All times are GMT -4. The time now is 23:43.

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