@@ -366,10 +366,6 @@ void CA_MatchBreak(void)
366
366
void track_player (gedict_t * observer )
367
367
{
368
368
gedict_t * player = ca_get_player (observer );
369
- vec3_t delta ;
370
- float vlen ;
371
- int follow_distance ;
372
- int upward_distance ;
373
369
374
370
if (player && !observer -> in_play && observer -> tracking_enabled )
375
371
{
@@ -396,37 +392,12 @@ void track_player(gedict_t *observer)
396
392
observer -> track_target = player ;
397
393
}
398
394
399
- // { spectate in 1st person
400
- follow_distance = -10 ;
401
- upward_distance = 0 ;
402
- observer -> hideentity = EDICT_TO_PROG (player ); // in this mode we want to hide player model for watcher's view
403
- VectorCopy (player -> s .v .v_angle , observer -> s .v .angles );
404
- // }
405
-
406
- observer -> s .v .fixangle = true; // force client v_angle (disable in 3rd person view)
407
-
408
- trap_makevectors (player -> s .v .angles );
409
- VectorMA (player -> s .v .origin , follow_distance , g_globalvars .v_forward , observer -> s .v .origin );
410
- VectorMA (observer -> s .v .origin , upward_distance , g_globalvars .v_up , observer -> s .v .origin );
411
-
412
- // avoid positionning in walls
413
- traceline (PASSVEC3 (player -> s .v .origin ), PASSVEC3 (observer -> s .v .origin ), false, player );
414
- VectorCopy (g_globalvars .trace_endpos , observer -> s .v .origin );
395
+ // Use trackent for smooth tracking
396
+ observer -> trackent = NUM_FOR_EDICT (player );
397
+ observer -> hideentity = EDICT_TO_PROG (player ); // Hide tracked player model
415
398
416
- if (g_globalvars .trace_fraction == 1 )
417
- {
418
- VectorCopy (g_globalvars .trace_endpos , observer -> s .v .origin );
419
- VectorMA (observer -> s .v .origin , 10 , g_globalvars .v_forward , observer -> s .v .origin );
420
- }
421
- else
422
- {
423
- VectorSubtract (g_globalvars .trace_endpos , player -> s .v .origin , delta );
424
- vlen = VectorLength (delta );
425
- vlen = vlen - 40 ;
426
- VectorNormalize (delta );
427
- VectorScale (delta , vlen , delta );
428
- VectorAdd (player -> s .v .origin , delta , observer -> s .v .origin );
429
- }
399
+ // Lock observer's orientation to player POV
400
+ observer -> s .v .movetype = MOVETYPE_LOCK ;
430
401
431
402
// set observer's health/armor/ammo/weapon to match the player's
432
403
observer -> s .v .ammo_nails = player -> s .v .ammo_nails ;
@@ -442,17 +413,14 @@ void track_player(gedict_t *observer)
442
413
observer -> weaponmodel = player -> weaponmodel ;
443
414
observer -> s .v .weaponframe = player -> s .v .weaponframe ;
444
415
445
- // smooth playing for ezq / zq
446
- observer -> s .v .movetype = MOVETYPE_LOCK ;
447
-
448
416
show_tracking_info (observer );
449
417
}
450
-
451
- if (!player || !observer -> tracking_enabled )
418
+ else
452
419
{
453
- // restore movement and show racer entity
454
- observer -> s . v . movetype = MOVETYPE_NOCLIP ;
420
+ // Clear tracking
421
+ observer -> trackent = 0 ;
455
422
observer -> hideentity = 0 ;
423
+ observer -> s .v .movetype = MOVETYPE_NOCLIP ;
456
424
457
425
// set health/item values back to nothing
458
426
observer -> s .v .ammo_nails = 0 ;
@@ -641,6 +609,7 @@ void CA_PutClientInServer(void)
641
609
642
610
// tracking enabled by default
643
611
self -> tracking_enabled = 1 ;
612
+ self -> trackent = 0 ; // Initialize trackent for dead players
644
613
645
614
self -> in_play = false;
646
615
self -> round_deaths ++ ; //increment death count for wipeout
@@ -766,9 +735,9 @@ void CA_SendTeamInfo(gedict_t *t)
766
735
break ;
767
736
}
768
737
769
- if (t -> trackent && (t -> trackent == NUM_FOR_EDICT (p )))
738
+ if (t -> ct == ctSpec && t -> trackent && (t -> trackent == NUM_FOR_EDICT (p )))
770
739
{
771
- continue ; // we pseudo speccing such player, no point to send info about him
740
+ continue ; // if we're spectating the player, don't send info about him
772
741
}
773
742
774
743
if (p -> ca_ready || match_in_progress != 2 ) // be sure to send info if in prewar
@@ -1488,26 +1457,34 @@ void CA_player_pre_think(void)
1488
1457
1489
1458
void CA_spectator_think (void )
1490
1459
{
1491
- gedict_t * p ;
1460
+ gedict_t * target , * teammate ;
1461
+ int id ;
1492
1462
1493
- p = PROG_TO_EDICT (self -> s .v .goalentity ); // who we are spectating
1463
+ target = PROG_TO_EDICT (self -> s .v .goalentity ); // who we are spectating
1494
1464
1495
- if (p -> ct == ctPlayer && !p -> in_play && p -> tracking_enabled )
1496
- {
1497
- // if the player you're observing is following someone else, hide the player model
1498
- self -> hideentity = EDICT_TO_PROG (p -> track_target );
1499
- }
1500
- else
1465
+ // If spectating a dead player, switch to an alive teammate
1466
+ if (target && target -> ct == ctPlayer && !target -> in_play )
1501
1467
{
1502
- self -> hideentity = 0 ;
1468
+ // Find any alive teammate
1469
+ teammate = ca_find_player (world , target );
1470
+ if (teammate && teammate -> in_play && teammate != target )
1471
+ {
1472
+ // Use stuffcmd to switch the spectator to the alive teammate
1473
+ if ((id = GetUserID (teammate )) > 0 )
1474
+ {
1475
+ stuffcmd_flags (self , STUFFCMD_IGNOREINDEMO , "track %d\n" , id );
1476
+ }
1477
+ }
1503
1478
}
1504
1479
1505
- if (p -> ct == ctPlayer )
1480
+ // Get the current viewing target (may have changed due to stuffcmd)
1481
+ target = PROG_TO_EDICT (self -> s .v .goalentity );
1482
+ if (target && target -> ct == ctPlayer )
1506
1483
{
1507
1484
if (match_in_progress == 2 && ra_match_fight == 2 && round_time > 2 && !ca_round_pause )
1508
1485
{
1509
1486
// any centerprint the player sees is sent to the spec
1510
- G_centerprint (self , "%s\n" , p -> cptext );
1487
+ G_centerprint (self , "%s\n" , target -> cptext );
1511
1488
}
1512
1489
}
1513
1490
}
0 commit comments