|
| 1 | +entities |
| 2 | +======== |
| 3 | + |
| 4 | +This page contains tutorials about the :mod:`entities` package. Basically, the |
| 5 | +entities package provides functions and classes to create, modify, access and |
| 6 | +delete entities. An entity is an object somewhere on the map that has a specific |
| 7 | +type (class name) and different properties (e. g. health, position, team index, |
| 8 | +speed, model, etc.). |
| 9 | + |
| 10 | +There are two types of entities: |
| 11 | + |
| 12 | +* Networked entities |
| 13 | +* Non-networked entities |
| 14 | + |
| 15 | +``Networked`` already indicates that those entities are sent over the network. |
| 16 | +Their information is shared with all players on the server. Some common examples |
| 17 | +for those entities are players, weapons, barrels or trigger entities. |
| 18 | +Non-networked entities are entities that only exist on the server or client, but |
| 19 | +not on both sides. Entities are uniquely identified by an index that |
| 20 | +starts at 0 and can go up to the |
| 21 | +`entity limit <https://developer.valvesoftware.com/wiki/Entity_limit>`_. |
| 22 | + |
| 23 | +.. note:: |
| 24 | + |
| 25 | + Indexes uniquely identify an entity. However, if the entity is deleted, a |
| 26 | + new entity can reuse that index. |
| 27 | + |
| 28 | + |
| 29 | +You will most likely want to access networked entities. Those are the most |
| 30 | +common and interesting ones. |
| 31 | + |
| 32 | +There are multiple classes in Source.Python to access the various entity types: |
| 33 | + |
| 34 | +* :class:`entities.entity.BaseEntity` - A very basic, but fast class to access networked and non-networked entities. |
| 35 | +* :class:`entities.entity.Entity` - An extended version of the :class:`entities.entity.BaseEntity` class. It provides a lot convenience methods, but is only able to access networked entities. |
| 36 | +* :class:`players.entity.Player` - An extended version of the :class:`entities.entity.Entity` class that provides additional methods to manipulate players. |
| 37 | +* :class:`weapons.entity.Weapon` - An extended version of the :class:`entities.entity.Entity` class that provides additional methods for weapons. |
| 38 | + |
| 39 | +This tutorial will only cover :class:`entities.entity.BaseEntity` and |
| 40 | +:class:`entities.entity.Entity`. For the other two classes, there will be |
| 41 | +separate tutorials. |
| 42 | + |
| 43 | + |
| 44 | +Accessing entities |
| 45 | +------------------ |
| 46 | + |
| 47 | +If you know the index of an entity, it's quite simple to access it. |
| 48 | + |
| 49 | +.. code-block:: python |
| 50 | +
|
| 51 | + from entities.entity import Entity |
| 52 | +
|
| 53 | + # Access the entity with index 0. The world entity always has the index 0. |
| 54 | + entity = Entity(0) |
| 55 | +
|
| 56 | + # Print the class name of the entity. This will print "worldspawn". |
| 57 | + print(entity.classname) |
| 58 | +
|
| 59 | +
|
| 60 | +However, often you need to search for entities of a specific type. E. g. to get |
| 61 | +all buy zones: |
| 62 | + |
| 63 | +.. code-block:: python |
| 64 | +
|
| 65 | + # Import the entity iterator |
| 66 | + from filters.entities import EntityIter |
| 67 | +
|
| 68 | + # Loop through all buy zones |
| 69 | + for buy_zone in EntityIter('func_buyzone'): |
| 70 | +
|
| 71 | + # Print the team index of the buy zone. Only teams with the same index can |
| 72 | + # use this buy zone. |
| 73 | + print(f'Buy zone for team: {buy_zone.team_index}') |
| 74 | +
|
| 75 | + # If you are not used to Python 3.6, the print statement might be |
| 76 | + # confusing at first. Alternatively, you could also write: |
| 77 | + # print('Buy zone for team: {}'.format(buy_zone.team_index)) |
| 78 | +
|
| 79 | +
|
| 80 | +You might wonder how to know which entity types are currently available on the |
| 81 | +map. You can easily discover that by using the following snippet. |
| 82 | + |
| 83 | +.. code-block:: python |
| 84 | +
|
| 85 | + # Import the entity iterator. |
| 86 | + from filters.entities import EntityIter |
| 87 | +
|
| 88 | + # Get the class name of every entity on the map. Use set() to get a distinct |
| 89 | + # set. |
| 90 | + classnames = set(entity.classname for entity in EntityIter()) |
| 91 | +
|
| 92 | + # Sort all class names alphabetically and then print them. |
| 93 | + for classname in sorted(classnames): |
| 94 | + print(classname) |
| 95 | +
|
| 96 | +
|
| 97 | +Modifying entities |
| 98 | +------------------ |
| 99 | + |
| 100 | +In the previous chapter we looped through all buy zones to print their team |
| 101 | +indexes. Now, let's loop through all doors on the map and open them. |
| 102 | + |
| 103 | +.. code-block:: python |
| 104 | +
|
| 105 | + # Import the entity iterator |
| 106 | + from filters.entities import EntityIter |
| 107 | +
|
| 108 | + # Loop through all doors |
| 109 | + for door in EntityIter('prop_door_rotating'): |
| 110 | +
|
| 111 | + # Open the door |
| 112 | + door.open() |
| 113 | +
|
| 114 | + # Or, if you are tired of the doors, simply remove them with: |
| 115 | + # door.remove() |
| 116 | +
|
| 117 | +
|
| 118 | +If you just tried to find information about ``door.open()`` on the wiki, you |
| 119 | +probably didn't find anything except this tutorial. This is because of all the |
| 120 | +different entity types. They all have different properties and methods, which |
| 121 | +also differs from game to game. Thus, you can only print these information at |
| 122 | +runtime. To do so, you can use the following snippet. |
| 123 | + |
| 124 | +.. code-block:: python |
| 125 | +
|
| 126 | + from entities.entity import Entity |
| 127 | +
|
| 128 | + # Find an entity with the class name "prop_door_rotating". If no entity was |
| 129 | + # found, it will be created. |
| 130 | + entity = Entity.find_or_create('prop_door_rotating') |
| 131 | +
|
| 132 | + # Loop through all attributes |
| 133 | + for attr in dir(entity): |
| 134 | +
|
| 135 | + # Print the attribute |
| 136 | + print(attr) |
| 137 | +
|
| 138 | +
|
| 139 | +Creating new entities |
| 140 | +--------------------- |
| 141 | + |
| 142 | +Creating new entities is quite simple. Often you just need to create an entity |
| 143 | +of the desired type, assign it a model and then spawn it. Here is how to do |
| 144 | +that. |
| 145 | + |
| 146 | +.. code-block:: python |
| 147 | +
|
| 148 | + # Import the required classes. |
| 149 | + from entities.entity import Entity |
| 150 | + from players.entity import Player |
| 151 | + from engines.precache import Model |
| 152 | + from events import Event |
| 153 | +
|
| 154 | + # Wrap the model (a barrel) with the Model class. It will ensure that the model |
| 155 | + # is precached, when you want to use it. Precaching is important. Otherwise |
| 156 | + # the model might not work. |
| 157 | + my_model = Model('models/props_c17/oildrum001.mdl') |
| 158 | +
|
| 159 | + # Listen to the player_say event. It gets fired everytime a player says |
| 160 | + # something in the chat. |
| 161 | + @Event('player_say') |
| 162 | + def on_player_say(event): |
| 163 | + # Get a Player instance for the player who typed something into the chat. |
| 164 | + player = Player.from_userid(event['userid']) |
| 165 | +
|
| 166 | + # Create an entity of the type "prop_physics_multiplayer". |
| 167 | + entity = Entity.create('prop_physics_multiplayer') |
| 168 | +
|
| 169 | + # Assign the model. |
| 170 | + entity.model = my_model |
| 171 | +
|
| 172 | + # Set the location where the entity should be created. In this case we want |
| 173 | + # to spawn it where the player is currently looking at. |
| 174 | + entity.origin = player.view_coordinates |
| 175 | +
|
| 176 | + # Finally spawn the entity. |
| 177 | + entity.spawn() |
| 178 | +
|
| 179 | +
|
| 180 | +.. note:: |
| 181 | + |
| 182 | + The model ``models/props_c17/oildrum001.mdl`` already exists in CS:S. In |
| 183 | + other games this might be different. |
0 commit comments