-
-
Save adamcunnington/a0bfe5481270cb20cbf1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# <path to game directory>/addons/eventscripts/_engines/python/Lib/esutils/ | |
# weapons.py | |
# by Adam Cunnington | |
"""Provide a uniform manner to register and store weapon information but also | |
methods to query realtime information, such as data for a specific weapon | |
index. | |
""" | |
from esutils import tools | |
import es | |
__all__ = ( | |
"SLOT_PRIMARY", | |
"SLOT_SECONDARY", | |
"SLOT_MELEE", | |
"SLOT_GRENADE", | |
"SLOT_BOMB", | |
"WeaponsError", | |
"WeaponManager", | |
"CATEGORY_OBJECTIVE", | |
"CATEGORY_GRENADE", | |
"CATEGORY_MACHINE_GUN", | |
"CATEGORY_MELEE", | |
"CATEGORY_PISTOL", | |
"CATEGORY_RIFLE", | |
"CATEGORY_SHOTGUN", | |
"CATEGORY_SNIPER_RIFLE", | |
"CATEGORY_SUBMACHINE_GUN", | |
"Weapon", | |
"idle_weapon_types_by_categories", | |
"indexes_by_categories", | |
"indexes_by_names", | |
"indexes_by_slot", | |
"transform_weapon_name", | |
"weapon_by_name", | |
"weapon_types_by_categories", | |
"weapon_types_by_slot", | |
) | |
SLOT_PRIMARY = 1 | |
SLOT_SECONDARY = 2 | |
SLOT_MELEE = 3 | |
SLOT_GRENADE = 4 | |
SLOT_BOMB = 5 | |
class WeaponsError(Exception): | |
"""General error encountered relating to esutils.weapons""" | |
pass | |
class _WeaponType(object): | |
def __init__(self, name, clip_size, max_ammo_variable, | |
ammo_property_number, weapon_mode_property=None): | |
"""Instantiate a _WeaponType object. | |
Arguments: | |
name - the full name of the weapon's classname. | |
clip_size - the size of the weapon's clip when full. | |
max_ammo_variable - the number representing the ammo type to be | |
substituted into the variable string, ammo_<number>_max. | |
ammo_property_number - the number representing the ammo property to be | |
substituted into the entity property, | |
"CBasePlayer.localdata.m_iAmmo.<number>". | |
weapon_mode_property (Keyword Default: None) - the entity property | |
name of the weapon's SLOT_SECONDARY attack mode. | |
""" | |
self._max_ammo_variable = es.ServerVar("ammo_%s_max" | |
% max_ammo_variable) | |
self.name = name | |
self.clip_size = clip_size | |
self.ammo_property = ("CBasePlayer.localdata.m_iAmmo.%s" | |
% ammo_property_number) | |
self.weapon_mode_property = weapon_mode_property | |
def _get_max_ammo(self): | |
return int(self._max_ammo_variable) | |
def _set_max_ammo(self, value): | |
self._max_ammo_variable.set(value) | |
max_ammo = property(_get_max_ammo, _set_max_ammo) | |
@property | |
def indexes(self): | |
# Property get function that returns the compiled entityindexlist for | |
# the weapon's classname. | |
return es.createentityindexlist(self.name) | |
class WeaponManager(object): | |
"""Create a thread safe instance to manage a game's weapons | |
individually. | |
""" | |
def __init__(self): | |
self.weapons = {} | |
def register(self, weapon_class, name, *args, **kwargs): | |
"""Register data about a weapon to the central data structure. | |
Arguments: | |
weapon_class - the category of weapon class the weapon belongs to. | |
name - the full classname of the weapon. | |
args - the positional arguments defined in the weapon class. | |
kwargs - the keyword arguments defined in the weapon class. | |
""" | |
self.weapons[name] = weapon_class(name, *args, **kwargs) | |
CATEGORY_OBJECTIVE = object() | |
class _Bomb(_WeaponType): | |
SLOT = SLOT_BOMB | |
CATEGORY = CATEGORY_OBJECTIVE | |
VERBOSE_CATEGORY = "Objective" | |
def __init__(self, name): | |
super(_Bomb, self).__init__(name, 0, None, None) | |
CATEGORY_GRENADE = object() | |
class _Grenade(_WeaponType): | |
SLOT = SLOT_GRENADE | |
CATEGORY = CATEGORY_GRENADE | |
VERBOSE_CATEGORY = "Grenade" | |
def __init__(self, name, ammo_property_number): | |
super(_Grenade, self).__init__(name, 0, name, ammo_property_number) | |
CATEGORY_MACHINE_GUN = object() | |
class _MachineGun(_WeaponType): | |
SLOT = SLOT_PRIMARY | |
CATEGORY = CATEGORY_MACHINE_GUN | |
VERBOSE_CATEGORY = "Machine Gun" | |
CATEGORY_MELEE = object() | |
class _Melee(_WeaponType): | |
SLOT = SLOT_MELEE | |
CATEGORY = CATEGORY_MELEE | |
VERBOSE_CATEGORY = "Melee" | |
def __init__(self, name): | |
super(_Melee, self).__init__(name, 0, None, None) | |
CATEGORY_PISTOL = object() | |
class _Pistol(_WeaponType): | |
SLOT = SLOT_SECONDARY | |
CATEGORY = CATEGORY_PISTOL | |
VERBOSE_CATEGORY = "Pistol" | |
CATEGORY_RIFLE = object() | |
class _Rifle(_WeaponType): | |
SLOT = SLOT_PRIMARY | |
CATEGORY = CATEGORY_RIFLE | |
VERBOSE_CATEGORY = "Rifle" | |
CATEGORY_SHOTGUN = object() | |
class _Shotgun(_WeaponType): | |
SLOT = SLOT_PRIMARY | |
CATEGORY = CATEGORY_SHOTGUN | |
VERBOSE_CATEGORY = "Shotgun" | |
CATEGORY_SNIPER_RIFLE = object() | |
class _SniperRifle(_WeaponType): | |
SLOT = SLOT_PRIMARY | |
CATEGORY = CATEGORY_SNIPER_RIFLE | |
VERBOSE_CATEGORY = "Sniper Rifle" | |
CATEGORY_SUBMACHINE_GUN = object() | |
class _SubMachineGun(_WeaponType): | |
SLOT = SLOT_PRIMARY | |
CATEGORY = CATEGORY_SUBMACHINE_GUN | |
VERBOSE_CATEGORY = "Submachine Gun" | |
_cstrike = WeaponManager() | |
_cstrike.register(_Shotgun, "weapon_m3", 8, "buckshot", "007") | |
_cstrike.register(_Shotgun, "weapon_xm1014", 7, "buckshot", "007") | |
_cstrike.register(_SubMachineGun, "weapon_mac10", 30, "45acp", "008") | |
_cstrike.register(_SubMachineGun, "weapon_tmp", 30, "9mm", "006") | |
_cstrike.register(_SubMachineGun, "weapon_mp5navy", 30, "9mm", "006") | |
_cstrike.register(_SubMachineGun, "weapon_ump45", 25, "45acp", "008") | |
_cstrike.register(_SubMachineGun, "weapon_p90", 50, "57mm", "010") | |
_cstrike.register(_Rifle, "weapon_galil", 35, "556mm", "003") | |
_cstrike.register(_Rifle, "weapon_famas", 25, "556mm", "003", | |
"CWeaponFamas.m_bBurstMode") | |
_cstrike.register(_Rifle, "weapon_ak47", 30, "762mm", "002") | |
_cstrike.register(_Rifle, "weapon_m4a1", 30, "556mm", "003", | |
"CWeaponM4A1.m_bSilencerOn") | |
_cstrike.register(_Rifle, "weapon_sg552", 30, "556mm", "003") | |
_cstrike.register(_Rifle, "weapon_aug", 30, "762mm", "002") | |
_cstrike.register(_MachineGun, "weapon_m249", 100, "556mm_box", "004") | |
_cstrike.register(_SniperRifle, "weapon_scout", 10, "762mm", "002") | |
_cstrike.register(_SniperRifle, "weapon_awp", 10, "338mag", "005") | |
_cstrike.register(_SniperRifle, "weapon_sg550", 30, "556mm", "003") | |
_cstrike.register(_SniperRifle, "weapon_g3sg1", 20, "762mm", "002") | |
_cstrike.register(_Pistol, "weapon_glock", 20, "9mm", "006", | |
"CWeaponGlock.m_bBurstMode") | |
_cstrike.register(_Pistol, "weapon_usp", 12, "45acp", "008", | |
"CWeaponUSP.m_bSilencerOn") | |
_cstrike.register(_Pistol, "weapon_p228", 13, "357sig", "009") | |
_cstrike.register(_Pistol, "weapon_deagle", 7, "50ae", "001") | |
_cstrike.register(_Pistol, "weapon_elite", 30, "9mm", "006") | |
_cstrike.register(_Pistol, "weapon_fiveseven", 20, "57mm", "010") | |
_cstrike.register(_Melee, "weapon_knife") | |
_cstrike.register(_Grenade, "weapon_flashbang", "012") | |
_cstrike.register(_Grenade, "weapon_heSLOT_GRENADE", "011") | |
_cstrike.register(_Grenade, "weapon_smokeSLOT_GRENADE", "013") | |
_cstrike.register(_Bomb, "weapon_c4") | |
class Weapon(object): | |
"""Create a unique weapon object representing an individual index that can | |
be queried and set.""" | |
def __init__(self, index): | |
"""Instantiate a Weapon object. | |
Arguments: | |
index - the individual index of the specific weapon. | |
""" | |
self.index = index | |
name = es.entitygetvalue(index, "classname") | |
if not name.startswith("weapon_"): | |
raise WeaponsError("%s is not a valid weapon index" % self.index) | |
self.weapon_type = _cstrike.weapons[name] | |
def _get_ammo(self): | |
owner = self.owner | |
if self.owner is None: | |
raise WeaponsError("weapon does not have an owner") | |
return es.getplayerprop(owner.user_ID, self.weapon_type.ammo_property) | |
def _get_clip(self): | |
clip = es.getindexprop(self.index, | |
"CBaseCombatWeapon.LocalWeaponData.m_iClip1") | |
if clip != -1: | |
return clip | |
# Instead of raising an exception, if the weapon has no clip value, | |
# return None. | |
return None | |
def _get_colour(self): | |
return tools.get_colour(self.index) | |
def _get_handle(self): | |
return es.getindexprop(index, "CBaseCombatWeapon.m_hOwner") | |
def _is_mode_on(self): | |
"""Determine whether the weapon's SLOT_SECONDARY attack mode is on and | |
return the result. Immediately return False if the weapon has no | |
SLOT_SECONDARY mode. | |
""" | |
if self.weapon_type.weapon_mode_property is None: | |
return False | |
return bool(es.getindexprop(self.index, self.weapon_type)) | |
def remove(self): | |
"""Remove the weapon from existence on the server.""" | |
es.server.insertcmd("es_xremove %s" % self.index) | |
def _set_ammo(self, value): | |
owner = self.owner | |
if self.owner is None: | |
raise WeaponsError("weapon does not have an owner") | |
return es.setplayerprop(owner.user_ID, self.weapon_type.ammo_property, | |
value) | |
ammo = property(_get_ammo, _set_ammo) | |
def _set_clip(self, value): | |
es.setindexprop(self.index, | |
"CBaseCombatWeapon.LocalWeaponData.m_iClip1", value) | |
clip = property(_get_clip, _set_clip) | |
def _set_colour(self, red, blue, green, alpha=255): | |
tools.set_colour(self.index, red, blue, green, alpha) | |
colour = property(_get_colour, _set_colour) | |
def _set_mode(self, value): | |
if self.weapon_type.weapon_mode_property is None: | |
raise AttributeError("can't set attribute") | |
# The property set function that will only be available if the weapon | |
# has a SLOT_SECONDARY weapon mode and can forcefully set the mode to | |
# be on or off. | |
es.setindexprop(self.index, self.weapon_type.weapon_mode_property, | |
int(value)) | |
mode_on = property(_is_mode_on, _set_mode) | |
def _get_indexes(iterable): | |
# Internal helper function that returns a generator of indexes. | |
for weapon_type in iterable: | |
for index in weapon_type.indexes: | |
yield index | |
def idle_weapon_types_by_categories(*args): | |
"""Return a generator object of idle weapon indexes. If arguments are | |
omitted, return all. | |
Arguments: | |
args - categories to filter return results by. | |
""" | |
for index in _get_indexes(weapon_types_by_categories(*args)): | |
if es.getindexprop(index, "CBaseCombatWeapon.m_hOwner") == -1: | |
yield index | |
def indexes_by_categories(*args): | |
"""Return a generator object of indexes for weapons in specific | |
categories. If arguments are omitted, return all. | |
Arguments: | |
args - categories to filter return results by. | |
""" | |
return _get_indexes(weapon_types_by_categories(*args)) | |
def indexes_by_names(*args, weapon_manager=_cstrike): | |
"""Return a generator object of indexes for weapons with specific names. | |
Arguments: | |
args - names to filter return results by. | |
""" | |
return _get_indexes(weapon_manager.weapons[name] | |
for transform_weapon_name(name) in *args) | |
def indexes_by_slot(slot): | |
"""Return a generator object of indexes for weapons in specific slots. | |
Arguments: | |
args - weapon slot to filter return results by. | |
""" | |
return _get_indexes(weapon_types_by_slot(slot)) | |
def transform_weapon_name(name): | |
if name.startswith("weapon_"): | |
return name | |
return "weapon_%s" % name | |
def weapon_types_by_name(*args, weapon_manager=_cstrike): | |
"""Return a generator object weapon type objects for weapons with | |
particular names. | |
Arguments: | |
args - names to filter return results by. | |
""" | |
for name in args: | |
yield weapon_manager.weapons[transform_weapon_name(name)] | |
def weapon_types_by_categories(*args, weapon_manager=_cstrike): | |
"""Return a generator object of weapon type objects for weapons in | |
specific categories. If arguments are omitted, return all. | |
Arguments: | |
args - categories to filter return results by. | |
""" | |
if not args: | |
return weapon_manager.weapons.itervalues() | |
return (weapon_type for weapon_type in weapon_manager.weapons.itervalues() | |
if weapon_type.CATEGORY in args) | |
def weapon_types_by_slot(slot, weapon_manager=_cstrike): | |
"""Return a generator object of weapon type objects for weapons in | |
specific slots. | |
Arguments: | |
args - weapon slot to filter return results by. | |
""" | |
for weapon_type in weapon_manager.weapons.itervalues(): | |
if weapon_type.SLOT == slot: | |
yield weapon_type |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment