Syntax: Select all
# ../addons/source-python/plugins/parachute/parachute.py
# ============================================================================
# >> IMPORTS
# ============================================================================
# Python Imports
# Math
from math import cos
from math import radians
from math import sin
# Source.Python Imports
# Core
from core import SOURCE_ENGINE
# Engines
from engines.precache import Model
# Entities
from entities.constants import MoveType
from entities.entity import Entity
# Listeners
from listeners import OnPlayerRunCommand
# Mathlib
from mathlib import Vector
# Paths
from paths import GAME_PATH
# Players
from players.constants import PlayerButtons
from players.constants import PlayerStates
from players.entity import Player
from players.dictionary import EntityDictionary
# Stringtables
from stringtables.downloads import Downloadables
# ============================================================================
# >> CONFIGURATION
# ============================================================================
# Define the falling speed in units/s. The higher this value is, the
# faster parachutists will fall.
falling_speed = 32
# Define the speed of the steering lines in units/s. To pull a steering line,
# parachutists must use their A or D keys to gain speed into the right or left
# direction allowing them to have a better control of their landing. However,
# pulling a line come with a falling speed cost.
#
# Set to 0 to disable the ability to pull a line.
steering_lines_speed = 5
# Define the falling speed penalty multiplier when pulling a line.
# e.g. With a falling speed of 32 and a penalty of 1.5, parachutists pulling
# their lines would fall at a speed of 48 units/s.
#
# Set to 1 to disable the falling speed penalty.
steering_lines_penalty = 1.5
# Define the key players must hold to deploy their parachute.
deployment_button = PlayerButtons.SPEED
# ============================================================================
# >> GLOBALS
# ============================================================================
if SOURCE_ENGINE == 'bms':
SOURCE_ENGINE = 'orangebox'
downloadables = Downloadables()
downloadables.add_directory(f'models/parachute/{SOURCE_ENGINE}')
downloadables.add_directory('materials/models/parachute')
parachutes = EntityDictionary()
_path = f'models/parachute/{SOURCE_ENGINE}/parachute_default.mdl'
if not (GAME_PATH / _path).isfile():
parachute_model = None
else:
parachute_model = Model(_path)
# ============================================================================
# >> FUNCTIONS
# ============================================================================
def get_player_parachute(player):
for parachute in parachutes.values():
if parachute.owner_handle != player.inthandle:
continue
return parachute
def close_parachute(player):
parachute = get_player_parachute(player)
if parachute is None:
return
parachute.remove()
def parachute_check(player):
angles = Vector(y=player.eye_angle.y)
parachute = get_player_parachute(player)
if parachute is None:
parachute = Entity.create('prop_dynamic_override')
parachutes[parachute.index] = parachute
weapon = player.active_weapon
if weapon is not None:
parachute.parent = weapon
parachute.model = parachute_model
parachute.owner_handle = player.inthandle
parachute.origin = player.origin
parachute.angles = angles
parachute.model_scale = 0.7
parachute.spawn()
return
weapon = player.active_weapon
if weapon is not None:
parent = parachute.parent
if parent != weapon:
parachute.parent = weapon
origin = player.origin
else:
parachute.parent = None
view_offset = player.view_offset.copy()
view_offset.z /= 2
origin = player.origin + view_offset
parachute.origin = origin
parachute.angles = angles
if parachute.model_scale >= 1.0:
return
parachute.model_scale += 0.024
# ============================================================================
# >> LISTENERS
# ============================================================================
@OnPlayerRunCommand
def _on_player_run_command(player, usercmd):
if player.is_bot():
return
if (player.dead or
player.move_type == MoveType.LADDER or
player.flags & PlayerStates.INWATER or
not usercmd.buttons & deployment_button):
close_parachute(player)
return
fall_velocity = player.fall_velocity
if fall_velocity < 1.0:
close_parachute(player)
return
side_move = usercmd.side_move
if side_move and steering_lines_speed > 1:
yaw = player.eye_angle.y
if side_move < 0:
yaw += 90
else:
yaw -= 90
yaw = radians(yaw)
vec = Vector(
x=cos(yaw) * steering_lines_speed,
y=sin(yaw) * steering_lines_speed,
z=fall_velocity + -(falling_speed * steering_lines_penalty))
else:
vec = Vector(z=fall_velocity + -falling_speed)
player.base_velocity = vec
if parachute_model is None:
return
player.delay(0, parachute_check, (player,))