Advertisement
Guest User

Push game mode

a guest
Jun 3rd, 2013
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.47 KB | None | 0 0
  1. """
  2. push.py last modified 2013-06-03 20:41:51
  3. Contributors: danhezee, StackOverflow, izzy, Danke, noway421
  4.  
  5. The concept:
  6.    Each team spawns at a set location with the enemy intel.
  7.    They must "push" the intel towards their control point, which is also at a
  8.    set location.
  9.  
  10. How to setup new maps:
  11.    Spawn and CP locations must be configured via extensions in the map's
  12.    map_name.txt metadata. Example:
  13.  
  14. extensions = {
  15.    'push': True,
  16.    'push_spawn_range' : 5,
  17.    'push_blue_spawn' : (91, 276, 59),
  18.    'push_blue_cp' : (91, 276, 59),
  19.    'push_green_spawn' : (78, 86, 59),
  20.    'push_green_cp' : (78, 86, 59),
  21.    'water_damage' : 100
  22. }
  23.  
  24. ToDo:
  25.    Block check by global array (For example, blockdata.py), not block color.
  26.    One time violet block spawns. Wtf!
  27.    Serverside player blocks stack. Cannot control filling stack on clientside.
  28. """
  29.  
  30. from pyspades.constants import *
  31. from random import randint
  32. from commands import add, admin
  33. from twisted.internet.reactor import callLater
  34. from pyspades.common import make_color
  35. from pyspades.server import set_color, block_action
  36.  
  37. import colorsys
  38.  
  39.  
  40. def byte_rgb_to_hls(rgb):
  41.     hls = colorsys.rgb_to_hls(*tuple(c / 255.0 for c in rgb))
  42.     return tuple(int(round(c * 255)) for c in hls)
  43.  
  44.  
  45. def byte_hls_to_rgb(hls):
  46.     rgb = colorsys.hls_to_rgb(*tuple(c / 255.0 for c in hls))
  47.     return tuple(int(round(c * 255)) for c in rgb)
  48.  
  49.  
  50. def byte_middle_range(byte):
  51.     half = 50 / 2.0  # half of (byte/5.1)
  52.     min = byte - half
  53.     max = byte + half
  54.     if min < 0:
  55.         min = 0
  56.         max = half
  57.     elif max > 255:
  58.         min = 255 - half
  59.         max = 255
  60.     return int(round(min)), int(round(max))
  61.  
  62.  
  63. # If ALWAYS_ENABLED is False, then the 'push' key must be set to True in
  64. # the 'extensions' dictionary in the map's map_name.txt metadata
  65. ALWAYS_ENABLED = True
  66. CANT_DESTROY = "You can't destroy your team's blocks. Attack the enemy!"
  67. NO_BLOCKS = "You out of blocks! Kill yourself or reach base to refill."
  68. # team is associated intel team
  69.  
  70.  
  71. def reset_intel(protocol, team):
  72.     if team is protocol.green_team and protocol.blue_team.spawn is not None:
  73.         z = protocol.map.get_z(*protocol.blue_team.spawn)
  74.         pos = (protocol.blue_team.spawn[0],
  75.                protocol.blue_team.spawn[1],
  76.                z)
  77.  
  78.     if team is protocol.blue_team and protocol.green_team.spawn is not None:
  79.         z = protocol.map.get_z(*protocol.green_team.spawn)
  80.         pos = (protocol.green_team.spawn[0],
  81.                protocol.green_team.spawn[1],
  82.                z)
  83.  
  84.     team.flag.set(*pos)  # If spawn not set, it would throw error.
  85.     team.flag.update()
  86.     protocol.send_chat("The %s intel has been reset." % team.name)
  87.  
  88.  
  89. @admin
  90. def resetblueintel(connection):
  91.     reset_intel(connection.protocol, connection.protocol.blue_team)
  92.  
  93.  
  94. @admin
  95. def resetgreenintel(connection):
  96.     reset_intel(connection.protocol, connection.protocol.green_team)
  97.  
  98.  
  99. add(resetblueintel)
  100. add(resetgreenintel)
  101.  
  102.  
  103. def get_entity_location(self, entity_id):
  104.     if entity_id == BLUE_BASE:
  105.         return self.protocol.blue_team.cp
  106.     elif entity_id == GREEN_BASE:
  107.         return self.protocol.green_team.cp
  108.  
  109.     # this next part might seem counter intuitive but you need the blue intel
  110.     # to spawn near the greens and vice versa
  111.     elif entity_id == BLUE_FLAG:
  112.         return self.protocol.green_team.spawn
  113.     elif entity_id == GREEN_FLAG:
  114.         return self.protocol.blue_team.spawn
  115.  
  116.  
  117. def get_spawn_location(connection):
  118.     # distance from spawn center to randomly spawn in
  119.     spawn_range = connection.protocol.spawn_range
  120.  
  121.     if connection.team.spawn is not None:
  122.         xb = connection.team.spawn[0]
  123.         yb = connection.team.spawn[1]
  124.         xb += randint(-spawn_range, spawn_range)
  125.         yb += randint(-spawn_range, spawn_range)
  126.         return (xb, yb, connection.protocol.map.get_z(xb, yb))
  127.  
  128.  
  129. def apply_script(protocol, connection, config):
  130.     class PushConnection(connection):
  131.         def on_login(self, name):
  132.             self.mylastblocks = [
  133.                 (-4, -1, -14),
  134.                 (-11, -5, -9),
  135.                 (-19, -20, -8),
  136.                 (-5, -2, -5),
  137.                 (-19, -20, 0)]
  138.             return connection.on_login(self, name)
  139.  
  140.         def on_flag_drop(self):
  141.             callLater(
  142.                 3,
  143.                 (lambda self:
  144.                     (reset_intel(self.protocol, self.team.other)
  145.                         if self.team.other.flag.get()[2] >= 63
  146.                         else None)),
  147.                 self)
  148.             return connection.on_flag_drop(self)
  149.  
  150.         def random_color(self):
  151.             (h, l, s) = self.team.hls
  152.             l = randint(self.team.light_range[0], self.team.light_range[1])
  153.             color = byte_hls_to_rgb((h, l, s))
  154.  
  155.             self.color = color
  156.             set_color.player_id = self.player_id
  157.             set_color.value = make_color(*color)
  158.             self.send_contained(set_color)
  159.             self.protocol.send_contained(set_color, save=True)
  160.  
  161.         def build_block(self, x, y, z, looped=False):
  162.             if ((x < 0 or x > 511 or
  163.                 y < 0 or y > 511 or
  164.                 z < 1 or z > 61)
  165.                     is False):
  166.                 self.protocol.map.set_point(x, y, z, self.color)
  167.                 block_action.x = x
  168.                 block_action.y = y
  169.                 block_action.z = z
  170.                 block_action.value = BUILD_BLOCK
  171.                 block_action.player_id = self.player_id
  172.                 self.protocol.send_contained(block_action, save=True)
  173.  
  174.         def on_line_build_attempt(self, points):
  175.             can_build = connection.on_line_build_attempt(self, points)
  176.             if can_build is False:
  177.                 return False
  178.  
  179.             if self.blocks < len(points):
  180.                 self.send_chat(NO_BLOCKS)
  181.                 return False
  182.  
  183.             spawn = self.team.spawn
  184.             spawn_range = self.protocol.spawn_range
  185.  
  186.             for point in points:
  187.                 x, y, z = point[0], point[1], point[2]
  188.                 self.mylastblocks.pop(0)
  189.                 self.mylastblocks.append((x, y, z))
  190.                 self.random_color()
  191.                 self.build_block(x, y, z)
  192.  
  193.             return can_build
  194.  
  195.         def on_block_build_attempt(self, x, y, z):
  196.             can_build = connection.on_block_build_attempt(self, x, y, z)
  197.             if can_build is False:
  198.                 return False
  199.  
  200.             if self.blocks < 1:
  201.                 self.send_chat(NO_BLOCKS)
  202.                 return False
  203.  
  204.             self.mylastblocks.pop(0)
  205.             self.mylastblocks.append((x, y, z))
  206.             self.random_color()
  207.             self.build_block(x, y, z)
  208.             return can_build
  209.  
  210.         def on_block_destroy(self, x, y, z, value):
  211.             if not (self.admin or
  212.                     self.god or
  213.                     self.user_types.moderator or
  214.                     self.user_types.guard or
  215.                     self.user_types.trusted):
  216.                 if value == DESTROY_BLOCK:
  217.                     blocks = ((x, y, z),)
  218.                 elif value == SPADE_DESTROY:
  219.                     blocks = ((x, y, z), (x, y, z + 1), (x, y, z - 1))
  220.                 elif value == GRENADE_DESTROY:
  221.                     blocks = []
  222.                     for nade_x in xrange(x - 1, x + 2):
  223.                         for nade_y in xrange(y - 1, y + 2):
  224.                             for nade_z in xrange(z - 1, z + 2):
  225.                                 blocks.append((nade_x, nade_y, nade_z))
  226.  
  227.                 is_in_last = lambda block: any(last == block
  228.                                                for last in self.mylastblocks)
  229.  
  230.                 for block in blocks:
  231.                     if is_in_last(block):
  232.                         continue
  233.  
  234.                     block_info = self.protocol.map.get_point(*block)
  235.  
  236.                     if block_info[0] is True:
  237.                         block_hls = byte_rgb_to_hls(block_info[1])
  238.                         if self.team is self.protocol.blue_team:
  239.                             team_hls = self.protocol.blue_team.hls
  240.                             # if hue and saturation match
  241.                             if (block_hls[0] == team_hls[0] and
  242.                                     block_hls[2] == team_hls[2]):
  243.                                 self.send_chat(CANT_DESTROY)
  244.                                 return False
  245.                         elif self.team is self.protocol.green_team:
  246.                             team_hls = self.protocol.green_team.hls
  247.                             if (block_hls[0] == team_hls[0] and
  248.                                     block_hls[2] == team_hls[2]):
  249.                                 self.send_chat(CANT_DESTROY)
  250.                                 return False
  251.  
  252.                 for block in blocks:
  253.                     if is_in_last(block):
  254.                         self.mylastblocks.remove(block)
  255.                         self.mylastblocks.append((-1, -1, -1))
  256.  
  257.             return connection.on_block_destroy(self, x, y, z, value)
  258.  
  259.     class PushProtocol(protocol):
  260.         game_mode = CTF_MODE
  261.         push = False
  262.         spawn_range = 5
  263.  
  264.         def __init__(self, *arg, **kw):
  265.             protocol.__init__(self, *arg, **kw)
  266.             self.blue_team.hls = byte_rgb_to_hls(self.blue_team.color)
  267.             self.blue_team.light_range = byte_middle_range(
  268.                 self.blue_team.hls[1])
  269.  
  270.             self.green_team.hls = byte_rgb_to_hls(self.green_team.color)
  271.             self.green_team.light_range = byte_middle_range(
  272.                 self.green_team.hls[1])
  273.  
  274.         def on_map_change(self, map):
  275.             extensions = self.map_info.extensions
  276.             if ALWAYS_ENABLED:
  277.                 self.push = True
  278.             else:
  279.                 self.push = extensions.get('push', False)
  280.  
  281.             if self.push:
  282.                 # distance from spawn center to randomly spawn in
  283.                 self.spawn_range = extensions.get('push_spawn_range')
  284.  
  285.                 self.blue_team.spawn = extensions.get('push_blue_spawn')
  286.                 self.blue_team.cp = extensions.get('push_blue_cp')
  287.  
  288.                 self.green_team.spawn = extensions.get('push_green_spawn')
  289.                 self.green_team.cp = extensions.get('push_green_cp')
  290.  
  291.                 self.map_info.get_entity_location = get_entity_location
  292.                 self.map_info.get_spawn_location = get_spawn_location
  293.  
  294.             return protocol.on_map_change(self, map)
  295.  
  296.     return PushProtocol, PushConnection
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement