static void select_test(edict_t *ent) { switch (ent->client->menu.cur) { case 3: if (ent->client->pers.connected == CONN_SPAWNED) { if (G_SpecRateLimited(ent)) { break; } spectator_respawn(ent, CONN_SPECTATOR); break; } if (ent->client->pers.connected != CONN_PREGAME) { if (G_SpecRateLimited(ent)) { break; } } spectator_respawn(ent, CONN_SPAWNED); break; case 5: if (become_spectator(ent)) { if (ent->client->chase_target) { SetChaseTarget(ent, NULL); } PMenu_Close(ent); } break; case 6: if (become_spectator(ent)) { if (!ent->client->chase_target) { GetChaseTarget(ent, CHASE_NONE); } PMenu_Close(ent); } break; case 7: if (become_spectator(ent)) { GetChaseTarget(ent, CHASE_LEADER); PMenu_Close(ent); } break; case 8: if (become_spectator(ent)) { GetChaseTarget(ent, CHASE_QUAD); PMenu_Close(ent); } break; case 9: if (become_spectator(ent)) { GetChaseTarget(ent, CHASE_INVU); PMenu_Close(ent); } break; case 11: PMenu_Close(ent); break; } }
void NextChaseMode( edict_t *ent ) { ent->client->chase_mode = (ent->client->chase_mode + 1) % 3; if (ent->client->chase_mode == 1) { //going 3rd person, remove gun and invisible player ent->client->clientNum = (ent - g_edicts) - 1; ent->client->ps.gunindex = ent->client->ps.gunframe = 0; if (!ent->client->chase_target) { GetChaseTarget( ent ); if (!ent->client->chase_target) { ent->client->chase_mode = 0; return; } } if (ent->client->resp.team && teamplay->value && limchasecam->value == 2) { NextChaseMode( ent ); return; } } else if (ent->client->chase_mode == 2) { if (!ent->client->chase_target) { GetChaseTarget( ent ); if (!ent->client->chase_target) { ent->client->chase_mode = 0; return; } } //set clientnum to hide chased person on supported server ent->client->clientNum = (ent->client->chase_target - g_edicts) - 1; ent->client->ps.gunindex = ent->client->ps.gunframe = 0; } else// if (ent->client->chase_mode == CHASE_FREE) { if (ent->client->resp.team && teamplay->value && limchasecam->value) { if (limchasecam->value == 1) { NextChaseMode( ent ); } else { ent->client->chase_mode = 2; } return; } DisableChaseCam( ent ); } }
static void Cmd_Chase_f(edict_t *ent) { edict_t *target = NULL; chase_mode_t mode = CHASE_NONE; if (gi.argc() == 2) { char *who = gi.argv(1); if (!Q_stricmp(who, "quad")) { mode = CHASE_QUAD; } else if (!Q_stricmp(who, "inv") || !Q_stricmp(who, "pent")) { mode = CHASE_INVU; } else if (!Q_stricmp(who, "top") || !Q_stricmp(who, "topfragger") || !Q_stricmp(who, "leader")) { mode = CHASE_LEADER; } else { target = G_SetPlayer(ent, 1); if (!target) { return; } if (!PlayerSpawned(target)) { gi.cprintf(ent, PRINT_HIGH, "Player '%s' is not in the game.\n", target->client->pers.netname); return; } } } if (!become_spectator(ent)) { return; } if (target) { if (target == ent->client->chase_target) { gi.cprintf(ent, PRINT_HIGH, "You are already chasing this player.\n"); return; } SetChaseTarget(ent, target); ent->client->chase_mode = CHASE_NONE; } else { if (!ent->client->chase_target || mode != CHASE_NONE) { GetChaseTarget(ent, mode); } else { SetChaseTarget(ent, NULL); } } }
/* ============== ToggleChaseCam ============== Player hit Spectator menu option or used chase command. */ void ToggleChaseCam (edict_t *ent) { if (ent->client->pers.team) { TDM_LeftTeam (ent, true); TDM_TeamsChanged (); if (tdm_match_status == MM_TIMEOUT && teaminfo[TEAM_A].players == 0 && teaminfo[TEAM_B].players == 0) TDM_ResumeGame (); respawn (ent); } if (ent->client->chase_target) DisableChaseCam (ent); else GetChaseTarget(ent); PMenu_Close (ent); }
/* ============== ClientThink This will be called once for each client frame, which will usually be a couple times for each server frame. ============== */ void ClientThink (edict_t *ent, usercmd_t *ucmd) { gclient_t *client; edict_t *other; int i, j; pmove_t pm; level.current_entity = ent; client = ent->client; if (level.intermissiontime) { client->ps.pmove.pm_type = PM_FREEZE; // can exit intermission after five seconds if (level.time > level.intermissiontime + 5.0 && (ucmd->buttons & BUTTON_ANY) ) level.exitintermission = true; return; } pm_passent = ent; if (ent->client->chase_target) { client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); } else { // set up for pmove memset (&pm, 0, sizeof(pm)); if (ent->movetype == MOVETYPE_NOCLIP) client->ps.pmove.pm_type = PM_SPECTATOR; else if (ent->s.modelindex != 255) client->ps.pmove.pm_type = PM_GIB; else if (ent->deadflag) client->ps.pmove.pm_type = PM_DEAD; else client->ps.pmove.pm_type = PM_NORMAL; client->ps.pmove.gravity = sv_gravity->value; pm.s = client->ps.pmove; for (i=0 ; i<3 ; i++) { pm.s.origin[i] = ent->s.origin[i]*8; pm.s.velocity[i] = ent->velocity[i]*8; } if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s))) { pm.snapinitial = true; // gi.dprintf ("pmove changed!\n"); } pm.cmd = *ucmd; pm.trace = PM_trace; // adds default parms pm.pointcontents = gi.pointcontents; // perform a pmove gi.Pmove (&pm); // save results of pmove client->ps.pmove = pm.s; client->old_pmove = pm.s; for (i=0 ; i<3 ; i++) { ent->s.origin[i] = pm.s.origin[i]*0.125; ent->velocity[i] = pm.s.velocity[i]*0.125; } VectorCopy (pm.mins, ent->mins); VectorCopy (pm.maxs, ent->maxs); client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0)) { gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); } ent->viewheight = pm.viewheight; ent->waterlevel = pm.waterlevel; ent->watertype = pm.watertype; ent->groundentity = pm.groundentity; if (pm.groundentity) ent->groundentity_linkcount = pm.groundentity->linkcount; if (ent->deadflag) { client->ps.viewangles[ROLL] = 40; client->ps.viewangles[PITCH] = -15; client->ps.viewangles[YAW] = client->killer_yaw; } else { VectorCopy (pm.viewangles, client->v_angle); VectorCopy (pm.viewangles, client->ps.viewangles); } gi.linkentity (ent); if (ent->movetype != MOVETYPE_NOCLIP) G_TouchTriggers (ent); // touch other objects for (i=0 ; i<pm.numtouch ; i++) { other = pm.touchents[i]; for (j=0 ; j<i ; j++) if (pm.touchents[j] == other) break; if (j != i) continue; // duplicated if (!other->touch) continue; other->touch (other, ent, NULL, NULL); } } client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; client->latched_buttons |= client->buttons & ~client->oldbuttons; // save light level the player is standing on for // monster sighting AI ent->light_level = ucmd->lightlevel; // fire weapon from final position if needed if (client->latched_buttons & BUTTON_ATTACK) { if (client->resp.spectator) { client->latched_buttons = 0; if (client->chase_target) { client->chase_target = NULL; client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; } else GetChaseTarget(ent); } else if (!client->weapon_thunk) { client->weapon_thunk = true; Think_Weapon (ent); } } if (client->resp.spectator) { if (ucmd->upmove >= 10) { if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { client->ps.pmove.pm_flags |= PMF_JUMP_HELD; if (client->chase_target) ChaseNext(ent); else GetChaseTarget(ent); } } else client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; } // update chase cam if being followed for (i = 1; i <= maxclients->value; i++) { other = g_edicts + i; if (other->inuse && other->client->chase_target == ent) UpdateChaseCam(other); } }