More questions

Please post any questions about developing your plugin here. Please use the search function before posting!
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

More questions

Postby decompile » Thu Dec 17, 2015 11:12 pm

Hello!

Im working now for a few days with SP and im happy to work with, but I still have some questions which i couldnt figure out yet :(

1. How can i fire a event?

Syntax: Select all

es.event("initialize", "player_say")
es.event("setint", "player_say", "userid", userid)
es.event("setstring", "player_say", "text", text)
es.event("fire", "player_say")


2. Im having realy weird problems with the PYMYSQL - cursor - fetchall.

Its fine for getting all data, but when it gets from the server an empty callback, it shows for my script

func:

Syntax: Select all

VIP = sql.get.getVIP(steamid) #Returns () from SQL server
if VIP:
VIP[0]["custom_chatrank"]


File '..\chatRanks.py', lin
e 167, in getRank
if VIP[0]['custom_chatrank']:

TypeError: 'map' object is not subscriptable


Syntax: Select all

print(VIP)


<map object at 0x1C7F2270>


3.

Can i use filters for saytext2 messages? I want to send "team-only" messages.

4. How can i use Centertell and KeyHintText for CS:S?

Someone told me its just PlayerEntity(index).keyhinttext

5.

Im having problems with the SayFilter

Syntax: Select all

@SayFilter
def say_filter(index, teamonly, CCommand):
text = CCommand[1]
userid = userid_from_index(index)


Took that from a forum post

[SP] Caught an Exception:

TypeError: No registered converter was able to produce a C++ rvalue of type int
from this Python object of type tuple



[SP] Caught an Exception:
Traceback (most recent call last):
File '..\chatRanks.py', lin
e 52, in say_filter
text = CCommand[1]

TypeError: 'bool' object is not subscriptable


6. How can i use the default color for SayText2 messages? I didnt found that when i try to switch from \x03 to "Default" (Yellow in css)

7. Is there an event or anything where i can see players key presses like 'IN_LEFT' 'IN_FORWARD'

8. How can i check if a player is onGround (couldnt find anything on forum/wiki)

9. Is there a module where I can check if a point is in a 3d rectangle? (think es had that with vecmath.isbetweenrect or something)

10. How can i Create triggers properly in SP??

Syntax: Select all

origin = Vector(map(min, zip(coord1,coord2)))
maxCoord = Vector(map(max, zip(coord1,coord2)))
index = es.createentity("trigger_multiple")
es.precachemodel("models/error.mdl")
es.entitysetvalue(index, "model", "models/error.mdl")
es.entitysetvalue(index, "delay", 0)
es.entitysetvalue(index, "spawnflags", 1)
es.spawnentity(index)
m_vecOrigin = origin
m_vecMins = Vector((0,0,0))
m_vecMaxs = maxCoord - m_vecOrigin
es.setindexprop(index, "CBaseEntity.m_Collision.m_vecMins", str(m_vecMins))
es.setindexprop(index, "CBaseEntity.m_Collision.m_vecMaxs", str(m_vecMaxs))
es.setindexprop(index, "CBaseEntity.m_Collision.m_nSolidType", 2)
teleport(index, m_vecOrigin, None, None)
return index


11. Is there something like
@OnStartTouch or @OnEndTouch

12. How can i actually call all trigger_multiples from a map and see their properties?

Syntax: Select all

entlist = es.createentityindexlist("trigger_multiple")
indexdict = {} for x in entlist:
indexdict[es.entitygetvalue(x, "targetname")] = x


13. Can i actually block someone's manuall clan tag change?
I mean when hes changing his clantag via the options menu from the player since im giving my players a specific clan_tag for each.

Thats all for now, thank you guys for the great support!

If i should stop creating for each questions a new thread just tell me so i can create a mega thread for my questions haha :p
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Thu Dec 17, 2015 11:50 pm

Actually, since your questions are not related to each others, I think you should create a new thread for each of them. I will be glad to provide some examples you asked for but quoting and answering multiples questions while editing seem to get messy rather quickly, lol.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Fri Dec 18, 2015 12:32 am

decompile wrote:1. How can i fire a event?

Syntax: Select all

es.event("initialize", "player_say")
es.event("setint", "player_say", "userid", userid)
es.event("setstring", "player_say", "text", text)
es.event("fire", "player_say")
To fire an event, you will first have to get a GameEvent instance. You can create one using the _GameEventManager.create method. A singleton of this class is exported and forwarded to the events.manager module. Here is a quick example:

Syntax: Select all

from events.manager import game_event_manager

# Get a GameEvent instance....
# NOTE: We need to set force to True otherwise this won't create
# a valid instance if no listener was registered for the given
# name.
game_event = game_event_manager.create_event('player_say', force=True)

# Set some values...
game_event.set_int('userid', userid)
game_event.set_string('text', text)

# Finally, fire the event...
game_event_manager.fire_event(game_event)



decompile wrote:2. Im having realy weird problems with the PYMYSQL - cursor - fetchall.

Its fine for getting all data, but when it gets from the server an empty callback, it shows for my script

func:

Syntax: Select all

VIP = list(sql.get.getVIP(steamid)) #Returns () from SQL server
if VIP:
VIP[0]["custom_chatrank"]




Syntax: Select all

print(VIP)


<map object at 0x1C7F2270>
Casting your map instance to a list should do the trick, I guess.

Syntax: Select all

VIP = list(sql.get.getVIP(steamid)) #Returns () from SQL server


decompile wrote:3.

Can i use filters for saytext2 messages? I want to send "team-only" messages.
Take a look at PlayerIter (you can see default registered filters in the "filter registration" section). Example:

Syntax: Select all

from filters.players import PlayerIter

# Get a PlayerIter generating human players...
human_players = PlayerIter('human')

# ...later in code...
for player in human_player:
player.ignite() # Burn baby burn...


decompile wrote:4. How can i use Centertell and KeyHintText for CS:S?

Someone told me its just PlayerEntity(index).keyhinttext
Check out the messages package. To send a KeyHintText message, you need to import the KeyHintText class. Example:

Syntax: Select all

from messages import KeyHintText

# Get a KeyHintText message instance...
hello = KeyHintText('Hello!')

# ...later in code...
# Send the message...
hello.send(player.index)
To send a message in the center of the screen, you need to use a TextMsg message - same usage as KeyHintText.

decompile wrote:5.

Im having problems with the SayFilter

Syntax: Select all

@SayFilter
def say_filter(index, teamonly, CCommand):
text = CCommand[1]
userid = userid_from_index(index)


Took that from a forum post

[SP] Caught an Exception:

TypeError: No registered converter was able to produce a C++ rvalue of type int
from this Python object of type tuple



[SP] Caught an Exception:
Traceback (most recent call last):
File '..\chatRanks.py', lin
e 52, in say_filter
text = CCommand[1]

TypeError: 'bool' object is not subscriptable
Arguments are mixed in your callback declaration. They should be in that order:

Syntax: Select all

def say_filter(CCommand, index, teamonly):


decompile wrote:6. How can i use the default color for SayText2 messages? I didnt found that when i try to switch from \x03 to "Default" (Yellow in css)
In CS:S (from what I remember), \x01 is default chat color, \x03 is lightgreen (or player's team based), \x04 is green, \x05 is dark green and \x06/7 is allowing custom colors.

decompile wrote:7. Is there an event or anything where i can see players key presses like 'IN_LEFT' 'IN_FORWARD'
For that, you will have to use a EntityPreHook around PlayerRunCommand. Here is an example printing something when a player is pressing his +attack button:

Syntax: Select all

from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from players import UserCmd
from players.constants import PlayerButtons
from players.entity import Player
from memory import make_object

@EntityPreHook(EntityCondition.is_human_player, 'run_command')
def pre_player_run_command(stack_data):
'''Pre hook around CBasePlayer::PlayerRunCommand.'''

# Get the Player instance...
player = make_object(Player, stack_data[0])

# Get the UserCmd instance...
usercmd = make_object(UserCmd, stack_data[1])

# Is the player holding his +attack button?
if (not player.buttons & PlayerButtons.ATTACK and
usercmd.buttons & PlayerButtons.ATTACK):

# Prints something...
print(player.name, 'pressed his +attack button!')


decompile wrote:8. How can i check if a player is onGround (couldnt find anything on forum/wiki)
I know there is a property you can check for changes but I also remember seeing a callback called by the engine itself in the CBasePlayer class. I will see if I can get this added in our data when I get the chance to.

decompile wrote:9. Is there a module where I can check if a point is in a 3d rectangle? (think es had that with vecmath.isbetweenrect or something)
-> Vector.is_within_box(corner1, corner2)
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Dec 18, 2015 1:06 am

**Note: I know L'In20Cible already posted a 2nd reply, but I was very close to done with this by the time I saw it.


I'm with L'In20Cible on this. I would much prefer that each question be its own thread. That makes searching for answers for other people's future questions much easier on them. Also, a very specific title helps with that, as well. Maybe we need to update the rules for this forum.

However, since this thread is already started, I will go ahead and answer most of them (the ones I know right off the top of my head without any research).

1. http://forums.sourcepython.com/showthread.php?545

3. The player_indexes argument of the send method of all messages classes can be any of the following (I might be forgetting one, but I can't remember):
  • Nothing - do not pass any arguments and all players will be sent the message
  • an integer - the index of the player to send the message to
  • multiple integer arguments - integers are the indexes of the players to send the message to
    • We use star args, so just pass in as many integer arguments as there are players to send
    • you typically won't actually use this, but it is available
  • a RecipientFilter instance
  • a PlayerIter instance

4. KeyHintText is a class in messages, as it is a message type. For center text, you have to use TextMsg with the destination parameter being HudDestination.CENTER (which is the default value).

5. http://forums.sourcepython.com/showthread.php?924

6. Default color is \x01. I will gather a list of colors together for all currently supported games and create a thread for it when I get the chance.

7. Hook the run_command virtual function with our Entity implementation (which Player has full access to, as well), if you want to know exactly when someone has pressed a key. Or, if you just want to know at a specific time what a player is pressing, use get_last_user_command. The Player class has access to all PlayerInfo methods, as well, so you don't have to get the PlayerInfo instance yourself.

9. We have a Vector.is_within_box method, which we just directly expose from the engine, so it's super fast.

11. Just like #7, you need to hook a virtual function. This time you would hook start_touch or end_touch.

12. Use EntityIter to iterate through the trigger_multiple entities. To see all available items to use for an entity, check this out:

Syntax: Select all

from entities.entity import Entity

entity = Entity.find_or_create('trigger_multiple')

# List all attributes of the entity
print('=' * 40)
print('Attributes:')
for x in dir(entity):
print('\t{0}'.format(x))
print('\n')
print('Inputs:')
for x in entity.inputs:
print('\t{0}'.format(x))
print('\n')
print('Properties:')
for x in entity.properties:
print('\t{0}'.format(x))
print('\n')
print('KeyValues:')
for x in entity.keyvalues:
print('\t{0}'.format(x))
print('\n')
print('Outputs:')
for x in entity.outputs:
print('\t{0}'.format(x))
print('=' * 40)



# To get an input that is not included in the data (primarily used to hook the input)
my_input = entity.get_input('<input_name>')

# To fire an input that is not included in the data
# Note that value must be the proper type (int, float, string, etc...) for the input
entity.call_input('<input_name>', [value], [caller], [activator])


# To get a property (note that you must use the correct type)
value = entity.get_property_<type>('<property_name>')

# To set a property (note that you must use the correct type)
entity.set_property_<type>('<property_name>', <value>)


# To get a keyvalue (note that you must use the correct type)
value = entity.get_key_value_<type>('<keyvalue_name>')

# To set a keyvalue (note that you must use the correct type)
entity.set_key_value_<type>('<keyvalue_name>', <value>)


13. I don't think we currently have the virtual or dynamic function included for when a clan tag changes, but we can look into that. You "can", for now, use a tick listener or a repeat to check and modify.
Image
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Dec 18, 2015 1:12 am

L'In20Cible wrote:In CS:S (from what I remember), \x01 is default chat color, \x03 is lightgreen (or player's team based), \x04 is green, \x05 is dark green and \x06/7 is allowing custom colors.

Just to clarify, it's [url=https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/src/core/modules/colors/colors.h#L50-#L53]\x07 and \x08[/url] that allow for hex value colors in OrangeBox games.
Image
User avatar
Doldol
Senior Member
Posts: 200
Joined: Sat Jul 07, 2012 7:09 pm
Location: Belgium

Postby Doldol » Fri Dec 18, 2015 3:59 am

Urh, I want to answer but it's a mess sifting through numbered replies, as everyone has stated already, please, please, create multiple topics when the questions aren't related!


8. How can i check if a player is onGround (couldnt find anything on forum/wiki)


This is the property:

Syntax: Select all

from players.entity import Player

player = Player(index)
if player.get_property_int('m_hGroundEntity') == -1:
pass # player is not touching the ground on -1


10. How can i Create triggers properly in SP??


This works in CSGO, spawnflags is set so only clients interact with it.

Syntax: Select all

from entities.entity import Entity
from engines.precache import Model

silo_model = Model("models/props/cs_militia/silo_01.mdl")

def spawn_trigger_multiple(mins, maxs):
trigger_multiple = Entity.create("trigger_multiple")
trigger_multiple.set_key_value_int("spawnflags", 1)
trigger_multiple.model = silo_model
trigger_multiple.spawn()
trigger_multiple.set_property_vector("m_Collision.m_vecMaxs", maxs)
trigger_multiple.set_property_vector("m_Collision.m_vecMins", mins)
trigger_multiple.set_property_uchar("m_nSolidType", 2) #3 ?
return trigger_multiple
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Dec 18, 2015 5:16 am

A few shortcuts, Doldol:

Syntax: Select all

# The following 3 lines:
trigger_multiple.set_key_value_int("spawnflags", 1)
trigger_multiple.set_property_vector("m_Collision.m_vecMaxs", maxs)
trigger_multiple.set_property_vector("m_Collision.m_vecMins", mins)

# Could just be
trigger_multiple.spawn_flags = 1
trigger_multiple.maxs = maxs
trigger_multiple.mins = mins
For reference:
spawn_flags
[url=https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/addons/source-python/data/source-python/entities/CBaseEntity.ini#L78-#L79]maxs and mins[/url]


We could easily add m_Collision.m_nSolidType and m_hGroundEntity (the last of which seems to be engine specific) to the data, too.
Image
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Fri Dec 18, 2015 9:35 am

Also, you could replace the hard-coded values using their respective constants.

Syntax: Select all

from entities.constants import INVALID_ENTITY_INTHANDLE

if player.get_property_int('m_hGroundEntity') == INVALID_ENTITY_INTHANDLE:


from entities.constants import SolidType

trigger_multiple.set_property_uchar("m_nSolidType", SolidType.BBOX)
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Postby decompile » Fri Dec 18, 2015 12:36 pm

Thank you guys! Amazing support on the forums.

Gonna do now for each questions a new thread except theyre related to each other.
User avatar
Doldol
Senior Member
Posts: 200
Joined: Sat Jul 07, 2012 7:09 pm
Location: Belgium

Postby Doldol » Fri Dec 18, 2015 3:59 pm

Thanks for pointing out those improvements! :)
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Dec 18, 2015 9:42 pm

Just a note, but we did add solid_type and ground_entity to the entity data:
https://github.com/Source-Python-Dev-Team/Source.Python/commit/4cd177d074c577ab6d157e1def36912aafd123b3

Now you can just use:

Syntax: Select all

from entities.constants import INVALID_ENTITY_INTHANDLE

if player.ground_entity == INVALID_ENTITY_INTHANDLE:


from entities.constants import SolidType

trigger_multiple.solid_type = SolidType.BBOX
Image
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Postby decompile » Fri Dec 18, 2015 11:58 pm

Hey, easy to use thanks!
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Postby decompile » Sat Dec 19, 2015 12:14 am

Most stuff is already done and worked! Thanks especially with the list().

Syntax: Select all

@SayFilter
def say_filter(CCommand, index, teamonly):
text = CCommand.get_arg_string()


skips actually the first say argument like if i write

"Hello im decompile"

it prints only "im decompile"

if i would write only "Hello" it would return ""
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Dec 19, 2015 12:25 am

Use get_command_string instead. get_arg_string, like the name is telling you, get the "arguments" as a string, not the entire command line.
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Postby decompile » Thu Jan 14, 2016 12:29 am

Hey,

Im getting back to this thread since im trying to use the keypress stuff now.

Syntax: Select all

from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from players import UserCmd
from players.constants import PlayerButtons
from players.entity import Player
from memory import make_object

@EntityPreHook(EntityCondition.is_human_player, 'run_command')
def pre_player_run_command(stack_data):
'''Pre hook around CBasePlayer::PlayerRunCommand.'''

# Get the Player instance...
player = make_object(Player, stack_data[0])

# Get the UserCmd instance...
usercmd = make_object(UserCmd, stack_data[1])

# Is the player holding his +attack button?
if (not player.buttons & PlayerButtons.ATTACK and
usercmd.buttons & PlayerButtons.ATTACK):

# Prints something...
print(player.name, 'pressed his +attack button!')


Lets say I want to create a showkeys plugin and only want to hook specific commands

Syntax: Select all

needed_commands = ["IN_JUMP", "IN_DUCK", "IN_FORWARD", "IN_BACK", "IN_LEFT", "IN_RIGHT", "IN_MOVELEFT", "IN_MOVELEFT"]
#(just created it fast)


Then I would create a playerclass with each command

and then change it when he used the command when its in the list

like keyPress(command, status) where command would be "IN_JUMP" and status 1 if hes "holding" the button or 0 when nothing

Or is there a better and smarter way to do that
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Thu Jan 14, 2016 6:50 pm

I don't really understand the idea with the "playerclass". This is how I would do it.

Syntax: Select all

from enum import IntEnum

from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from players import UserCmd
from players.constants import PlayerButtons
from players.entity import Player
from memory import make_object

class ButtonStatus(IntEnum):
RELEASED = 0
PRESSED = 1

@EntityPreHook(EntityCondition.is_human_player, 'run_command')
def pre_player_run_command(stack_data):
"""Pre hook around CBasePlayer::PlayerRunCommand."""
player = make_object(Player, stack_data[0])
usercmd = make_object(UserCmd, stack_data[1])

player_buttons = player.buttons
command_buttons = usercmd.buttons
for button in PlayerButtons:
previously_pressed = player_buttons & button.value
now_pressed = command_buttons & button.value

if not previously_pressed and now_pressed:
on_button_status_changed(player, button, ButtonStatus.PRESSED)

elif previously_pressed and not now_pressed:
on_button_status_changed(player, button, ButtonStatus.RELEASED)

BUTTONS_YOU_WANT_TO_LISTEN_TO = [PlayerButtons.ATTACK, PlayerButtons.JUMP]

def on_button_status_changed(player, button, status):
"""Called when the player's button status has changed."""
if button in BUTTONS_YOU_WANT_TO_LISTEN_TO:
print(player.name, button, status)
Btw. in many cases it's better to use enums instead of 0/1 or True/False, because you can choose descriptive names.

Let me show you an example. Imagine you read some code you have written weeks, months or years ago or even code from other people. And then you see this:

Syntax: Select all

if status:
# Do something
It doesn't tell you very much, right? But what if you look at this?

Syntax: Select all

if status == ButtonStatus.PRESSED:
# Do something
It's pretty obvious that "status" contains a button status. Moreover, it tells you that this if-clause handles a button that has been pressed.
decompile
Senior Member
Posts: 416
Joined: Sat Oct 10, 2015 10:37 am
Location: Germany
Contact:

Re: More questions

Postby decompile » Tue Apr 19, 2016 3:07 pm

def isOnGround(self):
if PlayerEntity(self.index).ground_entity == INVALID_ENTITY_INTHANDLE:
return False
else:
return True

Is this actually working? I created a test command which prints if im on ground or not. Tried both in air and on ground but both returns only True
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Re: More questions

Postby iPlayer » Tue Apr 19, 2016 3:13 pm

Ah, your question got deleted during migration.

First of all, this can be shortened to

Code: Select all

def isOnGround(self):
    return PlayerEntity(self.index).ground_entity != INVALID_ENTITY_INTHANDLE


Secondly, L'In20Cible told you to use -1 instead of INVALID_ENTITY_INTHANDLE
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Re: More questions

Postby satoon101 » Tue Apr 19, 2016 3:17 pm

iPlayer wrote:Ah, your question got deleted during migration.

Yeah, sorry about that. We didn't lock down the old forums until the database conversion was already underway. I did take a screenshot of the 3 lost posts, but completely forgot to post that here.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: More questions

Postby Ayuto » Sat Sep 24, 2016 8:58 am

I have just added an OnButtonStateChanged listener, which can be used instead of my code above:
http://wiki.sourcepython.com/developing ... atechanged

Btw. now there is also an OnPlayerRunCommand listener, so you don't need to hook "run_command" on your own anymore.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 29 guests