void G_RemoveFromAllIgnoreLists( int clientNum ) { int i; for ( i = 0; i < MAX_CLIENTS; i++ ) { COM_BitClear( level.clients[i].sess.ignoreClients, clientNum ); } }
void G_DropBinocs( gentity_t *ent ) { vec3_t angles, velocity, org, offset, mins, maxs; gclient_t *client = ent->client; gentity_t *ent2; gitem_t *item; trace_t tr; item = BG_FindItemForWeapon( WP_BINOCULARS ); VectorCopy( client->ps.viewangles, angles ); // clamp pitch if ( angles[PITCH] < -30 ) angles[PITCH] = -30; else if ( angles[PITCH] > 30 ) angles[PITCH] = 30; AngleVectors( angles, velocity, NULL, NULL ); VectorScale( velocity, 64, offset ); offset[2] += client->ps.viewheight / 2.f; VectorScale( velocity, 75, velocity ); velocity[2] += 50 + random() * 35; VectorAdd( client->ps.origin, offset, org ); VectorSet( mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 ); VectorSet( maxs, ITEM_RADIUS, ITEM_RADIUS, 2*ITEM_RADIUS ); trap_Trace( &tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID ); VectorCopy( tr.endpos, org ); ent2 = LaunchBinocs( item, org, velocity, client->ps.clientNum ); COM_BitClear( client->ps.weapons, WP_BINOCULARS ); // Clear out empty weapon, change to next best weapon G_AddEvent( ent, EV_WEAPONSWITCHED, 0 ); if( WP_BINOCULARS == client->ps.weapon ) client->ps.weapon = 0; client->ps.ammoclip[BG_FindClipForWeapon(WP_BINOCULARS)] = 0; }
void G_DropWeapon( gentity_t *ent, weapon_t weapon ) { vec3_t angles, velocity, org, offset, mins, maxs; gclient_t *client = ent->client; gentity_t *ent2; gitem_t *item; trace_t tr; item = BG_FindItemForWeapon( weapon ); VectorCopy( client->ps.viewangles, angles ); // clamp pitch if ( angles[PITCH] < -30 ) angles[PITCH] = -30; else if ( angles[PITCH] > 30 ) angles[PITCH] = 30; AngleVectors( angles, velocity, NULL, NULL ); VectorScale( velocity, 64, offset ); offset[2] += client->ps.viewheight / 2.f; VectorScale( velocity, 75, velocity ); velocity[2] += 50 + random() * 35; VectorAdd( client->ps.origin, offset, org ); VectorSet( mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 ); VectorSet( maxs, ITEM_RADIUS, ITEM_RADIUS, 2*ITEM_RADIUS ); trap_Trace( &tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID ); VectorCopy( tr.endpos, org ); ent2 = LaunchItem( item, org, velocity, client->ps.clientNum ); COM_BitClear( client->ps.weapons, weapon ); if( weapon == WP_KAR98 ) { COM_BitClear( client->ps.weapons, WP_GPG40 ); } else if ( weapon == WP_CARBINE ) { COM_BitClear( client->ps.weapons, WP_M7 ); } else if ( weapon == WP_FG42 ) { COM_BitClear( client->ps.weapons, WP_FG42SCOPE ); } else if( weapon == WP_K43 ) { COM_BitClear( client->ps.weapons, WP_K43_SCOPE ); } else if( weapon == WP_GARAND ) { COM_BitClear( client->ps.weapons, WP_GARAND_SCOPE ); } else if( weapon == WP_MORTAR ) { COM_BitClear( client->ps.weapons, WP_MORTAR_SET ); } else if( weapon == WP_MOBILE_MG42 ) { COM_BitClear( client->ps.weapons, WP_MOBILE_MG42_SET ); } // Clear out empty weapon, change to next best weapon G_AddEvent( ent, EV_WEAPONSWITCHED, 0 ); if( weapon == client->ps.weapon ) client->ps.weapon = 0; if( weapon == WP_MORTAR ) { ent2->count = client->ps.ammo[BG_FindAmmoForWeapon(weapon)] + client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } else { ent2->count = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } if( weapon == WP_KAR98 || weapon == WP_CARBINE ) { ent2->delay = client->ps.ammo[BG_FindAmmoForWeapon(weapAlts[weapon])] + client->ps.ammoclip[BG_FindClipForWeapon(weapAlts[weapon])]; } else { ent2->delay = 0; } // ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; // Gordon: um, modifying an item is not a good idea client->ps.ammoclip[BG_FindClipForWeapon(weapon)] = 0; }
/* ============== ClientThink This will be called once for each client frame, which will usually be a couple times for each server frame on fast clients. If "g_synchronousClients 1" is set, this will be called exactly once for each server frame, which makes for smooth demo recording. ============== */ void ClientThink_real( gentity_t *ent ) { gclient_t *client; pmove_t pm; // vec3_t oldOrigin; int oldEventSequence; int msec; usercmd_t *ucmd; int monsterslick = 0; // JPW NERVE int i; vec3_t muzzlebounce; gitem_t *item; gentity_t *ent2; vec3_t velocity, org, offset; vec3_t angles,mins,maxs; int weapon; trace_t tr; // jpw // Rafael wolfkick //int validkick; //static int wolfkicktimer = 0; client = ent->client; // don't think if the client is not yet connected (and thus not yet spawned in) if ( client->pers.connected != CON_CONNECTED ) { return; } if ( client->cameraPortal ) { G_SetOrigin( client->cameraPortal, client->ps.origin ); trap_LinkEntity( client->cameraPortal ); VectorCopy( client->cameraOrigin, client->cameraPortal->s.origin2 ); } // mark the time, so the connection sprite can be removed ucmd = &ent->client->pers.cmd; ent->client->ps.identifyClient = ucmd->identClient; // NERVE - SMF // JPW NERVE -- update counter for capture & hold display if ( g_gametype.integer == GT_WOLF_CPH ) { client->ps.stats[STAT_CAPTUREHOLD_RED] = level.capturetimes[TEAM_RED]; client->ps.stats[STAT_CAPTUREHOLD_BLUE] = level.capturetimes[TEAM_BLUE]; } // jpw // sanity check the command time to prevent speedup cheating if ( ucmd->serverTime > level.time + 200 ) { ucmd->serverTime = level.time + 200; // G_Printf("serverTime <<<<<\n" ); } if ( ucmd->serverTime < level.time - 1000 ) { ucmd->serverTime = level.time - 1000; // G_Printf("serverTime >>>>>\n" ); } msec = ucmd->serverTime - client->ps.commandTime; // following others may result in bad times, but we still want // to check for follow toggles if ( msec < 1 && client->sess.spectatorState != SPECTATOR_FOLLOW ) { return; /* // Ridah, fixes savegame timing issue if (msec < -100) { client->ps.commandTime = ucmd->serverTime - 100; msec = 100; } else { return; } */ // done. } if ( msec > 200 ) { msec = 200; } if ( pmove_msec.integer < 8 ) { trap_Cvar_Set( "pmove_msec", "8" ); } else if ( pmove_msec.integer > 33 ) { trap_Cvar_Set( "pmove_msec", "33" ); } if ( pmove_fixed.integer || client->pers.pmoveFixed ) { ucmd->serverTime = ( ( ucmd->serverTime + pmove_msec.integer - 1 ) / pmove_msec.integer ) * pmove_msec.integer; //if (ucmd->serverTime - client->ps.commandTime <= 0) // return; } // // check for exiting intermission // if ( level.intermissiontime ) { ClientIntermissionThink( client ); return; } // spectators don't do much // DHM - Nerve :: In limbo use SpectatorThink if ( client->sess.sessionTeam == TEAM_SPECTATOR || client->ps.pm_flags & PMF_LIMBO ) { if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) { return; } SpectatorThink( ent, ucmd ); return; } // JPW NERVE do some time-based muzzle flip -- this never gets touched in single player (see g_weapon.c) // #define RIFLE_SHAKE_TIME 150 // JPW NERVE this one goes with the commented out old damped "realistic" behavior below #define RIFLE_SHAKE_TIME 300 // per Id request, longer recoil time if ( client->sniperRifleFiredTime ) { if ( level.time - client->sniperRifleFiredTime > RIFLE_SHAKE_TIME ) { client->sniperRifleFiredTime = 0; } else { VectorCopy( client->ps.viewangles,muzzlebounce ); // JPW per Id request, longer recoil time muzzlebounce[PITCH] -= 2 * cos( 2.5 * ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME ); muzzlebounce[YAW] += 0.5*client->sniperRifleMuzzleYaw*cos( 1.0 - ( level.time - client->sniperRifleFiredTime ) * 3 / RIFLE_SHAKE_TIME ); muzzlebounce[PITCH] -= 0.25 * random() * ( 1.0f - ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME ); muzzlebounce[YAW] += 0.5 * crandom() * ( 1.0f - ( level.time - client->sniperRifleFiredTime ) / RIFLE_SHAKE_TIME ); SetClientViewAngle( ent,muzzlebounce ); } } if ( client->ps.stats[STAT_PLAYER_CLASS] == PC_MEDIC ) { if ( level.time > client->ps.powerups[PW_REGEN] + 5000 ) { client->ps.powerups[PW_REGEN] = level.time; } } // also update weapon recharge time // JPW drop button drops secondary weapon so new one can be picked up // TTimo explicit braces to avoid ambiguous 'else' if ( g_gametype.integer != GT_SINGLE_PLAYER ) { if ( ucmd->wbuttons & WBUTTON_DROP ) { if ( !client->dropWeaponTime ) { client->dropWeaponTime = 1; // just latch it for now if ( ( client->ps.stats[STAT_PLAYER_CLASS] == PC_SOLDIER ) || ( client->ps.stats[STAT_PLAYER_CLASS] == PC_LT ) ) { for ( i = 0; i < MAX_WEAPS_IN_BANK_MP; i++ ) { weapon = weapBanksMultiPlayer[3][i]; if ( COM_BitCheck( client->ps.weapons,weapon ) ) { item = BG_FindItemForWeapon( weapon ); VectorCopy( client->ps.viewangles, angles ); // clamp pitch if ( angles[PITCH] < -30 ) { angles[PITCH] = -30; } else if ( angles[PITCH] > 30 ) { angles[PITCH] = 30; } AngleVectors( angles, velocity, NULL, NULL ); VectorScale( velocity, 64, offset ); offset[2] += client->ps.viewheight / 2; VectorScale( velocity, 75, velocity ); velocity[2] += 50 + random() * 35; VectorAdd( client->ps.origin,offset,org ); VectorSet( mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 ); VectorSet( maxs, ITEM_RADIUS, ITEM_RADIUS, 2 * ITEM_RADIUS ); trap_Trace( &tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID ); VectorCopy( tr.endpos, org ); ent2 = LaunchItem( item, org, velocity, client->ps.clientNum ); COM_BitClear( client->ps.weapons,weapon ); if ( weapon == WP_MAUSER ) { COM_BitClear( client->ps.weapons,WP_SNIPERRIFLE ); } // Clear out empty weapon, change to next best weapon G_AddEvent( ent, EV_NOAMMO, 0 ); i = MAX_WEAPS_IN_BANK_MP; // show_bug.cgi?id=568 if ( client->ps.weapon == weapon ) { client->ps.weapon = 0; } ent2->count = client->ps.ammoclip[BG_FindClipForWeapon( weapon )]; ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon( weapon )]; client->ps.ammoclip[BG_FindClipForWeapon( weapon )] = 0; } } } } } else { client->dropWeaponTime = 0; } } // jpw // check for inactivity timer, but never drop the local client of a non-dedicated server if ( !ClientInactivityTimer( client ) ) { return; } if ( reloading || client->cameraPortal ) { ucmd->buttons = 0; ucmd->forwardmove = 0; ucmd->rightmove = 0; ucmd->upmove = 0; ucmd->wbuttons = 0; ucmd->wolfkick = 0; if ( client->cameraPortal ) { client->ps.pm_type = PM_FREEZE; } } else if ( client->noclip ) { client->ps.pm_type = PM_NOCLIP; } else if ( client->ps.stats[STAT_HEALTH] <= 0 ) { client->ps.pm_type = PM_DEAD; } else { client->ps.pm_type = PM_NORMAL; } // set parachute anim condition flag BG_UpdateConditionValue( ent->s.number, ANIM_COND_PARACHUTE, ( ent->flags & FL_PARACHUTE ) != 0, qfalse ); // all playing clients are assumed to be in combat mode if ( !client->ps.aiChar ) { client->ps.aiState = AISTATE_COMBAT; } client->ps.gravity = g_gravity.value; // set speed client->ps.speed = g_speed.value; if ( client->ps.powerups[PW_HASTE] ) { client->ps.speed *= 1.3; } // set up for pmove oldEventSequence = client->ps.eventSequence; client->currentAimSpreadScale = (float)client->ps.aimSpreadScale / 255.0; memset( &pm, 0, sizeof( pm ) ); pm.ps = &client->ps; pm.pmext = &client->pmext; pm.cmd = *ucmd; pm.oldcmd = client->pers.oldcmd; if ( pm.ps->pm_type == PM_DEAD ) { pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY; // DHM-Nerve added:: EF_DEAD is checked for in Pmove functions, but wasn't being set // until after Pmove pm.ps->eFlags |= EF_DEAD; // dhm-Nerve end } else { pm.tracemask = MASK_PLAYERSOLID; } // MrE: always use capsule for AI and player //pm.trace = trap_TraceCapsule;//trap_Trace; //DHM - Nerve :: We've gone back to using normal bbox traces pm.trace = trap_Trace; pm.pointcontents = trap_PointContents; pm.debugLevel = g_debugMove.integer; pm.noFootsteps = ( g_dmflags.integer & DF_NO_FOOTSTEPS ) > 0; pm.pmove_fixed = pmove_fixed.integer | client->pers.pmoveFixed; pm.pmove_msec = pmove_msec.integer; pm.noWeapClips = ( g_dmflags.integer & DF_NO_WEAPRELOAD ) > 0; if ( ent->aiCharacter && AICast_NoReload( ent->s.number ) ) { pm.noWeapClips = qtrue; // ensure AI characters don't use clips if they're not supposed to. } // Ridah // if (ent->r.svFlags & SVF_NOFOOTSTEPS) // pm.noFootsteps = qtrue; VectorCopy( client->ps.origin, client->oldOrigin ); // NERVE - SMF pm.gametype = g_gametype.integer; pm.ltChargeTime = g_LTChargeTime.integer; pm.soldierChargeTime = g_soldierChargeTime.integer; pm.engineerChargeTime = g_engineerChargeTime.integer; pm.medicChargeTime = g_medicChargeTime.integer; // -NERVE - SMF monsterslick = Pmove( &pm ); if ( monsterslick && !( ent->flags & FL_NO_MONSTERSLICK ) ) { //vec3_t dir; //vec3_t kvel; //vec3_t forward; // TTimo gcc: might be used unitialized in this function float angle = 0.0f; qboolean bogus = qfalse; // NE if ( ( monsterslick & SURF_MONSLICK_N ) && ( monsterslick & SURF_MONSLICK_E ) ) { angle = 45; } // NW else if ( ( monsterslick & SURF_MONSLICK_N ) && ( monsterslick & SURF_MONSLICK_W ) ) { angle = 135; } // N else if ( monsterslick & SURF_MONSLICK_N ) { angle = 90; } // SE else if ( ( monsterslick & SURF_MONSLICK_S ) && ( monsterslick & SURF_MONSLICK_E ) ) { angle = 315; } // SW else if ( ( monsterslick & SURF_MONSLICK_S ) && ( monsterslick & SURF_MONSLICK_W ) ) { angle = 225; } // S else if ( monsterslick & SURF_MONSLICK_S ) { angle = 270; } // E else if ( monsterslick & SURF_MONSLICK_E ) { angle = 0; } // W else if ( monsterslick & SURF_MONSLICK_W ) { angle = 180; } else { bogus = qtrue; } } // server cursor hints if ( ent->lastHintCheckTime < level.time ) { G_CheckForCursorHints( ent ); ent->lastHintCheckTime = level.time + FRAMETIME; } // DHM - Nerve :: Set animMovetype to 1 if ducking if ( ent->client->ps.pm_flags & PMF_DUCKED ) { ent->s.animMovetype = 1; } else { ent->s.animMovetype = 0; } // save results of pmove if ( ent->client->ps.eventSequence != oldEventSequence ) { ent->eventTime = level.time; ent->r.eventTime = level.time; } // Ridah, fixes jittery zombie movement if ( g_smoothClients.integer ) { BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue ); } else { BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); } if ( !( ent->client->ps.eFlags & EF_FIRING ) ) { client->fireHeld = qfalse; // for grapple } // // // use the precise origin for linking // VectorCopy( ent->client->ps.origin, ent->r.currentOrigin ); // // // use the snapped origin for linking so it matches client predicted versions VectorCopy( ent->s.pos.trBase, ent->r.currentOrigin ); VectorCopy( pm.mins, ent->r.mins ); VectorCopy( pm.maxs, ent->r.maxs ); ent->waterlevel = pm.waterlevel; ent->watertype = pm.watertype; // execute client events ClientEvents( ent, oldEventSequence ); // link entity now, after any personal teleporters have been used trap_LinkEntity( ent ); if ( !ent->client->noclip ) { G_TouchTriggers( ent ); } // NOTE: now copy the exact origin over otherwise clients can be snapped into solid VectorCopy( ent->client->ps.origin, ent->r.currentOrigin ); // store the client's current position for antilag traces G_StoreClientPosition( ent ); // touch other objects ClientImpacts( ent, &pm ); // save results of triggers and client events if ( ent->client->ps.eventSequence != oldEventSequence ) { ent->eventTime = level.time; } // swap and latch button actions client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; client->latched_buttons = client->buttons & ~client->oldbuttons; // client->latched_buttons |= client->buttons & ~client->oldbuttons; // FIXME:? (SA) MP method (causes problems for us. activate 'sticks') //----(SA) added client->oldwbuttons = client->wbuttons; client->wbuttons = ucmd->wbuttons; client->latched_wbuttons = client->wbuttons & ~client->oldwbuttons; // client->latched_wbuttons |= client->wbuttons & ~client->oldwbuttons; // FIXME:? (SA) MP method // Rafael - Activate // Ridah, made it a latched event (occurs on keydown only) if ( client->latched_buttons & BUTTON_ACTIVATE ) { Cmd_Activate_f( ent ); } if ( ent->flags & FL_NOFATIGUE ) { ent->client->ps.sprintTime = 20000; } // check for respawning if ( client->ps.stats[STAT_HEALTH] <= 0 ) { // DHM - Nerve if ( g_gametype.integer >= GT_WOLF ) { WolfFindMedic( ent ); } // dhm - end // wait for the attack button to be pressed if ( level.time > client->respawnTime ) { // forcerespawn is to prevent users from waiting out powerups if ( ( g_gametype.integer != GT_SINGLE_PLAYER ) && ( g_forcerespawn.integer > 0 ) && ( ( level.time - client->respawnTime ) > g_forcerespawn.integer * 1000 ) && ( !( ent->client->ps.pm_flags & PMF_LIMBO ) ) ) { // JPW NERVE // JPW NERVE if ( g_gametype.integer >= GT_WOLF ) { limbo( ent, qtrue ); } else { respawn( ent ); } // jpw return; } // DHM - Nerve :: Single player game respawns immediately as before, // but in multiplayer, require button press before respawn if ( g_gametype.integer == GT_SINGLE_PLAYER ) { respawn( ent ); } // NERVE - SMF - we want to only respawn on jump button now else if ( ( ucmd->upmove > 0 ) && ( !( ent->client->ps.pm_flags & PMF_LIMBO ) ) ) { // JPW NERVE // JPW NERVE if ( g_gametype.integer >= GT_WOLF ) { limbo( ent, qtrue ); } else { respawn( ent ); } // jpw } // dhm - Nerve :: end // NERVE - SMF - we want to immediately go to limbo mode if gibbed else if ( client->ps.stats[STAT_HEALTH] <= GIB_HEALTH && !( ent->client->ps.pm_flags & PMF_LIMBO ) ) { if ( g_gametype.integer >= GT_WOLF ) { limbo( ent, qfalse ); } else { respawn( ent ); } } // -NERVE - SMF } return; } // perform once-a-second actions ClientTimerActions( ent, msec ); }
/** * @brief Drop weapon. */ void G_DropWeapon(gentity_t *ent, weapon_t weapon) { vec3_t angles, velocity, org, offset, mins, maxs; gclient_t *client = ent->client; gentity_t *ent2; gitem_t *item; trace_t tr; if (!IS_VALID_WEAPON(weapon)) { return; } item = BG_FindItemForWeapon(weapon); VectorCopy(client->ps.viewangles, angles); // clamp pitch if (angles[PITCH] < -30) { angles[PITCH] = -30; } else if (angles[PITCH] > 30) { angles[PITCH] = 30; } AngleVectors(angles, velocity, NULL, NULL); VectorScale(velocity, 64, offset); offset[2] += client->ps.viewheight / 2.f; VectorScale(velocity, 75, velocity); velocity[2] += 50 + random() * 35; VectorAdd(client->ps.origin, offset, org); VectorSet(mins, -ITEM_RADIUS, -ITEM_RADIUS, 0); VectorSet(maxs, ITEM_RADIUS, ITEM_RADIUS, 2 * ITEM_RADIUS); trap_Trace(&tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID); VectorCopy(tr.endpos, org); ent2 = LaunchItem(item, org, velocity, client->ps.clientNum); COM_BitClear(client->ps.weapons, weapon); switch (weapon) { case WP_KAR98: COM_BitClear(client->ps.weapons, WP_GPG40); break; case WP_CARBINE: COM_BitClear(client->ps.weapons, WP_M7); break; case WP_FG42: COM_BitClear(client->ps.weapons, WP_FG42SCOPE); break; case WP_K43: COM_BitClear(client->ps.weapons, WP_K43_SCOPE); break; case WP_GARAND: COM_BitClear(client->ps.weapons, WP_GARAND_SCOPE); break; case WP_MORTAR: COM_BitClear(client->ps.weapons, WP_MORTAR_SET); break; case WP_MORTAR2: COM_BitClear(client->ps.weapons, WP_MORTAR2_SET); break; case WP_MOBILE_MG42: COM_BitClear(client->ps.weapons, WP_MOBILE_MG42_SET); break; case WP_MOBILE_BROWNING: COM_BitClear(client->ps.weapons, WP_MOBILE_BROWNING_SET); break; default: break; } // Clear out empty weapon, change to next best weapon G_AddEvent(ent, EV_WEAPONSWITCHED, 0); if (weapon == client->ps.weapon) { client->ps.weapon = 0; } if (IS_MORTAR_WEAPON_SET(weapon)) { ent2->count = client->ps.ammo[BG_FindAmmoForWeapon(weapon)] + client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } else { ent2->count = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } if (weapon == WP_KAR98 || weapon == WP_CARBINE) { ent2->delay = client->ps.ammo[BG_FindAmmoForWeapon(weaponTable[weapon].weapAlts)]; } else { ent2->delay = 0; } // ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; // um, modifying an item is not a good idea client->ps.ammoclip[BG_FindClipForWeapon(weapon)] = 0; #ifdef FEATURE_OMNIBOT Bot_Event_RemoveWeapon(client->ps.clientNum, Bot_WeaponGameToBot(weapon)); #endif }
static int PM_Weapon_CheckForRechamber(int time) { return 0; #define int_ptr_val(x) (*(int*)((int)x)) pmove_t *xm = *(pmove_t**)(int)pm; #define ps_off(type, off) (*(type*)((int)xm->ps + off)) int *weaponstate = (int*)((int)xm->ps + 180); int *weapons = *(int**)((int)xm->ps + 796); int weapon = *(int*)((int)xm->ps + 176); int *weaponTime = (int*)((int)xm->ps + 44); int *weaponDelay = (int*)((int)xm->ps + 48); int v2 = *(int*)((int)pml + 132); if(!int_ptr_val(v2 + 712)) return 0; if(!COM_BitCheck(weapons, weapon)) return 0; if(*weaponstate == WEAPON_RECHAMBERING) { if(time) { COM_BitClear(weapons, weapon); PM_AddEvent(EV_EJECT_BRASS); if(*weaponTime) return 1; } } if(!*weaponTime || ((*weaponstate - WEAPON_FIRING) > WEAPON_RAISING && *weaponstate != WEAPON_MELEE_WINDUP && *weaponstate != WEAPON_MELEE_RELAX && !*weaponDelay)) { if(*weaponstate == WEAPON_RECHAMBERING) { if(xm->cmd.wbuttons) { int *v9 = (int*)((int)xm->ps + 980); if(*v9 & 0xFFFFFDFF) { if(xm->ps->pm_type <= 5) { int v6 = *v9 & 0x200; BYTE1(v6) ^= 2; *v9 = v6; } } } *weaponstate = WEAPON_READY; return 0; } } if(*weaponstate == WEAPON_READY) { if(xm->ps->pm_type > 5 || !xm->cmd.wbuttons) goto label_27; /* v8 = 0.75 < *(float *)(v2 + 184); v9 = 0; v10 = 0.75 == *(float *)(v2 + 184); if ( (HIBYTE(v7) & 0x45) == 1 ) { if ( *(_DWORD *)(v2 + 4) > 5 || !*(_BYTE *)(xm + 10) ) goto LABEL_27; v11 = *(_DWORD *)(v2 + 980) & 0x200; BYTE1(v11) ^= 2u; LOBYTE(v11) = 7; } else { if ( *(_DWORD *)(v2 + 4) > 5 || !*(_BYTE *)(xm + 10) ) goto LABEL_27; v11 = *(_DWORD *)(v2 + 980) & 0x200; BYTE1(v11) ^= 2u; LOBYTE(v11) = 4; } *(_DWORD *)(v2 + 980) = v11; */ //set cool stuff for keys? //ps_off(int,980) = label_27: *weaponstate = WEAPON_RECHAMBERING; *weaponTime = int_ptr_val(v2 + 472); int v13 = int_ptr_val(v2 + 476); /* if(v13 && v13 < *weaponTime) *weaponDelay = v13; else *weaponDelay = 1;*/ PM_AddEvent(EV_RECHAMBER_WEAPON); } return 0; #undef int_ptr_val }
/** * @brief Drop Weapon * @param[in] ent * @param[in] weapon */ void G_DropWeapon(gentity_t *ent, weapon_t weapon) { vec3_t angles, velocity, org, offset, mins, maxs; gclient_t *client = ent->client; gentity_t *ent2; gitem_t *item; trace_t tr; if (!IS_VALID_WEAPON(weapon)) { return; } item = BG_FindItemForWeapon(weapon); VectorCopy(client->ps.viewangles, angles); // clamp pitch if (angles[PITCH] < -30) { angles[PITCH] = -30; } else if (angles[PITCH] > 30) { angles[PITCH] = 30; } AngleVectors(angles, velocity, NULL, NULL); VectorScale(velocity, 64, offset); offset[2] += client->ps.viewheight / 2.f; VectorScale(velocity, 75, velocity); velocity[2] += 50 + random() * 35; VectorAdd(client->ps.origin, offset, org); VectorSet(mins, -ITEM_RADIUS, -ITEM_RADIUS, 0); VectorSet(maxs, ITEM_RADIUS, ITEM_RADIUS, 2 * ITEM_RADIUS); trap_Trace(&tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID); VectorCopy(tr.endpos, org); ent2 = LaunchItem(item, org, velocity, client->ps.clientNum); COM_BitClear(client->ps.weapons, weapon); if (GetWeaponTableData(weapon)->weapAlts != WP_NONE) { weapon_t weapAlts = GetWeaponTableData(weapon)->weapAlts; if (GetWeaponTableData(weapAlts)->isRiflenade || GetWeaponTableData(weapAlts)->isScoped || GetWeaponTableData(weapAlts)->isSetWeapon) { COM_BitClear(client->ps.weapons, weapAlts); } } // Clear out empty weapon, change to next best weapon G_AddEvent(ent, EV_WEAPONSWITCHED, 0); if (weapon == client->ps.weapon) { client->ps.weapon = 0; } if (GetWeaponTableData(weapon)->isMortarSet) { ent2->count = client->ps.ammo[GetWeaponTableData(weapon)->ammoIndex] + client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex]; } else { ent2->count = client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex]; } if (weapon == WP_KAR98 || weapon == WP_CARBINE) { ent2->delay = client->ps.ammo[GetWeaponTableData(GetWeaponTableData(weapon)->weapAlts)->ammoIndex]; } else { ent2->delay = 0; } // ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; // um, modifying an item is not a good idea client->ps.ammoclip[GetWeaponTableData(weapon)->clipIndex] = 0; #ifdef FEATURE_OMNIBOT Bot_Event_RemoveWeapon(client->ps.clientNum, Bot_WeaponGameToBot(weapon)); #endif }
/* =========== ClientDisconnect Called when a player drops from the server. Will not be called between levels. This should NOT be called directly by any game logic, call trap_DropClient(), which will call this and do server system housekeeping. ============ */ void ClientDisconnect(int clientNum) { gentity_t *ent; gentity_t *flag = NULL; gitem_t *item = NULL; vec3_t launchvel; int i; ent = g_entities + clientNum; if (!ent->client) { return; } G_RemoveClientFromFireteams(clientNum, qtrue, qfalse); G_RemoveFromAllIgnoreLists(clientNum); G_LeaveTank(ent, qfalse); // Nico, remove the client from all specInvited lists for (i = 0; i < level.numConnectedClients; ++i) { COM_BitClear(level.clients[level.sortedClients[i]].sess.specInvitedClients, clientNum); } // stop any following clients for (i = 0 ; i < level.numConnectedClients ; i++) { flag = g_entities + level.sortedClients[i]; if (flag->client->sess.sessionTeam == TEAM_SPECTATOR && flag->client->sess.spectatorState == SPECTATOR_FOLLOW && flag->client->sess.spectatorClient == clientNum) { StopFollowing(flag); } if (flag->client->ps.pm_flags & PMF_LIMBO && flag->client->sess.spectatorClient == clientNum) { Cmd_FollowCycle_f(flag, 1); } } G_FadeItems(ent, MOD_SATCHEL); // remove ourself from teamlists { mapEntityData_t *mEnt; mapEntityData_Team_t *teamList; for (i = 0; i < 2; i++) { teamList = &mapEntityData[i]; if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL) { G_FreeMapEntityData(teamList, mEnt); } mEnt = G_FindMapEntityDataSingleClient(teamList, NULL, ent->s.number, -1); while (mEnt) { mapEntityData_t *mEntFree = mEnt; mEnt = G_FindMapEntityDataSingleClient(teamList, mEnt, ent->s.number, -1); G_FreeMapEntityData(teamList, mEntFree); } } } // send effect if they were completely connected if (ent->client->pers.connected == CON_CONNECTED && ent->client->sess.sessionTeam != TEAM_SPECTATOR && !(ent->client->ps.pm_flags & PMF_LIMBO)) { // They don't get to take powerups with them! // Especially important for stuff like CTF flags // New code for tossing flags if (ent->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItem("Red Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_REDFLAG] = 0; } if (ent->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItem("Blue Flag"); if (!item) { item = BG_FindItem("Objective"); } ent->client->ps.powerups[PW_BLUEFLAG] = 0; } if (item) { // OSP - fix for suicide drop exploit through walls/gates launchvel[0] = 0; //crandom()*20; launchvel[1] = 0; //crandom()*20; launchvel[2] = 0; //10+random()*10; flag = LaunchItem(item, ent->r.currentOrigin, launchvel, ent - g_entities); flag->s.modelindex2 = ent->s.otherEntityNum2; // JPW NERVE FIXME set player->otherentitynum2 with old modelindex2 from flag and restore here flag->message = ent->message; // DHM - Nerve :: also restore item name // Clear out player's temp copies ent->s.otherEntityNum2 = 0; ent->message = NULL; } } G_LogPrintf("ClientDisconnect: %i\n", clientNum); trap_UnlinkEntity(ent); ent->s.modelindex = 0; ent->inuse = qfalse; ent->classname = "disconnected"; ent->client->pers.connected = CON_DISCONNECTED; ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE; i = ent->client->sess.sessionTeam; ent->client->sess.sessionTeam = TEAM_FREE; ent->active = 0; trap_SetConfigstring(CS_PLAYERS + clientNum, ""); CalculateRanks(); }