Two ways to give a weapon + something about CS:GO weapons

Post Python examples to help other users.
User avatar
iPlayer
Developer
Posts: 545
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Two ways to give a weapon + something about CS:GO weapons

Postby iPlayer » Mon Aug 21, 2017 1:33 am

Approach #1. give_named_item
As it seems, not everybody knows that this function returns a pointer that you can use to gain control of the created weapon.

Syntax: Select all

from commands.typed import TypedSayCommand
from memory import make_object
from messages import SayText2
from players.entity import Player
from weapons.entity import Weapon


@TypedSayCommand('!gimme')
def cmd_on_gimme(command_info, weapon_name):
player = Player(command_info.index)

weapon = make_object(Weapon, player.give_named_item(weapon_name))

SayText2(f"Given {weapon.class_name} to {player.name}").send()


Approach #2. Weapon.create
When you create the entity by youself, obviously you have the reference to it, but the question is completely the opposite: how to give this weapon to a player. This is done by telling the player to touch a weapon. Doesn't even matter where the weapon was spawned.

Syntax: Select all

from commands.typed import TypedSayCommand
from messages import SayText2
from players.entity import Player
from weapons.entity import Weapon


@TypedSayCommand('!gimme')
def cmd_on_gimme(command_info, weapon_name):
player = Player(command_info.index)

weapon = Weapon.create(weapon_name)
weapon.spawn()
player.touch(weapon.pointer)

SayText2(f"Given {weapon.class_name} to {player.name}").send()


Now some information about CS:GO. As you may know, CS:GO introduced some weapons that share the classname (USP-S and HKP2000, for example, are both weapon_hkp2000). The difference between such weapons lies in their properties.
For your convenience, Source.Python's Weapon.create converts aliases (say, weapon_usp_silencer) to the real classname and assigns correct properties to the created entity to make sure that the resulting weapon will be USP-S and not HKP2000.

Well, at least it tries to do so. From my testing,

Syntax: Select all

Weapon.create('weapon_usp_silencer')

still spawns HKP2000, but if you drop it and look at it, the hint will caption it as "USP-S".

What about give_named_item then? It's a native Source function and it should do all the magic by itself. And it successfully recognizes the weapon_usp_silencer alias. The only problem is that this function is too good. Nobody asks for it, but the function will look up the player's inventory to see what weapon - USP or HKP2000 - the player has equipped. Then... it just ignores the alias and spawns the one it thinks "correct". I.e. it can spawn USP-S when you wanted it to spawn HKP2000 and vice versa.

How to prevent it? The inventory lookup only succeeds if the player is on the correct team. Remember that USP/HKP2000 can only be bought by Counter-Terrorists? Then when the player is on the Terrorists team, give_named_item will spawn the weapon that we ask for.

The following code:

Syntax: Select all

entity = Entity(player.index)
old_team = entity.team
entity.team = 2 # Terrorists
player.give_named_item('weapon_hkp2000')
entity.team = old_team


basically saves player's current team, moves them to terrorists, gives the correct weapon and then restores their team.
You might ask, why won't I use player.team? Because player.team is a shortcut to player.playerinfo.team, and changing the team using this shortcut will kill the player in process.
entity.team, on the other side, is more raw and allows us to change player's team without any casualties.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
L'In20Cible
Project Leader
Posts: 939
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: Two ways to give a weapon + something about CS:GO weapons

Postby L'In20Cible » Mon Aug 21, 2017 2:51 am

iPlayer wrote:You might ask, why won't I use player.team? Because player.team is a shortcut to player.playerinfo.team, and changing the team using this shortcut will kill the player in process.
entity.team, on the other side, is more raw and allows us to change player's team without any casualties.

This seems redundant to me. We should rather rename Entity.team to Entity,team_index in order to avoid duplicate with different behaviors from derived class.
User avatar
iPlayer
Developer
Posts: 545
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: Two ways to give a weapon + something about CS:GO weapons

Postby iPlayer » Mon Aug 21, 2017 3:06 am

L'In20Cible wrote:This seems redundant to me. We should rather rename Entity.team to Entity,team_index in order to avoid duplicate with different behaviors from derived class.

Splitting it into team_index and team is definitely better than having to instantiate an Entity when you already possess a Player instance.
But maybe remove the team definition from the Player entirely? Leave the inherited team, and if anybody wants to use the PlayerInfo one, they can (and could) always access it via player.playerinfo.team.
Image /id/its_iPlayer
My plugins: Map Cycle • Killstreaker • DeadChat • Infinite Jumping • TripMines • AdPurge • Bot Damage • PLRBots • Entity AntiSpam

Hail, Companion. [...] Hands to yourself, sneak thief. Image
User avatar
L'In20Cible
Project Leader
Posts: 939
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: Two ways to give a weapon + something about CS:GO weapons

Postby L'In20Cible » Wed Sep 13, 2017 1:41 am

iPlayer wrote:
L'In20Cible wrote:This seems redundant to me. We should rather rename Entity.team to Entity,team_index in order to avoid duplicate with different behaviors from derived class.

Splitting it into team_index and team is definitely better than having to instantiate an Entity when you already possess a Player instance.
But maybe remove the team definition from the Player entirely? Leave the inherited team, and if anybody wants to use the PlayerInfo one, they can (and could) always access it via player.playerinfo.team.

I thought about this and I don't think this is the best approach and I would rather prefer renaming Entity.team to Entity.team_index over removing Player.team behavior. The reasoning behind this is quite simple, it does make sense that the setter method for Player.team is redirected to PlayerInfo.team (or more precisely IPlayerInfo::ChangeTeam internally) because that method is responsible to correctly change the team of the player (which includes adding the player to the new CTeam array along by removing it from the old and sending the class selection HUD for the player to pick a class). For example, on games that have classes (at least, this is true for CS games), only changing the m_nTeamNumber value of a player doesn't change his team and cause a lot of weird things (player not respawning on new round being one of them).
By renaming Entity.team, we keep the correct behavior for Player instances and we add a more "raw" attribute to the hierarchy. Unless anyone have any objections or reasons to go a different route, I will go ahead and make that change.
User avatar
BackRaw
Senior Member
Posts: 415
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany

Re: Two ways to give a weapon + something about CS:GO weapons

Postby BackRaw » Sun Sep 17, 2017 3:11 pm

Great info, thanks! I have a little OT question about Approach #1 though:

iPlayer wrote:Approach #1. give_named_item
As it seems, not everybody knows that this function returns a pointer that you can use to gain control of the created weapon.

Syntax: Select all

from commands.typed import TypedSayCommand
from memory import make_object
from messages import SayText2
from players.entity import Player
from weapons.entity import Weapon


@TypedSayCommand('!gimme')
def cmd_on_gimme(command_info, weapon_name):
player = Player(command_info.index)

weapon = make_object(Weapon, player.give_named_item(weapon_name))

SayText2(f"Given {weapon.class_name} to {player.name}").send()


What does the f"" string flag at the very last line do exactly? Is it what I'm thinking and it takes the locals to format the string? I really missed that lol.
User avatar
satoon101
Project Leader
Posts: 2387
Joined: Sat Jul 07, 2012 1:59 am

Re: Two ways to give a weapon + something about CS:GO weapons

Postby satoon101 » Sun Sep 17, 2017 3:43 pm

Image
User avatar
BackRaw
Senior Member
Posts: 415
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany

Re: Two ways to give a weapon + something about CS:GO weapons

Postby BackRaw » Sun Sep 17, 2017 4:01 pm

Awesome, thanks for the hint.

Return to “Code examples / Cookbook”

Who is online

Users browsing this forum: No registered users and 1 guest