from piqueserver.commands import command, admin, player_only, target_player from piqueserver.config import config from pyspades.world import Grenade from pyspades.common import Vertex3 from random import random from random import gauss from math import sqrt from piqueserver import map sectionConfig = config.section('superGrenade') radius = sectionConfig.option('explosionRadius', default=2.5).get() grenadeAmount = sectionConfig.option('grenadeAmount', default=50).get() @command('supergrenades') @target_player @player_only def checkSuperGrenades(connection, player): connection.send_chat("%s has %d super grenades." % (player.name, player.superGrenades)) @admin @command('givesupergrenade', 'gsg') @target_player def givenuke(connection, player): """ Gives a super grenade to target player /givesupergrenade *<player>* """ player.superGrenades = player.superGrenades + 1 try:
^^^^^^^^ * ``/autosave`` Toogle the feature * ``/save`` Manually save the map * ``/recentsaves`` Show the last 5 saves """ import os import fnmatch from time import time, strftime, localtime from twisted.internet.task import LoopingCall from twisted.internet.reactor import callLater from piqueserver.commands import command from piqueserver.config import config, cast_duration AUTOSAVE_CONFIG = config.section("autosave") SAVE_INTERVAL = AUTOSAVE_CONFIG.option("save_interval", default="60min", cast=cast_duration) SAVE_TO_FOLDER = AUTOSAVE_CONFIG.option("save_to_folder", default=True, cast=bool) MAP_FOLDER_SUFFIX = AUTOSAVE_CONFIG.option("map_folder_suffix", default="_BAK") DELETE_AFTER = AUTOSAVE_CONFIG.option("delete_after", default="30days", cast=cast_duration) DATE_FORMAT = AUTOSAVE_CONFIG.option("date_format", default="%Y%m%d-%H%M") @command(admin_only=True) def autosave(connection):
""" Gives a specified amount of medkits on spawn Author: Booboorocks998 Maintainer: mat^2 """ from piqueserver.commands import command from piqueserver.config import config from pyspades.constants import FALL_KILL medkit_config = config.section("medkit") default_medkits = medkit_config.option("medkits", 1) medkit_heal_amount = medkit_config.option("medkit_heal_amount", 40) @command('medkit', 'm') def medkit(connection): if connection.medkits and connection.hp < 100: connection.set_hp(connection.hp + connection.protocol.heal_amount, kill_type=FALL_KILL) connection.medkits -= 1 connection.send_chat('You have been healed') else: connection.send_chat("You don't have any medkits or have full health!") def apply_script(protocol, connection, config): class MedkitConnection(connection): medkits = 0
import aiohttp from aiohttp import web from multidict import MultiDict from jinja2 import Environment, PackageLoader import json import time from PIL import Image from io import BytesIO from aiohttp.abc import AbstractAccessLogger from twisted.logger import Logger from piqueserver.utils import as_deferred from piqueserver.config import config, cast_duration status_server_config = config.section("status_server") host_option = status_server_config.option("host", "0.0.0.0") port_option = status_server_config.option("port", 32886) logging_option = status_server_config.option("logging", False) interval_option = status_server_config.option("update_interval", default="1min", cast=cast_duration) scripts_option = config.option("scripts", []) class AccessLogger(AbstractAccessLogger): def log(self, request, response, time): self.logger.info( "{remote} {method} {url}: {status} {time:0.2f}ms -- {ua}", remote=request.remote, ua=request.headers["User-Agent"],
.. codeauthor:: hompy """ from operator import attrgetter from twisted.internet import reactor from pyspades.common import prettify_timespan from piqueserver.commands import command, get_player, admin from piqueserver.config import config, cast_duration S_AFK_CHECK = '{player} has been inactive for {time}' S_NO_PLAYERS_INACTIVE = 'No players or connections inactive for {time}' S_AFK_KICKED = ('{num_players} players kicked, {num_connections} connections ' 'terminated for {time} inactivity') S_AFK_KICK_REASON = 'Inactive for {time}' afk_config = config.section('afk') time_limit_option = afk_config.option('time_limit', default="1hour", cast=cast_duration) def afk(connection, player): player = get_player(connection.protocol, player) elapsed = prettify_timespan(reactor.seconds() - player.last_activity, True) return S_AFK_CHECK.format(player=player.name, time=elapsed) @command('kickafk', admin_only=True) def kick_afk(connection, minutes, amount=None): protocol = connection.protocol minutes = int(minutes)
# format is [{"ip" : "1.1.1.1", "reason : "blah"}, ...] def validate_bansub_config(c): if not isinstance(c, list): return False for item in c: if not item.get('url') or not isinstance(item.get('whitelist'), list): return False return True bans_config = config.section('bans') bans_config_urls = bans_config.option('bansubscribe', default=[], validate=validate_bansub_config) class BanManager(object): bans = None new_bans = None def __init__(self, protocol): self.protocol = protocol self.urls = [(entry.get('url'), entry.get('whitelist')) for entry in bans_config_urls.get()] self.loop = LoopingCall(self.update_bans) self.loop.start(UPDATE_INTERVAL, now=True)
NEAR_MISS_ANGLE = 10.0 # Approximate size of player's heads in blocks HEAD_RADIUS = 0.7 # 128 is the approximate fog distance, but bump it up a little # just in case FOG_DISTANCE = 135.0 # Don't touch any of this stuff FOG_DISTANCE2 = FOG_DISTANCE**2 NEAR_MISS_COS = cos(NEAR_MISS_ANGLE * (pi / 180.0)) HEADSHOT_SNAP_ANGLE_COS = cos(HEADSHOT_SNAP_ANGLE * (pi / 180.0)) aimbot_pattern = re.compile(".*(aim|bot|ha(ck|x)|cheat).*", re.IGNORECASE) aimbot_config = config.section("aimbot") collect_data = aimbot_config.option("collect_data", False) config_dir = config.config_dir def point_distance2(c1, c2): if c1.world_object is not None and c2.world_object is not None: p1 = c1.world_object.position p2 = c2.world_object.position return (p1.x - p2.x)**2 + (p1.y - p2.y)**2 + (p1.z - p2.z)**2 def dot3d(v1, v2): return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]
.. code-block:: guess [blockinfo] griefcheck_on_votekick = true irc_only = false .. codeauthor:: hompy """ from twisted.internet.reactor import seconds from pyspades.collision import distance_3d_vector from pyspades.common import prettify_timespan from piqueserver.commands import command, admin, get_player from piqueserver.config import config blockinfo_config = config.section("blockinfo") GRIEFCHECK_ON_VOTEKICK = blockinfo_config.option("griefcheck_on_votekick", True) IRC_ONLY = blockinfo_config.option("irc_only", False) @command('griefcheck', 'gc') def grief_check(connection, player, minutes=2): player = get_player(connection.protocol, player) protocol = connection.protocol color = connection not in protocol.players and connection.colors minutes = float(minutes) if minutes <= 0.0: raise ValueError('minutes must be number greater than 0') time = seconds() - minutes * 60.0 blocks_removed = player.blocks_removed or []
from piqueserver.config import config from pyspades.constants import FALL_KILL from pyspades import contained as loaders sectionConfig = config.section('grenades') grenadeLimitConfig = sectionConfig.option('startingGrenades', default=3) grenadeDudLimitConfig = sectionConfig.option('duds', default=5) startingGrenades = grenadeLimitConfig.get() dudLimit = grenadeDudLimitConfig.get() def apply_script(protocol, connection, config): class scriptConnection(connection): liveGrenades = 0 dudGrenades = 0 def on_spawn(self, position): self.liveGrenades = startingGrenades self.dudGrenades = dudLimit connection.on_spawn(self, position) def on_grenade_thrown(self, grenade): self.refillAndSetHPAmmo() if (self.liveGrenades > 0): self.liveGrenades -= 1 connection.send_chat(self, "%d grenade%s left" % (self.liveGrenades, ("s", "")[self.liveGrenades == 1]), global_message=False) connection.send_chat_notice( self,
attacker_ratio = 1.6 Originally created by: TheGrandmaster / hompy """ from twisted.internet.reactor import callLater from twisted.internet.task import LoopingCall from pyspades import contained as loaders from pyspades.constants import * from pyspades.player import create_player, player_left, intel_capture from piqueserver.config import config, cast_duration ATTACKER_TEAM = 1 # 0 = blue, 1 = green INFIL_CONFIG = config.section("infiltration") ATTACKER_RATIO_OPTION = INFIL_CONFIG.option("attacker_ratio", default=1.6, cast=int) ATTACKER_SCORE_MULTIPLIER_OPTION = INFIL_CONFIG.option( "attacker_score_multiplier", default=10, cast=int) DEFENDER_SCORE_INTERVAL_OPTION = INFIL_CONFIG.option("defender_score_interval", default="30sec", cast=cast_duration) ATTACKER_SCORE_MULTIPLIER = 10 DEFENDER_SCORE_INTERVAL = 30 # seconds ON_FLAG_TAKE_FLASHES_FOG = True S_TEAM_FULL = 'Team full! The defending team always has less players' S_ATTACKER_OBJECTIVE = '*** ATTACKERS: Infiltrate the enemy base and steal ' \
* ``/mode`` Show information about the modes. """ from pyspades.constants import * from pyspades.common import make_color from pyspades import contained as loaders from piqueserver.commands import command from piqueserver.config import config from random import choice BUILDER_HEAL_RATE = 5 SAPPER_HIT_AMOUNT = 0.6 BUILDER, SAPPER = range(2) MODE_CONFIG = config.section("buildersapper") @command() def builder(connection): """ Choose the builder mode /builder """ if connection.class_mode == BUILDER: return "You are already a builder." connection.class_mode = BUILDER connection.kill() @command()
from piqueserver import map from pyspades.common import Vertex3 from pyspades.world import Grenade from pyspades import contained as loaders from math import ceil, sqrt, pi, sin, cos, exp, floor from random import random from time import time from pyspades.constants import GRENADE_KILL, DESTROY_BLOCK from twisted.internet import reactor #Things for overriding grenade_explode from itertools import product from pyspades.constants import GRENADE_DESTROY nukeErrorMessage = "Invalid Input, provide coordinate (eg: C3) and region (eg: NE for northeast)" sectionConfig = config.section('nuke') radiusConfig = sectionConfig.option('explosionRadius', default=10) maximumRadiusConfig = sectionConfig.option('maximumExplosionRadius', default=50) flatnessConfig = sectionConfig.option('flatness', default=0.0083) shiftnessConfig = sectionConfig.option('shiftness', default=131) #f\left(x\right)\ =\ \left(\left(M-N\right)\right)/(1+1e^{-k\left(x-\left(S\right)\right)}) #N = minimum; M = maximum; S = shiftness (slider 0-*200*); F = flatness (slider 0-0.25) #X axis = grenade, Y axis = distance from radius propogationTimeConfig = sectionConfig.option('propogationTime', default=2.5) upHeightConfig = sectionConfig.option('upHeight', default=8) downHeightConfig = sectionConfig.option('downHeight', default=2) grenadeAmountConfig = sectionConfig.option('grenadeAmount', default=400) teamSuccessCDConfig = sectionConfig.option('teamSuccessCooldown', default=30) playerSuccessCDConfig = sectionConfig.option('playerSuccessCooldown', default=60)
[antijerk] ban_duration = "15min" .. codeauthor:: ? """ import re from piqueserver.config import config, cast_duration chat_pattern = re.compile(".*(airstrike).*(esc|escape|alt-f4|alt f4)", re.IGNORECASE) chat_pattern_2 = re.compile(".*(esc|escape|alt-f4|alt f4).*(airstrike)", re.IGNORECASE) admin_pattern = re.compile(".*(admin)", re.IGNORECASE) antijerk_config = config.section("antijerk") ban_duration = antijerk_config.option("ban_duration", default="15min", cast=cast_duration) def antijerk_match(player, msg): if not (player.user_types.trusted or player.admin): return chat_pattern.match(msg) or chat_pattern_2.match(msg) or\ admin_pattern.match(player.name) def apply_script(protocol, connection, config): def jerk_kick(connection): connection.ban('Autoban: anti-jerk', ban_duration.get())
from pyspades.constants import CTF_MODE from piqueserver.config import config from random import choice, random from pyspades.contained import ChangeTeam from pyspades.constants import MELEE_KILL from time import time from piqueserver.commands import command, player_only from twisted.internet import reactor from twisted.internet.error import AlreadyCalled from pyspades.contained import KillAction, CreatePlayer, PlayerLeft, StateData, CTFState sectionConfig = config.section('tag') safeTimeConfig = sectionConfig.option('safeTime', default = 5) shotsTagConfig = sectionConfig.option('shotsTag', default = False) pointsEveryXSecondsConfig = sectionConfig.option('pointsEveryXSeconds', default = 5) taggerTimeConfig = sectionConfig.option('taggerTime', default = 30) #safeTime = 1 #shotsTag = True #pointsEveryXSeconds = 1 #taggerTime = 30 @command('tag') def tagTutorial(connection): connection.send_chat("The longer the runner survives, the more points they gain") connection.send_chat("The tagger, who is \"it\" must try to hit a runner") connection.send_chat("To play tag, runners must run away and hide from the tagger") def apply_script(protocol, connection, config): class tagProtocol(protocol): game_mode = CTF_MODE
# automatically load the saved map on map load load_saved_map = true # automatically save map at shutdown save_at_shutdown = false # automatically save map at map rotation or server shutdown always_save_map = false """ import os from twisted.internet import reactor from twisted.logger import Logger from piqueserver.config import config from piqueserver.commands import command from piqueserver.map import RotationInfo savemap_config = config.section('savemap') config_dir = config.config_dir log = Logger() @command('savemap', admin_only=True) def savemap(connection, custom_name=None): name = connection.protocol.save_map(custom_name) return "Map saved to '%s'" % name @command('rmsaved', admin_only=True) def rmsaved(connection): name = connection.protocol.map_info.rot_info.name path = get_path(name) if os.path.isfile(path):
S_INVALID_MAP_NAME = 'Invalid map name' S_ROLLBACK_IN_PROGRESS = 'Rollback in progress' S_ROLLBACK_COMMENCED = '{player} commenced a rollback...' S_AUTOMATIC_ROLLBACK_PLAYER_NAME = 'Map' S_NO_ROLLBACK_IN_PROGRESS = 'No rollback in progress' S_ROLLBACK_CANCELLED = 'Rollback cancelled by {player}' S_ROLLBACK_ENDED = 'Rollback ended. {result}' S_MAP_CHANGED = 'Map was changed' S_ROLLBACK_PROGRESS = 'Rollback progress {percent:.0%}' S_ROLLBACK_COLOR_PASS = '******' S_ROLLBACK_TIME_TAKEN = 'Time taken: {seconds:.3}s' NON_SURFACE_COLOR = (0, 0, 0) rollback_config = config.section('rollback') ROLLBACK_ON_GAME_END_OPTION = rollback_config.option('rollback_on_game_end', False) @command(admin_only=True) def rollmap(connection, mapname=None, value=None): start_x, start_y, end_x, end_y = 0, 0, 512, 512 if value is not None: start_x, start_y = coordinates(value) end_x, end_y = start_x + 64, start_y + 64 return connection.protocol.start_rollback(connection, mapname, start_x, start_y, end_x, end_y) @command(admin_only=True)
time = 120 percentage = 80 .. codeauthor:: James Hofmann a.k.a triplefox (GPL LICENSE) """ import random from twisted.internet import reactor from twisted.internet.task import LoopingCall from pyspades.common import prettify_timespan from piqueserver.map import check_rotation from piqueserver.scheduler import Scheduler from piqueserver.commands import command from piqueserver.config import config votemap_config = config.section('votemap') VOTEMAP_AUTOSCHEDULE_OPTION = votemap_config.option('autoschedule', 180) VOTEMAP_PUBLIC_VOTES_OPTION = votemap_config.option('public_votes', True) VOTEMAP_TIME_OPTION = votemap_config.option('time', 120) VOTEMAP_EXTENSION_TIME_OPTION = votemap_config.option('extension_time', 15) VOTEMAP_PLAYER_DRIVEN_OPTION = votemap_config.option('player_driven', False) VOTEMAP_PERCENTAGE_OPTION = votemap_config.option('percentage', 80) def cancel_verify(connection, instigator): return (connection.admin or connection is instigator or connection.rights.cancel) class VoteMap(object):
"regen_delay" : 1, "heal_loop_speed" : 0.07, "heal_amount" : 1 } Script by Rugg """ from pyspades.contained import * from twisted.internet.task import LoopingCall from pyspades.constants import FALL_KILL from twisted.internet import reactor from twisted.internet.error import AlreadyCalled from piqueserver.config import config #define variables from config regen_config = config.section("regen") regen_delay_config = regen_config.option("regen_delay", default = 5) heal_loop_speed_config = regen_config.option("heal_loop_speed", default = 0.05) heal_amount_config = regen_config.option("heal_amount", default = 1) regen_delay = regen_delay_config.get() heal_loop_speed = heal_loop_speed_config.get() heal_amount = heal_amount_config.get() def apply_script(protocol, connection, config): class Regen(connection): hpValues = [] regencalllater = None #X is the regen delayed call, can't think of a concise descriptive name for it def starthealing(self, hpAfterHit): #Activates healing if self.hp is not None: hp = round(self.hp)
p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) f = manhole_ssh.ConchFactory(p) ssh_key_base_path = path.join(config.config_dir, "ssh-keys") ssh_pubkey_path = path.join(ssh_key_base_path, "ssh_host_rsa_key.pub") ssh_privkey_path = path.join(ssh_key_base_path, "ssh_host_rsa_key") try: f.publicKeys[b"ssh-rsa"] = keys.Key.fromFile(ssh_pubkey_path) f.privateKeys[b"ssh-rsa"] = keys.Key.fromFile(ssh_privkey_path) except FileNotFoundError: print("ERROR: You don't have any keys in the host key location") print("Generate one with:") print(" mkdir {}".format(ssh_key_base_path)) print(" ssh-keygen -f {} -t rsa".format(ssh_privkey_path)) print("make sure to specify no password") sys.exit(1) return f ssh_config = config.section("ssh") class RemoteConsole(object): def __init__(self, server): users = ssh_config.option("users", {}) port = ssh_config.option("port", 38827) factory = create_remote_factory(locals(), users.get()) server.listenTCP(port.get(), factory)
""" import random from piqueserver.commands import command, get_player from piqueserver import commands from piqueserver.config import config from piqueserver.server import respawn_time_option SQUAD_NAMES = set([ 'Alpha', 'Bravo', 'Charlie', 'Delta', 'Epsilon', 'Foxtrot', 'Gamma', 'Golf', 'Hotel', 'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar', 'Papa', 'Quebec', 'Romero', 'Sierra', 'Tango', 'Uniform', 'Victor', 'Whiskey', 'X-ray', 'Yankee', 'Zulu' ]) squad_config = config.section('squad') RESPAWN_TIME_OPTION = squad_config.option('respawn_time', default=respawn_time_option.get()) SIZE_OPTION = squad_config.option('size', 0) AUTO_SQUAD_OPTION = squad_config.option('auto_squad', True) @command() def follow(self, playerkey=None): if playerkey is None: squad_pref = None squad = self.squad else: squad_pref = get_player(self.protocol, playerkey) squad = squad_pref.squad if squad_pref.team is not self.team:
# positions can add the right "specpower" to the group rights in commands.py # to have the guards/minimods be immune to the spectator kick and chat # restrictions. # # # Oh, and admins are also automatically immune to spectator kick and chat # restrictions. # # Hope you enjoy! # Tocksman from math import ceil, floor from twisted.internet import reactor from piqueserver.config import config spectator_ctrl_config = config.section("spectator_control") no_chat = spectator_ctrl_config.option("no_chat", False) kick = spectator_ctrl_config.option("kick", False) kick_time = spectator_ctrl_config.option("kick_time", 300) # in seconds def apply_script(protocol, connection, config): class SpectatorControlConnection(connection): spec_check = None def on_chat(self, value, global_message): # if no chat is set and they're a spectator and not an admin # also, check for the right "specpower" for owners who add additional # rights such as guards, mini-mods, etc. if self.team.spectator and no_chat.get(): if not self.admin and not self.rights.specpower: # not an admin self.send_chat('Spectators cannot speak on this server.')
import os from glob import glob from struct import unpack from random import choice from itertools import product from collections import deque, namedtuple from twisted.internet.reactor import seconds from twisted.internet.task import LoopingCall from pyspades.contained import BlockAction, SetColor from pyspades.common import make_color from pyspades.constants import BUILD_BLOCK from piqueserver.commands import command from piqueserver.config import config grownade_section = config.section("grownade") FLYING_MODELS = grownade_section.option("flying_models") GROW_ON_WATER = grownade_section.option("grow_on_water") KV6_DIR = "./" + config.config_dir + '/kv6' LOWEST_Z = 63 if GROW_ON_WATER.get() else 62 GROW_INTERVAL = 0.3 S_NO_KV6_FOLDER = "You haven't created a kv6 folder yet!" S_NO_MATCHES = "Couldn't find any model files matching {expression}" S_LOADED_SINGLE = 'Loaded model {filename}' S_LOADED = 'Loaded {filenames}. Each grenade will pick one at random' S_FAILED = 'Failed to load {filenames}' S_PIVOT_TIP = 'Make sure the pivot points are correctly placed' S_CANCEL = 'No longer spawning models' S_SPECIFY_FILES = 'Specify model files to load. Wildcards are allowed, ' \
from piqueserver.config import config from twisted.internet import reactor from pyspades.constants import FALL_KILL from twisted.internet.error import AlreadyCalled sectionConfig = config.section('regen') regenDelay = sectionConfig.option('regenDelay', default=5.0).get() healSpeed = sectionConfig.option('healSpeed', default=0.05).get() healAmount = sectionConfig.option('healAmount', default=1.0).get() friendly_fire = config.option('friendly_fire', default=True).get() def apply_script(protocol, connection, config): class regenConnection(connection): regenCallID = None def regen(self): if (self.hp is not None): connection.set_hp(self, self.hp + healAmount, kill_type=FALL_KILL) self.regenCallID = reactor.callLater(healSpeed, self.regen) def stopRegen(self): try: self.regenCallID.cancel() except AttributeError as aterr: pass except AlreadyCalled as acerr: pass
# Disable grenade damage within enemy spawn. disable_grenades_at_spawn = false """ from pyspades.constants import * from pyspades.common import make_color from pyspades.contained import SetColor from piqueserver.commands import command, admin, get_team from piqueserver.config import config, cast_duration from twisted.internet.task import LoopingCall from random import randint import colorsys import time PUSH_CONFIG = config.section("push") PROTECT_MAP_BLOCKS = PUSH_CONFIG.option("protect_map_blocks", default=True, cast=bool) ALLOW_RESPAWN_COMMAND = PUSH_CONFIG.option("allow_respawn_command", default=True, cast=bool) RESPAWN_CMD_DELAY = PUSH_CONFIG.option("respawn_cmd_delay", default="15sec", cast=cast_duration) INTEL_PICKUP_DELAY = PUSH_CONFIG.option("intel_pickup_delay", default="3sec", cast=cast_duration) BLOCK_REMOVAL_DELAY = PUSH_CONFIG.option("block_removal_delay", default="15sec", cast=cast_duration) RESET_INTEL_AFTER_DROP = PUSH_CONFIG.option("reset_intel_after_drop", default="3min", cast=cast_duration) DEFAULT_CP_PROTECT_RANGE = PUSH_CONFIG.option("default_cp_protect_range", default=8, cast=int) DISABLE_GRENADES_AT_SPAWN = PUSH_CONFIG.option("disable_grenades_at_spawn", default=False, cast=bool) CANT_DESTROY = "You can't destroy your team's blocks!" NO_BLOCKS = "Out of blocks! Refill at base or type /r" BUILDING_AT_CP = "You can't build near your base!"
""" Zones of control: Dropped intel and tents exert influence over nearby area, restricting player ability to destroy. Maintainer: ? """ from collections import deque from twisted.internet.task import LoopingCall from pyspades.constants import GRENADE_DESTROY, SPADE_DESTROY, CTF_MODE, TC_MODE from piqueserver.config import config BK_FREE, BK_FRIENDLY, BK_ENEMY_FAR, BK_ENEMY_NEAR, BK_UNDO = range(5) zoc_config = config.section("zoc") zoc_radius = zoc_config.option("radius", 32) zoc_attack_distance = zoc_config.option("attack_distance", 64) zoc_block_undo = zoc_config.option("block_undo", 10) zoc_block_cost = zoc_config.option("block_cost", 5) zoc_points_per_tick = zoc_config.option("points_per_tick", 1) zoc_point_cap = zoc_config.option("point_cap", 6 * zoc_block_cost.get()) zoc_grenade_cost = zoc_config.option("grenade_cost", zoc_point_cap.get()) def apply_script(protocol, connection, config): class ZOCConnection(connection): def on_connect(self): self.block_undo = deque() self.zoc_destruction_points = 0
""" Greets specified people entering with messages Options ^^^^^^^ .. code-block:: toml [welcome] welcomes = { nota = "Hi notafile", feik = "Hi feik" } .. codeauthor: mat^2 """ from piqueserver.config import config welcome_config = config.section("welcome") welcomes_option = welcome_config.option("welcomes", {}) def apply_script(protocol, connection, config): welcomes = welcomes_option.get() class EnterConnection(connection): def on_login(self, name): if name in welcomes: self.protocol.send_chat(welcomes[name]) connection.on_login(self, name) return protocol, EnterConnection
""" Protects spawned players for a specified amount of seconds. Maintainer: ? Fixed error by kmsi([email protected]) : replaced player to hit_player """ from pyspades.common import prettify_timespan from piqueserver.config import config from twisted.internet import reactor spawn_protect_config = config.section("spawn_protect") protection_time = spawn_protect_config.option("protection_time", 3.0) def apply_script(protocol, connection, config): spawn_protect_time = protection_time.get() class SpawnProtectConnection(connection): spawn_timestamp = None def on_spawn(self, pos): self.spawn_timestamp = reactor.seconds() return connection.on_spawn(self, pos) def on_hit(self, hit_amount, hit_player, type, grenade): cur_timestamp = reactor.seconds() - spawn_protect_time if cur_timestamp < hit_player.spawn_timestamp: timespan = -(cur_timestamp - hit_player.spawn_timestamp) self.send_chat( "%s is spawn-protected for %s." %
S_RESULT_BANNED = 'Banned by admin' S_RESULT_KICKED = 'Kicked by admin' S_RESULT_INSTIGATOR_KICKED = 'Instigator kicked by admin' S_RESULT_LEFT = '{victim} left during votekick' S_RESULT_INSTIGATOR_LEFT = 'Instigator {instigator} left' S_RESULT_PASSED = 'Player kicked' S_ANNOUNCE_IRC = '* {instigator} started a votekick against player {victim}. ' \ 'Reason: {reason}' S_ANNOUNCE = '{instigator} started a VOTEKICK against {victim}. Say /Y to agree' S_ANNOUNCE_SELF = 'You started a votekick against {victim}. Say /CANCEL to ' \ 'stop it' S_UPDATE = '{instigator} is votekicking {victim}. /Y to vote ({needed} left)' S_REASON = 'Reason: {reason}' # register options VOTEKICK_CONFIG = config.section('votekick') REQUIRED_PERCENTAGE_OPTION = VOTEKICK_CONFIG.option('percentage', 35.0) BAN_DURATION_OPTION = VOTEKICK_CONFIG.option('ban_duration', default="30min", cast=cast_duration) PUBLIC_VOTES_OPTION = VOTEKICK_CONFIG.option('public_votes', True) class VotekickFailure(Exception): pass @command('votekick') @player_only def start_votekick(connection, *args): """
) # TODO: Once issue #345 is sorted out, we can do a proper validation # for now we just warn # return False return True # TODO: move to a better place if reusable def sleep(secs): return deferLater(reactor, secs, lambda: None) # declare configuration options bans_config = config.section('bans') logging_config = config.section('logging') team1_config = config.section('team1') team2_config = config.section('team2') bans_file = bans_config.option('file', default='bans.txt') bans_urls = bans_config.option('urls', []) respawn_time_option = config.option('respawn_time', default="8sec", cast=cast_duration) respawn_waves = config.option('respawn_waves', default=False) game_mode = config.option('game_mode', default='ctf') random_rotation = config.option('random_rotation', default=False) passwords = config.option('passwords', default={}) logfile = logging_config.option('logfile', default='./logs/log.txt') loglevel = logging_config.option('loglevel', default='info')
[charge] cooldown = 10 duration = 2 power = 1.7 .. codeauthor:: Jipok """ import time import asyncio from piqueserver.commands import command, admin, target_player, get_player from piqueserver.config import config from pyspades import world CHARGE_CONFIG = config.section('charge') CHARGE_COOLDOWN = CHARGE_CONFIG.option('cooldown', 10) CHARGE_DURATION = CHARGE_CONFIG.option('duration', 2) CHARGE_POWER = CHARGE_CONFIG.option('power', 1.7) @command('charge', admin_only=True) def give_charge(connection, player): player = get_player(connection.protocol, player) protocol = connection.protocol if player in protocol.charge_list: protocol.charge_list.remove(player) player.send_chat("You lost the charge ability") else: protocol.charge_list.append(player) player.last_charge_time = 0