Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kills accumulated function + Plot map improvements: player colors, bomb new icon, annotations #133

Open
pablonieto0981 opened this issue Jan 31, 2022 · 2 comments

Comments

@pablonieto0981
Copy link

pablonieto0981 commented Jan 31, 2022

colors_annotations

Hi there,

Based on some testing and needs from my CSGO team (a bunch of GN2/GN1...), I have made the following changes locally, which you might want to implement in the code:

1. Accumulated kills function

I might be mistaken, but I think there is no entry in the parsed data to track total kills by a player at any given round start. I created a function for that, as we thought understanding behavior of player by skill ("or who is just having a good day") might be interesting.

Here below is the function:

def create_kills_dictionary(demo_parsed):

    kills_dict = {}
    
    ''' Get names '''
    
    for Round in demo_parsed['gameRounds']:
        for frame in Round['frames']:
            for side in ['ct','t']:
                for player in frame[side]['players']:
                    kills_dict[player['name']] = 0

    for X in range(0,len(demo_parsed['gameRounds'])):
        for kill in demo_parsed['gameRounds'][X]['kills']:
            try: # Sometimes "attackerName" gives None, this is to manage the exception
                kills_dict[kill['attackerName']] = kills_dict[kill['attackerName']] + 1
            except:
                pass
        demo_parsed['gameRounds'][X]['kill_scores'] = dict(kills_dict)

    return demo_parsed

This adds the accumulated number of kills at round start for each round in the demo.

Other changes I have made locally are an option to plot player colors over the default T or CT marker in the round plot, and to add annotations on top of each player. See below (2. and 3. all go into plot.py):

2. Function to plot annotations

def plot_annotations(plot_variable,positions=[],annotations=[],map_name="de_ancient",apply_transformation=False):
    for p, ann in zip(positions, annotations):
        if apply_transformation:
            plot_variable.annotate(ann,(position_transform(map_name, p[0], "x")-15, position_transform(map_name, p[1], "y")-20),fontsize=5,color='white')
        else:
            plot_variable.annotate(ann,(p[0]-15,p[1]-20),fontsize=5,color='white')
            
    return plot_variable

3. Plot round function with annotations and color input for players and color choice for the bomb

Note that player_names_colors is a dictionary that should take the exact names used by the players in the game, and a color of choice for each. Here below is an example from Saturday's match:

player_names_colors={'Glaurung':'blue','0_o Draco':'orange','Peluche81 [I CH]':'green',"Tum Tu'pabs":'yellow','R0x0r':'purple','mig2504':'purple','labuguresti':'orange','Hammood taking 1taps':'blue','cascasvelos.PT':'yellow','99p.exe':'green'}

If the function kill_stats={}, the annotations are the health points; if player_names_colors is empty, then no colors are given, and only red / cyan outer marker is used.

An option to decide the color of the bomb is given, and I have made the bomb a Y marker, as it layers well with the team and player color markers.

And here is the function...

def plot_round(
    filename, frames, kill_stats={}, map_name="de_ancient", map_type="original", dark=False, player_names_colors={}, bomb_color='pink'):
    """Creates gif from frame. Writes to filename"""
    if os.path.isdir("csgo_tmp"):
        shutil.rmtree("csgo_tmp/")
    os.mkdir("csgo_tmp")
    image_files = []
    for i, f in tqdm(enumerate(frames)):
        positions = []
        colors = []
        markers = []
        annotations = []
            
        '''This was the usual drawing of players...'''
        
        for side in ["ct", "t"]:
            for p in f[side]["players"]:
                if side == "ct":
                    colors.append("cyan")
                else:
                    colors.append("red")
                if p["hp"] == 0:
                    markers.append("x")
                else:
                    markers.append("o")
                                             
                pos = (
                    position_transform(map_name, p["x"], "x"),
                    position_transform(map_name, p["y"], "y"),
                )
                positions.append(pos)
                
                if kill_stats == {}:
                    annotations.append(p['hp'])
                else:
                    annotations.append(kill_stats[p['name']])
                
        '''Now the bomb is also drawn here...'''
        
        for object_type in f['world']:
            
            if object_type['objectType'] == 'bomb':
        
                colors.append(bomb_color)
                markers.append("1")
                
                pos = (
                    position_transform(map_name, object_type["x"], "x"),
                    position_transform(map_name, object_type["y"], "y"),
                )
                
                positions.append(pos)
                
            else:
                pass   

        '''Here we overlay the colors assigned to each player...'''                
                
        for side in ["ct", "t"]:
            for p in f[side]["players"]:
                if p['name'] in player_names_colors.keys():
                    markers.append(".")
                    colors.append(player_names_colors[p['name']])
                else:
                    markers.append(".")
                    if side == 't':
                        colors.append('red')
                    if side == 'ct':
                        colors.append('cyan')                                             
                pos = (
                    position_transform(map_name, p["x"], "x"),
                    position_transform(map_name, p["y"], "y"),
                )
                positions.append(pos)   
                
        f, a = plot_positions(
            positions=positions,
            colors=colors,
            markers=markers,
            map_name=map_name,
            map_type=map_type,
            dark=dark,
        )
        
        ''' Plotting annotations (HP, kills) '''
        
        a = plot_annotations(a,positions=positions,annotations=annotations,map_name=map_name)
        
        image_files.append("csgo_tmp/{}.png".format(i))
        f.savefig(image_files[-1], dpi=300, bbox_inches="tight")
        plt.close()
    images = []
    for file in image_files:
        images.append(imageio.imread(file))
    imageio.mimsave(filename, images)
    shutil.rmtree("csgo_tmp/")
    return True

...yes, we lost the game.

@pnxenopoulos
Copy link
Owner

Once again with a wonderful set of functions! Everything looks good, it's just a matter of figuring out where to place it. I'll get to this over the coming days.

@JanEricNitschke
Copy link
Collaborator

JanEricNitschke commented Nov 23, 2022

Might make sense to allow for custom color, marker and annotation functions in general in the plot_round function. They should just default to what is currently there.

     try: # Sometimes "attackerName" gives None, this is to manage the exception
         kills_dict[kill['attackerName']] = kills_dict[kill['attackerName']] + 1
     except:
         pass

This should probably be an explicit None check i think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants