Crowbar throw

A place for requesting new Source.Python plugins to be made for your server.

Please request only one plugin per thread.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Crowbar throw

Postby daren adler » Thu Aug 20, 2020 7:38 pm

Hello SourcePython Team and Community,
Would it be possible to make a SP for me in my hl2dm server for crowbar throwing?
Thank you.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Re: Crowbar throw

Postby satoon101 » Fri Aug 21, 2020 1:17 am

I tried to achieve this for my ThrowMelee plugin, but never could get any of the hl2dm melee weapons to work, iirc. Not saying it can't be done, though, but I did try a number of things to get it to work.
Image
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: Crowbar throw

Postby daren adler » Fri Aug 21, 2020 1:50 am

satoon101 wrote:I tried to achieve this for my ThrowMelee plugin, but never could get any of the hl2dm melee weapons to work, iirc. Not saying it can't be done, though, but I did try a number of things to get it to work.


Ok, thanks for the info, I tryed the sourcemod ones and also failed on them.
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: Crowbar throw

Postby Painkiller » Fri Aug 21, 2020 6:17 am

With a few minor adjustments, it could work for you.

Syntax: Select all

# ../addons/source-python/plugins/supermod/modules/throwbar.py

# ============================================================================
# >> IMPORTS
# ============================================================================
from engines.precache import Model
from entities.entity import Entity
from events import Event
from players.entity import Player
from filters.players import PlayerIter
from listeners.tick import Repeat
from players.constants import PlayerButtons
from mathlib import Vector
from colors import Color

from listeners.tick import Delay, Repeat
import core
from entities.constants import SolidFlags
from entities.hooks import EntityPreHook
from entities.hooks import EntityCondition
from entities.helpers import index_from_inthandle
from entities.constants import CollisionGroup, SolidType
from memory import make_object
from messages.base import HintText
import random
from entities import TakeDamageInfo
from weapons.manager import weapon_manager
from messages import SayText2
import core

crowbar = Model("models/weapons/w_crowbar.mdl")
stunstick = Model("models/weapons/w_stunbaton.mdl")
cr_path = "models/weapons/w_crowbar.mdl"
st_path = "models/weapons/w_stunbaton.mdl"
sound = "weapons/slam/throw.wav"
sound_empty = "physics/metal/weapon_footstep1.wav"
sound_pickup = ""
shoot_delay = 2.0
kill_delay = 15.0
throw_force = 10000
core.console_message("\n[Supermod] Throwbar loaded!")

max_ammo = 10
ammo = {}
can_shoot = {}
thrown = []


def init_player(userid):
ammo[userid] = max_ammo
can_shoot[userid] = 1


@Event('player_connect')
def connect(ev):
init_player(ev['userid'])


def load():
for player in PlayerIter('all'):
init_player(player.userid)


@Event('player_spawn')
def spawn(ev):
ammo[ev['userid']] = max_ammo
can_shoot[ev['userid']] = 1


def check_buttons():
for player in PlayerIter('alive'):
if player.buttons & PlayerButtons.ATTACK2:
userid = player.userid
if player.active_weapon is not None:
if userid not in can_shoot:
init_player(userid)

_weapon = player.active_weapon.weapon_name
if _weapon == "weapon_crowbar":
if can_shoot[player.userid] == 1:
throwStuff(player.index, "weapon_crowbar")

if _weapon == "weapon_stunstick":
if can_shoot[player.userid] == 1:
throwStuff(player.index, "weapon_stunstick")


@EntityPreHook(EntityCondition.is_player, 'touch')
def pre_start_touch(stack):
entity = make_object(Entity, stack[1])
other = make_object(Entity, stack[0])
if entity.classname.startswith("prop_physics"):
if other.classname == "player":
if entity.owner_handle == -1:
if entity.model.path == cr_path or entity.model.path == st_path:
entity.call_input("Kill")
ammo[Player(other.index).userid] += 1
# Player(other.index).play_sound(sound_pickup,download=True)
handle = entity.get_property_int('m_pParent')
if handle != -1:
return False


def reset_shot(userid):
can_shoot[userid] = 1


def kill_ent(entity):
if entity in thrown:
thrown.remove(entity)
entity.call_input("Kill")


def throwStuff(index, weapon_name):
player = Player(index)
if ammo[player.userid] == 0:
player.play_sound(sound_empty, download=True)
return
if can_shoot[player.userid] == 1:
player.play_sound(sound, download=True)

entity = Entity.create("prop_physics_override")
thrown.append(entity.index)
massScale = 1.0
if weapon_name == "weapon_crowbar":
entity.model = crowbar


if weapon_name == "weapon_stunstick":
entity.model = stunstick
massScale = 2.67

entity.set_key_value_string("Damagetype", "1")
entity.set_key_value_float("massScale", massScale * 8)

entity.spawn()
#entity.solid_flags = SolidFlags(entity.solid_flags | ~SolidFlags.NOT_SOLID)
#entity.collision_group = CollisionGroup.WEAPON
pos = player.eye_location
vel = player.velocity.length_2D/10
forward = player.view_vector * (5 + vel)
pos.x += forward.x
pos.y += forward.y
pos.z += forward.z
ang = player.view_angle
entity.owner_handle = player.inthandle
entity.set_property_vector("m_vecAngVelocity", Vector(4877.4, 0.0, 0.0))
entity.set_property_float("m_flElasticity", 2.0)

entity.teleport(pos, ang, player.view_vector * throw_force)
ammo[player.userid] -= 1

entity.delay(kill_delay, kill_ent, (entity,))
can_shoot[player.userid] = 0
entity.delay(shoot_delay, reset_shot, (player.userid,))
entity.delay(1.5, enablePickup, (entity,))


def enablePickup(entity):
entity.owner_handle = -1


@EntityPreHook(EntityCondition.is_player, 'on_take_damage')
def _pre_take_damage(stack_data):
victim = make_object(Entity, stack_data[0])
if not victim.is_player():
return

info = make_object(TakeDamageInfo, stack_data[1])
attacker = Entity(info.attacker)
# World damage?
if info.attacker in thrown:
weapon = Entity(info.attacker)
owner = Player(index_from_inthandle(weapon.owner_handle))
info.attacker = owner.index
info.inflictor = owner.index


repeat_check = Repeat(check_buttons)
repeat_check.start(0.1)
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: Crowbar throw

Postby VinciT » Sat Oct 10, 2020 7:56 pm

So.. Daren.. I noticed a few days ago that you removed a couple of your posts from this thread. If I remember correctly, you were getting some errors - probably an issue with long range kills. In case you're not satisfied with the plugin Painkiller posted, here's my take on your request:

Syntax: Select all

# ../throwables/throwables.py

# Python
from random import choice
from time import time

# Source.Python
from core import PLATFORM
from effects.base import TempEntity
from engines.precache import Model
from engines.server import global_vars
from engines.sound import Sound
from engines.trace import (ContentMasks, engine_trace, GameTrace, Ray,
SurfaceFlags)
from entities.constants import RenderMode, RenderEffects, WORLD_ENTITY_INDEX
from entities.datamaps import InputData
from entities.entity import Entity
from entities.helpers import index_from_pointer
from entities.hooks import EntityPreHook, EntityCondition
from events import Event
from filters.recipients import RecipientFilter
from listeners import (ButtonStatus, OnButtonStateChanged,
get_button_combination_status)
from mathlib import Vector, QAngle, NULL_VECTOR
from memory import Convention, DataType
from memory.manager import CustomType, TypeManager, Type
from players.constants import PlayerButtons
from players.entity import Player


# How much melee ammo should the player spawn with?
INITIAL_AMMO = 2
# Maximum number of melee ammo the player can carry.
MAX_AMMO = 5
# Should the player be allowed to throw their own melee weapon, leaving them
# without one? (True/False)
LAST_DITCH_EFFORT = True
# Time (in seconds) until the thrown melee despawns/gets removed. (0 - never)
LIFE_TIME = 60


# Material/sprite used for the trail.
TRAIL_MODEL = Model('materials/sprites/laser.vmt')


# Sound that plays when the player is out of melee ammo and tries to throw
# their melee weapon (and LAST_DITCH_EFFORT is set to False).
SOUND_DENIED = Sound('player/suit_denydevice.wav', pitch=90)


# Dictionary used to store relevant information about melee weapons.
# weapon_name: (weapon world model, angle offset, angular impulse)
melee_weapons = {
'weapon_crowbar': (
Model('models/weapons/w_crowbar.mdl'),
QAngle(90, 0, -34),
Vector(0, 520, 360)
),
'weapon_stunstick': (
Model('models/weapons/w_stunbaton.mdl'),
QAngle(90, 0, 0),
Vector(0, 520, 0)
)
}


is_prop_physics_override = EntityCondition.equals_entity_classname(
'prop_physics_override')


manager = TypeManager()


VPHYSICS_COLLISION_OFFSET = 161 if PLATFORM == 'windows' else 162


# =============================================================================
# >> EVENTS AND LISTENERS
# =============================================================================
@OnButtonStateChanged
def on_button_state_changed(player, old_buttons, new_buttons):
"""Called when the button state of a player changed."""
status = get_button_combination_status(
old_buttons, new_buttons, PlayerButtons.ATTACK2)

# Did the player just press right click (+attack2)?
if status == ButtonStatus.PRESSED:
PlayerT(player.index).start_charging_throw()

# Or did they release it?
elif status == ButtonStatus.RELEASED:
PlayerT(player.index).throw()


@Event('player_spawn')
def player_spawn(event):
PlayerT.from_userid(event['userid']).on_spawned()


# =============================================================================
# >> VPHYSICSCOLLISION - (thank you L'In20Cible, Jezza, and Ayuto)
# viewtopic.php?f=20&t=2402
# =============================================================================
class GameVCollisionEvent(CustomType, metaclass=manager):
"""Reconstructed 'gamevcollisionevent_t' struct from the engine."""
pre_velocity = manager.static_instance_array('Vector', 32, 2)
post_velocity = manager.static_instance_array('Vector', 56, 2)
pre_angular_velocity = manager.static_instance_array('Vector', 80, 2)
entity_pointers = manager.static_instance_array(Type.POINTER, 104, 2)


@EntityPreHook(
EntityCondition.equals_entity_classname('worldspawn'),
lambda entity: entity.pointer.make_virtual_function(
VPHYSICS_COLLISION_OFFSET,
Convention.THISCALL,
(DataType.POINTER, DataType.INT, DataType.POINTER),
DataType.VOID
)
)
def vphysics_collision_pre(stack_data):
"""Called when two physical objects (VPhysics) collide."""
event = GameVCollisionEvent._obj(stack_data[2])
index = stack_data[1] ^ 1

try:
throwable = Throwable.cache[index_from_pointer(
event.entity_pointers[index])]
except (KeyError, IndexError, RuntimeError):
# KeyError: Not a Throwable instance.
# IndexError: Missing entity pointer - invalid vphysics collision.
# RuntimeError: Not sure why this happens yet. Pops up when the player
# dies, and a couple of other places.
return

velocity = event.pre_velocity[index]

# Is the throwable going fast enough?
if velocity.length > 950:
start = throwable.origin
end = start + velocity.normalized() * 50

trace = GameTrace()
# Fire a GameTrace() to see where the throwable hit the world.
engine_trace.clip_ray_to_entity(
Ray(start, end),
ContentMasks.ALL,
Entity(WORLD_ENTITY_INDEX),
trace
)

# Did the trace hit the world?
if trace.did_hit():
# Was it the skybox?
if trace.surface.flags & SurfaceFlags.SKY:
# We don't want to stick to the skybox, don't go further.
return

# Convert the throwable's current angles into a directional vector.
forward = Vector()
throwable.angles.get_angle_vectors(forward)

# Let's check how similar the forward and normal vectors are in
# order to determine which part of the throwable hit the world.
# 0: The vectors are perpendicular.
# 1: The vectors are pointing in the same direction.
# -1: The vectors are pointing in the opposite direction.
dot = trace.plane.normal.dot(forward)

if throwable.should_stick(dot):
throwable.stick_to_world(trace.end_position)


# =============================================================================
# >> USE
# =============================================================================
@EntityPreHook(is_prop_physics_override, 'use')
def use_pre(stack_data):
"""Called when a player presses +USE (E by default) on a 'prop_physics'
entity."""
index = index_from_pointer(stack_data[0])

try:
throwable = Throwable.cache[index]
except KeyError:
return

# Is the throwable moving somewhat fast?
if throwable.physics_object.velocity[0].length > 250:
return

if throwable.already_picked_up:
return

# Get the InputData object so we can see who pressed +USE on the throwable.
input_data = InputData._obj(stack_data[1])
player = PlayerT(input_data.activator.index)

# Does the player have full melee ammo?
if player.melee_ammo >= MAX_AMMO:
return

# Is the player missing their melee weapon?
if player.melee_ammo == -1:
player.give_melee_weapon(throwable.weapon_name)

# Increase the player's melee ammo by 1.
player.melee_ammo += 1
# Notify the throwable that it has been picked up.
throwable.on_picked_up()


# =============================================================================
# >> WEAPON SWITCH
# =============================================================================
@EntityPreHook(EntityCondition.is_player, 'weapon_switch')
def weapon_switch_pre(stack_data):
"""Called when a player changes their weapon."""
PlayerT(index_from_pointer(stack_data[0])).stop_charging_throw()


# =============================================================================
# >> THROWABLE
# =============================================================================
class Throwable(Entity):
"""Class used to represent thrown/throwable melee weapons."""

impact_sound = {
'weapon_crowbar': (
'physics/metal/sawblade_stick1.wav',
'physics/metal/sawblade_stick2.wav',
'physics/metal/sawblade_stick3.wav'
),
'weapon_stunstick': (
'weapons/stunstick/stunstick_impact1.wav',
'weapons/stunstick/stunstick_impact2.wav'
)
}

sparks = TempEntity(
temp_entity='Sparks',
magnitude=1,
trail_length=1,
direction=Vector(0, 0, -1)
)

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.already_picked_up = False
self.weapon_name = None

@classmethod
def create(cls, origin, angles, velocity, model, owner_handle, **kwargs):
throwable = super().create('prop_physics_override')
throwable.origin = origin
throwable.angles = angles
throwable.model = model
throwable.owner_handle = owner_handle
# Invalidate the owner handle after a short delay. Without this, the
# player who threw the object won't be able to pick it back up unless
# it got stuck in the world.
throwable.delay(0.3, setattr, (throwable, 'owner_handle', -1))
# Store the 'weapon_name' so we can determine which weapon to give to
# the player in case they are without a melee weapon.
throwable.weapon_name = kwargs.get('weapon_name', None)
# How much damage should entities take from this entity when hit by it?
throwable.set_key_value_float('physdamagescale', 0.45)
# Multiplier for the object's mass.
throwable.set_key_value_float('massscale', 8)
throwable.set_key_value_float('inertiascale', 0.5)
# Make the 'prop_physics_override' sharp.
throwable.set_key_value_int('Damagetype', 1)
# Set certain spawn flags for the entity.
# 64: Enable motion when grabbed by gravity gun.
# 256: Generate output on +USE.
throwable.spawn_flags = 64 + 256
throwable.spawn()

# Setup all of the throw/physics properties so the player counts as the
# attacker when dealing damage with the Throwable.
throwable.set_property_bool('m_bThrownByPlayer', True)
throwable.set_property_bool('m_bFirstCollisionAfterLaunch', True)
throwable.set_property_int('m_hPhysicsAttacker', owner_handle)
throwable.set_property_float(
'm_flLastPhysicsInfluenceTime', global_vars.current_time)

# Add a visual effect.
trail = create_sprite_trail(
origin, TRAIL_MODEL.path, 5, 1, '255 255 255', 0.4
)
trail.set_parent(throwable)

# Set the entity's velocity after a single frame delay.
throwable.delay(0, throwable.apply_velocity, (
velocity, kwargs.get('angular_impulse', NULL_VECTOR)))

# Should we remove the entity after a while?
if LIFE_TIME > 0:
throwable.delay(LIFE_TIME, throwable.remove)

return throwable

def apply_velocity(self, velocity, angular_impulse, impulse_multiplier=1):
"""Sets the Throwable's velocity and angular impulse."""
self.physics_object.set_velocity(
velocity, angular_impulse * impulse_multiplier)

def create_impact_effect(self, origin):
"""Creates sparks at the given origin."""
Throwable.sparks.origin = origin
Throwable.sparks.create(RecipientFilter())

def should_stick(self, dot):
"""Checks whether or not the Throwable should stick to the world."""
# Is this a crowbar?
if 'crowbar' in self.weapon_name:
# Did either the top or bottom of the crowbar hit the world?
if dot > 0.78 or dot < -0.85:
return True

# Checking for everything else (stunstick)..
else:
# Did the top part of the object hit the world?
if dot > 0.78:
return True

# Nothing sharp hit, move along.
return False

def stick_to_world(self, end_position):
"""Freezes and puts the Throwable inside world geometry/brushes."""
# Freeze the entity.
self.call_input('DisableMotion')
# Invalidate the owner handle.
self.owner_handle = -1

direction = end_position - self.origin
# After a short delay, move the Throwable a bit towards where the
# collision took place (stick it inside of world geometry).
self.delay(
0.05, self.teleport, (self.origin + direction.normalized() * 10,))

self.create_impact_effect(end_position)

try:
# Try to get what sound the impact should make.
sample = choice(Throwable.impact_sound[self.weapon_name])
except KeyError:
return

self.emit_sound(
sample=sample,
attenuation=0.5
)

def on_picked_up(self):
"""Called when a player picks up the Throwable with +USE."""
self.already_picked_up = True
self.delay(0, self.remove)


# =============================================================================
# >> PLAYER
# =============================================================================
class PlayerT(Player):
"""Extended Player class.

Args:
index (int): A valid Player index.
caching (bool): Check for a cached instance?

Attributes:
is_charging (bool): Is the player currently preparing to throw their
melee weapon?
melee_ammo (int): Current amount of melee weapons the player can throw.
_pressed_time (float): Time (seconds since the epoch) when the player
pressed +attack2 (right click).
"""

throw_sound = {
'default': 'weapons/slam/throw.wav',
'weapon_crowbar': ('weapons/iceaxe/iceaxe_swing1.wav',),
'weapon_stunstick': (
'weapons/stunstick/stunstick_swing1.wav',
'weapons/stunstick/stunstick_swing2.wav'
)
}

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)
self.is_charging = False
self.melee_ammo = INITIAL_AMMO
self._pressed_time = 0

@property
def charging_time(self):
"""Returns how long the player held their +attack2 for."""
charging_time = time() - self._pressed_time
# Return the clamped value.
return 2 if charging_time > 2 else charging_time

def has_melee(self):
"""Checks if the player has a melee weapon."""
for weapon in self.weapons(is_filters='melee'):
# As soon as we find at least one melee weapon, return True.
return True

else:
# No melee weapons found - return False.
return False

def give_melee_weapon(self, weapon_name):
"""Gives the player the specified melee weapon, if they don't already
have one."""
# Did the player get a melee weapon in the meantime?
if self.has_melee():
# Just increase their ammo by 1.
self.melee_ammo += 1
return

# Give them a melee weapon.
self.give_named_item(weapon_name)

def change_fov(self, target_fov, rate=0.3, starting_fov=None):
"""Changes a player's field of view (FOV) smoothly.

Args:
index (int): A valid player index.
target_fov (int): The new FOV value.
rate (float): Duration of the FOV transition (in seconds).
starting_fov (int): FOV value from which to start the transition.

Raises:
OverflowError: If 'target_fov' is less than 0 or greater than 255.
"""
# Get the player's current FOV.
old_fov = self.fov if starting_fov is None else starting_fov

if old_fov == 0:
# When changing a player's FOV for the first time, the value of
# 'fov' will be zero. So we get the 'default_fov' instead.
old_fov = self.default_fov

# Time when the FOV starts changing.
self.fov_time = global_vars.current_time
# Duration of the transition (in seconds).
self.fov_rate = rate

# The FOV will transition from 'fov_start' to 'fov'.
self.fov_start = old_fov
self.fov = target_fov

def start_charging_throw(self):
"""Begins the throwing process."""
try:
# Try to get the name of the weapon the player is holding.
weapon_name = self.active_weapon.classname
except AttributeError:
# Player might be dead or missing their weapons.
return

# Don't go further if the player isn't holding a melee weapon.
if weapon_name not in melee_weapons:
return

# Is the player out of ammo? (and LAST_DITCH_EFFORT is set to False)
if self.melee_ammo < 1 and not LAST_DITCH_EFFORT:
SOUND_DENIED.play(self.index)
return

# Don't allow the player to use +attack (left click) while charging.
self.active_weapon.set_network_property_float(
'LocalActiveWeaponData.m_flNextPrimaryAttack',
global_vars.current_time + 600
)

self._pressed_time = time()
self.is_charging = True
# Transition the player's field of view to 102 over the next 2 seconds.
self.change_fov(102, 2)

def stop_charging_throw(self):
"""Stops the player from charging the throw."""
if not self.is_charging:
return

self.is_charging = False
self.change_fov(90, 0.1, 90 + int(6 * self.charging_time))

def throw(self):
"""Throws the player's melee weapon."""
if not self.is_charging:
return

self.is_charging = False
charging_time = self.charging_time
weapon = self.active_weapon

# Has the player held +attack2 (right click) for at least 200ms and
# are they holding an actual weapon?
if charging_time > 0.2 and weapon is not None:
# Restore the player's ability to use +attack (left click).
weapon.set_network_property_float(
'LocalActiveWeaponData.m_flNextPrimaryAttack',
global_vars.current_time + 0.05
)

view_vector = self.view_vector
weapon_name = weapon.classname

try:
model, angles, angular_impulse = melee_weapons[weapon_name]
except KeyError:
return

Throwable.create(
origin=self.eye_location + view_vector * 10,
angles=self.view_angle + angles,
velocity=view_vector * (600 + 900 * charging_time),
model=model,
owner_handle=self.inthandle,
angular_impulse=angular_impulse,
weapon_name=weapon_name
)

try:
# Try to get a weapon specific throw sound.
sample = choice(PlayerT.throw_sound[weapon_name])
except KeyError:
# No specific sound found, use the default one.
sample = PlayerT.throw_sound['default']

self.emit_sound(
sample=sample,
attenuation=0.8,
# Adjust the pitch depending on how long the player held their
# +attack2 (right click) for.
pitch=int(90 + 15 * charging_time)
)

# Is the player completely out of ammo?
if self.melee_ammo <= 0:
# Force them to drop their melee weapon.
self.drop_weapon(weapon.pointer, NULL_VECTOR, NULL_VECTOR)
# And remove it.
weapon.remove()

# Does the player not have any other melee weapons?
if not self.has_melee():
# Set their ammo to -1.
self.melee_ammo = -1

else:
# Reduce the ammo by 1.
self.melee_ammo -= 1

# Restore the player's field of view back to normal.
self.change_fov(90, 0.1, 90 + int(6 * charging_time))

def on_spawned(self):
"""Called when the player spawns."""
# Reset the player's ammo.
self.melee_ammo = INITIAL_AMMO


# =============================================================================
# >> ENV_SPRITETRAIL
# =============================================================================
def create_sprite_trail(
origin, sprite_path, start_width, end_width, color_str, life_time):
"""Creates an 'env_spritetrail' entity.

Args:
origin (Vector): Spawn position.
sprite_path (string): Path to the sprite material.
start_width (float): Starting width of the trail.
end_width (float): Ending width of the trail.
color_str (str): String containing the RGB values of the color.
(e.g. '255 255 255' for white)
life_time (float): How long does the trail last before it starts to
fade (in seconds)?

Returns:
Entity: The entity instance of the created 'env_spritetrail'.

"""
trail = Entity.create('env_spritetrail')
trail.sprite_name = sprite_path
trail.origin = origin

trail.life_time = life_time
trail.start_width = start_width
trail.end_width = end_width

trail.render_mode = RenderMode.TRANS_ADD
trail.render_amt = 120
trail.render_fx = RenderEffects.NONE
trail.set_key_value_string('rendercolor', color_str)
trail.spawn()

# Texture resolution of the trail.
trail.texture_res = 0.05
return trail
In addition to killing/destroying things, you can do stuff like this:
Last edited by VinciT on Mon Nov 02, 2020 6:33 am, edited 3 times in total.
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: Crowbar throw

Postby L'In20Cible » Sat Oct 10, 2020 8:34 pm

VinciT wrote:So.. Daren.. I noticed a few days ago that you removed a couple of your posts from this thread. If I remember correctly, you were getting some errors - probably an issue with long range kills. In case you're not satisfied with the plugin Painkiller posted, here's my take on your request:

Syntax: Select all

...

Looks really good, nice job! :smile:

Two minor points at first look:

  • Syntax: Select all

    throwables = EntityDictionary(None)
    You don't really need that dictionary, since your active instances are already accessible through:

    Syntax: Select all

    Throwable.cache


  • Syntax: Select all

    vphysics_collision = Entity(WORLD_ENTITY_INDEX)
    If your plugin is loaded via autoexec.cfg, it will raise here because the world isn't created at that point. Try something like this:

    Syntax: Select all

    @EntityPreHook(
    EntityCondition.equals_entity_classname('worldspawn'),
    lambda entity: entity.pointer.make_virtual_function(
    VPHYSICS_COLLISION_OFFSET,
    Convention.THISCALL,
    (DataType.POINTER, DataType.INT, DataType.POINTER),
    DataType.VOID
    )
    )
    def vphysics_collision_pre(stack_data):
    ...
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: Crowbar throw

Postby VinciT » Sat Oct 10, 2020 8:57 pm

L'In20Cible wrote:Looks really good, nice job! :smile:
Thank you! :grin:

L'In20Cible wrote:You don't really need that dictionary, since your active instances are already accessible through:

Syntax: Select all

Throwable.cache
This is amazing! I can't believe I never used .cache before.

L'In20Cible wrote:If your plugin is loaded via autoexec.cfg, it will raise here because the world isn't created at that point. Try something like this:

Syntax: Select all

@EntityPreHook(
EntityCondition.equals_entity_classname('worldspawn'),
lambda entity: entity.pointer.make_virtual_function(
VPHYSICS_COLLISION_OFFSET,
Convention.THISCALL,
(DataType.POINTER, DataType.INT, DataType.POINTER),
DataType.VOID
)
)
def vphysics_collision_pre(stack_data):
...
Yeah.. I had a feeling the way I hooked that function was quite flimsy. Thank you for showing me this!
Updated the code in my previous post.
ImageImageImageImageImage
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: Crowbar throw

Postby daren adler » Sat Oct 10, 2020 9:50 pm

VinciT wrote:
L'In20Cible wrote:Looks really good, nice job! :smile:
Thank you! :grin:

L'In20Cible wrote:You don't really need that dictionary, since your active instances are already accessible through:

Syntax: Select all

Throwable.cache
This is amazing! I can't believe I never used .cache before.

L'In20Cible wrote:If your plugin is loaded via autoexec.cfg, it will raise here because the world isn't created at that point. Try something like this:

Syntax: Select all

@EntityPreHook(
EntityCondition.equals_entity_classname('worldspawn'),
lambda entity: entity.pointer.make_virtual_function(
VPHYSICS_COLLISION_OFFSET,
Convention.THISCALL,
(DataType.POINTER, DataType.INT, DataType.POINTER),
DataType.VOID
)
)
def vphysics_collision_pre(stack_data):
...
Yeah.. I had a feeling the way I hooked that function was quite flimsy. Thank you for showing me this!
Updated the code in my previous post.


Ok i will try yours, thank you.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: Crowbar throw

Postby daren adler » Sat Oct 10, 2020 10:07 pm

Works great :cool: :cool: Thank you again, took me a min to figer out you can pick up the ones your throw by going to the crowbar or stick and hitting e button. :rolleyes: :rolleyes: THANK YOU :cool:

update - getting this error now

Code: Select all

2020-10-10 18:39:30 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\throwables\throwables.py", line 88, in on_button_state_changed
    PlayerT(player.index).start_charging_throw()
  File "..\addons\source-python\plugins\throwables\throwables.py", line 455, in start_charging_throw
    if self.active_weapon.classname not in melee_weapons:

AttributeError: 'NoneType' object has no attribute 'classname'
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: Crowbar throw

Postby VinciT » Sun Oct 11, 2020 4:43 pm

daren adler wrote:Works great :cool: :cool: Thank you again, took me a min to figer out you can pick up the ones your throw by going to the crowbar or stick and hitting e button. :rolleyes: :rolleyes: THANK YOU :cool:
I probably should've given some details how the plugin works. :tongue:

For anyone else trying out the plugin: Change to your melee weapon (crowbar, stunstick), hold right click to begin charging your throw, and release it to actually throw your melee weapon. The longer you hold your right click, the faster/more powerful the throw will be. The power maxes out at 2 seconds of holding, and the minimum to throw is 0.2 seconds (200ms).

The weapons can be stuck to world geometry/walls if they hit them at a certain angle. As the weapons spin when you throw them, this can be a bit tricky at first. It takes some time to figure out how far away from the wall you need to be or for how long to charge the throw. But with a little practice, I'm sure you'll get the hang of it. Another thing to keep in mind is that the crowbar is better at getting stuck, as it has two "sharp" points - the top and the bottom, while the stunstick only has one - the top.

If they are thrown at you, you can catch them with your gravity gun. And if the weapons are not moving or are moving very slowly, you can pick them up with your +USE key (E by default), thus increasing your melee ammo count.


I've included a fix for the error you got in my original post. I forgot to make sure the player had a weapon before getting its name.
ImageImageImageImageImage
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: Crowbar throw

Postby daren adler » Sun Oct 11, 2020 5:41 pm

VinciT wrote:
daren adler wrote:Works great :cool: :cool: Thank you again, took me a min to figer out you can pick up the ones your throw by going to the crowbar or stick and hitting e button. :rolleyes: :rolleyes: THANK YOU :cool:
I probably should've given some details how the plugin works. :tongue:

For anyone else trying out the plugin: Change to your melee weapon (crowbar, stunstick), hold right click to begin charging your throw, and release it to actually throw your melee weapon. The longer you hold your right click, the faster/more powerful the throw will be. The power maxes out at 2 seconds of holding, and the minimum to throw is 0.2 seconds (200ms).

The weapons can be stuck to world geometry/walls if they hit them at a certain angle. As the weapons spin when you throw them, this can be a bit tricky at first. It takes some time to figure out how far away from the wall you need to be or for how long to charge the throw. But with a little practice, I'm sure you'll get the hang of it. Another thing to keep in mind is that the crowbar is better at getting stuck, as it has two "sharp" points - the top and the bottom, while the stunstick only has one - the top.

If they are thrown at you, you can catch them with your gravity gun. And if the weapons are not moving or are moving very slowly, you can pick them up with your +USE key (E by default), thus increasing your melee ammo count.


I've included a fix for the error you got in my original post. I forgot to make sure the player had a weapon before getting its name.


Thank you so much :grin: , i will try them out. Thanks again :cool:
Thank you, no more errors.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: Crowbar throw

Postby daren adler » Sun Nov 01, 2020 11:50 pm

new error

Code: Select all

2020-11-01 16:27:54 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\throwables\throwables.py", line 92, in on_button_state_changed
    PlayerT(player.index).throw()
  File "..\addons\source-python\plugins\throwables\throwables.py", line 503, in throw
    self.active_weapon.set_network_property_float(

AttributeError: 'NoneType' object has no attribute 'set_network_property_float'
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: Crowbar throw

Postby VinciT » Mon Nov 02, 2020 6:38 am

daren adler wrote:new error

Code: Select all

2020-11-01 16:27:54 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\throwables\throwables.py", line 92, in on_button_state_changed
    PlayerT(player.index).throw()
  File "..\addons\source-python\plugins\throwables\throwables.py", line 503, in throw
    self.active_weapon.set_network_property_float(

AttributeError: 'NoneType' object has no attribute 'set_network_property_float'
Grab the updated plugin and you should be good to go.
ImageImageImageImageImage

Return to “Plugin Requests”

Who is online

Users browsing this forum: No registered users and 29 guests