Page 1 of 1

Simple Deagle Headshot Only

Posted: Fri Jan 15, 2016 8:29 pm
by Kami
Here is a simple deagle headshot-only plugin for you guys. Nothing fancy but it does the job!

Syntax: Select all

from events.hooks import PreEvent
from events import Event
from weapons.entity import Weapon
from entities.helpers import index_from_inthandle
from players.entity import Player
from players.helpers import index_from_userid

from mathlib import NULL_VECTOR
from entities.entity import BaseEntity

from players.constants import HitGroup


@PreEvent('player_hurt')
def _player_pre_hurt(event):
player = Player(index_from_userid(event.get_int('userid')))
hitgroup = event.get_int('hitgroup')
if hitgroup != HitGroup.HEAD:
damage = int(event.get_float('dmg_health'))
damage_armor = int(event.get_float('dmg_armor'))
player.armor += damage_armor
player.health += damage


@Event('player_spawn')
def _player_spawn(event):
player = Player(index_from_userid(event.get_int('userid')))
for index in player.weapon_indexes():
weapon = Weapon(index)
player.drop_weapon(weapon.pointer, NULL_VECTOR, NULL_VECTOR)
weapon.remove()
player.give_named_item('weapon_deagle', 0, None, True)

Posted: Fri Jan 15, 2016 9:06 pm
by iPlayer
Hey, it's good you actually thought of armor.

There're a few possible issues I see
1. AWP can still kill people in body. Of course you'll have to buy it after you've spawned. What about hooking OnTakeDamage?
2. You only strip player's active weapon once. You can successfully, say, strip their rifle or grenade or knife, and they will keep their glock/usp and your deagle will just fall on the ground. To prevent this, I would iterate over player.weapon_indexes:

Syntax: Select all

from mathlib import NULL_VECTOR
from entities.entity import BaseEntity

...


for index in player.weapon_indexes():
weapon = BaseEntity(index)
player.drop_weapon(weapon.pointer, NULL_VECTOR, NULL_VECTOR)
weapon.remove()

3. As you can see, I force player to drop the weapon first. I'm not sure, but here's the thing: SP doesn't iterate over all possible entity indexes when trying to get player's weapons. Instead, it just gets the needed indexes directly from player's props - player has some props pointing to the weapons they are holding. And the trick is that if you remove the weapon without dropping it first, this index will still remain in player's props. And any time you access .weapon_indexes() from then on, there will be an exception. Breaking everything. But I need somebody to confirm this theory.


EDIT: Also, you can use HitGroup class from players.constants:

Syntax: Select all

from players.constants import HitGroup

...

if hitgroup != HitGroup.HEAD:
...


That would make it more readable and flexible

Posted: Fri Jan 15, 2016 9:26 pm
by Kami
Thank you for your answer!

To 1: Thats why I used PreEvent which fires before the damage is done, so an AWP body kill is not possible (to be sure I tested that)
I tried hooking OnTakeDamage but TakeDamageInfo didn't seem to include the hitgroup so I went with PreEvent

To 2: Added that, thank you! I think I should add buy restriction too, so you can really only have a deagle.

Posted: Fri Jan 15, 2016 9:38 pm
by satoon101

Posted: Fri Jan 15, 2016 9:41 pm
by Kami
Ah okay. Is it better to use OnTakeDamage here instead of PreEvent or doesn't it matter?

Posted: Fri Jan 15, 2016 9:45 pm
by iPlayer
If'd suggest that you can check if it was a headshot using TakeDamageInfo.type property:

Syntax: Select all

from entities import TakeDamageInfo
from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from memory import make_object
from players.entity import Player


HEADSHOT = 1 << 30


@EntityPreHook(EntityCondition.is_player, 'on_take_damage')
def on_take_damage(args):
info = make_object(TakeDamageInfo, args[1])
if not info.type & HEADSHOT:
info.damage = 0


I'm not sure, but headshot appears to be a bit at 30th position. Though I couldn't find it here, I guess 1 << 30 is a headshot in Counter-Strike games.

To prevent picking up weapons at all, consider hooking 'bump_weapon':

Syntax: Select all

from entities.helpers import edict_from_pointer
from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook


@EntityPreHook(EntityCondition.is_player, 'bump_weapon')
def on_bump_weapon(args):
weapon_edict = edict_from_pointer(args[1])
if weapon_edict.get_class_name() == 'weapon_deagle':
# Allow bumping
return None

# Disallow bumping
return True


That would prevent getting the weapon even through give_named_item.

Posted: Fri Jan 15, 2016 9:54 pm
by iPlayer
Also what happens if player runs out of ammo? You can think of !give command that restores ammo or restore it automatically every X seconds.

Posted: Fri Jan 15, 2016 10:40 pm
by L'In20Cible

Posted: Sat Jan 16, 2016 5:05 am
by iPlayer


Completely missed that one, thanks

Posted: Thu Jan 21, 2016 3:45 am
by satoon101
I should also note that instead of changing the damage amount to 0, you should just block the function from happening. Also, if a server has bots on it and a bot joins the server prior to a player, then EntityCondition.is_player will not properly hook the on_take_damage. OnTakeDamage is a member function of CCSBot. Hooking on_take_damage on a bot would hook that function instead of CCSPlayer::OnTakeDamage. To counteract that, you can hook both of them like this:

Syntax: Select all

from entities import TakeDamageInfo
from entities.constants import DamageTypes
from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from memory import make_object


@EntityPreHook(EntityCondition.is_human_player, 'on_take_damage')
@EntityPreHook(EntityCondition.is_bot_player, 'on_take_damage')
def _pre_take_damage(args):
take_damage_info = make_object(TakeDamageInfo, args[1])
if not take_damage_info.type & DamageTypes.HEADSHOT:
return 0


Also, I do plan on working on the restriction system again very soon. I have been very busy lately, but should hopefully get some time to work on SP stuff in the coming weeks. The restriction system is near the top of my agenda.