Module clientController
[hide private]
[frames] | no frames]

Source Code for Module clientController

  1  import cocos 
  2  import cocos.euclid as eu 
  3  import utils 
  4  import math 
  5  import twisted 
  6  import random 
  7  from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint 
  8  from twisted.python.log import err 
  9  from twisted.internet.error import * 
 10  from twisted.internet import reactor 
 11   
 12  from cocos import collision_model 
 13  from cocos.director import director 
 14  from cocos.layer import Layer 
 15  from cocos.layer.scrolling import ScrollingManager 
 16  from cocos.actions.instant_actions import CallFuncS 
 17  from cocos.actions.interval_actions import Delay 
 18   
 19   
 20  from pyglet.event import EventDispatcher 
 21  from pyglet.window import key 
 22   
 23  import constants 
 24  from commands import * 
 25  from constants import * 
 26  from imageLayer import ImageLayer 
 27  from maps import Map, Vertex 
 28  from models import * 
 29  from player_new import Player 
 30   
 31  from utils import get_action_button_clicked 
 32  from playerai import ComputerPlayer 
 33  from research import RESEARCH 
 34  from game_layers import StatusMenu, InfoLayer, SettingsLayer,ActionButton,TransTimer, MenuButton, HotkeysLayer, StickyNote, TutorialXButton 
 35  import music 
 36  from game import EndMenu 
 37  from tutorial import * 
 38  from server import ClientNoteFactory 
 39  from client import ServerNoteFactory 
 40   
41 -class ClientController(Layer,EventDispatcher):
42 is_event_handler = True 43
44 - def __init__(self,mapName):
45 super(ClientController, self).__init__() 46 47 if mapName: #if there's no mapName, the server's passing it in at some point 48 self.map = self._init_map_and_cm(mapName) 49 self._add_tutorial(mapName) 50 self.tutorial = None 51 52 self.curLevel = 1 53 54 self.curAction = None 55 56 self.selectedUnits = [] # units selected by the current player 57 58 self.players = {} # k:pid, v: player object 59 60 self.player = None # the player on this computer 61 62 self.playerList = [] # list of pid for all players 63 64 self.pid = -1 65 66 self.arrow_flags = {key.LEFT: 0, key.RIGHT: 0, key.UP: 0, key.DOWN: 0} 67 68 self.mouse_flags = {"x": 0, "y": 0} 69 70 self.ip = "" # ip address, lazily instentiated 71 72 self.serverStarted = False 73 74 self.connectedToServer = False 75 76 self.endpoint = None 77 78 self.visibleASes = set() 79 80 self.isControlDown = False # For Hotkeying 81 82 self.hotKeyedUnits = { 83 key._0 : None, 84 key._1 : None, 85 key._2 : None, 86 key._3 : None, 87 key._4 : None, 88 key._5 : None, 89 key._6 : None, 90 key._7 : None, 91 key._8 : None, 92 key._9 : None 93 }
94
95 - def _add_tutorial(self, mapName):
96 if mapName == "level1": 97 self.tutorial = Tutorial(1,self) 98 return 99 elif mapName[:-1] == "level" and mapName[-1] in [str(i) for i in range(2,6)]: 100 # Adds the sticky note for levels 2-5 101 self.stickyNote = StickyNote(mapName[-1]) 102 self.stickyXButton = TutorialXButton(self.stickyNote) 103 self.map.add(self.stickyNote) 104 self.map.add(self.stickyXButton) 105 self.cm.add(self.stickyXButton)
106
107 - def _init_map_and_cm(self,mapName):
108 if mapName == "srandom" or mapName == "sRandom" or mapName == "sr" or mapName == "sR": 109 # Single player random -> adds AI 110 self.mapName = str(random.randint(100,10000)) 111 m = Map("random", numPlayers = 2, AIPlayers = ["1"], seed = int(self.mapName)) 112 elif mapName == "random" or mapName == "Random" or mapName == "r" or mapName == "R": 113 # Multi player random -> doesn't add AI 114 self.mapName = str(random.randint(100,10000)) 115 m = Map("random", numPlayers = 2, seed = int(self.mapName)) 116 elif mapName.isdigit(): 117 m = Map("random", numPlayers = 2, seed = int(mapName)) 118 self.mapName = mapName 119 else: 120 m = Map(os.path.join("maps", mapName + ".map")) 121 self.mapName = mapName 122 # self.map = Map(os.path.join("maps", "random", "random487.map")) 123 self.cm = collision_model.CollisionManagerGrid( 124 -BLEED, m.w * CELL_SIZE + BLEED, -BLEED, m.h * CELL_SIZE + BLEED, CELL_SIZE / 2, CELL_SIZE / 2) 125 m.cm = self.cm 126 self.scroller = ScrollingManager(viewport=director.window) 127 self.scroller.add(m) 128 129 self.h = CELL_SIZE * m.h 130 if self.h < WINDOW_HEIGHT: 131 self.h = WINDOW_HEIGHT 132 133 self.w = CELL_SIZE * m.w 134 if self.w < WINDOW_WIDTH: 135 self.w = WINDOW_WIDTH 136 137 return m
138
139 - def on_enter(self):
140 super(ClientController, self).on_enter() 141 if constants.MUSIC: 142 music.theme_player.play() 143 if self.tutorial: 144 self.tutorial.first_prompt("on_enter") 145 self.push_handlers( 146 self.tutorial.player_add_unit, self.tutorial.player_unit_attack) 147 self.push_handlers( 148 self.tutorial.click_on_move, self.tutorial.click_on_action) 149 self.schedule(self.step) 150 self.infoLayer = InfoLayer(self.map, self.scroller, self.pid) 151 self.settingsMenu = SettingsLayer() 152 self.statusMenu = StatusMenu(self.settingsMenu,self.player) 153 self.hotkeysLayer = HotkeysLayer(self.hotKeyedUnits,self.scroller) 154 self.hotkeysLayer.toggle_hotkeys_menu() 155 self.add(self.statusMenu,z=1) 156 self.add(self.infoLayer,z=1) 157 self.add(self.settingsMenu,z=2) 158 self.add(self.hotkeysLayer,z=2)
159 160
161 - def end_game(self, didWin):
162 self.stop_server() 163 if constants.MUSIC: 164 music.theme_player.stop() 165 166 for child in self.map.get_children(): 167 child.stop() 168 169 if didWin: 170 s = cocos.scene.Scene(EndMenu("Won",self.curLevel)) 171 else: 172 s = cocos.scene.Scene(EndMenu("Lost",self.curLevel)) 173 s.add(ImageLayer(os.path.join("images", "backgrounds", "menu-chalkboard.png")),z=-1) 174 cocos.director.director.replace(s)
175 176
177 - def stop_server(self):
178 try: 179 self.serverStarted = False 180 d = self.endpoint.stopListening() # returns deferred 181 d.addBoth(err, err) 182 except: 183 pass
184
185 - def step(self, dt):
186 # scrolling logic 187 if self.mouse_flags["x"] == 0 and self.mouse_flags["y"] == 0: 188 # keyboard scrolling 189 buttons = self.arrow_flags 190 move_dir = eu.Vector2(buttons[key.RIGHT] - buttons[key.LEFT], 191 buttons[key.UP] - buttons[key.DOWN]) 192 else: 193 # mouse scrolling 194 move_dir = eu.Vector2(self.mouse_flags['x'], self.mouse_flags['y']) 195 newPos = move_dir.normalize() * dt * MAP_MOUSE_SCROLL_SPEED 196 newx, newy = self.clamp(newPos) 197 self.scroller.set_focus(newx, newy)
198
199 - def clamp(self, pos):
200 x, y = pos 201 newx = self.scroller.fx + x 202 newy = self.scroller.fy + y 203 if newx <= -BLEED: 204 newx = -BLEED 205 elif newx >= self.w - WINDOW_WIDTH + BLEED: 206 newx = self.w - WINDOW_WIDTH + BLEED 207 if newy <= -BLEED: 208 newy = -BLEED 209 elif newy >= self.h - WINDOW_HEIGHT + BLEED: 210 newy = self.h - WINDOW_HEIGHT + BLEED 211 return newx, newy
212 213 ''' 214 Methods responding to local events 215 '''
216 - def on_mouse_motion(self, x, y, dx, dy):
217 if x <= 1: 218 self.mouse_flags["x"] = -1.0 219 self.mouse_flags["y"] = float(y - (WINDOW_HEIGHT / 220 2)) / WINDOW_HEIGHT 221 elif x >= WINDOW_WIDTH - 1: 222 self.mouse_flags["x"] = 1.0 223 self.mouse_flags["y"] = float(y - (WINDOW_HEIGHT / 224 2)) / WINDOW_HEIGHT 225 elif y <= 1: 226 self.mouse_flags["y"] = -1.0 227 self.mouse_flags["x"] = float(x - (WINDOW_WIDTH / 2)) / WINDOW_WIDTH 228 elif y >= WINDOW_HEIGHT - 1: 229 self.mouse_flags["y"] = 1.0 230 self.mouse_flags["x"] = float(x - (WINDOW_WIDTH / 2)) / WINDOW_WIDTH 231 else: 232 self.mouse_flags["x"] = 0 233 self.mouse_flags["y"] = 0
234
235 - def on_key_press(self, k, modifiers):
236 if k == key.ESCAPE: 237 self.end_game(False) 238 return True 239 240 # If the 'N' key was pressed, toggle selection to the next troop that belongs to this player in the vertex. 241 if k == key.N and self.selectedUnits != []: 242 vert = self.selectedUnits[0].curVertex 243 if len(vert.troopSlots) > 1 or (issubclass(type(self.selectedUnits[0]), Building) and len(vert.troopSlots) > 0): 244 if (issubclass(type(self.selectedUnits[0]), Building)): 245 # Selected unit is a building, so we want to grab the first Troop (that belongs to this player) that we find. 246 getNextTroop = True 247 else: 248 getNextTroop = False 249 250 i = 0 251 troopSlotIndex = vert.troopSlots.keys()[i] 252 haveNotChangedTroop = True 253 254 # Find a suitable troop 255 while haveNotChangedTroop: 256 troop = vert.troopSlots[troopSlotIndex].troop 257 if troop != None: 258 if getNextTroop and troop == self.selectedUnits[0]: 259 # Looped around and did not find any of our units in this vertex, so break. 260 break 261 elif getNextTroop and troop.pid == self.selectedUnits[0].pid and troop != self.selectedUnits[0]: 262 # Found one of this players units in this vertex. Select it and break. 263 self._deselect_all_units() 264 troop.set_is_selected(True, self.map, self.cm, self.player) 265 self.selectedUnits = [troop] 266 break 267 elif troop.isSelected: 268 getNextTroop = True 269 270 # Reset index 271 i = (i + 1) % len(vert.troopSlots.keys()) 272 troopSlotIndex = vert.troopSlots.keys()[i] 273 274 # If the 'B' key was pressed, toggle selection to the building that belongs to this player in the vertex. 275 if k == key.B and self.selectedUnits != []: 276 vert = self.selectedUnits[0].curVertex 277 if vert.building != None and vert.building.pid == self.selectedUnits[0].pid and vert.building != self.selectedUnits[0]: 278 self._deselect_all_units() 279 vert.building.set_is_selected(True, self.map, self.cm, self.player) 280 self.selectedUnits = [vert.building] 281 282 283 if k == key.LCTRL or k == key.RCTRL: 284 # Set so we can select the units we hotkeyed. 285 self.isControlDown = True 286 287 288 if k in self.hotKeyedUnits.keys(): 289 if self.isControlDown: 290 # We're hotkeying a new unit. 291 if len(self.selectedUnits) > 0: 292 # Check to ensure we have selected something first. 293 self.hotKeyedUnits[k] = self.selectedUnits[0] 294 self.hotkeysLayer.update_hotkeys_menu() 295 296 elif self.hotKeyedUnits[k] != None: 297 # print "m", self.hotKeyedUnits[k].isMoving 298 # We want to go to the location of the troop. 299 if issubclass(type(self.hotKeyedUnits[k]), Unit) or self.hotKeyedUnits[k].isSelectable: 300 self._deselect_all_units() 301 self.hotKeyedUnits[k].set_is_selected(True, self.map, self.cm, self.player) 302 self.selectedUnits = [self.hotKeyedUnits[k]] 303 self.hotkeysLayer.update_hotkeys_menu() 304 self._set_focus_to_unit(self.hotKeyedUnits[k]) 305 306 307 # scrolling logic 308 if k in self.arrow_flags.keys(): 309 self.arrow_flags[k] = 1 310 return True 311 312 return False
313
314 - def on_key_release(self, k, m):
315 # Determine the type of units we've selected so we can assign hotkeys 316 # appropriately 317 selType = None 318 319 # scrolling logic 320 if k in self.arrow_flags.keys(): 321 self.arrow_flags[k] = 0 322 323 if k == key.LCTRL or k == key.RCTRL: 324 # Reset so we can select the units we hotkeyed. 325 self.isControlDown = False 326 327 # Delete the selected unit. 328 if k == key.BACKSPACE: 329 if len(self.selectedUnits) > 0: 330 temp = list(self.selectedUnits) 331 self._deselect_all_units() 332 for unit in temp: 333 utils.play_sound("delete.wav") 334 unit.destroy_action() 335 336 if len(self.selectedUnits) > 0: 337 selType = type(self.selectedUnits[0]) 338 actNum = None 339 if selType and issubclass(selType, Troop): 340 actNum = TROOP_HOTKEYS.get(k, None) 341 elif selType and issubclass(selType, Building): 342 actNum = BUILDING_HOTKEYS.get(k, None) 343 344 if actNum != None: 345 for unit in self.selectedUnits: 346 if actNum < len(unit.actionList): 347 self._deselect_all_units() 348 self.execute_action(unit.get_action_list(self.player)[actNum], unit) 349 break 350 351 352 return True
353
354 - def on_mouse_release(self, x, y, buttons, modifiers):
355 356 x, y = self.scroller.pixel_from_screen(x, y) 357 if self.infoLayer.miniMapToggled and self.infoLayer.miniMap.cshape.touches_point(x,y): 358 return 359 360 #I'm not sure why we need this, please talk to me - Robert 361 # if self.statusMenu.menuButton.cshape.touches_point(x,y): 362 # director.pop() 363 364 clicked_units = self.cm.objs_touching_point(x, y) 365 temp_units = [] 366 actionButton = None 367 368 for unit in clicked_units: 369 if type(unit) == ActionButton: 370 actionButton = unit 371 break 372 if unit.opacity == 255: # Using opacity to check unit is visible and finished building 373 if issubclass(type(unit),Unit) and not unit.isSelectable: 374 continue 375 temp_units.append(unit) 376 if unit == self.stickyXButton: 377 # Delete the sticky note. 378 379 self.map.remove(self.stickyNote) 380 self.map.remove(self.stickyXButton) 381 self.cm.remove_tricky(self.stickyXButton) 382 utils.play_sound("delete.wav") 383 384 if self.stickyNote.levelFiveCounter in [1,2]: 385 # Adds the sticky note for levels 2-5 386 self.stickyNote = StickyNote("5", self.stickyNote.levelFiveCounter) 387 self.stickyXButton = TutorialXButton(self.stickyNote) 388 self.map.add(self.stickyNote) 389 self.map.add(self.stickyXButton) 390 self.cm.add(self.stickyXButton) 391 392 clicked_units = temp_units[:1] 393 394 if buttons == 1: # left button 395 if self.curAction: 396 if self.curAction == "Shake": 397 for unit in list(clicked_units): 398 if type(unit) == Handshake and unit.pid == self.pid: 399 self.hand_shake(unit,self.selectedUnits.pop()) 400 401 elif self.curAction == "Attack": 402 for unit in list(clicked_units): 403 if (issubclass(type(unit), Unit) and unit.pid != self.pid) or issubclass(type(unit), Vertex): 404 if self.selectedUnits: 405 self.dispatch_event("player_unit_attack", self.selectedUnits[0]) 406 attacker = self.selectedUnits.pop() 407 if type(self) == ClientController: 408 self.server_attack_unit(attacker,unit) 409 else: 410 self.attack_unit(unit,attacker) 411 412 self.curAction = None 413 return 414 415 self._deselect_all_units() 416 if actionButton: 417 self.execute_action(actionButton.name, actionButton.unitParent) 418 else: 419 self._select_units(clicked_units) 420 421 if buttons == 4: # right button 422 if not self.selectedUnits: 423 return 424 for unit in list(clicked_units): 425 if type(unit) == Vertex: 426 self._move_selected_units(unit) 427 return
428
429 - def _move_selected_units(self, dest):
430 for unit in self.selectedUnits: 431 self.server_move_troop(unit.uid, dest.vid) 432 self._deselect_all_units()
433
434 - def execute_action(self, actionName, unit):
435 if actionName[0] == "B": 436 if actionName[1:] == "CPU": #build CPU 437 for a in self.visibleASes: 438 if self.map.AS[a].cores: 439 k, core = self.map.AS[a].cores.popitem() 440 self.map.AS[a].usedCores[k] = core 441 self.server_build_unit(actionName[1:],core.vid, unit) 442 break 443 else: 444 self.server_build_unit(actionName[1:], unit.curVertex.vid, unit) 445 elif actionName[0] == "T": 446 self.server_build_unit(actionName[1:], unit.curVertex.vid, None) 447 elif actionName == "DEL": 448 self.server_remove_unit(unit) 449 elif actionName[0] == "R": 450 self.perform_research(actionName, unit) 451 elif actionName == "Ping": 452 unit.ping(self.server_remove_unit) 453 elif actionName == "UPingOfDeath": 454 self.upgrade_unit(unit,actionName[1:]) 455 elif actionName == "UNMap": 456 self.upgrade_unit(unit,actionName[1:]) 457 elif actionName == "USinkhole": 458 self.upgrade_unit(unit,actionName[1:]) 459 elif actionName == "Shake": 460 self.curAction = "Shake" 461 self.selectedUnits = [unit] 462 elif actionName == "Attack" or actionName == "Decimate" or actionName == "Inject": 463 self.curAction = "Attack" 464 self.selectedUnits = [unit] 465 elif actionName == "Decrypt": 466 self.upgrade_unit(unit,unit.originalType)
467 468 ''' 469 Methods responding to local/network events 470 ''' 471
472 - def update_location(self, unit, position, vertex=None):
473 474 unit.curVertex = vertex 475 if vertex.vid == unit.destVertex.vid: # if same, use set_trans_troop instead 476 slot = vertex.add_troop(unit) 477 # final position 478 if slot: 479 action = MoveTo(slot.position, 0.2) 480 action += CallFuncS(self._update_cshape, slot.position) 481 action += CallFuncS(self.cm.add) 482 unit.do(action)
483 484
485 - def build_unit(self, tid, owner, vid=-1, uid=-1,onInit=False):
486 # print "in client build unit" 487 curVertex = self.map.get_vertex(vid) 488 newUnit = self.build_unit_common(tid, owner, curVertex, uid=uid,onInit=onInit) 489 if newUnit: 490 if not onInit and newUnit.buildTime != 0: 491 owner.underConstruction[newUnit.uid] = newUnit 492 newUnit.update_opacity(math.floor(curVertex.visibilityState) * UNIT_STARTING_OPACITY) 493 return newUnit
494
495 - def remove_unit(self, unit):
496 self.remove_unit_common(unit)
497
498 - def perform_research(self,researchName,researchFactory):
499 utils.play_sound("Clock.wav") 500 researchType = RESEARCH[researchName] 501 researchType.on_start(self.player) 502 action = Delay(researchType.buildTime) 503 action += CallFunc(self.finish_research,researchType,self.player,None) 504 self.do(action)
505
506 - def finish_research(self, newResearch,owner,researchFactory):
507 newResearch.on_completion(owner) 508 ''' 509 #DEPRECATED 510 owner.completedResearch *= newResearch.uid 511 for s in self.map.availResearch: 512 research = RESEARCH[s] 513 if (owner.completedResearch % research.dependencies) == 0 and (owner.completedResearch % research.uid != 0) and (s not in owner.availableResearch): 514 # first cond ensures we have met dependencies 515 # second cond ensures we haven't done the research already 516 owner.availableResearch.append(s) 517 '''
518
519 - def move_unit(self, unit, path):
520 dest = self.map.vertices[str(path[-1])] 521 if dest != unit.destVertex: #if this gets called after update location 522 unit.curVertex.remove_troop(unit) 523 unit.destVertex = dest 524 self.cm.remove_tricky(unit) 525 526 # first vertex 527 if unit.pid == self.pid: 528 utils.play_sound("Move.wav") 529 action = MoveTo(unit.curVertex.position, 0.2) 530 531 # intermediate vertices 532 for i in range(1, len(path)): 533 vertex = self.map.vertices[str(path[i])] 534 action += MoveTo(vertex.position, 1 / unit.speed) 535 unit.do(action)
536
537 - def _update_cshape(self, unit, position):
538 unit.cshape.center = position
539
540 - def _set_focus_to_unit(self, unit):
541 self.scroller.set_focus(unit.position[0] - WINDOW_WIDTH / 2, unit.position[1] - WINDOW_HEIGHT / 2)
542 543 ''' 544 Twisted client methods 545 ''' 546
547 - def connect_end_point(self):
548 from twisted.internet import reactor 549 endpoint = TCP4ClientEndpoint(reactor, SERVER_IP, 8750) 550 factory = ClientNoteFactory() 551 return endpoint.connect(factory)
552
553 - def upgrade_unit(self,oldUnit,newType):
554 curVertex = oldUnit.curVertex 555 owner = self.players[oldUnit.pid] 556 self.server_remove_unit(oldUnit) 557 self.server_build_unit(newType,curVertex.vid,None)
558
559 - def server_attack_unit(self,attacker,target):
560 # print "server_attack_unit", attacker, target 561 d = self.connect_end_point() 562 def c(ampProto): 563 if type(target) == Vertex: 564 return ampProto.callRemote(AttackAnimation, pid=attacker.pid,uid=attacker.uid,tpid=int(target.vid),tuid=-1,path=[]) 565 else: 566 return ampProto.callRemote(AttackAnimation, pid=attacker.pid,uid=attacker.uid,tpid=target.pid,tuid=target.uid,path=[])
567 568 d.addCallback(c) 569 d.addErrback(err) 570 reactor.callLater(10, d.cancel)
571 572
573 - def server_build_unit(self, unitName, vid,builder):
574 d = self.connect_end_point() 575 def c(ampProto): 576 if builder: 577 u = int(builder.uid) 578 return ampProto.callRemote(BuildUnit, pid=self.pid, tid=unitName, vid=vid, uid=-1,buid=u) 579 else: 580 return ampProto.callRemote(BuildUnit, pid=self.pid, tid=unitName, vid=vid, uid=-1,buid=-1)
581 d.addCallback(c) 582 d.addErrback(err) 583 reactor.callLater(10, d.cancel) 584
585 - def server_remove_unit(self, unit):
586 d = self.connect_end_point() 587 588 def c(ampProto): 589 return ampProto.callRemote(RemoveUnit, pid=unit.pid, uid=unit.uid)
590 d.addCallback(c) 591 d.addErrback(err) 592 reactor.callLater(10, d.cancel) 593
594 - def server_move_troop(self, uid, vid):
595 # add the destination to troop.destVertex, to be used in update location 596 d = self.connect_end_point() 597 598 def c(ampProto): 599 return ampProto.callRemote(MoveTroop, pid=self.pid, uid=uid, vid=vid, path=[])
600 d.addCallback(c) 601 d.addErrback(err) 602 reactor.callLater(10, d.cancel) 603 604
605 - def server_connect(self):
606 if self.ip: 607 return False 608 self.ip = str(utils.get_ip()) 609 if (not self.ip) or self.ip == SERVER_IP or self.connectedToServer: 610 print "no connection to the network" 611 return False 612 d = self.connect_end_point() 613 def c(ampProto): 614 return ampProto.callRemote(Connect, ip=self.ip)
615 d.addCallback(c) 616 d.addErrback(err) 617 reactor.callLater(10, d.cancel) 618 619 620 def connected_server(args): 621 pid = args['id'] 622 otherPids = args['cur'] 623 mapName = args['map'] 624 # callback for after connection, arg:pid of self and server 625 if pid != -1: # check no error 626 print "my pid is ", pid 627 self.pid = pid 628 self.playerList = otherPids 629 self.map = self._init_map_and_cm(mapName) 630 else: 631 print "Connected server but can't play game, map is full or game already started" 632 d.addCallback(connected_server) 633 d.addErrback(err) 634 reactor.callLater(10, d.cancel) 635 636 return True 637 638 ''' 639 Helper methods 640 ''' 641
642 - def remove_unit_common(self, unit):
643 p = self.players[unit.pid] 644 p.units.pop(unit.uid) 645 if issubclass(type(unit), Building): 646 unit.curVertex.remove_building() 647 else: 648 unit.curVertex.remove_troop(unit) 649 self.map.remove(unit) 650 if unit.pid == self.pid and unit in self.cm.known_objs(): 651 self.cm.remove_tricky(unit) 652 unit.isRemoved = True 653 if len(p.units) <= 0: 654 if p.pid == self.pid: 655 self.end_game(False) 656 else: 657 self.end_game(True)
658
659 - def build_unit_common(self, tid, owner, curVertex=None, uid=-1, builder=None, onInit=False):
660 # print "build unit common", tid, owner.pid 661 #check for valid conditions 662 if owner.idleCPUs or tid == "CPU": 663 #create the unit 664 unitType = eval(tid) 665 newUnit = unitType(curVertex, pid=owner.pid) 666 667 #no empty slot 668 if newUnit.slotIndex == -1: 669 print "vertex full" 670 if newUnit.pid == self.pid: 671 utils.play_sound("error.wav") 672 return None 673 674 #add to map and set uid 675 newUnit.add_to_map(self.map) 676 uid = owner.set_unit_uid(newUnit, uid) 677 678 #tutorial 679 if newUnit.pid == self.pid: 680 self.dispatch_event("player_add_unit", tid) 681 682 if newUnit.buildTime == 0 or onInit: #instentaneous upgrade to encrypted 683 newUnit.health = newUnit.maxHealth 684 self._complete_build(newUnit, owner, newUnit.uid,onInit=onInit) 685 686 #start building unit and tell client 687 if not onInit: 688 if tid != "CPU": 689 self.start_cpu(newUnit, owner, builder) 690 elif builder: 691 self.remove_unit(builder) 692 if owner == self.player: 693 utils.play_sound("Clock.wav") 694 695 # set visibility 696 if type(curVertex) == Vertex and owner.pid == self.pid: 697 self._show_as(curVertex.asID) 698 699 return newUnit 700 701 print "no idle CPU" 702 if owner.pid == self.pid and not onInit: 703 utils.play_sound("error.wav") 704 return None
705
706 - def _select_units(self, units):
707 for unit in units: 708 if issubclass(type(unit), Unit) and unit.pid == self.pid: 709 utils.play_sound("click_troop.wav") 710 unit.set_is_selected(True, self.map, self.cm, self.player) 711 self.selectedUnits.append(unit)
712
713 - def _deselect_all_units(self):
714 for unit in self.selectedUnits: 715 unit.set_is_selected(False, self.map, self.cm, self.player) 716 self.selectedUnits = []
717
718 - def _show_as(self, ASid):
719 if ASid not in self.visibleASes: 720 self.visibleASes.add(ASid) 721 for v in self.map.AS[ASid].vertices.values(): 722 v._update_visibility() 723 self.cm.add(v) 724 for v in self.map.AS[ASid].cores.values(): 725 v._update_visibility() 726 for v in self.map.AS[ASid].usedCores.values(): 727 v._update_visibility()
728
729 - def start_cpu(self, newUnit, owner, builder):
730 pass
731
732 - def start_server(self): #start the server on the server/client side
733 if self.serverStarted: 734 return False 735 if type(self) != ClientController: 736 pf = ClientNoteFactory() 737 else: 738 pf = ServerNoteFactory() 739 740 from twisted.internet import reactor 741 endpoint = TCP4ServerEndpoint(reactor, 8750) 742 d = endpoint.listen(pf) 743 def c(port): 744 self.endpoint = port 745 d.addCallback(c) 746 d.addErrback(err) 747 print "started server" 748 self.serverStarted = True 749 return True 750 751
752 - def _init_players(self):
753 self.map.pid = self.pid 754 self.map.draw_map() 755 756 # init human player 757 for pid in self.playerList: 758 self.players[pid] = Player(pid) 759 self.players[self.pid] = Player(self.pid) 760 self.player = self.players[self.pid] # convenience 761 762 763 for pid in self.map.AIPlayers: 764 self.players[pid] = ComputerPlayer(pid) 765 766 for p in self.players.keys(): 767 self.init_units(p) 768 ai = self.players[p] 769 if type(ai) == ComputerPlayer and type(self)!= ClientController: 770 # Yasin's note: This is where the AI gets commented out. Note: Do. Not. Mess. With. This. 771 # Any. More. Thanks. 772 if not self.tutorial: 773 self.schedule_interval(ai.ai_loop, 1) 774 pass
775 # DEBUG 776 # print "finish init players" 777 778 #DEPRECATED, see the research class
779 - def init_research(self, pid):
780 p = self.players[pid] 781 # add starting research 782 for r in self.map.startingResearch[pid]: 783 p.completedResearch *= RESEARCH[r].uid 784 # add available research 785 for r in self.map.availResearch: 786 if p.completedResearch % RESEARCH[r].dependencies == 0: 787 p.availableResearch.append(r)
788
789 - def init_units(self, pid):
790 # add starting units 791 p = self.players[pid] 792 focus = None 793 for vid in reversed(sorted(self.map.startingUnits[pid])): #ensures CPU built first 794 for t in self.map.startingUnits[pid][vid]: 795 newUnit = self.build_unit(t, p, vid=vid, onInit=True) 796 if t == "Server" and pid == self.pid: 797 focus = newUnit.position 798 if t == "CPU": 799 c = self.map.AS[newUnit.curVertex.asID].cores.pop(vid) 800 self.map.AS[newUnit.curVertex.asID].usedCores[vid] = c 801 if focus: 802 self.scroller.set_focus(focus[0] - WINDOW_WIDTH / 2, focus[1] - WINDOW_HEIGHT / 2)
803
804 - def start_game(self):
805 g = cocos.scene.Scene(self.map, self) 806 g.add(ImageLayer(os.path.join("images", "backgrounds", "notebook-paper.png")), z=BACKGROUND_Z) 807 self.connectedToServer = True 808 cocos.director.director.push(g)
809 810 # add unit to cm, player's units and set visibility
811 - def _complete_build(self, unit, p, uid,onInit=False):
812 if unit.health >= unit.maxHealth: 813 unit.health = unit.maxHealth 814 self.cm.add(unit) 815 if unit.buildTime != 0 and not onInit: 816 del p.underConstruction[uid] 817 if type(unit) == CPU: 818 p.idleCPUs.append(unit) 819 else: 820 p.units[uid] = unit 821 unit.on_completion() # gets called when a unit is built 822 unit.update_opacity(((float(unit.health) / unit.maxHealth) * ( 823 255 - UNIT_STARTING_OPACITY) + UNIT_STARTING_OPACITY) * math.floor(unit.curVertex.visibilityState))
824 825 826 ClientController.register_event_type("click_on_move") 827 ClientController.register_event_type("click_on_action") 828 ClientController.register_event_type('player_unit_attack') 829 ClientController.register_event_type('player_add_unit') 830