simple death and kill streaks tracker

Release your plugins here!
nergal
Member
Posts: 57
Joined: Sun Mar 15, 2015 2:58 pm

simple death and kill streaks tracker

Postby nergal » Mon Jun 15, 2015 5:25 am

This is untested but it should work for any game supported on sauce.py :3

Syntax: Select all

# Python Imports
from collections import defaultdict

# SourcePython imports
from players.entity import PlayerEntity

from players.helpers import userid_from_index
from players.helpers import index_from_userid

from events import Event

from cvars.public import PublicConVar
from plugins.info import PluginInfo

info = PluginInfo()
info.name = "Death and Kill Streaks"
info.author = "Nergal/Assyrian"
info.version = "1.0"
info.basename = "dkstreaks"
info.variable = info.basename + "_version"
info.convar = PublicConVar(info.variable, info.version, 0, info.name + " Version")

#create a list
deathstreaks = defaultdict(int) #[i+1 for i in range(66)]
killstreaks = defaultdict(int) #[i+1 for i in range(66)]


def set_playerlist(index):
deathstreaks[index] = 0
killstreaks[index] = 0

@Event
def player_connect(game_event):
set_playerlist( index_from_userid(game_event.get_int('userid')) )

@Event
def player_disconnect(game_event):
set_playerlist( index_from_userid(game_event.get_int('userid')) )

@Event
def player_death(game_event):
victim = index_from_userid( game_event.get_int('userid') )
attacker = index_from_userid( game_event.get_int('attacker') )

if victim == attacker || attacker == -1:
return

if killstreaks[victim] == 0:
deathstreaks[victim] += 1

killstreaks[victim] = 0
deathstreaks[attacker] = 0
killstreaks[attacker] += 1
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Mon Jun 15, 2015 8:17 pm

You should take a look at python dictionary! :)
nergal
Member
Posts: 57
Joined: Sun Mar 15, 2015 2:58 pm

Postby nergal » Wed Jun 17, 2015 7:50 pm

L'In20Cible wrote:You should take a look at python dictionary! :)


Why a dictionary and not a list/array?
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Jun 17, 2015 7:59 pm

CauseCause accessing dictionaries is fasterfaster since this is done internally. It also makes the code cleaner and easier to read imo.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Jun 17, 2015 8:00 pm

Sorry for repeated words, I broke the screen on my phine and for some reasons it does duplicate some words.. lol
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Jun 17, 2015 8:02 pm

Also, your code wont load due to ; after return which is an invalid syntax.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Wed Jun 17, 2015 8:42 pm

L'In20Cible wrote:Also, your code wont load due to ; after return which is an invalid syntax.
No, a semicolon is valid in Python. It allows you to use multiple statements within the same row.[PYTHON]>>> def f(x):
print(x); x += 5; return x;


>>> f(5)
5
10[/PYTHON]Though, you usually don't use that in Python.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Jun 17, 2015 8:52 pm

I know, but I guess python compiler is looking for something after the semi-colon and being nothing most likely fails. I honnestly never used multiple statements on the same line, so I could not say without testing.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Wed Jun 17, 2015 8:55 pm

This is also working fine.^^

Syntax: Select all

>>> def f(x):
print(x)
return;

>>> f(5)
5
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Thu Jun 18, 2015 10:31 am

nergal wrote:
L'In20Cible wrote:You should take a look at python dictionary! :)


Why a dictionary and not a list/array?
I'll give you a quick example with dicts:

Syntax: Select all

# create a dict
deathstreaks = {}

@Event
def player_connect(game_event):
set_playerlist( index_from_userid(game_event.get_int('userid')) )


# map the player's index to 0
def set_playerlist(index):
deathstreaks[index] = 0


@Event
def player_disconnect(game_event):

# remove the player from the dict and therefore from memory
del deathstreaks[index_from_userid(game_event.get_int('userid'))]
The difference is, that you create an empty dict, instead of a list pre-defined with the values 0...65 -- why range(0, 66) anyway?

I'd suggest you to look into this: https://docs.python.org/3/library/stdtypes.html#typesmapping
My Github repositories:

Source.Python: https://github.com/backraw
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Thu Jun 18, 2015 8:52 pm

You also might want to set the deathstreaks regardless of whether victim id equals attacker id or not, otherwise suicides wouldn't count as deaths.
nergal
Member
Posts: 57
Joined: Sun Mar 15, 2015 2:58 pm

Postby nergal » Fri Jun 19, 2015 4:41 am

stonedegg wrote:You also might want to set the deathstreaks regardless of whether victim id equals attacker id or not, otherwise suicides wouldn't count as deaths.


in the cases of suicide, the killer is the player I believe.

reason why range of 0-65 is because the Source Engine supports 64 players + a SourceTV or Replay Bot.

Another reason is that I'm used to making Player Arrays in SourceMod by just doing "myplayerarray[65];"

Do not forget that I'm transitioning from SourceMod to Python so my skills aren't going to be 100% with Python :>
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Fri Jun 19, 2015 12:16 pm

Yes, if the player suicides attacker id equals victim id, which means in your script suicides won't count as deaths (in case of self explosive damage or falldamage).
You also might want to check if the attacker userid != -1, otherwise this will give you a conversion error: attacker = index_from_userid( game_event.get_int('attacker') )
Not sure if that is possible in TF2 but in CS, the attacker userid is -1 if the player gets killed by the bomb and you can't get an index from that.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Jun 19, 2015 1:35 pm

nergal wrote:
stonedegg wrote:You also might want to set the deathstreaks regardless of whether victim id equals attacker id or not, otherwise suicides wouldn't count as deaths.


in the cases of suicide, the killer is the player I believe.

reason why range of 0-65 is because the Source Engine supports 64 players + a SourceTV or Replay Bot.

Another reason is that I'm used to making Player Arrays in SourceMod by just doing "myplayerarray[65];"

Do not forget that I'm transitioning from SourceMod to Python so my skills aren't going to be 100% with Python :>


Well, we understand that you are transitioning. This is why we are suggesting more Pythonic ways to do things. Using a list as if it were an array is not the way to handle those sorts of things in Python. Dictionaries are a much better, more Pythonic way. I do see in your example that you imported defaultdict and commented it out. I imagine this is from another thread on the forum where the defaultdict was utilized. If you don't understand it, just google "Python defaultdict" to get the Python docs for that functionality. If you are still confused, feel free to ask questions.
Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Fri Jun 19, 2015 11:14 pm

nergal wrote:reason why range of 0-65 is because the Source Engine supports 64 players + a SourceTV or Replay Bot.

Another reason is that I'm used to making Player Arrays in SourceMod by just doing "myplayerarray[65];"

Do not forget that I'm transitioning from SourceMod to Python so my skills aren't going to be 100% with Python :>
Aaaahhh okay, it makes more sense now. I wasn't being offensive or anything like that :) All good, this forum and this plugin is here for us all to learn :D
My Github repositories:

Source.Python: https://github.com/backraw
nergal
Member
Posts: 57
Joined: Sun Mar 15, 2015 2:58 pm

Postby nergal » Mon Jun 29, 2015 6:15 am

satoon101 wrote:
nergal wrote:
stonedegg wrote:You also might want to set the deathstreaks regardless of whether victim id equals attacker id or not, otherwise suicides wouldn't count as deaths.


in the cases of suicide, the killer is the player I believe.

reason why range of 0-65 is because the Source Engine supports 64 players + a SourceTV or Replay Bot.

Another reason is that I'm used to making Player Arrays in SourceMod by just doing "myplayerarray[65];"

Do not forget that I'm transitioning from SourceMod to Python so my skills aren't going to be 100% with Python :>


Well, we understand that you are transitioning. This is why we are suggesting more Pythonic ways to do things. Using a list as if it were an array is not the way to handle those sorts of things in Python. Dictionaries are a much better, more Pythonic way. I do see in your example that you imported defaultdict and commented it out. I imagine this is from another thread on the forum where the defaultdict was utilized. If you don't understand it, just google "Python defaultdict" to get the Python docs for that functionality. If you are still confused, feel free to ask questions.


yes ur right, I've updated the OP using defaultdict, hopefully it'll still work ok.

Has anybody tested this out? I'm not sure if it's working or not.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 29, 2015 1:07 pm

Well, the way you are currently using it, you might as well just use dict instead of defaultdict. The purpose of defaultdict is to automatically set the value of a key the first time it is used. I would recommend either changing it to dict or, if you want to utilize defaultdict correctly, remove your set_playerlist function and player_connect event and modify your player_disconnect event to remove the key when a player disconnects:

Syntax: Select all

@Event
def player_disconnect(game_event):
index = index_from_userid(game_event.get_int('userid'))
if index in deathstreaks:
del deathstreaks[index]
if index in killstreaks:
del killstreaks[index]


There is no purpose to have an index in the dictionary if there is no player with that index on the server. You might also want to clear the dictionaries on LevelShutdown, since, if I remember correctly, bots do not cause player_disconnect when leaving on map change:

Syntax: Select all

from listeners import LevelShutdown


@LevelShutdown
def level_shutdown():
deathstreaks.clear()
killstreaks.clear()


Also, this line would give a syntax error:

Syntax: Select all

if victim == attacker || attacker == -1:


That should be:

Syntax: Select all

if victim == attacker or attacker == -1:
Image

Return to “Plugin Releases”

Who is online

Users browsing this forum: No registered users and 35 guests