/* ============== ClientBeginServerFrame This will be called once for each server frame, before running any other entities in the world. ============== */ void ClientBeginServerFrame (edict_t *ent) { gclient_t *client; int buttonMask; if (level.intermissiontime) return; client = ent->client; if (deathmatch->value && client->pers.spectator != client->resp.spectator && (level.time - client->respawn_time) >= 5) { spectator_respawn(ent); return; } // run weapon animations if it hasn't been done by a ucmd_t if (!client->weapon_thunk && !client->resp.spectator) Think_Weapon (ent); else client->weapon_thunk = false; if (ent->deadflag) { // wait for any button just going down if ( level.time > client->respawn_time) { // in deathmatch, only wait for attack button if (deathmatch->value) buttonMask = BUTTON_ATTACK; else buttonMask = -1; if ( ( client->latched_buttons & buttonMask ) || (deathmatch->value && ((int)dmflags->value & DF_FORCE_RESPAWN) ) ) { respawn(ent); client->latched_buttons = 0; } } return; } // add player trail so monsters can follow if (!deathmatch->value) if (!visible (ent, PlayerTrail_LastSpot() ) ) PlayerTrail_Add (ent->s.old_origin); client->latched_buttons = 0; }
/* ============== ClientBeginServerFrame This will be called once for each server frame, before running any other entities in the world. ============== */ void ClientBeginServerFrame (edict_t *ent) { gclient_t *client; int buttonMask; if (level.intermissiontime) return; client = ent->client; // run weapon animations if it hasn't been done by a ucmd_t if (!client->weapon_thunk) Think_Weapon (ent); else client->weapon_thunk = false; // make sure the fov and weapon models are gone if we're in camera mode if (client->zCameraTrack) { client->ps.fov = 90; client->ps.gunindex = 0; } if (ent->deadflag) { // wait for any button just going down if ( level.time > client->respawn_time) { // in deathmatch, only wait for attack button if (deathmatch->value) buttonMask = BUTTON_ATTACK; else buttonMask = -1; if ( ( client->latched_buttons & buttonMask ) || (deathmatch->value && ((int)dmflags->value & DF_FORCE_RESPAWN) ) ) { respawn(ent); client->latched_buttons = 0; } } return; } // add player trail so monsters can follow if (!deathmatch->value) if (!visible (ent, PlayerTrail_LastSpot() ) ) PlayerTrail_Add (ent->s.old_origin); client->latched_buttons = 0; }
/* ============== 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; #if defined(_DEBUG) && defined(_Z_TESTMODE) if(testitemOriginMove && testItemDroped) { if(ucmd->forwardmove > 0) { testItemDroped->s.origin[2]++; } else if(ucmd->forwardmove < 0) { testItemDroped->s.origin[2]--; } return; } #endif level.current_entity = ent; client = ent->client; #ifdef GAME_MOD Blinky_BeginClientThink(ent, ucmd); #endif 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; } if(ent->movetype == MOVETYPE_FREEZE) { client->ps.pmove.pm_type = PM_FREEZE; return; } pm_passent = ent; // 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->weapon_thunk) { client->weapon_thunk = true; Think_Weapon (ent); } } #ifdef WITH_ACEBOT // ACEBOT_ADD if (!ent->is_bot && !ent->deadflag && !ent->client->resp.spectator) ACEND_PathMap(ent); // ACEBOT_END #endif }
/* ============== 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); } }