1 /* $Id: Player.cpp,v 1.55 2003/11/19 16:49:31 nan Exp $ */
2
3 // Copyright (C) 2000-2003 ���� �ȹ�(Kanna Yoshihiro)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 #include "ttinc.h"
20 #include "Player.h"
21 #include "Ball.h"
22 #include "BaseView.h"
23 #include "Control.h"
24 #include "Event.h"
25 #include "PenAttack.h"
26 #include "PenDrive.h"
27 #include "ShakeCut.h"
28 #include "comPenAttack.h"
29 #include "comPenDrive.h"
30 #include "comShakeCut.h"
31 #include "TrainingPenAttack.h"
32 #include "TrainingPenDrive.h"
33 #include "ComTrainingPenAttack.h"
34 #include "ComTrainingPenDrive.h"
35 #include "HitMark.h"
36 #include "PlayGame.h"
37 #include "Network.h"
38 #include "RCFile.h"
39 #ifdef LOGGING
40 #include "Logging.h"
41 #endif
42
43 extern RCFile *theRC;
44
45 extern Ball theBall;
46
47 extern long mode;
48
Player()49 Player::Player() {
50 m_side = 1;
51 m_playerType = PLAYER_PROTO;
52
53 m_x = 0;
54 m_y = -TABLELENGTH/2-0.2;
55 m_z = 1.4;
56 m_vx = m_vy = m_vz = 0.0;
57
58 m_status = 200;
59 m_swing = 0;
60 m_afterSwing = 0;
61 m_swingType = SWING_NORMAL;
62 m_swingError = SWING_PERFECT;
63 m_targetX = 0.0;
64 m_targetY = TABLELENGTH/16*5;
65
66 m_eyeX = 0.0;
67 m_eyeY = -1.0;
68 m_eyeZ = 0.2;
69
70 m_pow = 0;
71 m_spin = 0.0;
72
73 m_stamina = 80.0;
74
75 m_statusMax = 200;
76
77 m_lookAtX = 0.0;
78 m_lookAtY = TABLELENGTH/2*m_side;
79 m_lookAtZ = TABLEHEIGHT;
80
81 m_View = NULL;
82
83 m_lastSendX = m_lastSendY = m_lastSendZ = 0.0;
84 m_lastSendVX = m_lastSendVY = m_lastSendVZ = 0.0;
85 m_lastSendCount = 0;
86 }
87
Player(long side)88 Player::Player( long side ) {
89 m_playerType = PLAYER_PROTO;
90
91 m_x = 0;
92 m_y = -TABLELENGTH/2-0.2;
93 m_z = 1.4;
94 m_vx = m_vy = m_vz = 0.0;
95
96 m_status = 200;
97 m_swing = 0;
98 m_afterSwing = 0;
99 m_swingType = SWING_NORMAL;
100 m_swingError = SWING_PERFECT;
101 m_targetX = 0.0;
102 m_targetY = TABLELENGTH/16*5;
103
104 m_eyeX = 0.0;
105 m_eyeY = -1.0;
106 m_eyeZ = 0.2;
107
108 m_pow = 0;
109 m_spin = 0.0;
110
111 m_stamina = 80.0;
112
113 m_View = NULL;
114
115 m_side = side;
116 if ( side < 0 ) {
117 m_y = -m_y;
118 m_targetY = -m_targetY;
119 m_eyeY = -m_eyeY;
120 }
121
122 m_lookAtX = 0.0;
123 m_lookAtY = TABLELENGTH/2*m_side;
124 m_lookAtZ = TABLEHEIGHT;
125
126 m_lastSendX = m_lastSendY = m_lastSendZ = 0.0;
127 m_lastSendVX = m_lastSendVY = m_lastSendVZ = 0.0;
128 m_lastSendCount = 0;
129 }
130
Player(long playerType,long side,double x,double y,double z,double vx,double vy,double vz,long status,long swing,long swingType,bool swingSide,long afterSwing,long swingError,double targetX,double targetY,double eyeX,double eyeY,double eyeZ,long pow,double spin,double stamina,long statusMax)131 Player::Player( long playerType, long side, double x, double y, double z,
132 double vx, double vy, double vz,long status, long swing,
133 long swingType, bool swingSide, long afterSwing,
134 long swingError,
135 double targetX, double targetY, double eyeX, double eyeY,
136 double eyeZ, long pow, double spin, double stamina,
137 long statusMax ) {
138 m_side = side;
139 m_playerType = playerType;
140
141 m_x = x;
142 m_y = y;
143 m_z = z;
144 m_vx = vx;
145 m_vy = vy;
146 m_vz = vz;
147
148 m_status = status;
149 m_swing = swing;
150 m_afterSwing = afterSwing;
151 m_swingType = swingType;
152 m_swingSide = swingSide;
153 m_swingError = swingError;
154 m_targetX = targetX;
155 m_targetY = targetY;
156
157 m_eyeX = eyeX;
158 m_eyeY = eyeY;
159 m_eyeZ = eyeZ;
160
161 m_pow = pow;
162 m_spin = spin;
163
164 m_stamina = stamina;
165 m_statusMax = statusMax;
166
167 m_lookAtX = 0.0;
168 m_lookAtY = TABLELENGTH/2*m_side;
169 m_lookAtZ = TABLEHEIGHT;
170
171 m_View = NULL;
172
173 m_lastSendX = m_lastSendY = m_lastSendZ = 0.0;
174 m_lastSendVX = m_lastSendVY = m_lastSendVZ = 0.0;
175 m_lastSendCount = 0;
176 }
177
~Player()178 Player::~Player() {
179 if ( m_View ){
180 BaseView::TheView()->RemoveView( m_View );
181 delete m_View;
182 }
183 }
184
185 void
operator =(Player & p)186 Player::operator=(Player& p) {
187 m_playerType = p.m_playerType;
188 m_side = p.m_side;
189
190 m_x = p.m_x;
191 m_y = p.m_y;
192 m_z = p.m_z;
193 m_vx = p.m_vx;
194 m_vy = p.m_vy;
195 m_vz = p.m_vz;
196
197 m_status = p.m_status;
198 m_swing = p.m_swing;
199 m_swingType = p.m_swingType;
200 m_swingSide = p.m_swingSide;
201 m_afterSwing = p.m_afterSwing;
202 m_swingError = p.m_swingError;
203 m_targetX = p.m_targetX;
204 m_targetY = p.m_targetY;
205
206 m_eyeX = p.m_eyeX;
207 m_eyeY = p.m_eyeY;
208 m_eyeZ = p.m_eyeZ;
209
210 m_lookAtX = p.m_lookAtX;
211 m_lookAtY = p.m_lookAtY;
212 m_lookAtZ = p.m_lookAtZ;
213
214 m_pow = p.m_pow;
215 m_spin = p.m_spin;
216
217 m_stamina = p.m_stamina;
218
219 m_dragX = p.m_dragX;
220 m_dragY = p.m_dragY;
221
222 m_View = NULL;
223 }
224
225 Player*
Create(long player,long side,long type)226 Player::Create( long player, long side, long type ) {
227 switch (type) {
228 case 0: // normal
229 switch (player) {
230 case 0:
231 return new PenAttack(side);
232 case 1:
233 return new ShakeCut(side);
234 case 2:
235 return new PenDrive(side);
236 }
237 break;
238 case 1: // Com
239 switch (player) {
240 case 0:
241 return new ComPenAttack(side);
242 case 1:
243 return new ComShakeCut(side);
244 case 2:
245 return new ComPenDrive(side);
246 }
247 break;
248 case 2: // Training
249 switch (player) {
250 case 0:
251 return new TrainingPenAttack(side);
252 case 1:
253 return new TrainingPenDrive(side);
254 }
255 break;
256 case 3: // ComTraining
257 switch (player) {
258 case 0:
259 return new ComTrainingPenAttack(side);
260 case 1:
261 return new ComTrainingPenDrive(side);
262 }
263 break;
264 }
265
266 printf( _("no player %ld\n"), player );
267 exit(1);
268 }
269
270 bool
Init()271 Player::Init() {
272 m_View = (PlayerView *)View::CreateView( VIEW_PLAYER );
273
274 m_View->Init( this );
275
276 BaseView::TheView()->AddView( m_View );
277
278 if ( theRC->gmode != GMODE_2D )
279 HitMark::Init();
280
281 return true;
282 }
283
284 bool
Reset(Player * p)285 Player::Reset( Player *p ) {
286 *this = *p;
287
288 return true;
289 }
290
291 bool
Move(SDL_keysym * KeyHistory,long * MouseXHistory,long * MouseYHistory,unsigned long * MouseBHistory,int Histptr)292 Player::Move( SDL_keysym *KeyHistory, long *MouseXHistory,
293 long *MouseYHistory, unsigned long *MouseBHistory,
294 int Histptr ) {
295 //static double lastSendX = 0, lastSendY = 0, lastSendZ = 0;
296 //static double lastSendVX = 0, lastSendVY = 0, lastSendVZ = 0;
297 //static long lastSendCount = 0;
298
299 // swing
300 if ( m_swing > 0 ){
301 if ( m_swing > 30 && m_afterSwing > 0 ) {
302 m_afterSwing--;
303 } else {
304 if ( theBall.GetStatus() == 6 || theBall.GetStatus() == 7 ) {
305 if ( theBall.GetVZ() < 0 )
306 m_swing++;
307 } else {
308 if ( m_swing == 10 ) {
309 if ( theBall.GetStatus() == -1 )
310 m_swing = 0;
311 else if ( ( m_side > 0 && theBall.GetStatus() == 0) ||
312 ( m_side < 0 && theBall.GetStatus() == 2) ) {
313 m_swing++;
314 }
315 } else
316 m_swing++;
317 }
318 }
319 }
320
321 // If the ball goes out of sight, look at the ball direction
322 double x, y, z;
323 double tx, ty, tz;
324 double vx1, vy1, vz1;
325 double vxt, vyt, vzt;
326 double vx2, vy2, vz2;
327 double vl;
328 double p, q;
329 double sinP, cosP;
330
331 tx = 0.0;
332 ty = TABLELENGTH/2*m_side;
333 tz = TABLEHEIGHT;
334
335 x = m_x + m_eyeX;
336 y = m_y + m_eyeY;
337 z = m_z + m_eyeZ;
338
339 vx1 = tx-x;
340 vy1 = ty-y;
341 vz1 = tz-z;
342 vl = sqrt(vx1*vx1+vy1*vy1+vz1*vz1);
343 vx1 /= vl;
344 vy1 /= vl;
345 vz1 /= vl;
346
347 vxt = theBall.GetX()-x;
348 vyt = theBall.GetY()-y;
349 if ( theBall.GetStatus() == 6 || theBall.GetStatus() == 7 )
350 vzt = TABLEHEIGHT + 0.15-z;
351 else
352 vzt = theBall.GetZ()-z;
353 vl = sqrt(vxt*vxt+vyt*vyt+vzt*vzt);
354 vxt /= vl;
355 vyt /= vl;
356 vzt /= vl;
357
358 if ( (cosP = vx1*vxt+vy1*vyt+vz1*vzt) < cos(3.141592/180.0*15) &&
359 fabs(theBall.GetY()) > fabs(y) ) {
360 sinP = sqrt(1-cosP*cosP);
361 p = cos(3.141592/180.0*15) - sin(3.141592/180.0*15)*cosP/sinP;
362 q = sin(3.141592/180.0*15)/sinP;
363
364 vx2 = p*vxt+q*vx1;
365 vy2 = p*vyt+q*vy1;
366 vz2 = p*vzt+q*vz1;
367
368 m_lookAtX = x+vx2;
369 m_lookAtY = y+vy2;
370 m_lookAtZ = z+vz2;
371 } else if ( (cosP = (vy1*vyt+vz1*vzt)/(hypot(vy1, vz1)*hypot(vyt, vzt)))
372 < cos(3.141592/180.0*15) && theBall.GetZ() > z &&
373 (theBall.GetStatus() == 0 || theBall.GetStatus() == 2) ) {
374 sinP = sqrt(1-cosP*cosP);
375 p = cos(3.141592/180.0*15) - sin(3.141592/180.0*15)*cosP/sinP;
376 q = sin(3.141592/180.0*15)/sinP;
377
378 vx2 = p*vxt+q*vx1;
379 vy2 = p*vyt+q*vy1;
380 vz2 = p*vzt+q*vz1;
381
382 m_lookAtX = x+vx2;
383 m_lookAtY = y+vy2;
384 m_lookAtZ = z+vz2;
385 } else {
386 m_lookAtX = tx;
387 m_lookAtY = ty;
388 m_lookAtZ = tz;
389 }
390
391 // backswing and inpact
392 if ( m_swing == 20 ){
393 HitBall();
394
395 if ( Control::TheControl()->GetThePlayer() == this &&
396 theRC->gmode != GMODE_2D ) {
397 HitMark *hit;
398
399 hit = new HitMark();
400 hit->Hit( theBall.GetX(), m_y, theBall.GetZ(),
401 theBall.GetVX(), theBall.GetVY(), theBall.GetVZ(),
402 GetSwingError() );
403
404 BaseView::TheView()->AddView( hit );
405 }
406 m_spin = 0.0;
407 }
408 else if ( m_swing == 50 ){
409 m_swing = 0;
410 m_swingType = SWING_NORMAL;
411 }
412
413 // Automatically move towards the ball
414 // Only for human.
415 if ( (mode == MODE_SOLOPLAY || mode == MODE_MULTIPLAY ||
416 mode == MODE_PRACTICE) && KeyHistory &&
417 theRC->gameLevel != LEVEL_TSUBORISH ) {
418 if ( m_swing > 10 && m_swing < 20 ) {
419 Ball *tmpBall;
420
421 tmpBall = new Ball( theBall.GetX(), theBall.GetY(), theBall.GetZ(),
422 theBall.GetVX(), theBall.GetVY(), theBall.GetVZ(),
423 theBall.GetSpin(), theBall.GetStatus() );
424
425 for ( int i = 0 ; i < 20-m_swing ; i++ )
426 tmpBall->Move();
427
428 if ( ((tmpBall->GetStatus() == 3 && m_side == 1) ||
429 (tmpBall->GetStatus() == 1 && m_side == -1)) ) {
430 double hitpointX = m_swingSide ? m_x+0.3*m_side : m_x-0.3*m_side;
431 double xdiff = tmpBall->GetX() - (hitpointX+m_vx*(20-m_swing)*TICK);
432 double ydiff = tmpBall->GetY() - (m_y+m_vy*(20-m_swing)*TICK);
433
434 double vxdiff, vydiff;
435 vxdiff = xdiff/TICK/(20-m_swing);
436
437 if ( vxdiff > 2.0 )
438 vxdiff = 2.0;
439 else if ( vxdiff < -2.0 )
440 vxdiff = -2.0;
441
442 vxdiff /= theRC->gameLevel+1;
443
444 m_vx += vxdiff;
445
446 if ( fabs(ydiff) > 0.3 ) {
447 vydiff = ydiff/TICK/(20-m_swing);
448 if ( vydiff > 2.0 )
449 vydiff = 2.0;
450 else if ( vydiff < -2.0 )
451 vydiff = -2.0;
452
453 vydiff /= theRC->gameLevel+1;
454
455 m_vy += vydiff;
456 }
457 }
458 delete tmpBall;
459 }
460 }
461
462 // move player
463 if ( m_x+m_vx*TICK < -AREAXSIZE/2 ){
464 m_x = -AREAXSIZE/2;
465 m_vx = 0.0;
466 }
467 else if ( m_x+m_vx*TICK > AREAXSIZE/2 ){
468 m_x = AREAXSIZE/2;
469 m_vx = 0.0;
470 }
471 else if ( m_x <= -TABLEWIDTH/2 && m_x+m_vx*TICK >= -TABLEWIDTH/2 &&
472 m_y > -TABLELENGTH/2+0.5 && m_y < TABLELENGTH/2-0.5 ){
473 m_x = -TABLEWIDTH/2;
474 m_vx = 0.0;
475 }
476 else if ( m_x >= TABLEWIDTH/2 && m_x+m_vx*TICK <= TABLEWIDTH/2 &&
477 m_y > -TABLELENGTH/2+0.5 && m_y < TABLELENGTH/2-0.5 ){
478 m_x = TABLEWIDTH/2;
479 m_vx = 0.0;
480 }
481 else
482 m_x += m_vx*TICK;
483
484 if ( m_y+m_vy*TICK < -AREAYSIZE/2 ) {
485 m_y = -AREAYSIZE/2;
486 m_vy = 0.0;
487 } else if ( m_y+m_vy*TICK > AREAYSIZE/2 ) {
488 m_y = AREAYSIZE/2;
489 m_vy = 0.0;
490 } else if ( m_y <= -TABLELENGTH/2+0.5 && m_y+m_vy*TICK >= -TABLELENGTH/2+0.5
491 && m_x > -TABLEWIDTH/2 && m_x < TABLEWIDTH/2 ) {
492 m_y = -TABLELENGTH/2+0.5;
493 m_vy = 0.0;
494 } else if ( m_y >= TABLELENGTH/2-0.5 && m_y+m_vy*TICK <= TABLELENGTH/2-0.5
495 && m_x > -TABLEWIDTH/2 && m_x < TABLEWIDTH/2 ) {
496 m_y = TABLELENGTH/2-0.5;
497 m_vy = 0.0;
498 } else
499 m_y += m_vy*TICK;
500
501 // Go back to the endline before serve
502 if ( Control::TheControl()->IsPlaying() && theBall.GetStatus() == 8 &&
503 ((PlayGame *)Control::TheControl())->GetService() == GetSide() ) {
504 if ( m_side > 0 && m_y > -TABLELENGTH/2 )
505 m_y = -TABLELENGTH/2;
506 else if ( m_side < 0 && m_y < TABLELENGTH/2 )
507 m_y = TABLELENGTH/2;
508 }
509
510 // Auto backswing
511 if ( m_swing == 0 ) {
512 Ball *tmpBall;
513
514 tmpBall = new Ball( theBall.GetX(), theBall.GetY(), theBall.GetZ(),
515 theBall.GetVX(), theBall.GetVY(), theBall.GetVZ(),
516 theBall.GetSpin(), theBall.GetStatus() );
517
518 for ( int i = 0 ; i < 30 ; i++ ) { /* A bit earlier */
519 tmpBall->Move();
520
521 if ( ((tmpBall->GetStatus() == 3 && m_side == 1) ||
522 (tmpBall->GetStatus() == 1 && m_side == -1)) &&
523 (m_y-tmpBall->GetY())*m_side < 0.3 &&
524 (m_y-tmpBall->GetY())*m_side > -0.05 ){
525 StartSwing( 3 );
526 break;
527 }
528 }
529 delete tmpBall;
530 }
531
532 // calc status
533 if ( hypot( m_vx, m_vy ) > 2.0 )
534 AddStatus( -1 );
535
536 if ( m_swing > 10 )
537 AddStatus( -1 );
538
539 if ( theBall.GetStatus() == 8 || theBall.GetStatus() == -1 )
540 AddStatus( 200 );
541
542 if ( SDL_WM_GrabInput( SDL_GRAB_QUERY ) == SDL_GRAB_ON )
543 KeyCheck( KeyHistory, MouseXHistory, MouseYHistory, MouseBHistory,Histptr );
544
545 if ( Control::TheControl()->GetThePlayer() == this &&
546 mode == MODE_MULTIPLAY ) {
547 m_lastSendCount++;
548
549 m_lastSendX += m_lastSendVX*TICK;
550 m_lastSendY += m_lastSendVY*TICK;
551 m_lastSendZ += m_lastSendVZ*TICK;
552
553 if ( m_lastSendCount >= 100 ||
554 fabs(m_lastSendVX-m_vx) >= 0.25 ||
555 fabs(m_lastSendVY-m_vy) >= 0.25 || fabs(m_lastSendVZ-m_vz) >= 0.25 ) {
556 Event::TheEvent()->SendPlayer( this );
557 }
558
559 // theBall goes out of hitting area.
560 if ( ((theBall.GetStatus() == 1 && m_side == -1) ||
561 (theBall.GetStatus() == 3 && m_side == 1 ) ) &&
562 m_swing <= 10 &&
563 (m_y-theBall.GetY())*m_side > 0.3 &&
564 (m_y+m_vy*TICK-(theBall.GetY()+theBall.GetVY()*TICK))*m_side > 0.3 )
565 Event::TheEvent()->SendBall();
566 }
567
568 return true;
569 }
570
571 bool
KeyCheck(SDL_keysym * KeyHistory,long * MouseXHistory,long * MouseYHistory,unsigned long * MouseBHistory,int Histptr)572 Player::KeyCheck( SDL_keysym *KeyHistory, long *MouseXHistory,
573 long *MouseYHistory, unsigned long *MouseBHistory,
574 int Histptr ) {
575 long mouse, lastmouse;
576
577 const char keytable[][5] = {
578 {'\0', '\0', '\0', '\0', '\0'},
579 {'\0', '\0', '\0', '\0', '\0'},
580 {'1', '1', '1', '[', '\0'},
581 {'2', '2', '2', '7', '\0'},
582 {'3', '3', '3', '5', '\0'},
583 {'4', '4', '4', '3', '\0'},
584 {'5', '5', '5', '1', '\0'},
585 {'6', '6', '6', '9', '\0'},
586 {'7', '7', '7', '0', '\0'},
587 {'8', '8', '8', '2', '\0'},
588 {'9', '9', '9', '6', '\0'},
589 {'0', '0', '0', '8', '\0'},
590 {'\0', '\0', '\0', '\0', '\0'},
591 {'\0', '\0', '\0', '\0', '\0'},
592 {'\0', '\0', '\0', '\0', '\0'},
593 {'\0', '\0', '\0', '\0', '\0'},
594 {'q', 'q', 'a', '/', '\0'},
595 {'w', 'w', 'z', ',', '\0'},
596 {'e', 'e', 'e', '.', '\0'},
597 {'r', 'r', 'r', 'p', '\0'},
598 {'t', 't', 't', 'y', '\0'},
599 {'y', 'z', 'y', 'f', '\0'},
600 {'u', 'u', 'u', 'g', '\0'},
601 {'i', 'i', 'i', 'c', '\0'},
602 {'o', 'o', 'o', 'r', '\0'},
603 {'p', 'p', 'p', 'l', '\0'},
604 {'\0', '\0', '\0', '\0', '\0'},
605 {'\0', '\0', '\0', '\0', '\0'},
606 {'\0', '\0', '\0', '\0', '\0'},
607 {'\0', '\0', '\0', '\0', '\0'},
608 {'a', 'a', 'q', 'a', '\0'},
609 {'s', 's', 's', 'o', '\0'},
610 {'d', 'd', 'd', 'e', '\0'},
611 {'f', 'f', 'f', 'u', '\0'},
612 {'g', 'g', 'g', 'i', '\0'},
613 {'h', 'h', 'h', 'd', '\0'},
614 {'j', 'j', 'j', 'h', '\0'},
615 {'k', 'k', 'k', 't', '\0'},
616 {'l', 'l', 'l', 'n', '\0'},
617 {'\0', '\0', '\0', '\0', '\0'}, // { 'm', 's', '\0'},
618 {'\0', '\0', '\0', '\0', '\0'},
619 {'\0', '\0', '\0', '\0', '\0'},
620 {'\0', '\0', '\0', '\0', '\0'},
621 {'\0', '\0', '\0', '\0', '\0'},
622 {'z', 'y', 'w', ';', '\0'},
623 {'x', 'x', 'x', 'q', '\0'},
624 {'c', 'c', 'c', 'j', '\0'},
625 {'v', 'v', 'v', 'k', '\0'},
626 {'b', 'b', 'b', 'x', '\0'},
627 {'n', 'n', 'n', 'b', '\0'},
628 {'m', 'm' , 'm', '\0', '\0'},
629 {'\0', '\0', '\0', '\0', '\0'}, // { 'w', '\0'},
630 {'\0', '\0', '\0', '\0', '\0'}, // { 'v', '\0'},
631 {'\0', '\0', '\0', '\0', '\0'} // { 'z', '\0'}
632 };
633
634 // COM
635 if ( !KeyHistory || !MouseXHistory || !MouseYHistory || !MouseBHistory )
636 return true;
637
638 // key input
639 // Check keyboard type and modify keycode.
640 int code = -1;
641
642 if ( KeyHistory[Histptr].scancode < 54 ) {
643 int i = 0;
644 while (keytable[KeyHistory[Histptr].scancode][i]) {
645 if ( keytable[KeyHistory[Histptr].scancode][i]
646 == KeyHistory[Histptr].unicode ) {
647 code = keytable[KeyHistory[Histptr].scancode][0];
648 break;
649 }
650 i++;
651 }
652 }
653
654 if ( KeyHistory[Histptr].scancode >= 8 &&
655 KeyHistory[Histptr].scancode < 62 &&
656 code < 0 ) { // for X11
657 int i = 0;
658 while (keytable[KeyHistory[Histptr].scancode-8][i]) {
659 if ( keytable[KeyHistory[Histptr].scancode-8][i]
660 == KeyHistory[Histptr].unicode ) {
661 code = keytable[KeyHistory[Histptr].scancode-8][0];
662 break;
663 }
664 i++;
665 }
666 }
667
668 if ( code < 0 )
669 code = KeyHistory[Histptr].unicode;
670
671
672 switch ( code ) {
673 case '1': case 'q': case 'a': case 'z':
674 case '2': case 'w': case 's': case 'x':
675 case '3':
676 m_targetX = -TABLEWIDTH/2*0.9*GetSide();
677 break;
678 case 'e':
679 m_targetX = -TABLEWIDTH/2*0.75*GetSide();
680 break;
681 case 'd':
682 m_targetX = -TABLEWIDTH/2*0.6*GetSide();
683 break;
684 case '4': case 'c':
685 m_targetX = -TABLEWIDTH/2*0.45*GetSide();
686 break;
687 case 'r':
688 m_targetX = -TABLEWIDTH/2*0.3*GetSide();
689 break;
690 case 'f':
691 m_targetX = -TABLEWIDTH/2*0.15*GetSide();
692 break;
693 case '5': case 'v':
694 m_targetX = 0;
695 break;
696 case 't':
697 m_targetX = TABLEWIDTH/2*0.15*GetSide();
698 break;
699 case 'g':
700 m_targetX = TABLEWIDTH/2*0.3*GetSide();
701 break;
702 case '6': case 'b':
703 m_targetX = TABLEWIDTH/2*0.45*GetSide();
704 break;
705 case 'y':
706 m_targetX = TABLEWIDTH/2*0.6*GetSide();
707 break;
708 case 'h':
709 m_targetX = TABLEWIDTH/2*0.75*GetSide();
710 break;
711 case '7': case 'n': case 'u': case 'j':
712 case '8': case 'm': case 'i': case 'k':
713 case '9': case ',': case 'o': case 'l':
714 case '0': case '.': case 'p': case ';':
715 m_targetX = TABLEWIDTH/2*0.9*GetSide();
716 break;
717 }
718
719 switch ( code ){
720 case '1': case '2': case '3': case '4': case '5': case '6':
721 case '7': case '8': case '9': case '0': case '-': case '^':
722 m_targetY = TABLELENGTH/12*5*GetSide();
723 break;
724 case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
725 case 'u': case 'i': case 'o': case 'p': case '@': case '[':
726 m_targetY = TABLELENGTH/12*4*GetSide();
727 break;
728 case 'a': case 's': case 'd': case 'f': case 'g': case 'h':
729 case 'j': case 'k': case 'l': case ';': case ':': case ']':
730 m_targetY = TABLELENGTH/12*3*GetSide();
731 break;
732 case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
733 case 'm': case ',': case '.': case '/': case '\\':
734 m_targetY = TABLELENGTH/12*2*GetSide();
735 break;
736 }
737
738
739 if ( (Histptr == 0 &&
740 KeyHistory[Histptr].unicode != KeyHistory[MAX_HISTORY-1].unicode) ||
741 (Histptr != 0 &&
742 KeyHistory[Histptr].unicode != KeyHistory[Histptr-1].unicode) ) {
743 switch ( KeyHistory[Histptr].unicode ) {
744 case 'H':
745 m_eyeX -= 0.05;
746 break;
747 case 'J':
748 m_eyeZ -= 0.05;
749 break;
750 case 'K':
751 m_eyeZ += 0.05;
752 break;
753 case 'L':
754 m_eyeX += 0.05;
755 break;
756 case '<':
757 m_eyeY -= 0.05;
758 break;
759 case '>':
760 m_eyeY += 0.05;
761 break;
762
763 case 'A':
764 m_lookAtX -= 0.05;
765 break;
766 case 'S':
767 m_lookAtZ -= 0.05;
768 break;
769 case 'D':
770 m_lookAtZ += 0.05;
771 break;
772 case 'F':
773 m_lookAtX += 0.05;
774 break;
775 case 'C':
776 m_lookAtY -= 0.05;
777 break;
778 case 'V':
779 m_lookAtY += 0.05;
780 break;
781
782 }
783 }
784
785 // Sorry in Japanese...
786 // ���������®�٤��Ѥ��ʤ��褦�ˤ���. �������뤳�Ȥ�
787 // MultiPlay ���ˤ��Ʊ����Ȥ�䤹���ʤ�.
788 // ������ͳ��, �����Ϥ��������� Player �Υ���ѥ���
789 // �ޤǤι�ư�����ꤵ��뤿��, �������ϻ��˾�������
790 // Ʊ�����Ȥ��褦�ˤʤ뤿��Ǥ���. ����ޤǤ�, ����ѥ��Ȼ���
791 // �������Ƥ����Τ�, 0.1���Ʊ�����Ȥ�뤳�Ȥˤʤ�.
792
793 // ���ʤߤ�, ������Υޥ����Υɥ�å��ˤ�äƥܡ���β�ž��
794 // ���椹����, ������ˡ�ϻȤ��ʤ������Τ�ʤ�.
795
796 if ( SDL_WM_GrabInput( SDL_GRAB_QUERY ) == SDL_GRAB_OFF )
797 return true;
798
799 if ( m_swing > 10 && m_swing <= 20 ) {
800 long hptr = Histptr-(m_swing-11);
801 if ( hptr < 0 )
802 hptr += MAX_HISTORY;
803
804 m_dragX = MouseXHistory[Histptr]-MouseXHistory[hptr];
805 m_dragY = MouseYHistory[Histptr]-MouseYHistory[hptr];
806 } else {
807 m_vx = (MouseXHistory[Histptr] - BaseView::GetWinWidth()/2) /
808 (BaseView::GetWinWidth()/40)*GetSide();
809 m_vy = -(MouseYHistory[Histptr] - BaseView::GetWinHeight()/2) /
810 (BaseView::GetWinHeight()/40)*GetSide();
811 m_vx /= 4;
812 m_vy /= 4;
813 }
814
815 mouse = MouseBHistory[Histptr];
816 if ( Histptr-1 < 0 )
817 lastmouse = MouseBHistory[MAX_HISTORY-1];
818 else
819 lastmouse = MouseBHistory[Histptr-1];
820
821 if ( (mouse & BUTTON_RIGHT) && !(lastmouse & BUTTON_RIGHT) ){
822 if ( theBall.GetStatus() == 8 &&
823 ((PlayGame *)Control::TheControl())->GetService() == GetSide() ) {
824 theBall.Toss( this, 3 );
825 StartSwing( 3 );
826 } else {
827 AddStatus( (m_swing-10)*10 );
828 Swing( 3 );
829 }
830 }
831 else if ( (mouse & BUTTON_MIDDLE) && !(lastmouse & BUTTON_MIDDLE) ){
832 if ( theBall.GetStatus() == 8 &&
833 ((PlayGame *)Control::TheControl())->GetService() == GetSide() ) {
834 theBall.Toss( this, 2 );
835 StartSwing( 2 );
836 } else {
837 AddStatus( (m_swing-10)*10 );
838 Swing( 2 );
839 }
840 }
841 else if ( (mouse & BUTTON_LEFT) && !(lastmouse & BUTTON_LEFT) ){
842 if ( theBall.GetStatus() == 8 &&
843 ((PlayGame *)Control::TheControl())->GetService() == GetSide() ) {
844 theBall.Toss( this, 1 );
845 StartSwing( 1 );
846 } else {
847 AddStatus( (m_swing-10)*10 );
848 Swing( 1 );
849 }
850 }
851
852 return true;
853 }
854
855 bool
AddStatus(long diff)856 Player::AddStatus( long diff ) {
857 if ( diff == 200 ) { // Not good...
858 m_statusMax = 200;
859 m_status = 200;
860 } else {
861 m_status += diff;
862
863 if ( m_status > m_statusMax )
864 m_status = m_statusMax;
865
866 if ( m_status < 1 ) {
867 m_stamina += (m_status-1) / 10.0;
868 m_status = 1;
869 }
870
871 if ( diff < -3 ) { // Not good... When status decreased without moving...
872 if ( Control::TheControl()->GetThePlayer() == this ) {
873 switch (theRC->gameLevel) {
874 case LEVEL_EASY:
875 m_statusMax += diff/4;
876 break;
877 case LEVEL_NORMAL:
878 m_statusMax += diff/3;
879 break;
880 case LEVEL_HARD:
881 m_statusMax += diff/2;
882 break;
883 case LEVEL_TSUBORISH:
884 m_statusMax += diff/2;
885 break;
886 }
887 } else {
888 m_statusMax += diff/4; /* �ǵ���֤ǤΥڥʥ�ƥ����껦 */
889 }
890 }
891 }
892
893 return true;
894 }
895
896 // Calc the shoulder location
897 // x --- x
898 // y --- y
899 // deg --- rotation degree around z axis
900 bool
GetShoulder(double & x,double & y,double & deg)901 Player::GetShoulder( double &x, double &y, double ° ) {
902 double px, py, bx, by, bvx, bvy;
903 double t, btx;
904
905 // rotate 180 when the player is in the opposite side
906 if ( m_side < 0 ){
907 px = -m_x;
908 py = -m_y;
909 bx = -theBall.GetX();
910 by = -theBall.GetY();
911 bvx = -theBall.GetVX();
912 bvy = -theBall.GetVY();
913 }
914 else{
915 px = m_x;
916 py = m_y;
917 bx = theBall.GetX();
918 by = theBall.GetY();
919 bvx = theBall.GetVX();
920 bvy = theBall.GetVY();
921 }
922
923 // target
924 if ( bvy == 0.0 || m_swing == 0 ){
925 btx = bx;
926 t = -1;
927 }
928 else{
929 t = (py - by) / bvy;
930 btx = bx + bvx*t;
931 }
932
933 // Forehand or backhand?
934 if ( btx - px > 0 ){ // Forehand
935 switch ( m_swingType ){
936 case SWING_NORMAL:
937 case SWING_DRIVE:
938 if ( m_swing < 10 )
939 deg = -(double)m_swing/10*15-30;
940 else if ( m_swing < 30 )
941 deg = -45+(double)(m_swing-10)/20*45;
942 else
943 deg = -(double)(m_swing-30)/20*30;
944 break;
945 case SWING_POKE:
946 if ( m_swing < 10 )
947 deg = -(double)m_swing/10*10-30;
948 else if ( m_swing < 30 )
949 deg = -40+(double)(m_swing-10)/20*20;
950 else
951 deg = -20-(double)(m_swing-30)/20*10;
952 break;
953 case SWING_CUT:
954 if ( m_swing < 10 )
955 deg = -(double)m_swing/10*60-30;
956 else if ( m_swing < 30 )
957 deg = -60+(double)(m_swing-10)/20*60;
958 else
959 deg = -(double)(m_swing-30)/20*30;
960 break;
961 case SWING_SMASH:
962 if ( m_swing < 10 )
963 deg = -(double)m_swing/10*30-30;
964 else if ( m_swing < 30 )
965 deg = -60+(double)(m_swing-10)/20*90;
966 else
967 deg = 30-(double)(m_swing-30)/20*60;
968 break;
969 }
970
971 if ( m_swing == 0 ){
972 x = y = 0.0;
973 return true;
974 }
975
976 // The distance from the ideal location for hitting
977 if ( btx - px < 0.6 ){
978 x = btx - px - 0.3;
979 y = 0.0;
980 }
981 else {
982 x = 0.3;
983 y = 0.0;
984 }
985 }
986 else{ // Backhand
987 switch ( m_swingType ){
988 case SWING_NORMAL:
989 case SWING_SMASH:
990 case SWING_DRIVE:
991 if ( m_swing < 10 )
992 deg = (double)m_swing/10*30-30;
993 else if ( m_swing < 30 )
994 deg = -(double)(m_swing-10)/20*45;
995 else
996 deg = -45+(double)(m_swing-30)/20*15;
997 break;
998 case SWING_POKE:
999 if ( m_swing < 30 )
1000 deg = (double)m_swing/30*60-30;
1001 else
1002 deg = 30-(double)(m_swing-30)/20*60;
1003 break;
1004 case SWING_CUT:
1005 if ( m_swing < 10 )
1006 deg = (double)m_swing/10*120-30;
1007 else if ( m_swing < 30 )
1008 deg = 90-(double)(m_swing-10)/20*90;
1009 else
1010 deg = -(double)(m_swing-30)/20*30;
1011 break;
1012 }
1013
1014 if ( m_swing == 0 ){
1015 x = y = 0.0;
1016 return true;
1017 }
1018
1019 // The distance from the ideal location for hitting
1020 if ( btx - px > -0.6 ){
1021 x = btx - px + 0.3;
1022 y = 0.0;
1023 }
1024 else{
1025 x = -0.3;
1026 y = 0.0;
1027 }
1028 }
1029
1030 if ( m_swing < 30 ) {
1031 x *= (double)m_swing / 30.0;
1032 y *= (double)m_swing / 30.0;
1033 } else {
1034 x *= (double)(50-m_swing) / 20.0;
1035 y *= (double)(50-m_swing) / 20.0;
1036 }
1037
1038 return true;
1039 }
1040
1041 // Calc the elbow location
1042 // degx --- rotation degree around x axis
1043 // degy --- rotation degree around y axis. default=-15
1044 bool
GetElbow(double & degx,double & degy)1045 Player::GetElbow( double °x, double °y ) {
1046 if ( ForeOrBack() ){
1047 switch ( m_swingType ){
1048 case SWING_NORMAL:
1049 case SWING_SMASH:
1050 if ( m_swing < 10 )
1051 degx = 0.0;
1052 else if ( m_swing < 30 )
1053 degx = (double)(m_swing-10)/20*15;
1054 else
1055 degx = 15-(double)(m_swing-30)/20*15;
1056 degy = -15.0;
1057 break;
1058 case SWING_POKE:
1059 degx = 0.0;
1060 degy = -15.0;
1061 break;
1062 case SWING_CUT:
1063 if ( m_swing < 10 ){
1064 degx = 0.0;
1065 degy = -15-(double)m_swing/10*75;
1066 } else if ( m_swing < 30 ){
1067 degx = 0.0;
1068 degy = -90+(double)(m_swing-10)/20*90;
1069 } else {
1070 degx = 0.0;
1071 degy = -(double)(m_swing-30)/20*15;
1072 }
1073 break;
1074 case SWING_DRIVE:
1075 if ( m_swing < 10 ){
1076 degx = -(double)m_swing/10*10;
1077 degy = -15.0;
1078 } else if ( m_swing < 30 ){
1079 degx = -10+(double)(m_swing-10)/20*160;
1080 degy = -15+(double)(m_swing-10)/20*45;
1081 } else{
1082 degx = 150-(double)(m_swing-30)/20*150;
1083 degy = 30-(double)(m_swing-30)/20*45;
1084 }
1085 break;
1086 }
1087 }
1088 else{
1089 switch ( m_swingType ){
1090 case SWING_NORMAL:
1091 case SWING_SMASH:
1092 case SWING_DRIVE:
1093 degx = 0.0;
1094 degy = -15.0;
1095 break;
1096 case SWING_POKE:
1097 if ( m_swing < 10 ){
1098 degx = (double)m_swing/10*15;
1099 degy = -15.0;
1100 }
1101 else if ( m_swing < 30 ){
1102 degx = 15 - (double)(m_swing-10)/20*15;
1103 degy = -15.0;
1104 } else{
1105 degx = 0.0;
1106 degy = -15.0;
1107 }
1108 break;
1109 case SWING_CUT:
1110 if ( m_swing < 10 ){
1111 degx = (double)m_swing/10*10;
1112 degy = (double)m_swing/10*45;
1113 } else if ( m_swing < 30 ){
1114 degx = 10-(double)(m_swing-10)/20*10;
1115 degy = 45-(double)(m_swing-10)/20*45;
1116 } else{
1117 degx = 0.0;
1118 degy = -(double)(m_swing-30)/20*15;
1119 }
1120 break;
1121 }
1122 }
1123 return true;
1124 }
1125
1126 // Calc the hand location
1127 // degx --- rotation degree around x axis
1128 // degy --- rotation degree around y axis
1129 // degz --- rotation degree around z axis
1130 bool
GetHand(double & degx,double & degy,double & degz)1131 Player::GetHand( double °x, double °y, double °z ) {
1132
1133 if ( ForeOrBack() ){
1134 switch ( m_swingType ){
1135 case SWING_NORMAL:
1136 case SWING_SMASH:
1137 if ( m_swing < 10 ){
1138 degz = -(double)m_swing/10*90;
1139 degx = degy = 0.0;
1140 }
1141 else if ( m_swing < 30 ){
1142 degz = -90+(double)(m_swing-10)/20*120;
1143 degx = (double)(m_swing-10)/20*75;
1144 degy = 0.0;
1145 }
1146 else{
1147 degz = 30-(double)(m_swing-30)/20*30;
1148 degx = 75-(double)(m_swing-30)/20*75;
1149 degy = 0.0;
1150 }
1151 break;
1152 case SWING_POKE:
1153 if ( m_swing < 10 ){
1154 degz = -(double)m_swing/10*90;
1155 degx = (double)m_swing/10*45;
1156 degy = (double)m_swing/10*45;
1157 }
1158 else if ( m_swing < 30 ){
1159 degz = -90+(double)(m_swing-10)/20*150;
1160 degx = 45 - (double)(m_swing-10)/20*45;
1161 degy = 45.0;
1162 }
1163 else{
1164 degz = 60-(double)(m_swing-30)/20*30;
1165 degx = 0.0;
1166 degy = 45.0 - (double)(m_swing-30)/20*45;
1167 }
1168 break;
1169 case SWING_CUT:
1170 if ( m_swing < 10 ){
1171 degz = -(double)m_swing/10*90;
1172 degx = 0.0;
1173 degy = (double)m_swing/10*45;
1174 }
1175 else if ( m_swing < 30 ){
1176 degz = -90+(double)(m_swing-10)/20*150;
1177 degx = -(double)(m_swing-10)/20*60;
1178 degy = 45.0;
1179 }
1180 else{
1181 degz = 60-(double)(m_swing-30)/20*30;
1182 degx = -60+(double)(m_swing-30)/20*60;
1183 degy = 45.0 - (double)(m_swing-30)/20*45;
1184 }
1185 break;
1186 case SWING_DRIVE:
1187 if ( m_swing < 10 ){
1188 degz = -(double)m_swing/10*90;
1189 degx = -(double)m_swing/10*90;
1190 degy = 0.0;
1191 }
1192 else if ( m_swing < 30 ){
1193 degz = -90+(double)(m_swing-10)/20*120;
1194 degx = -90;
1195 degy = 0.0;
1196 }
1197 else{
1198 degz = 30-(double)(m_swing-30)/20*30;
1199 degx = -90+(double)(m_swing-30)/20*90;
1200 degy = 0.0;
1201 }
1202 break;
1203 }
1204 }
1205 else{
1206 switch ( m_swingType ){
1207 case SWING_NORMAL:
1208 case SWING_SMASH:
1209 case SWING_DRIVE:
1210 if ( m_swing < 10 ){
1211 degz = (double)m_swing/10*90;
1212 degx = degy = 0.0;
1213 }
1214 else if ( m_swing < 30 ){
1215 degz = 90-(double)(m_swing-10)/20*120;
1216 degx = (double)(m_swing-10)/20*75;
1217 degy = 0.0;
1218 }
1219 else{
1220 degz = -30+(double)(m_swing-30)/20*30;
1221 degx = 75-(double)(m_swing-30)/20*75;
1222 degy = 0.0;
1223 }
1224 break;
1225 case SWING_POKE:
1226 if ( m_swing < 10 ){
1227 degz = (double)m_swing/10*90;
1228 degx = 0.0;
1229 degy = -(double)m_swing/10*45;
1230 }
1231 else if ( m_swing < 30 ){
1232 degz = 90-(double)(m_swing-10)/20*120;
1233 degx = 0.0;
1234 degy = -45.0;
1235 }
1236 else{
1237 degz = -30+(double)(m_swing-30)/20*30;
1238 degx = 0.0;
1239 degy = -45.0 + (double)(m_swing-30)/20*45;
1240 }
1241 break;
1242 case SWING_CUT:
1243 if ( m_swing < 10 ){
1244 degz = (double)m_swing/10*90;
1245 degx = (double)m_swing/10*30;
1246 degy = -(double)m_swing/10*45;
1247 }
1248 else if ( m_swing < 30 ){
1249 degz = 90-(double)(m_swing-10)/20*120;
1250 degx = 30-(double)(m_swing-10)/20*90;
1251 degy = -45.0;
1252 }
1253 else{
1254 degz = -30+(double)(m_swing-30)/20*30;
1255 degx = -60+(double)(m_swing-30)/20*60;
1256 degy = -45.0 + (double)(m_swing-30)/20*45;
1257 }
1258 break;
1259 }
1260 }
1261
1262 return true;
1263 }
1264
1265 bool
ForeOrBack()1266 Player::ForeOrBack() {
1267 return GetSwingSide();
1268 }
1269
1270 bool
SwingError()1271 Player::SwingError() {
1272 double diff;
1273
1274 if ( (m_y-theBall.GetY())*m_side < 0 )
1275 diff = fabs(m_y-theBall.GetY())/2;
1276 else
1277 diff = fabs(m_y-theBall.GetY());
1278
1279 if ( diff < 0.03 )
1280 m_swingError = SWING_PERFECT;
1281 else if ( diff < 0.1 )
1282 m_swingError = SWING_GREAT;
1283 else if ( diff < 0.2 )
1284 m_swingError = SWING_GOOD;
1285 else
1286 m_swingError = SWING_BOO;
1287
1288 return true;
1289 }
1290
1291 bool
Warp(double x,double y,double z,double vx,double vy,double vz)1292 Player::Warp( double x, double y, double z, double vx, double vy, double vz ) {
1293 m_x = x;
1294 m_y = y;
1295 m_z = z;
1296 m_vx = vx;
1297 m_vy = vy;
1298 m_vz = vz;
1299
1300 return true;
1301 }
1302
1303 bool
Warp(char * buf)1304 Player::Warp( char *buf ) {
1305 char *b = buf;
1306 b = ReadDouble( b, m_x );
1307 b = ReadDouble( b, m_y );
1308 b = ReadDouble( b, m_z );
1309 b = ReadDouble( b, m_vx );
1310 b = ReadDouble( b, m_vy );
1311 b = ReadDouble( b, m_vz );
1312
1313 return true;
1314 }
1315
1316 bool
ExternalSwing(long pow,double spin,long swingType,long swing)1317 Player::ExternalSwing( long pow, double spin, long swingType, long swing ) {
1318 m_swing = swing;
1319 m_pow = pow;
1320 m_spin = spin;
1321 m_swingType =swingType;
1322
1323 return true;
1324 }
1325
1326 bool
ExternalSwing(char * buf)1327 Player::ExternalSwing( char *buf ) {
1328 char *b = buf;
1329 long swingSide;
1330 b = ReadLong( b, m_pow );
1331 b = ReadDouble( b, m_spin );
1332 b = ReadLong( b, m_swingType );
1333 b = ReadLong( b, swingSide );
1334 b = ReadLong( b, m_swing );
1335
1336 m_swingSide = (bool)(swingSide != 0);
1337
1338 return true;
1339 }
1340
1341 char *
SendSwing(char * buf)1342 Player::SendSwing( char *buf ) {
1343 long l;
1344 double d;
1345
1346 l = SwapLong(m_pow);
1347 memcpy( buf, (char *)&l, 4 );
1348 d = SwapDbl(m_spin);
1349 memcpy( &(buf[4]), (char *)&d, 8 );
1350 l = SwapLong(m_swingType);
1351 memcpy( &(buf[12]), (char *)&l, 4 );
1352 l = SwapLong((long)m_swingSide);
1353 memcpy( &(buf[16]), (char *)&l, 4 );
1354 l = SwapLong(m_swing);
1355 memcpy( &(buf[20]), (char *)&l, 4 );
1356
1357 #ifdef LOGGING
1358 Logging::GetLogging()->LogSendPSMessage( this );
1359 #endif
1360
1361 return buf;
1362 }
1363
1364 char *
SendLocation(char * buf)1365 Player::SendLocation( char *buf ) {
1366 double d;
1367
1368 d = SwapDbl(m_x);
1369 memcpy( buf, (char *)&d, 8 );
1370 d = SwapDbl(m_y);
1371 memcpy( &(buf[8]), (char *)&d, 8 );
1372 d = SwapDbl(m_z);
1373 memcpy( &(buf[16]), (char *)&d, 8 );
1374 d = SwapDbl(m_vx);
1375 memcpy( &(buf[24]), (char *)&d, 8 );
1376 d = SwapDbl(m_vy);
1377 memcpy( &(buf[32]), (char *)&d, 8 );
1378 d = SwapDbl(m_vz);
1379 memcpy( &(buf[40]), (char *)&d, 8 );
1380
1381 UpdateLastSend();
1382
1383 #ifdef LOGGING
1384 Logging::GetLogging()->LogSendPVMessage( this );
1385 #endif
1386
1387 return buf;
1388 }
1389
1390 bool
SendAll(int sd)1391 Player::SendAll( int sd ) {
1392 SendLong( sd, m_playerType );
1393 SendLong( sd, m_side );
1394
1395 SendDouble( sd, m_x );
1396 SendDouble( sd, m_y );
1397 SendDouble( sd, m_z );
1398 SendDouble( sd, m_vx );
1399 SendDouble( sd, m_vy );
1400 SendDouble( sd, m_vz );
1401
1402 SendLong( sd, m_status );
1403 SendLong( sd, m_swing );
1404 SendLong( sd, m_swingType );
1405 SendLong( sd, (long)m_swingSide );
1406 SendLong( sd, m_afterSwing );
1407 SendLong( sd, m_swingError );
1408
1409 SendDouble( sd, m_targetX );
1410 SendDouble( sd, m_targetY );
1411 SendDouble( sd, m_eyeX );
1412 SendDouble( sd, m_eyeY );
1413 SendDouble( sd, m_eyeZ );
1414
1415 SendLong( sd, m_pow );
1416
1417 SendDouble( sd, m_spin );
1418 SendDouble( sd, m_stamina );
1419
1420 SendLong( sd, m_statusMax );
1421
1422 return true;
1423 }
1424
1425 // Must be overridden
1426 bool
GetModifiedTarget(double & targetX,double & targetY)1427 Player::GetModifiedTarget( double &targetX, double &targetY ) {
1428 return false;
1429 }
1430
1431 void
CalcLevel(Ball * ball,double & diff,double & level,double & maxVy)1432 Player::CalcLevel( Ball *ball, double &diff, double &level, double &maxVy ) {
1433 }
1434
1435 bool
Swing(long power)1436 Player::Swing( long power ) {
1437 return false;
1438 }
1439
1440 bool
StartSwing(long power)1441 Player::StartSwing( long power ) {
1442 return false;
1443 }
1444
1445 bool
HitBall()1446 Player::HitBall() {
1447 return false;
1448 }
1449
1450 void
UpdateLastSend()1451 Player::UpdateLastSend() {
1452 m_lastSendCount = 0;
1453
1454 m_lastSendX = m_x;
1455 m_lastSendY = m_y;
1456 m_lastSendZ = m_z;
1457 m_lastSendVX = m_vx;
1458 m_lastSendVY = m_vy;
1459 m_lastSendVZ = m_vz;
1460 }
1461
1462 void
AddError(double & vx,double & vy,double & vz)1463 Player::AddError( double &vx, double &vy, double &vz ) {
1464 double v;
1465 double n1x, n1y, n1z, n2x, n2y, n2z;
1466 double radDiff, radRand;
1467
1468 #if 0
1469 radDiff = hypot( fabs(fabs(m_x-theBall.GetX())-0.3)/0.3,
1470 fabs(m_y-theBall.GetY())/0.3 );
1471 radDiff = sqrt( radDiff );
1472 radDiff *= (double)(200-m_status)/200*3.141592/12;
1473 #else
1474 radDiff = (double)(200-m_status)/200*3.141592/12;
1475 #endif
1476
1477 v = sqrt(vx*vx+vy*vy+vz*vz);
1478 n1x = vy/hypot(vx, vy) * v*tan(radDiff);
1479 n1y = -vx/hypot(vx, vy) * v*tan(radDiff);
1480 n1z = 0;
1481 n2x = vx*vz/(v*hypot(vx, vy)) * v*tan(radDiff);
1482 n2y = vy*vz/(v*hypot(vx, vy)) * v*tan(radDiff);
1483 n2z = (vx*vx+vy*vy)/(v*hypot(vx, vy)) * v*tan(radDiff);
1484
1485 // Hit the ball too fast --- net miss
1486 // Hit the ball too slow --- over miss
1487 if ( (m_y-theBall.GetY())*m_side < 0 )
1488 radRand = (RAND(180)+180)*3.141592/180.0;
1489 else
1490 radRand = RAND(180)*3.141592/180.0;
1491
1492 vx += n1x*cos(radRand)+n2x*sin(radRand);
1493 vy += n1y*cos(radRand)+n2y*sin(radRand);
1494 vz += n1z*cos(radRand)+n2z*sin(radRand);
1495 }
1496
1497 // If status point is less than this value, player will miss.
1498 long
StatusBorder()1499 Player::StatusBorder() {
1500 double nearEdge = TABLEWIDTH/2-fabs(m_targetX);
1501 if ( TABLELENGTH/4-fabs(fabs(m_targetY)-TABLELENGTH/4) < nearEdge )
1502 nearEdge = TABLELENGTH/4-fabs(fabs(m_targetY)-TABLELENGTH/4);
1503
1504 return 50+(TABLELENGTH/4-nearEdge)*40;
1505
1506 }
1507