Script Editing

The original, free Ace of Spades game powered by the Voxlap engine. Known as “Classic,” 0.75, 0.76, and all 0.x versions. Created by Ben Aksoy.
10 posts Page 1 of 1 First unread post
RetroStation
Deuce
Posts: 5
Joined: Mon Dec 17, 2012 8:34 am


I recently discovered AoS (ironically through JagEx on Steam), and I really like .75. I've been in a bunch of servers today, and I really like the feel of the game.


Now, I've been searching the whole time, and I've yet to come across a tutorial on how to change your server's gametype. I DL'd pyspades so I could possibly make a Free-for-All or TDM server.

I know scripts have something to do with it, but I haven't seen anything as far as how to edit scripts. Would anyone be willing to lend a hand?
GreaseMonkey
Coder
Coder
Posts: 733
Joined: Tue Oct 30, 2012 11:07 pm


Unfortunately, Pysnip is mostly undocumented.

The ./feature_server/ directory has the most important stuff, really. run.py is your entry point, config.txt is your config, maps/ has maps (if I recall correctly), and scripts/ has some scripts you can use.

If you want to get into writing your own scripts, here's a template script to get you started.
Look in ./pyspades/server.py for the on_* hooks you can use.
And yeah, you'll need to be fairly good with Python.

But I'm pretty sure you just want to use some already working scripts.
RetroStation
Deuce
Posts: 5
Joined: Mon Dec 17, 2012 8:34 am


GreaseMonkey wrote:
Unfortunately, Pysnip is mostly undocumented.

The ./feature_server/ directory has the most important stuff, really. run.py is your entry point, config.txt is your config, maps/ has maps (if I recall correctly), and scripts/ has some scripts you can use.

If you want to get into writing your own scripts, here's a template script to get you started.
Look in ./pyspades/server.py for the on_* hooks you can use.
And yeah, you'll need to be fairly good with Python.

But I'm pretty sure you just want to use some already working scripts.
This is a very good start; thank you.

Do I need an external program to edit the script, or could I just copy and paste into config, overwriting CTF?
GreaseMonkey
Coder
Coder
Posts: 733
Joined: Tue Oct 30, 2012 11:07 pm


A text editor will be fine. I suggest using one which does syntax highlighting though - it makes stuff much easier.
RetroStation
Deuce
Posts: 5
Joined: Mon Dec 17, 2012 8:34 am


GreaseMonkey wrote:
A text editor will be fine. I suggest using one which does syntax highlighting though - it makes stuff much easier.
I tried changing it to Babel, but the server won't start up now.

Spoiler:
{
"name" : "pyspades server",
"motd" : [
"Welcome to %(server_name)s! See /help for commands",
"Map is %(map_name)s by %(map_author)s",
"(server powered by pyspades)"
],
"help" : [
"/SQUAD Creates or joins a squad, letting you spawn with friends",
"/STREAK Shows how many kills in a row you got without dying",
"/AIRSTRIKE Air support! Try it out just like that for more details",
"/INTEL Tells you who's got the enemy intel"
],
"tips" : [
"Here you can deploy airstrikes, form squads and more! Type /help for info",
"The spade does melee damage! Use it wisely"
],
"tip_frequency" : 5,
"rules" : [
"No griefing, no cheating"
],

"master" : false,
"max_players" : 32,
"max_connections_per_ip" : 7,
"port" : 32887,
"network_interface" : "",

"game_mode" : "ctf",
"cap_limit" : 10,
"default_time_limit" : 15,
"advance_on_win" : false,
"maps" : ["December 21 2012", "bridgewars", "pinpoint",
"hallway", "harbor2"],
"random_rotation" : false,

from pyspades.constants import *
from random import randint

# If ALWAYS_ENABLED is False, then babel can be enabled by setting 'babel': True
# in the map metadat extensions dictionary.
ALWAYS_ENABLED = True

PLATFORM_WIDTH = 100
PLATFORM_HEIGHT = 32
PLATFORM_COLOR = (255, 255, 255, 255)
BLUE_BASE_COORDS = (256-138, 256)
GREEN_BASE_COORDS = (256+138, 256)
SPAWN_SIZE = 40


# Don't touch this stuff
PLATFORM_WIDTH /= 2
PLATFORM_HEIGHT /= 2
SPAWN_SIZE /= 2

def get_entity_location(self, entity_id):
if entity_id == BLUE_BASE:
return BLUE_BASE_COORDS + (self.protocol.map.get_z(*BLUE_BASE_COORDS),)
elif entity_id == GREEN_BASE:
return GREEN_BASE_COORDS + (self.protocol.map.get_z(*GREEN_BASE_COORDS),)
elif entity_id == BLUE_FLAG:
return (256 - PLATFORM_WIDTH + 1, 256, 0)
elif entity_id == GREEN_FLAG:
return (256 + PLATFORM_WIDTH - 1, 256, 0)

def get_spawn_location(connection):
xb = connection.team.base.x
yb = connection.team.base.y
xb += randint(-SPAWN_SIZE, SPAWN_SIZE)
yb += randint(-SPAWN_SIZE, SPAWN_SIZE)
return (xb, yb, connection.protocol.map.get_z(xb, yb))

def coord_on_platform(x, y, z):
if z <= 2:
if x >= (256 - PLATFORM_WIDTH) and x <= (256 + PLATFORM_WIDTH) and y >= (256 - PLATFORM_HEIGHT) and y <= (256 + PLATFORM_HEIGHT):
return True
if z == 1:
if x >= (256 - PLATFORM_WIDTH - 1) and x <= (256 + PLATFORM_WIDTH + 1) \
and y >= (256 - PLATFORM_HEIGHT - 1) and y <= (256 + PLATFORM_HEIGHT + 1):
return True
return False

def apply_script(protocol, connection, config):
class BabelProtocol(protocol):
babel = False
def on_map_change(self, map):
extensions = self.map_info.extensions
if ALWAYS_ENABLED:
self.babel = True
else:
if extensions.has_key('babel'):
self.babel = extensions['babel']
else:
self.babel = False
if self.babel:
self.map_info.cap_limit = 1
self.map_info.get_entity_location = get_entity_location
self.map_info.get_spawn_location = get_spawn_location
for x in xrange(256 - PLATFORM_WIDTH, 256 + PLATFORM_WIDTH):
for y in xrange(256 - PLATFORM_HEIGHT, 256 + PLATFORM_HEIGHT):
map.set_point(x, y, 1, PLATFORM_COLOR)
return protocol.on_map_change(self, map)

def is_indestructable(self, x, y, z):
if self.babel:
if coord_on_platform(x, y, z):
protocol.is_indestructable(self, x, y, z)
return True
return protocol.is_indestructable(self, x, y, z)

class BabelConnection(connection):
def invalid_build_position(self, x, y, z):
if not self.god and self.protocol.babel:
if coord_on_platform(x, y, z):
connection.on_block_build_attempt(self, x, y, z)
return True
# prevent enemies from building in protected areas
if self.team is self.protocol.blue_team:
if self.world_object.position.x >= 301 and self.world_object.position.x <= 384 \
and self.world_object.position.y >= 240 and self.world_object.position.y <= 272:
self.send_chat('You can\'t build near the enemy\'s tower!')
return True
if self.team is self.protocol.green_team:
if self.world_object.position.x >= 128 and self.world_object.position.x <= 211 \
and self.world_object.position.y >= 240 and self.world_object.position.y <= 272:
self.send_chat('You can\'t build near the enemy\'s tower!')
return True
return False

def on_block_build_attempt(self, x, y, z):
if self.invalid_build_position(x, y, z):
return False
return connection.on_block_build_attempt(self, x, y, z)

def on_line_build_attempt(self, points):
for point in points:
if self.invalid_build_position(*point):
return False
return connection.on_line_build_attempt(self, points)

# anti team destruction
def on_block_destroy(self, x, y, z, mode):
if self.team is self.protocol.blue_team:
if self.tool is SPADE_TOOL and self.world_object.position.x >= 128 and self.world_object.position.x <= 211 \
and self.world_object.position.y >= 240 and self.world_object.position.y <= 272:
self.send_chat('You can\'t destroy your team\'s blocks in this area. Attack the enemy\'s tower!')
return False
if self.world_object.position.x <= 288:
if self.tool is WEAPON_TOOL:
self.send_chat('You must be closer to the enemy\'s base to shoot blocks!')
return False
if self.tool is GRENADE_TOOL:
self.send_chat('You must be closer to the enemy\'s base to grenade blocks!')
return False
if self.team is self.protocol.green_team:
if self.tool is SPADE_TOOL and self.world_object.position.x >= 301 and self.world_object.position.x <= 384 \
and self.world_object.position.y >= 240 and self.world_object.position.y <= 272:
self.send_chat('You can\'t destroy your team\'s blocks in this area. Attack the enemy\'s tower!')
return False
if self.world_object.position.x >= 224:
if self.tool is WEAPON_TOOL:
self.send_chat('You must be closer to the enemy\'s base to shoot blocks!')
return False
if self.tool is GRENADE_TOOL:
self.send_chat('You must be closer to the enemy\'s base to grenade blocks!')
return False
return connection.on_block_destroy(self, x, y, z, mode)

return BabelProtocol, BabelConnection


"respawn_time" : 3,
"respawn_waves" : true,
"friendly_fire" : false,
"grief_friendly_fire_time" : 2,
"spade_teamkills_on_grief" : false,
"balanced_teams" : 1,
"teamswitch_interval" : 0,

"speedhack_detect" : true,
"votekick_percentage" : 25,
"votekick_ban_duration" : 15,
"votekick_public_votes" : true,
"votemap_public_votes" : true,
"votemap_extension_time" : 15,
"votemap_player_driven" : false,
"votemap_autoschedule" : 180,
"votemap_time" : 120,
"votemap_percentage" : 80,

"melee_damage" : 80,
"fall_damage" : true,
"user_blocks_only" : false,
"set_god_build" : false,
"server_prefix" : "[*]",
"time_announcements" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180,
240, 300, 600, 900, 1200, 1800, 2400, 3000],
"login_retries" : 3,
"default_ban_duration" : 1440,

"logfile" : "./logs/log.txt",
"rotate_daily" : true,
"debug_log" : false,
"profile" : false,

"team1" : {
"name" : "Akuma",
"color" : [205, 150, 205]
},
"team2" : {
"name" : "Ryu",
"color" : [205, 205, 205]
},
"passwords" : {
"admin" : ["replaceme"],
"trusted" : [],
"builder" : []
},
"rights" : {
"builder" : ["god", "goto"]
},
"ssh" : {
"enabled" : false,
"port" : 32887,
"users" : {
"user" : "pass"
}
},
"status_server" : {
"enabled" : false,
"port" : 32886
},
"ban_publish" : {
"enabled" : false,
"port" : 32885
},
"ban_subscribe" : {
"enabled" : true,
"urls" : [
["http://www.blacklist.spadille.net/subscribe.json", []]
]
},
"irc" : {
"enabled" : false,
"nickname" : "pyspades",
"username" : "pyspades",
"realname" : "pyspades server bot",
"server" : "irc.quakenet.org",
"port" : 6667,
"channel" : "#pyspades.bots",
"password" : "",
"commandprefix" : ".",
"chatprefix" : ""
},
"scripts" : [
"welcome",
"rollback",
"trusted",
"protect",
"map_extensions",
"airstrike",
"squad",
"disco",
"votekick",
"ratio",
"memcheck"
],

"squad_respawn_time" : 45,
"squad_size" : 4,
"auto_squad" : false,
"load_saved_map" : false,
"statistics" : {
"host" : "localhost",
"server_name" : "stats server",
"port" : 32880,
"password" : "marmelade"
},
"welcomes" : {
"mat^2" : "The very likeable mat^2 has entered!"
}
}
Tried do just copy-paste it somewhere in the config. What'd I do wrong?
Donatello
Deuced Up
Posts: 25
Joined: Sat Dec 01, 2012 7:07 pm


I made you a tutorial about running "babel gamemode" on your server:

Set game_mode to: "ctf" IN CONFIG.txt
Then, go to the "maps" folder in Pyspades or Pysnip directory (whichever you're using), and look for the map you are trying to run on your server, for example i'm using "map1", you will find a .txt file called the same as the map, example: map1.txt.
Open it, it should look like this:
Code: Select all
name = 'map1'
version = '1.0'
author = 'unknown'
description = 'Example map.txt'
At the end, add "extensions = { 'babel' : True }"

So it should look like this:
Code: Select all
name = 'map1'
version = '1.0'
author = 'unknown'
description = 'Example map.txt'
extensions = { 'babel' : True }
Save the .txt and open Config.txt again.
Go to the script list, and add "onectf" and "babel" to the list, and you're done (make sure you got the "babel" script in the scripts folder)
So the whole Config.txt should look like this (Pysnip, same as Pyspades):
Code: Select all
{
    "name" : "your server name here",
    "motd" : [
        "Welcome to %(server_name)s! See /help for commands",
        "Map is %(map_name)s by %(map_author)s",
        "(server powered by PySnip and BuildandShoot.com)"
    ],
    "help" : [
        "/SQUAD     Creates or joins a squad, letting you spawn with friends",
        "/STREAK    Shows how many kills in a row you got without dying",
        "/AIRSTRIKE Air support!  Try it out just like that for more details",
        "/INTEL     Tells you who's got the enemy intel"
    ],
    "tips" : [
        "Here you can deploy airstrikes, form squads and more!  Type /help for info",
        "The spade does melee damage!  Use it wisely"
    ],
    "tip_frequency" : 5,
    "rules" : [
        "No griefing, no cheating"
    ],
    
    "master" : true,
    "max_players" : 32,
    "max_connections_per_ip" : 7,
    "port" : 32887,
    "network_interface" : "",
    
    "game_mode" : "ctf",
    "cap_limit" : 10,
    "default_time_limit" : 999999,
    "advance_on_win" : false,
    "maps" : ["the maps you want here!"],
    "random_rotation" : false,
    
    "respawn_time" : 5,
    "respawn_waves" : true,
    "friendly_fire" : false,
    "grief_friendly_fire_time" : 5,
    "spade_teamkills_on_grief" : false,
    "balanced_teams" : 1,
    "teamswitch_interval" : 0,
    
    "speedhack_detect" : true,
    "votekick_percentage" : 25,
    "votekick_ban_duration" : 15,
    "votekick_public_votes" : true,
    "votemap_public_votes" : true,
    "votemap_extension_time" : 15,
    "votemap_player_driven" : false,
    "votemap_autoschedule" : 180,
    "votemap_time" : 120,
    "votemap_percentage" : 80,
    
    "melee_damage" : 80,
    "fall_damage" : true,
    "user_blocks_only" : false,
    "set_god_build" : false,
    "server_prefix" : "[*]",
    "time_announcements" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180,
                            240, 300, 600, 900, 1200, 1800, 2400, 3000],
    "login_retries" : 3,
    "default_ban_duration" : 1440,
    
    "logfile" : "./logs/log.txt",
    "rotate_daily" : true,
    "debug_log" : false,
    "profile" : false,
    
    "team1" : {
        "name" : "Blue",
        "color" : [0, 0, 255]
    },
    "team2" : {
        "name" : "Green",
        "color" : [0, 255, 0]
    },
    "passwords" : {
        "admin" : ["Replace me"],
        "trusted" : [],
        "builder" : []
    },
    "rights" : {
        "builder" : ["god", "goto"]
    },
    "ssh" : {
        "enabled" : false,
        "port" : 32887,
        "users" : {
            "user" : "pass"
        }
    },
    "status_server" : {
        "enabled" : false,
        "port" : 32886
    },
    "ban_publish" : {
        "enabled" : false,
        "port" : 32885
    },
    "ban_subscribe" : {
        "enabled" : true,
        "urls" : [
            ["http://www.blacklist.spadille.net/subscribe.json", []]
        ]
    },
    "irc" : {
        "enabled" : false,
        "nickname" : "pysnip",
        "username" : "pysnip",
        "realname" : "pysnip server bot",
        "server" : "irc.quakenet.org",
        "port" : 6667,
        "channel" : "#pysnip.bots",
        "password" : "",
        "commandprefix" : ".",
        "chatprefix" : ""
    },
    "scripts" : [
        "welcome",
        "rollback",
        "protect",
        "map_extensions",
        "airstrike",
        "squad",
        "onectf",
        "babel",
        "trusted",
        "ratio",
        "memcheck"
    ],
    
    "squad_respawn_time" : 45,
    "squad_size" : 4,
    "auto_squad" : false,
    "load_saved_map" : false,
    "statistics" : {
        "host" : "localhost",
        "server_name" : "stats server",
        "port" : 32880,
        "password" : "marmelade"
    },
    "welcomes" : {
        "mat^2" : "The very likeable mat^2 has entered!"
    }
}


And that's how you run Babel mode on your server.
Hope i helped Blue_BigSmile Green_BigSmile
RetroStation
Deuce
Posts: 5
Joined: Mon Dec 17, 2012 8:34 am


Donatello wrote:
I made you a tutorial about running "babel gamemode" on your server:

Set game_mode to: "ctf" IN CONFIG.txt
Then, go to the "maps" folder in Pyspades or Pysnip directory (whichever you're using), and look for the map you are trying to run on your server, for example i'm using "map1", you will find a .txt file called the same as the map, example: map1.txt.
Open it, it should look like this:
Code: Select all
name = 'map1'
version = '1.0'
author = 'unknown'
description = 'Example map.txt'
At the end, add "extensions = { 'babel' : True }"

So it should look like this:
Code: Select all
name = 'map1'
version = '1.0'
author = 'unknown'
description = 'Example map.txt'
extensions = { 'babel' : True }
Save the .txt and open Config.txt again.
Go to the script list, and add "onectf" and "babel" to the list, and you're done (make sure you got the "babel" script in the scripts folder)
So the whole Config.txt should look like this (Pysnip, same as Pyspades):
Code: Select all
{
    "name" : "your server name here",
    "motd" : [
        "Welcome to %(server_name)s! See /help for commands",
        "Map is %(map_name)s by %(map_author)s",
        "(server powered by PySnip and BuildandShoot.com)"
    ],
    "help" : [
        "/SQUAD     Creates or joins a squad, letting you spawn with friends",
        "/STREAK    Shows how many kills in a row you got without dying",
        "/AIRSTRIKE Air support!  Try it out just like that for more details",
        "/INTEL     Tells you who's got the enemy intel"
    ],
    "tips" : [
        "Here you can deploy airstrikes, form squads and more!  Type /help for info",
        "The spade does melee damage!  Use it wisely"
    ],
    "tip_frequency" : 5,
    "rules" : [
        "No griefing, no cheating"
    ],
    
    "master" : true,
    "max_players" : 32,
    "max_connections_per_ip" : 7,
    "port" : 32887,
    "network_interface" : "",
    
    "game_mode" : "ctf",
    "cap_limit" : 10,
    "default_time_limit" : 999999,
    "advance_on_win" : false,
    "maps" : ["the maps you want here!"],
    "random_rotation" : false,
    
    "respawn_time" : 5,
    "respawn_waves" : true,
    "friendly_fire" : false,
    "grief_friendly_fire_time" : 5,
    "spade_teamkills_on_grief" : false,
    "balanced_teams" : 1,
    "teamswitch_interval" : 0,
    
    "speedhack_detect" : true,
    "votekick_percentage" : 25,
    "votekick_ban_duration" : 15,
    "votekick_public_votes" : true,
    "votemap_public_votes" : true,
    "votemap_extension_time" : 15,
    "votemap_player_driven" : false,
    "votemap_autoschedule" : 180,
    "votemap_time" : 120,
    "votemap_percentage" : 80,
    
    "melee_damage" : 80,
    "fall_damage" : true,
    "user_blocks_only" : false,
    "set_god_build" : false,
    "server_prefix" : "[*]",
    "time_announcements" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180,
                            240, 300, 600, 900, 1200, 1800, 2400, 3000],
    "login_retries" : 3,
    "default_ban_duration" : 1440,
    
    "logfile" : "./logs/log.txt",
    "rotate_daily" : true,
    "debug_log" : false,
    "profile" : false,
    
    "team1" : {
        "name" : "Blue",
        "color" : [0, 0, 255]
    },
    "team2" : {
        "name" : "Green",
        "color" : [0, 255, 0]
    },
    "passwords" : {
        "admin" : ["Replace me"],
        "trusted" : [],
        "builder" : []
    },
    "rights" : {
        "builder" : ["god", "goto"]
    },
    "ssh" : {
        "enabled" : false,
        "port" : 32887,
        "users" : {
            "user" : "pass"
        }
    },
    "status_server" : {
        "enabled" : false,
        "port" : 32886
    },
    "ban_publish" : {
        "enabled" : false,
        "port" : 32885
    },
    "ban_subscribe" : {
        "enabled" : true,
        "urls" : [
            ["http://www.blacklist.spadille.net/subscribe.json", []]
        ]
    },
    "irc" : {
        "enabled" : false,
        "nickname" : "pysnip",
        "username" : "pysnip",
        "realname" : "pysnip server bot",
        "server" : "irc.quakenet.org",
        "port" : 6667,
        "channel" : "#pysnip.bots",
        "password" : "",
        "commandprefix" : ".",
        "chatprefix" : ""
    },
    "scripts" : [
        "welcome",
        "rollback",
        "protect",
        "map_extensions",
        "airstrike",
        "squad",
        "onectf",
        "babel",
        "trusted",
        "ratio",
        "memcheck"
    ],
    
    "squad_respawn_time" : 45,
    "squad_size" : 4,
    "auto_squad" : false,
    "load_saved_map" : false,
    "statistics" : {
        "host" : "localhost",
        "server_name" : "stats server",
        "port" : 32880,
        "password" : "marmelade"
    },
    "welcomes" : {
        "mat^2" : "The very likeable mat^2 has entered!"
    }
}


And that's how you run Babel mode on your server.
Hope i helped Blue_BigSmile Green_BigSmile
That definitely helped the Babel portion; thank you! Now would the same process apply to Free-For-All and Arena servers?
Donatello
Deuced Up
Posts: 25
Joined: Sat Dec 01, 2012 7:07 pm


To use Arena gamemode, you need to find an Arena map.
Example: open the .txt for the Arena map, it should be like this:
Code: Select all
name = 'Arena Map'
version = '1.0'
author = 'blah blah'
description = ('blah blah')
extensions = {
     'arena': True,
     'arena_blue_spawn' : (235, 310, 58),
     'arena_green_spawn' : (275, 180, 49),
     'arena_gates': ((268, 183, 47), (268, 184, 48), (283, 182, 46), (283, 182, 48), (236, 304, 54), (235, 304, 56), (232, 304, 55), (268, 179, 47), (283, 180, 47)),
     'water_damage' : 100
 }
After you find an Arena map, download the Arena script: http://www.mediafire.com/?k7rt2mi4vj9t93g
And put it in your "Scripts" folder in Pysnip (or Pyspades), and then, open your config.txt, and add "arena" to the script list.

As for the FreeForAll, just download the script: http://www.mediafire.com/?r5243eq6bj47a16
And open config.txt and add "freeforall" in the script list, and you're done!
ElementalVenom
Deuce
Posts: 5
Joined: Sat Jan 18, 2014 3:40 am


Can You Send Me The Script For HALLWAY?
Jdrew
Mapper
Mapper
Posts: 4808
Joined: Tue Oct 30, 2012 10:48 pm


Hallway is a map not a script. Aloha.pk uses reverse one ctf on it's hallway server. You can go to there website(aloha.pk) and ask for it there. (please do not bump old threads)
10 posts Page 1 of 1 First unread post
Return to “Ace of Spades 0.x Discussion”

Who is online

Users browsing this forum: No registered users and 20 guests