Views/GameView.m

00001 //
00002 //  GameView.m
00003 //  MacTrek
00004 //
00005 //  Created by Aqua on 02/06/2006.
00006 //  Copyright 2006 Luky Soft. All rights reserved.
00007 //
00008 
00009 #import "GameView.h"
00010 
00011 
00012 @implementation GameView
00013 
00014 - (void) awakeFromNib {
00015     
00016     [super awakeFromNib];
00017     
00018     step = GV_SCALE_STEP;
00019     keyMap = nil;
00020     scale = 40; // default
00021     trigonometry = [LLTrigonometry defaultInstance];
00022 
00023     angleConvertor = [[Entity alloc] init];
00024     busyDrawing = NO;
00025     
00026     inputMode = GV_NORMAL_MODE;
00027 }
00028 
00029 - (void) setPainter:(PainterFactory*)newPainter {
00030     painter = newPainter;
00031     // reset inputMode too
00032     inputMode = GV_NORMAL_MODE;
00033 }
00034 
00035 - (NSPoint) gamePointRepresentingCentreOfView {
00036     return [[universe playerThatIsMe] predictedPosition];
00037 }
00038 
00039 - (void) setScaleFullView {
00040     NSSize viewSize = [self bounds].size;
00041     
00042     int minSize = (viewSize.height < viewSize.width ? viewSize.height : viewSize.width);
00043     
00044     // minSize must cover UNIVERSE_PIXEL_SIZE thus zoom is
00045     scale = UNIVERSE_PIXEL_SIZE / minSize;
00046 }
00047 
00048 - (void) setScale:(int)newScale {
00049     scale = newScale;
00050 }
00051 
00052 - (int) scale {
00053     return scale;
00054 }
00055 
00056 // draw the view
00057 - (void)drawRect:(NSRect)aRect {
00058     
00059     // sometimes the drawing takes so long the timer invokes another go
00060     // maybe should use locks..
00061     if (busyDrawing) {
00062         NSLog(@"GameView.drawRect busy drawing");
00063         return;
00064     }    
00065     busyDrawing = YES;
00066     
00067     // during this draw i want to lock universal access (try for half a framerate)
00068     if ([[universe synchronizeAccess] lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:MAX_WAIT_BEFORE_DRAW]]) { 
00069         
00070         // first set up the gamebounds based on my position
00071         NSRect gameBounds = [painter gameRectAround:[self gamePointRepresentingCentreOfView]
00072                                             forView:[self bounds]
00073                                           withScale:scale]; 
00074         // then draw it        
00075         [painter drawRect:aRect 
00076              ofViewBounds:[self bounds] 
00077 whichRepresentsGameBounds:gameBounds
00078                 withScale:scale]; 
00079         
00080         [[universe synchronizeAccess] unlock];
00081     } else {
00082         NSLog(@"GameView.drawRect waited %f seconds for lock, discarding", MAX_WAIT_BEFORE_DRAW);
00083         
00084         // first set up the gamebounds based on my position
00085         NSRect gameBounds = [painter gameRectAround:[self gamePointRepresentingCentreOfView]
00086                                             forView:[self bounds]
00087                                           withScale:scale]; 
00088         // then draw it        
00089         [painter drawRect:aRect 
00090              ofViewBounds:[self bounds] 
00091 whichRepresentsGameBounds:gameBounds
00092                 withScale:scale]; 
00093         
00094         // no lock obtained, so no need to unlock
00095     }
00096     busyDrawing = NO;
00097 }
00098 
00099 - (void) setKeyMap:(MTKeyMap *)newKeyMap {
00100     keyMap = newKeyMap;
00101 }
00102 
00103 // view functions
00104 - (void) keyDown:(NSEvent *)theEvent {
00105     
00106     if (keyMap == nil) {
00107         NSLog(@"GameView.keyDown have no keymap");
00108         [super keyDown:theEvent];
00109         return;
00110     }
00111     
00112     switch (inputMode) {
00113     case GV_NORMAL_MODE:
00114         NSLog(@"GameView.keyDown handle in normal mode");
00115         [self normalModeKeyDown:theEvent];
00116         break;
00117     case GV_MESSAGE_MODE:
00118         NSLog(@"GameView.keyDown handle in message mode");
00119         [self messageModeKeyDown:theEvent];
00120         break;
00121     case GV_MACRO_MODE:
00122         NSLog(@"GameView.keyDown handle in macro mode");
00123         [self macroModeKeyDown:theEvent];
00124         break;
00125     case GV_REFIT_MODE:
00126         NSLog(@"GameView.keyDown handle in refit mode");
00127         [self refitModeKeyDown:theEvent];
00128         break;
00129     default:
00130         NSLog(@"GameView.keyDown unknown mode %d", inputMode);
00131         // reset
00132         inputMode = GV_NORMAL_MODE;
00133         break;
00134     }    
00135 }
00136 
00137 - (void) normalModeKeyDown:(NSEvent *)theEvent  {
00138     
00139     // check all characters in the event
00140     NSString *characters = [theEvent characters];
00141     
00142     for (int i = 0; i < [characters length]; i++) {
00143         unichar theChar = [characters characterAtIndex:i];
00144         unsigned int modifierFlags = [theEvent modifierFlags];
00145         
00146         int action = [keyMap actionForKey:theChar withModifierFlags:modifierFlags];
00147         
00148         // only valid keys
00149         if (action == ACTION_UNKNOWN) {
00150             [super keyDown:theEvent];
00151         }
00152         else {
00153             if ([self performAction: action] == NO) {
00154                 [super keyDown:theEvent];
00155             }
00156         }        
00157     }  
00158 }
00159 
00160 - (void) messageModeKeyDown:(NSEvent *)theEvent {
00161     
00162     // always reset
00163     inputMode = GV_NORMAL_MODE;
00164     
00165     // fish for [A|G|T|F|K|O|R|0..f] 
00166     // create address and send the event
00167     
00168     // going for the first char only
00169     unichar theChar = [[theEvent characters] characterAtIndex:0];
00170     int playerId = -1;    
00171     
00172     switch (theChar) {
00173     case 'A':
00174     //case 'a': // could also be player a
00175         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"ALL"];
00176         return;
00177         break;
00178     case 'G':
00179     case 'g':
00180         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"GOD"];
00181         return;
00182         break;
00183     case 'T':
00184     case 't':
00185         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"TEAM"];
00186         return;
00187         break;
00188     case 'F':
00189     //case'f': // could also be player f
00190         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"FED"];
00191         return;
00192         break;
00193     case 'K':
00194     case 'k':
00195         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"KLI"];
00196         return;
00197         break;
00198     case 'R':
00199     case 'r':
00200         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"ROM"];
00201         return;
00202         break;
00203     case 'O':
00204     case 'o':
00205         [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" userInfo:@"ORI"];
00206         return;
00207         break;
00208     case '0':
00209     case '1':
00210     case '2':
00211     case '3':
00212     case '4':
00213     case '5':
00214     case '6':
00215     case '7':
00216     case '8':
00217     case '9':
00218         playerId = theChar - '0';
00219         break;
00220     case 'a':
00221     case 'b':
00222     case 'c':
00223     case 'd':
00224     case 'e':
00225     case 'f':
00226         playerId = theChar - 'a' + 10;
00227         break;
00228     default:    // should be GV_ but lets limmit the nr of observers
00229         [notificationCenter postNotificationName:@"PM_WARNING" userInfo:@"Unknown player. message not sent."]; 
00230         return;
00231         break;
00232     }
00233     [notificationCenter postNotificationName:@"GV_MESSAGE_DEST" 
00234                                     userInfo:[[universe playerWithId:playerId] mapChars]];
00235 }
00236 
00237 - (void) macroModeKeyDown:(NSEvent *)theEvent {
00238     // $$ should do something here
00239     NSLog(@"GameView.macroModeKeyDown not implemented");
00240     // reset
00241     inputMode = GV_NORMAL_MODE;
00242 }
00243 
00244 - (void) refitModeKeyDown:(NSEvent *)theEvent {
00245     // always reset
00246     inputMode = GV_NORMAL_MODE;   
00247     
00248     // going for the first char only
00249     unichar theChar = [[theEvent characters] characterAtIndex:0];
00250     
00251     char ship_type = SHIP_CA;
00252     switch(theChar) {
00253                 case 's' : case 'S' :
00254                         ship_type = SHIP_SC;                    
00255                         break;
00256                 case 'd' : case 'D' :
00257                         ship_type = SHIP_DD;
00258                         break;
00259                 case 'c' : case 'C' :
00260                         ship_type = SHIP_CA;
00261                         break;
00262                 case 'b' : case 'B' :
00263                         ship_type = SHIP_BB;
00264                         break;
00265                 case 'g' : case 'G' :
00266                         ship_type = SHIP_GA;
00267                         break;
00268                 case 'o' : case 'O' :
00269                         ship_type = SHIP_SB;
00270                         break;
00271                 case 'a' : case 'A' :
00272                         ship_type = SHIP_AS;
00273                         break;
00274                 default :
00275                         return;
00276     }
00277     [notificationCenter postNotificationName:@"COMM_SEND_REFIT_REQ" userInfo:[NSNumber numberWithChar:ship_type]];    
00278 }
00279 
00280 // mouse events $$ currently static allocated
00281 - (void) mouseDown:(NSEvent *)theEvent {
00282     [self performAction:ACTION_FIRE_TORPEDO];
00283 }
00284 
00285 - (void) otherMouseDown:(NSEvent *)theEvent {
00286     [self performAction:ACTION_FIRE_PHASER];
00287 }
00288 
00289 - (void) dummyMouseAction {
00290     
00291     // must become the first responder,
00292     // or a arbitrary view crashes...
00293     [[self window] makeKeyWindow];
00294     [self becomeFirstResponder];
00295    
00296     NSEvent *evt = [NSEvent mouseEventWithType:NSRightMouseDown 
00297                                       location:[painter centreOfRect:[self bounds]]
00298                                  modifierFlags:256 
00299                                      timestamp:GetCurrentEventTime()
00300                                   windowNumber:[[self window] windowNumber]
00301                                        context:[NSGraphicsContext currentContext] 
00302                                    eventNumber:0 
00303                                     clickCount:1 
00304                                       pressure:0];
00305     
00306     [[NSApplication sharedApplication] postEvent:evt atStart:YES];
00307 }
00308 
00309 - (void) rightMouseDown:(NSEvent *)theEvent {
00310     
00311     [self performAction:ACTION_SET_COURSE];
00312 }
00313 
00314 - (void) scrollWheel:(NSEvent *)theEvent {
00315     float mouseRole = [theEvent deltaY];
00316     // 1.0 means zoom in
00317     // -1.0 means zoom out
00318     if (mouseRole > 0) {
00319         // zoom in means smaller scale factor
00320         int newScale = scale - step*scale;
00321         if (newScale == scale) {
00322             newScale = scale - 1; // at least 1
00323         }
00324         // if scale is small it may not be possible to zoom in
00325         // scale*step = 0;
00326         if (newScale > [painter minScale]) {
00327             scale = newScale; 
00328         }
00329     } else {
00330         // zoom out means larger factor
00331         // if scale is small it may not be possible to zoom out
00332         // scale*step = 0 this means you'll stay zoomed in
00333         int newScale = scale + step*scale;
00334         if (newScale == scale) {
00335             newScale = scale + 1; // at least 1
00336         }
00337         if (newScale < [painter maxScale]) {
00338             scale = newScale;
00339         }
00340     }
00341     NSLog(@"GameView.scrollWheel setting scale to %d", scale);
00342 }
00343 
00344 
00345 - (void) sendSpeedReq:(int)speed {
00346     if (universe == nil) {
00347         NSLog(@"GameView.sendSpeedReq have no universe?");
00348     }
00349     
00350     int maxSpeed = [[[universe playerThatIsMe] ship] maxSpeed];   
00351     if (speed > maxSpeed) {
00352         speed = maxSpeed;
00353     }
00354     
00355     [[universe playerThatIsMe] setRequestedSpeed:speed]; // store here so we can track accelertaion in the future
00356     [notificationCenter postNotificationName:@"COMM_SEND_SPEED_REQ" userInfo:[NSNumber numberWithInt:speed]];
00357 }
00358 
00359 - (float) mouseDir {
00360 
00361     NSPoint mouseLocation = [self mousePos];
00362     
00363     // we are at the center
00364     NSPoint ourLocation;
00365     NSRect bounds = [self bounds];
00366     ourLocation.x = bounds.size.width / 2;
00367     ourLocation.y = bounds.size.height / 2;
00368     
00369     // the direction is
00370     float dir = [trigonometry angleDegBetween:mouseLocation andPoint:ourLocation];
00371     dir -= 90;  // north is 0 deg
00372     if (dir < 0) {
00373         dir += 360;
00374     }
00375     //NSLog(@"GameView.mouseDir = %f", dir);
00376     
00377     return dir;
00378 }
00379 
00380 // $$ may need locks here if the code becomes multi threaded
00381 - (bool) performAction:(int) action {
00382     
00383     //NSLog(@"GameView.performAction performing action %d", action);
00384     
00385     int maxSpeed, speed;
00386     Player *target = nil;
00387     Planet *planet = nil;
00388     NSPoint targetGamePoint;
00389     Player *me = [universe playerThatIsMe];    // IS used sometimes, compiler just complains..
00390     
00391     switch (action) {
00392         case ACTION_UNKNOWN:
00393             NSLog(@"GameView.performAction unknown action %d", action);
00394             return NO;
00395             break;
00396             case ACTION_CLOAK:
00397             if ([[universe playerThatIsMe] flags] & PLAYER_CLOAK) {
00398                 [notificationCenter postNotificationName:@"COMM_SEND_CLOAK_REQ" userInfo:[NSNumber numberWithBool:NO]];                
00399             } else {
00400                 [notificationCenter postNotificationName:@"COMM_SEND_CLOAK_REQ" userInfo:[NSNumber numberWithBool:YES]];
00401             }
00402             break;
00403             case ACTION_DET_ENEMY:
00404             // $$ JTrek checks if current time - last det time > 100 ms before sending this again
00405             // sounds sensible...
00406             [notificationCenter postNotificationName:@"COMM_SEND_DETONATE_REQ" userInfo:nil];
00407             break;
00408             case ACTION_DET_OWN: // detting ALL
00409             [notificationCenter postNotificationName:@"COMM_SEND_DET_MINE_ALL_REQ" userInfo:nil];
00410             break;
00411             case ACTION_FIRE_PLASMA:
00412             // $$ we can check if we are able to fire plasmas at all before poluting the network
00413             [angleConvertor setCourse:[self mouseDir]];            
00414             [notificationCenter postNotificationName:@"COMM_SEND_PLASMA_REQ" userInfo:[NSNumber numberWithChar:[angleConvertor netrekFormatCourse]]];
00415             break;
00416             case ACTION_FIRE_TORPEDO:
00417             [angleConvertor setCourse:[self mouseDir]];            
00418             [notificationCenter postNotificationName:@"COMM_SEND_TORPS_REQ" userInfo:[NSNumber numberWithChar:[angleConvertor netrekFormatCourse]]];
00419             break;
00420             case ACTION_FIRE_PHASER:
00421             [angleConvertor setCourse:[self mouseDir]];            
00422             [notificationCenter postNotificationName:@"COMM_SEND_PHASER_REQ" userInfo:[NSNumber numberWithChar:[angleConvertor netrekFormatCourse]]];
00423             break;
00424             case ACTION_SHIELDS:
00425             if ([me flags] & PLAYER_SHIELD) {
00426                 [notificationCenter postNotificationName:@"COMM_SEND_SHIELD_REQ" userInfo:[NSNumber numberWithBool:NO]];                
00427             } else {
00428                 [notificationCenter postNotificationName:@"COMM_SEND_SHIELD_REQ" userInfo:[NSNumber numberWithBool:YES]];
00429             }
00430             break;
00431             case ACTION_TRACTOR:
00432             // convert the mouse pointer to a point in the game grid
00433             targetGamePoint = [painter gamePointFromViewPoint:[self mousePos] 
00434                                                      viewRect:[self bounds]
00435                                         gamePosInCentreOfView:[self gamePointRepresentingCentreOfView] 
00436                                                     withScale:scale];
00437             // find the nearest player
00438             target = [universe playerNearPosition:targetGamePoint ofType:UNIVERSE_TARG_PLAYER];
00439             
00440             // if we are already tracktoring/pressoring, disable
00441             if ([[universe playerThatIsMe] flags] & PLAYER_TRACT) {
00442                 // $$ it is probaly not needed to figure out the correct playerId..
00443                 [notificationCenter postNotificationName:@"COMM_SEND_TRACTOR_OFF_REQ" 
00444                                                 userInfo:[NSNumber numberWithInt:[target playerId]]];
00445             } else {
00446                 [notificationCenter postNotificationName:@"COMM_SEND_TRACTOR_ON_REQ" 
00447                                                 userInfo:[NSNumber numberWithInt:[target playerId]]];
00448                 [[universe playerThatIsMe] setTractorTarget:target];
00449             }
00450                 break;
00451             case ACTION_PRESSOR:
00452             // convert the mouse pointer to a point in the game grid
00453             targetGamePoint = [painter gamePointFromViewPoint:[self mousePos] 
00454                                                      viewRect:[self bounds]
00455                                         gamePosInCentreOfView:[self gamePointRepresentingCentreOfView] 
00456                                                     withScale:scale];
00457             // find the nearest player
00458             target = [universe playerNearPosition:targetGamePoint ofType:UNIVERSE_TARG_PLAYER];
00459             
00460             // if we are already tracktoring/pressoring, disable
00461             if ([[universe playerThatIsMe] flags] & PLAYER_PRESS) {
00462                 // $$ it is probaly not needed to figure out the correct playerId..
00463                 [notificationCenter postNotificationName:@"COMM_SEND_REPRESSOR_OFF_REQ" 
00464                                                 userInfo:[NSNumber numberWithInt:[target playerId]]];
00465             } else {
00466                 [notificationCenter postNotificationName:@"COMM_SEND_REPRESSOR_ON_REQ" 
00467                                                 userInfo:[NSNumber numberWithInt:[target playerId]]];
00468                 // $$ bit strange, but i assume we cannot pressor one target and tractor another at
00469                 // the same time
00470                 [[universe playerThatIsMe] setTractorTarget:target];
00471             }
00472             break;
00473         case ACTION_WARP_0:  
00474             [self sendSpeedReq:0];
00475             break;
00476             case ACTION_WARP_1:
00477             [self sendSpeedReq:1];
00478             break;
00479             case ACTION_WARP_2:
00480             [self sendSpeedReq:2];
00481             break;
00482             case ACTION_WARP_3:
00483             [self sendSpeedReq:3];
00484             break;
00485         case ACTION_WARP_4:
00486             [self sendSpeedReq:4];
00487             break;
00488         case ACTION_WARP_5:
00489             [self sendSpeedReq:5];
00490             break;
00491         case ACTION_WARP_6:
00492             [self sendSpeedReq:6];
00493             break;
00494         case ACTION_WARP_7:
00495             [self sendSpeedReq:7];
00496             break;
00497         case ACTION_WARP_8:
00498             [self sendSpeedReq:8];
00499             break;
00500         case ACTION_WARP_9:
00501             [self sendSpeedReq:9];
00502             break;
00503         case ACTION_WARP_10:
00504             [self sendSpeedReq:10];
00505             break;
00506         case ACTION_WARP_11:
00507             [self sendSpeedReq:11];
00508             break;
00509         case ACTION_WARP_12:
00510             [self sendSpeedReq:0];
00511             break;
00512         case ACTION_WARP_MAX:
00513             maxSpeed = [[[universe playerThatIsMe] ship] maxSpeed];
00514             [self sendSpeedReq:maxSpeed];
00515             break;
00516         case ACTION_WARP_HALF_MAX:
00517             maxSpeed = [[[universe playerThatIsMe] ship] maxSpeed];
00518             [self sendSpeedReq:maxSpeed / 2];
00519             break;
00520         case ACTION_WARP_INCREASE:
00521             speed = [[universe playerThatIsMe] speed];
00522             [self sendSpeedReq:speed + 1];
00523             break;
00524         case ACTION_WARP_DECREASE:
00525             speed = [[universe playerThatIsMe] speed];
00526             [self sendSpeedReq:speed - 1];
00527             break;
00528         case ACTION_SET_COURSE:
00529             [angleConvertor setCourse:[self mouseDir]];            
00530             [notificationCenter postNotificationName:@"COMM_SEND_DIR_REQ" userInfo:[NSNumber numberWithChar:[angleConvertor netrekFormatCourse]]];
00531             // remove the planet lock
00532             [me setFlags:[me flags] & ~(PLAYER_PLOCK | PLAYER_PLLOCK)];
00533             break;
00534         case ACTION_LOCK:
00535             // convert the mouse pointer to a point in the game grid
00536             targetGamePoint = [painter gamePointFromViewPoint:[self mousePos] 
00537                                                      viewRect:[self bounds]
00538                                         gamePosInCentreOfView:[self gamePointRepresentingCentreOfView] 
00539                                                     withScale:scale];
00540             // find the nearest player
00541             target = [universe playerNearPosition:targetGamePoint ofType:UNIVERSE_TARG_PLAYER];
00542             // find the nearest planet
00543             planet = [universe planetNearPosition:targetGamePoint];
00544             // lock on the closest
00545             if ([universe entity:target closerToPos:targetGamePoint than:planet]) {
00546                 // lock on player
00547                 [notificationCenter postNotificationName:@"COMM_SEND_PLAYER_LOCK_REQ" 
00548                                                 userInfo:[NSNumber numberWithInt:[target playerId]]];
00549                 [me setPlayerLock:target];
00550             } else {
00551                 // lock on planet
00552                 [notificationCenter postNotificationName:@"COMM_SEND_PLANET_LOCK_REQ" 
00553                                                 userInfo:[NSNumber numberWithInt:[planet planetId]]];
00554                 [me setPlanetLock:planet];
00555             }
00556             break;
00557         case ACTION_PRACTICE_BOT:
00558             [notificationCenter postNotificationName:@"COMM_SEND_PRACTICE_REQ"];
00559             break;
00560         case ACTION_TRANSWARP:
00561             // netrek uses the same message for this, it could lead to very
00562             // funny results now we seperate it.
00563             [notificationCenter postNotificationName:@"COMM_SEND_PRACTICE_REQ"];
00564             break;
00565         case ACTION_BOMB:
00566             if (([me flags] & PLAYER_BOMB) == 0) { // already bombing?
00567                 [notificationCenter postNotificationName:@"COMM_SEND_BOMB_REQ" 
00568                                                 userInfo:[NSNumber numberWithBool:YES]];
00569             }
00570             break;
00571         case ACTION_ORBIT:
00572             [notificationCenter postNotificationName:@"COMM_SEND_ORBIT_REQ" 
00573                                             userInfo:[NSNumber numberWithBool:YES]];
00574             break;
00575         case ACTION_BEAM_DOWN:
00576             if (([me flags] & PLAYER_BEAMDOWN) == 0) { // already beaming?
00577                 [notificationCenter postNotificationName:@"COMM_SEND_BEAM_REQ" 
00578                                                 userInfo:[NSNumber numberWithBool:NO]]; // no means down
00579             }
00580             break;
00581         case ACTION_BEAM_UP:
00582             if (([me flags] & PLAYER_BEAMUP) == 0) { // already beaming?
00583                 [notificationCenter postNotificationName:@"COMM_SEND_BEAM_REQ" 
00584                                                 userInfo:[NSNumber numberWithBool:YES]]; // no means down
00585             }
00586             break;
00587         case ACTION_DISTRESS_CALL:
00588             NSLog(@"GameView.performAction Marcro's not implemented"); // $$ todo
00589             break;
00590         case ACTION_ARMIES_CARRIED_REPORT:
00591             NSLog(@"GameView.performAction Marcro's not implemented"); // $$ todo
00592             break;
00593         case ACTION_MESSAGE:
00594             //NSLog(@"GameView.performAction MESSAGE not implemented"); 
00595             // update warning
00596             [notificationCenter postNotificationName:@"GV_MODE_INFO" userInfo:@"A=all, [TFORK]=team, [0..f]=player"];
00597             inputMode = GV_MESSAGE_MODE;
00598             // next keystroke gets handled differently and will cause the 
00599             // destination to be set and may set the focus to input panel.
00600             break;
00601         case ACTION_DOCK_PERMISSION:
00602             if (([me flags] & PLAYER_DOCKOK) == 0) {  // toggle
00603                 [notificationCenter postNotificationName:@"COMM_SEND_DOCK_REQ" 
00604                                                 userInfo:[NSNumber numberWithBool:YES]]; 
00605             } else {
00606                 [notificationCenter postNotificationName:@"COMM_SEND_DOCK_REQ" 
00607                                                 userInfo:[NSNumber numberWithBool:NO]]; 
00608             }
00609             break;
00610         case ACTION_INFO:
00611             // convert the mouse pointer to a point in the game grid
00612             targetGamePoint = [painter gamePointFromViewPoint:[self mousePos] 
00613                                                      viewRect:[self bounds]
00614                                         gamePosInCentreOfView:[self gamePointRepresentingCentreOfView] 
00615                                                     withScale:scale];
00616             // find the nearest player
00617             target = [universe playerNearPosition:targetGamePoint ofType:(UNIVERSE_TARG_PLAYER | UNIVERSE_TARG_SELF)];
00618             // find the nearest planet
00619             planet = [universe planetNearPosition:targetGamePoint];
00620             // lock on the closest            
00621             if ([universe entity:target closerToPos:targetGamePoint than:planet]) {
00622                 // toggle info on player
00623                 [target setShowInfo:![target showInfo]];
00624             } else {
00625                 [planet setShowInfo:![planet showInfo]];
00626             }
00627             break;
00628         case ACTION_REFIT:
00629             //NSLog(@"GameView.performAction REFIT not implemented"); 
00630             // update warning
00631             [notificationCenter postNotificationName:@"GV_MODE_INFO" userInfo:@"s=scout, d=destroyer, c=cruiser, b=battleship, a=assault, g=galaxy, o=starbase"];
00632             inputMode = GV_REFIT_MODE;
00633             // next keystroke gets handled differently            
00634             break;
00635         case ACTION_REPAIR:
00636             // $$ no toggle ?
00637             [notificationCenter postNotificationName:@"COMM_SEND_REPAIR_REQ" 
00638                                             userInfo:[NSNumber numberWithBool:YES]];
00639             break;
00640         case ACTION_QUIT:
00641             // $$ how do we quit ? send BYE, reset some data and flip to the outfit
00642             // or go through state machine to main menu...
00643             break;
00644         case ACTION_HELP:
00645             NSLog(@"GameView.performAction HELP not implemented"); // $$ todo
00646         case ACTION_DEBUG:
00647             [painter setDebugLabels:![painter debugLabels]];
00648             break;
00649         default:
00650             NSLog(@"GameView.performAction unknown action %d", action);
00651             return NO;
00652             break;
00653     }
00654     return YES;
00655 }
00656 
00657 @end

Generated on Sat Aug 26 21:14:17 2006 for MacTrek by  doxygen 1.4.7