/* ================ CG_Respawn A respawn happened this snapshot ================ */ void CG_Respawn( qboolean revived ) { int bank; cg.serverRespawning = qfalse; // Arnout: just in case // no error decay on player movement cg.thisFrameTeleport = qtrue; // need to reset client-side weapon animations cg.predictedPlayerState.weapAnim = ( ( cg.predictedPlayerState.weapAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | PM_IdleAnimForWeapon(cg.snap->ps.weapon); // reset weapon animations cg.predictedPlayerState.weaponstate = WEAPON_READY; // hmm, set this? what to? // display weapons available cg.weaponSelectTime = cg.time; cg.cursorHintIcon = 0; cg.cursorHintTime = 0; cg.cameraMode = qfalse; //----(SA) get out of camera for sure // select the weapon the server says we are using cg.weaponSelect = cg.snap->ps.weapon; // DHM - Nerve :: Clear even more things on respawn cg.zoomedBinoc = qfalse; cg.zoomedScope = qfalse; cg.zoomTime = 0; cg.zoomval = 0; trap_SendConsoleCommand( "-zoom\n" ); cg.binocZoomTime = 0; // clear pmext memset( &cg.pmext, 0, sizeof(cg.pmext) ); cg.pmext.bAutoReload = (cg_autoReload.integer > 0); cg.pmext.sprintTime = SPRINTTIME; if( !revived ) { cgs.limboLoadoutSelected = qfalse; // set lastWeapSelInBank to the current weapon CG_WeaponIndex(cg.weaponSelect, &bank, NULL); cg.lastWeapSelInBank[bank] = cg.weaponSelect; } if( cg.predictedPlayerState.stats[STAT_PLAYER_CLASS] == PC_COVERTOPS ) { cg.pmext.silencedSideArm = 1; } cg.proneMovingTime = 0; // reset fog to world fog (if present) trap_R_SetFog(FOG_CMD_SWITCHFOG, FOG_MAP,20,0,0,0,0); // dhm - end }
/* ================ CG_Respawn A respawn happened this snapshot ================ */ void CG_Respawn(qboolean revived) { static int oldTeam = -1; static int oldCls = -1; cg.serverRespawning = qfalse; // just in case // no error decay on player movement cg.thisFrameTeleport = qtrue; // need to reset client-side weapon animations cg.predictedPlayerState.weapAnim = ((cg.predictedPlayerState.weapAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | PM_IdleAnimForWeapon(cg.snap->ps.weapon); // reset weapon animations cg.predictedPlayerState.weaponstate = WEAPON_READY; // hmm, set this? what to? // display weapons available cg.weaponSelectTime = cg.time; cg.cursorHintIcon = 0; cg.cursorHintTime = 0; // select the weapon the server says we are using cg.weaponSelect = cg.snap->ps.weapon; // clear even more things on respawn cg.zoomedBinoc = qfalse; cg.zoomedScope = qfalse; cg.zoomTime = 0; cg.zoomval = 0; trap_SendConsoleCommand("-zoom\n"); cg.binocZoomTime = 0; // ensure scoped weapons are reset after revive if (revived) { if (cg.snap->ps.weapon == WP_FG42SCOPE) { CG_FinishWeaponChange(WP_FG42SCOPE, WP_FG42); } if (cg.snap->ps.weapon == WP_GARAND_SCOPE) { CG_FinishWeaponChange(WP_GARAND_SCOPE, WP_GARAND); } if (cg.snap->ps.weapon == WP_K43_SCOPE) { CG_FinishWeaponChange(WP_K43_SCOPE, WP_K43); } } // clear pmext memset(&cg.pmext, 0, sizeof(cg.pmext)); cg.pmext.bAutoReload = (cg_autoReload.integer > 0); cg.pmext.sprintTime = SPRINTTIME; if (!revived) { cgs.limboLoadoutSelected = qfalse; } // Saves the state of sidearm (riflenade weapon is considered as one too) // Puts the silencer on if class is COVERTOPS // Puts riflenade on if current weapon is riflenade weapon if (cg.predictedPlayerState.stats[STAT_PLAYER_CLASS] == PC_COVERTOPS) { cg.pmext.silencedSideArm = 1; } else if (cg.predictedPlayerState.weapon == WP_GPG40 || cg.predictedPlayerState.weapon == WP_M7) { cg.pmext.silencedSideArm = 2; } cg.proneMovingTime = 0; // reset fog to world fog (if present) trap_R_SetFog(FOG_CMD_SWITCHFOG, FOG_MAP, 20, 0, 0, 0, 0); // try to exec a cfg file if it is found if (!revived) { if ((cgs.clientinfo[cg.clientNum].team == TEAM_AXIS || cgs.clientinfo[cg.clientNum].team == TEAM_ALLIES) && (cgs.clientinfo[cg.clientNum].cls != oldCls)) { CG_execFile(va("autoexec_%s", BG_ClassnameForNumberFilename(cgs.clientinfo[cg.clientNum].cls))); oldCls = cgs.clientinfo[cg.clientNum].cls; } if (cgs.clientinfo[cg.clientNum].team != oldTeam) { CG_execFile(va("autoexec_%s", BG_TeamnameForNumber(cgs.clientinfo[cg.clientNum].team))); oldTeam = cgs.clientinfo[cg.clientNum].team; } } }
/* =========== ClientSpawn Called every time a client is placed fresh in the world: after the first ClientBegin, and after each respawn Initializes all non-persistant parts of playerState ============ */ void ClientSpawn(gentity_t *ent) { int index; vec3_t spawn_origin, spawn_angles; gclient_t *client; int i; clientPersistant_t saved; clientSession_t savedSess; int persistant[MAX_PERSISTANT]; gentity_t *spawnPoint; int flags; int savedPing; int savedTeam; qboolean update = qfalse; save_position_t *pos = NULL; index = ent - g_entities; client = ent->client; G_UpdateSpawnCounts(); client->pers.lastSpawnTime = level.time; if (client->sess.sessionTeam != TEAM_AXIS && client->sess.sessionTeam != TEAM_ALLIES) { spawnPoint = SelectSpectatorSpawnPoint(spawn_origin, spawn_angles); } else { spawnPoint = SelectPlayerSpawnPoint(client->sess.sessionTeam, spawn_origin, spawn_angles, client->sess.spawnObjectiveIndex); } client->pers.teamState.state = TEAM_ACTIVE; // toggle the teleport bit so the client knows to not lerp flags = ent->client->ps.eFlags & EF_TELEPORT_BIT; flags ^= EF_TELEPORT_BIT; flags |= (client->ps.eFlags & EF_VOTED); // clear everything but the persistant data ent->s.eFlags &= ~EF_MOUNTEDTANK; // Nico, notify timerun_stop notify_timerun_stop(ent, 0); ent->client->sess.timerunActive = qfalse; saved = client->pers; savedSess = client->sess; savedPing = client->ps.ping; savedTeam = client->ps.teamNum; for (i = 0 ; i < MAX_PERSISTANT ; i++) { persistant[i] = client->ps.persistant[i]; } memset(client, 0, sizeof (*client)); client->pers = saved; client->sess = savedSess; client->ps.ping = savedPing; client->ps.teamNum = savedTeam; for (i = 0 ; i < MAX_PERSISTANT ; i++) { client->ps.persistant[i] = persistant[i]; } // increment the spawncount so the client will detect the respawn client->ps.persistant[PERS_SPAWN_COUNT]++; client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam; client->ps.persistant[PERS_HWEAPON_USE] = 0; client->airOutTime = level.time + 12000; // clear entity values client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth; client->ps.eFlags = flags; ent->s.groundEntityNum = ENTITYNUM_NONE; ent->client = &level.clients[index]; ent->takedamage = qtrue; ent->inuse = qtrue; ent->classname = "player"; ent->r.contents = CONTENTS_BODY; ent->clipmask = MASK_PLAYERSOLID; // DHM - Nerve :: Init to -1 on first spawn; ent->props_frame_state = -1; ent->die = player_die; ent->waterlevel = 0; ent->watertype = 0; ent->flags = 0; VectorCopy(playerMins, ent->r.mins); VectorCopy(playerMaxs, ent->r.maxs); // Ridah, setup the bounding boxes and viewheights for prediction VectorCopy(ent->r.mins, client->ps.mins); VectorCopy(ent->r.maxs, client->ps.maxs); client->ps.crouchViewHeight = CROUCH_VIEWHEIGHT; client->ps.standViewHeight = DEFAULT_VIEWHEIGHT; client->ps.deadViewHeight = DEAD_VIEWHEIGHT; client->ps.crouchMaxZ = client->ps.maxs[2] - (client->ps.standViewHeight - client->ps.crouchViewHeight); client->ps.runSpeedScale = 0.8; client->ps.sprintSpeedScale = 1.1; client->ps.crouchSpeedScale = 0.25; client->ps.weaponstate = WEAPON_READY; // Rafael client->ps.friction = 1.0; // done. // TTimo // retrieve from the persistant storage (we use this in pmoveExt_t beause we need it in bg_*) client->pmext.bAutoReload = client->pers.bAutoReloadAux; // done client->ps.clientNum = index; trap_GetUsercmd(client - level.clients, &ent->client->pers.cmd); // NERVE - SMF - moved this up here if (client->sess.playerType != client->sess.latchPlayerType) { update = qtrue; } client->sess.playerType = client->sess.latchPlayerType; if (client->sess.playerWeapon != client->sess.latchPlayerWeapon) { client->sess.playerWeapon = client->sess.latchPlayerWeapon; update = qtrue; } client->sess.playerWeapon2 = client->sess.latchPlayerWeapon2; if (update) { ClientUserinfoChanged(index); } G_UpdateCharacter(client); SetWolfSpawnWeapons(client); client->pers.maxHealth = 125; client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth; client->pers.cmd.weapon = ent->client->ps.weapon; // dhm - end ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH]; G_SetOrigin(ent, spawn_origin); VectorCopy(spawn_origin, client->ps.origin); // the respawned flag will be cleared after the attack and jump keys come up client->ps.pm_flags |= PMF_RESPAWNED; SetClientViewAngle(ent, spawn_angles); if (ent->client->sess.sessionTeam != TEAM_SPECTATOR) { trap_LinkEntity(ent); } client->inactivityTime = level.time + g_inactivity.integer * 1000; client->latched_buttons = 0; client->latched_wbuttons = 0; //----(SA) added // fire the targets of the spawn point G_UseTargets(spawnPoint, ent); // run a client frame to drop exactly to the floor, // initialize animations and other things client->ps.commandTime = level.time - 100; ent->client->pers.cmd.serverTime = level.time; ClientThink(ent - g_entities); // positively link the client, even if the command times are weird if (ent->client->sess.sessionTeam != TEAM_SPECTATOR) { BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue); VectorCopy(ent->client->ps.origin, ent->r.currentOrigin); trap_LinkEntity(ent); } // run the presend to set anything else ClientEndFrame(ent); // set idle animation on weapon ent->client->ps.weapAnim = ((ent->client->ps.weapAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | PM_IdleAnimForWeapon(ent->client->ps.weapon); // clear entity state values BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue); // show_bug.cgi?id=569 G_ResetMarkers(ent); // RF, start the scripting system if (client->sess.sessionTeam != TEAM_SPECTATOR) { // RF, call entity scripting event G_Script_ScriptEvent(ent, "playerstart", ""); } // Nico, autoload position if (ent->client->pers.autoLoad && !ent->client->sess.lastDieWasASelfkill && (ent->client->sess.sessionTeam == TEAM_AXIS || ent->client->sess.sessionTeam == TEAM_ALLIES)) { if (ent->client->sess.sessionTeam == TEAM_ALLIES) { pos = ent->client->sess.alliesSaves; } else { pos = ent->client->sess.axisSaves; } if (pos->valid) { VectorCopy(pos->origin, ent->client->ps.origin); // Nico, load angles if cg_loadViewAngles = 1 if (ent->client->pers.loadViewAngles) { SetClientViewAngle(ent, pos->vangles); } // Nico, load saved weapon if cg_loadWeapon = 1 if (ent->client->pers.loadWeapon) { ent->client->ps.weapon = pos->weapon; } VectorClear(ent->client->ps.velocity); if (ent->client->ps.stats[STAT_HEALTH] < 100 && ent->client->ps.stats[STAT_HEALTH] > 0) { ent->health = 100; } } } }