PDA

View Full Version : [REQ][CSGO] Team Icons above heads.


Unbelievable
06-21-2016, 08:58
I wanted to ask if someone could create a simple plugin that would use a sprite to display team icons on above their heads.

For example:
Counter-Terrorist has a sprite above head saying "CT"
Terrorist has a sprite above head saying "T"

Why do i want this? Well if you ran a server with custom skins and its team deathmatch you can sometimes get confused of who is in what team.

I found a plugin that is similar to what I want but only works for admins not player teams.
https://forums.alliedmods.net/showthread.php?t=252600

Would anyone be able to edit this and allow team icons instead of just admin ones?

Arkarr
06-21-2016, 12:42
Removed.


Not tested through.

----------------------------------------

Take a look here : https://forums.alliedmods.net/showpost.php?p=2430520&postcount=11

Unbelievable
06-22-2016, 04:31
I'll give it a test bro thanks for the reply, I'll let you know if there's any problems.

Unbelievable
06-22-2016, 06:05
How would i select which team the icon is applied for?? can there be a option where we set which icon is used for select team
example: "Team" "2" or "Team" "3"

"File"
{
"01" // Specify whatever. It doesn't matter at all.
{
"class" "Terrorist" // IMPORTANT: This is going to be your reference sprite name, choose it carefully. DON'T REPLICATE IT
"vmt" "materials/sprites/terrorist.vmt" // Filename
"vtf" "materials/sprites/terrorist.vtf"
}
"02"
{
"class" "CounterTerrorist" // IMPORTANT: This is going to be your reference sprite name, choose it carefully. DON'T REPLICATE IT
"vmt" "materials/sprites/counterterrorist.vmt"
"vtf" "materials/sprites/counterterrorist.vtf"
}
}

Arkarr
06-22-2016, 06:34
Wait, it does work ? Also, I just removed the auth part, so if you have troubles configuring it, post it on the plugin thread.

Unbelievable
06-22-2016, 06:42
Wait, it does work ? Also, I just removed the auth part, so if you have troubles configuring it, post it on the plugin thread.

The config is not the problem, its just getting the config to show the icon for selected team and then applying it to players in that team (which the plugin has no option for).
Would you be able to add a section in plugin to allow you to set which team it loads for?

Arkarr
06-22-2016, 07:36
The config is not the problem, its just getting the config to show the icon for selected team and then applying it to players in that team (which the plugin has no option for).
Would you be able to add a section in plugin to allow you to set which team it loads for?
Yeah.... later.

Unbelievable
06-22-2016, 09:20
Yeah.... later.

Sorry man i don't mean to be rude thank you for you're help +1

Arkarr
06-22-2016, 09:56
Sorry man i don't mean to be rude thank you for you're help +1
Uh, you wasn't rude at all, I just don't have time yet.

Unbelievable
06-25-2016, 08:11
Can anyone help?

Arkarr
06-25-2016, 12:25
Can anyone help?
Yeah. Accepted value for "team" : "T", "RED", "SURVIVOR", "CT", "BLU", "INFECTED".
Exemple :

// "Icon"
// {
// "File"
// {
// "01"
// {
// "class" "OtherClass" // IMPORTANT: This is going to be your reference sprite name, choose it carefully. DON'T REPLICATE IT
// "vmt" "materials/sprites/other.vmt"
// "vtf" "materials/sprites/other.vtf"
// }
// }
// "Player"
// { // STACK STRUCTURE, the plugin will read it from up to down, so you can adjust the order to specify what you want. For example:
// "PlayerOther"
// { // All other than above players
// "auth" "flags"
// "attribute" "" // Null flags mean all
// "class" "OtherClass"
// "scale" "" // Means default engine scale(1.0)
// "team" "CT"
// }
// }
// }

Again, not tested, so some random result might happen, or not result at all DX !
Anyway, here is the code :

#include <sourcemod>
#include <sdktools>

#pragma semicolon 1

#define DEBUG

#define CONFIGPATH "configs/icon.cfg"

public Plugin:myinfo =
{
name = "Icon",
author = "benefitOfLaughing",
description = "Put an icon above the head",
version = "0.3",
url = "www.sourcemod.net"
};

enum AuthOption
{
AuthOption_Flags,
AuthOption_Steam,
};

new bool:g_bPrecached = false;
new g_Models[MAXPLAYERS + 1] = {-1, ...};
new Handle:g_hClasses = INVALID_HANDLE;
new Handle:g_hClassIndexes = INVALID_HANDLE;
new Handle:g_hAuthStack = INVALID_HANDLE;

public OnPluginStart()
{
Initialize();

HookEvent("player_spawn", Event_PlayerSpawn);
}

public OnPluginEnd()
{
for(new i = 0; i < sizeof(g_Models); i++) {
Entity_SafeDelete(g_Models[i]);
}
}

public OnMapStart()
{
g_bPrecached = false;

new Handle:hKv = Kv_Parse();
if(hKv == INVALID_HANDLE) {
SetFailState("I cannot load keyvalue file from %s", CONFIGPATH);
}

LoadFileFromConfig(hKv);
LoadPlayerFromConfig(hKv);

CloseHandle(hKv);

g_bPrecached = true;
}

public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontbroadcast)
{
if(!g_bPrecached) return Plugin_Continue;

new client = GetClientOfUserId(GetEventInt(event, "userid"));

if(IsClientInGame(client) && IsPlayerAlive(client)) {
if(GiveModel(client)) {
#if defined DEBUG
LogMessage("Give Model for client %d", client);
#endif
}
}

return Plugin_Continue;
}

public OnGameFrame()
{
for(new i = 1; i <= MaxClients; i++) {
if(IsValidEntity(g_Models[i])) {
CheckClientAliveForModel(i);
}
}
}

CheckClientAliveForModel(client)
{
if(!IsClientInGame(client) || !IsPlayerAlive(client)) {
#if defined DEBUG
LogMessage("Delete Model from client %d", client);
#endif
Entity_SafeDelete(g_Models[client]);
g_Models[client] = -1;
}
}

bool:GiveModel(client)
{
new String:sAttribute[30];
new String:sClass[50];
new String:sScale[10];
new String:sTeam[20];

for(new i = 0; i < GetArraySize(g_hAuthStack); i++) {
new Handle:datapack = Handle:GetArrayCell(g_hAuthStack, i);
ResetPack(datapack);

ReadPackString(datapack, sAttribute, sizeof(sAttribute));
ReadPackString(datapack, sClass, sizeof(sClass));
ReadPackString(datapack, sScale, sizeof(sScale));
ReadPackString(datapack, sTeam, sizeof(sTeam));

if(!ClassGiveModel(client, sClass, sScale, sTeam)) {
LogMessage("Couldnt give class %s for client %d", sClass, client);
return false;
} else {
// Success.
return true;
}
}
// Not found.
return false;
}

Handle:Kv_Parse()
{
new String:filepath[PLATFORM_MAX_PATH];
new Handle:kv = CreateKeyValues("Icon");

BuildPath(Path_SM, filepath, sizeof(filepath), CONFIGPATH);

if(!FileToKeyValues(kv, filepath))
return INVALID_HANDLE;

return kv;
}

Initialize()
{
g_hClasses = CreateArray();
g_hClassIndexes = CreateTrie();
g_hAuthStack = CreateArray();
}

CreateIcon(const String:vmt[], const String:scale[])
{
#if defined DEBUG
LogMessage("CreateIcon vmt: %s, scale: %s", vmt, scale);
#endif
new sprite = CreateEntityByName("env_sprite_oriented");

if(sprite == -1) return -1;

DispatchKeyValue(sprite, "classname", "env_sprite_oriented");
DispatchKeyValue(sprite, "spawnflags", "1");
DispatchKeyValue(sprite, "scale", scale);
DispatchKeyValue(sprite, "rendermode", "1");
DispatchKeyValue(sprite, "rendercolor", "255 255 255");
DispatchKeyValue(sprite, "model", vmt);
if(DispatchSpawn(sprite)) return sprite;

return -1;
}

PlaceAndBindIcon(client, entity)
{
new Float:origin[3];

if(IsValidEntity(entity)) {
GetClientAbsOrigin(client, origin);
origin[2] = origin[2] + 90.0;
TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR);

SetVariantString("!activator");
AcceptEntityInput(entity, "SetParent", client);
}
}

Entity_SafeDelete(entity)
{
if(IsValidEntity(entity)) {
AcceptEntityInput(entity, "Kill");
}
}

LoadPlayerFromConfig(Handle:kv)
{
new String:sAttribute[30];
new String:sClass[50];
new String:sScale[10];
new String:sTeam[20];

ClearArray(g_hAuthStack);

KvRewind(kv);

if(!KvJumpToKey(kv, "Player")) return false;
if(!KvGotoFirstSubKey(kv)) return false;

do {
KvGetString(kv, "class", sClass, sizeof(sClass));

if(sClass[0] == '\0') {
LogMessage("Undefined class name in \"Player %s\"", sClass);
continue;
}

KvGetString(kv, "attribute", sAttribute, sizeof(sAttribute));
KvGetString(kv, "scale", sScale, sizeof(sScale));
KvGetString(kv, "team", sTeam, sizeof(sTeam));

new Handle:datapack = CreateDataPack();

// 1: Auth Attribute
WritePackString(datapack, sAttribute);
// 2: Class Name
WritePackString(datapack, sClass);
// 3: Scale
WritePackString(datapack, sScale);
// 4: Teams
WritePackString(datapack, sTeam);

PushArrayCell(g_hAuthStack, datapack);
} while(KvGotoNextKey(kv));

return 0;
}

// Load config to turn file information into classes
LoadFileFromConfig(Handle:kv)
{
new Handle:hPrecachedFiles = CreateArray();
new String:sClass[50];
new String:sVMT[PLATFORM_MAX_PATH];
new String:sVTF[PLATFORM_MAX_PATH];

ClearArray(g_hClasses);
ClearTrie(g_hClassIndexes);

KvRewind(kv);

// No file, no meaning. Return false to show error
if(!KvJumpToKey(kv, "File")) return false;
if(!KvGotoFirstSubKey(kv)) return false;

do {
KvGetString(kv, "class", sClass, sizeof(sClass));
KvGetString(kv, "vmt", sVMT, sizeof(sVMT));
KvGetString(kv, "vtf", sVTF, sizeof(sVTF));

if(FindStringInArray(hPrecachedFiles, sVMT) == -1 && FindStringInArray(hPrecachedFiles, sVTF) == -1) {
if(!PrecacheModel(sVMT)) {
LogMessage("Failed to precache file in class: %s", sClass);
continue;
}
} else {
continue;
}

AddFileToDownloadsTable(sVMT);
AddFileToDownloadsTable(sVTF);

PushArrayString(hPrecachedFiles, sVMT);
PushArrayString(hPrecachedFiles, sVTF);

new count = GetArraySize(g_hClasses);

// Save VMT filepath
new Handle:classPack = CreateDataPack();
WritePackString(classPack, sVMT);

PushArrayCell(g_hClasses, classPack);
SetTrieValue(g_hClassIndexes, sClass, count);
} while(KvGotoNextKey(kv));

CloseHandle(hPrecachedFiles);

return 0;
}

bool:ClassGiveModel(client, const String:class[], const String:scale[], const String:steam[])
{
if(StringToTeam(steam) != GetClientTeam(client))
return true; //It's not a error, but it's also not sucessfull.

new index;
new String:filepath[PLATFORM_MAX_PATH];

if(!GetTrieValue(g_hClassIndexes, class, index)) return false;
new Handle:classPack = Handle:GetArrayCell(g_hClasses, index);
ResetPack(classPack);
ReadPackString(classPack, filepath, sizeof(filepath));

// Delete an entity(if exists) first
Entity_SafeDelete(g_Models[client]);

g_Models[client] = CreateIcon(filepath, scale);

if(g_Models[client] != -1) {
PlaceAndBindIcon(client, g_Models[client]);
return true;
}

return false;
}

StringToTeam(const String:steam[])
{
if(StrEqual(steam, "T") || StrEqual(steam, "RED") || StrEqual(steam, "SURVIVOR"))
return 2;

if(StrEqual(steam, "CT") || StrEqual(steam, "BLU") || StrEqual(steam, "INFECTED"))
return 3;

return 1;
}


PS: If you could remove the code in your quote, above, it would be really nice for other, so they won't get confused about wich version they have to use, thanks :3 !

PS2: Also, like always, please donate if you enjoy my work :D !!

Unbelievable
06-25-2016, 13:23
Thank you man no problem ill test it and let you know.

Unbelievable
06-26-2016, 12:47
It seems that the sprites do not show above head, the plugin compiles with no errors but doesn't work for some reason.

Arkarr
06-26-2016, 15:01
It seems that the sprites do not show above head, the plugin compiles with no errors but doesn't work for some reason.
Without logs, I can't help you, and I can't test it right now.

Bonkorn
06-27-2016, 10:34
Hi this my my icon.cfg

"Icon"
{
"File"
{
"01"
{
"class" "CT"
"vmt" "materials/sprites/sg_detective_icon.vmt"
"vtf" "materials/sprites/sg_detective_icon.vtf"
}
"02"
{
"class" "T"
"vmt" "materials/sprites/sg_traitor_icon.vmt"
"vtf" "materials/sprites/sg_traitor_icon.vtf"
}
}
"Player"
{
"PlayerCT"
{
"auth" "flags"
"attribute" ""
"class" "CT"
"scale" ""
"team" "CT"
}
"PlayerT"
{
"auth" "flags"
"attribute" ""
"class" "T"
"scale" ""
"team" "T"
}
}
}

The icon only works for CT but T doesn't, did i make any mistakes?
I do have their icon material files in server/my client


EDIT:
Just duplicate the icon plugin, 1 for CT (w/ icon_ct.cfg) , 1 T (w/ icon_t.cfg) then done.

Unbelievable
06-29-2016, 16:49
I'll give it a try, Once I've got it to work I'll upload the sprites I made for both teams so that others can use it.

Unbelievable
06-29-2016, 23:22
Thanks to Bonkorn suggestion I got it working for both teams.

Here is a link to a zip file containing edited plugin and sprites. Uploaded it to my site because its faster.
http://blaze-clan.com/teamicon.zip

The screenshot was taken by a low spec pc so the quality of the sprites will be low.
http://blaze-clan.com/screenshot.jpg

author: benefitOfLaughing - https://forums.alliedmods.net/showthread.php?t=252600
Special thanks to Arkarr for getting the plugin to work with teams.

Arkarr
06-30-2016, 11:16
Using two times the same plugin isn't right. I should fix my plugin.

Unbelievable
06-30-2016, 11:48
Using two times the same plugin isn't right. I should fix my plugin.

That would be great man would help alot.
for some reason it only reads the first sprite in config and not the second or third one.

Arkarr
06-30-2016, 11:58
That would be great man would help alot.
for some reason it only reads the first sprite in config and not the second or third one.
You don't have any logs ? What happen if you type :
sm plugins reload [PLUGIN_NAME]
Any errors ? There should be some.

Unbelievable
06-30-2016, 12:05
There is nothing in the error logs. strange.. even after i reloaded the plugin.

Arkarr
06-30-2016, 12:20
There is nothing in the error logs. strange.. even after i reloaded the plugin.
I'll test by myself then.