Page 1 of 2

[TF2] *_from_index functions are screwed up...

Posted: Sat Jul 11, 2015 7:35 pm
by nergal
everytime I use a "*_from_index" function on players, it keeps throwing me this error...

incorrect CPP sigs...

boost.python.argerror: Python argument types in _players._helpers.playerinfo_from_index(PlayerInfo)
did not match CPP signature: playerinfo_from_index(int, bool raise_exception=True)

http://imgur.com/Lchfsyq

Posted: Sat Jul 11, 2015 8:24 pm
by Mahi
"playerinfo_from_index(PlayerInfo)" tells us that you're passing in a PlayerInfo instance, not an index. Try printing out the "index" before using it on a function

Posted: Sat Jul 11, 2015 9:06 pm
by nergal
Mahi wrote:"playerinfo_from_index(PlayerInfo)" tells us that you're passing in a PlayerInfo instance, not an index. Try printing out the "index" before using it on a function


hmmmm?

Syntax: Select all

@SayCommand('!pro')
def pro_command(index, teamonly, CCommand):

text = CCommand[1].split()
if not len(text) > 0:
return True

print('Ding !pro')
iProPlayer[index] = text
player = playerinfo_from_index(index)
playeruser = userid_from_playerinfo(player)
set_weapon_invis(playeruser, text)


that sounds extremely weird...

Posted: Sat Jul 11, 2015 9:12 pm
by nergal
ok what about this picture?

http://i.imgur.com/KHKQPAp.png

wtf?

Posted: Sat Jul 11, 2015 9:23 pm
by L'In20Cible
That picture tells you your "index" is a PlayerInfo instance, not an integer.

Posted: Sat Jul 11, 2015 9:30 pm
by satoon101
SayCommand, SayFilter, ClientCommand, and ClientCommandFilter all have the player's PlayerInfo instance as the first argument in the callback, not their index:
http://wiki.sourcepython.com/pages/commands.client
http://wiki.sourcepython.com/pages/commands.say

Posted: Sat Jul 11, 2015 9:52 pm
by nergal
satoon101 wrote:SayCommand, SayFilter, ClientCommand, and ClientCommandFilter all have the player's PlayerInfo instance as the first argument in the callback, not their index:
http://wiki.sourcepython.com/pages/commands.client
http://wiki.sourcepython.com/pages/commands.say


I got the code from an example snippet of a thread of you demonstrating SayCommand and friends :/

last problem is this V

Syntax: Select all

@SayCommand( ['!pro', '/pro'] )
def pro_command(playerinfo, teamonly, command):
numAlpha = int( command[1] )
index = index_from_playerinfo(playerinfo)
iProPlayer[index] = numAlpha
user = userid_from_playerinfo(playerinfo)
set_weapon_invis(user, numAlpha)


the entire command keeps turning out the command itself though I asked for the 1st argument from command[1]

when I do "!pro 50", it just spits out the entire command when I want to convert the first arg (the 50) to an int...

Posted: Sat Jul 11, 2015 11:31 pm
by satoon101
That thread you were looking at was probably very old. The wiki should typically be up to date. Threads on the forum are never updated for API changes.

Posted: Sun Jul 12, 2015 12:09 am
by satoon101
As for your other issue:
http://forums.sourcepython.com/showthread.php?745

We have discussed passing a new CCommand instance instead of the one given by the "say" server command, but have not gotten around to making a testable implementation.

Posted: Sun Jul 12, 2015 12:22 am
by nergal
satoon101 wrote:That thread you were looking at was probably very old. The wiki should typically be up to date. Threads on the forum are never updated for API changes.


still having issue with command[1]...

The wiki says command[1] will give me the 1st argument while command[0] is the command name itself.

Everytime I try to convert the command[1] to an integer, the console bitches at me "command_name arg_1" is not a literal base of 10...

All I want is the first argument which is supposed to be a number and I've been trying to fix this issue for an hour with no progress...

Posted: Sun Jul 12, 2015 12:31 am
by satoon101
I think you missed my most recent post (I double posted). Currently, we just pass the CCommand instance itself. That instance will always have exactly 2 values. command[0] is always "say" and command[1] is always the actual message the player said in chat. So, currently, you will need to use something like:

Syntax: Select all

words = command[1].strip().split()


Also, you could easily find some of this out by printing values to the server console when testing. This would help you debug your own plugin to figure out what is going wrong.

Posted: Sun Jul 12, 2015 12:39 am
by nergal
satoon101 wrote:I think you missed my most recent post (I double posted). Currently, we just pass the CCommand instance itself. That instance will always have exactly 2 values. command[0] is always "say" and command[1] is always the actual message the player said in chat. So, currently, you will need to use something like:

Syntax: Select all

words = command[1].strip().split()


Also, you could easily find some of this out by printing values to the server console when testing. This would help you debug your own plugin to figure out what is going wrong.


I did use print() but it never printed anything out :\

I'm just sitting here wondering why the hell it's not printing out anything

Posted: Sun Jul 12, 2015 12:49 am
by satoon101
If you are encountering an error prior to your print statement, the print statement will never be called. Since you use int(command[1]), and command[1] is not an value that can be typecast to integer, you will get a ValueError. If you put your print statement prior to the erroring line, it will print.

Posted: Sun Jul 12, 2015 4:33 am
by nergal
satoon101 wrote:If you are encountering an error prior to your print statement, the print statement will never be called. Since you use int(command[1]), and command[1] is not an value that can be typecast to integer, you will get a ValueError. If you put your print statement prior to the erroring line, it will print.


I got it! Now I have one final problem lol

Syntax: Select all

def set_weapon_invis(userid, alpha):
try:
index = index_from_userid(userid)
except ValueError:
print('Wrong userid: ', userid)

player = PlayerEntity(index)
alpha = max( min(alpha, 255), 0 )

for weapon_index in player.weapon_indexes():
print(weapon_index)
wep = WeaponEntity(weapon_index)
wep.render_mode = RenderMode.TRANS_COLOR
wep.color = Color(150, 150, 150, alpha)


the very last part of the code, the loop, doesn't seem to run; doesn't print or anything, it's as if it's completely ignored but I know it's not...

Posted: Sun Jul 12, 2015 5:05 am
by L'In20Cible
You can avoid try/except here.

Syntax: Select all

from entities.constants import INVALID_ENTITY_INDEX

index = index_from_userid(userid, raise_exception=False)
if index == INVALID_ENTITY_INDEX:
print('Wrong userid.')

Posted: Sun Jul 12, 2015 10:27 am
by Ayuto
For which game are you trying to get this working?

Also instead of catching a ValueError or testing for an invalid userid your function should just require an "index" argument. It's not the task of the function to convert the userid to an index. That's the task of the caller. Moreover, your code would throw an error when the given userid is invalid, because after you have printed "Wrong userid x" your code would still continue, but the "index" variable was never defined. Additionally, you would rather want to get notified about an invalid userid than just passing it silently. Because that means that your previous code doesn't do proper security checks. Long story short: Just use this:

Syntax: Select all

def set_weapon_invis(index, alpha): 
player = PlayerEntity(index)
# TODO:
# You would also want to throw an error when alpha is below 0 or greater than 255.
# Correcting the value to the minimum or maximum does not seem to be the proper aproach.
alpha = max( min(alpha, 255), 0 )

for weapon_index in player.weapon_indexes():
print(weapon_index)
wep = WeaponEntity(weapon_index)
wep.render_mode = RenderMode.TRANS_COLOR
wep.color = Color(150, 150, 150, alpha)


satoon101 wrote:

Syntax: Select all

words = command[1].strip().split()

The strip() call is not required here. You can just call split() directly.

Syntax: Select all

>>> ' asd 123   '.split()
['asd', '123']

Posted: Sun Jul 12, 2015 1:35 pm
by satoon101
Ayuto wrote:
satoon101 wrote:

Syntax: Select all

words = command[1].strip().split()

The strip() call is not required here. You can just call split() directly.

Syntax: Select all

>>> ' asd 123   '.split()
['asd', '123']

You are correct. For some reason I thought that the quotes were included in the string. Though, I did forget to use '"' in my strip anyway.


nergal wrote:

Syntax: Select all

def set_weapon_invis(userid, alpha):
try:
index = index_from_userid(userid)
except ValueError:
print('Wrong userid: ', userid)

player = PlayerEntity(index)
alpha = max( min(alpha, 255), 0 )

for weapon_index in player.weapon_indexes():
print(weapon_index)
wep = WeaponEntity(weapon_index)
wep.render_mode = RenderMode.TRANS_COLOR
wep.color = Color(150, 150, 150, alpha)


the very last part of the code, the loop, doesn't seem to run; doesn't print or anything, it's as if it's completely ignored but I know it's not...


There is no need for you to set the render_mode yourself, as that is already taken care of when setting the color:
https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/addons/source-python/packages/source-python/entities/entity.py#L284


Also, currently setting the color doesn't work, due to this error:
http://forums.sourcepython.com/showthread.php?869&p=5369&viewfull=1#post5369

So, the only way you wouldn't have an error when calling your set_weapon_invis function is if the userid is valid but the player has no weapons. Outside of that scenario, you will definitely encounter a NameError for either index not being defined or for rendermode not being a valid KeyValue.

Posted: Sun Jul 12, 2015 4:42 pm
by nergal
Just saying, this is all on TF2. I understand that you guys JUST came out with TF2 support about last month or so, so I apologize for bothering you guys about it.

Also, how can sourcemod set render mode without errors?

Syntax: Select all

stock void SetWeaponInvis(int client, int &alpha)
{
for (int i = 0; i < 5; i++)
{
int entity = GetPlayerWeaponSlot(client, i);
if ( IsValidEdict(entity) && IsValidEntity(entity) )
{
SetEntityRenderMode(entity, RENDER_TRANSCOLOR);
SetEntityRenderColor(entity, 150, 150, 150, alpha);
}
}
return;
}

Posted: Sun Jul 12, 2015 4:48 pm
by necavi
Everything I've seen you mention is cross-game.

Posted: Sun Jul 12, 2015 5:35 pm
by satoon101
I feel the need to reiterate this point:
http://forums.sourcepython.com/showthread.php?822&p=5006&viewfull=1#post5006

Again, we have had TF2 support since the first time we had OrangeBox support. We didn't just recently add TF2 support. Currently, the only difference between TF2 and CSS is the DAMAGE_HEADSHOT DamageTypes value.

The reason that error happens is that, for some reason this line errors when rendermode is given:
https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/src/core/modules/entities/entities_entity_wrap.h#L135

even though this line doesn't cause the same error:
https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/src/core/modules/entities/entities_entity_wrap.h#L87

SourceMod is written completely different that Source.Python. The error is something on our end that we need to fix.