/* =================== PM_Toggle_Gear =================== */ void PM_Toggle_HeloGear() { if( !(availableVehicles[pm->vehicle].caps & HC_GEAR) ) { return; } if( pm->ps->ONOFF & OO_LANDED ) { return; } if( pm->cmd.serverTime < pm->ps->timers[TIMER_GEAR] && pm->ps->timers[TIMER_GEARANIM] ) { return; } if( pm->ps->speed > availableVehicles[pm->vehicle].stallspeed * 10 * SPEED_GREEN_ARC ) { pm->ps->timers[TIMER_GEAR] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime + 100; return; } if( pm->ps->ONOFF & OO_GEAR ) { PM_AddEvent( EV_GEAR_UP ); pm->ps->timers[TIMER_GEARANIM] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime; // pm->ps->ONOFF &= ~OO_GEAR; } else { PM_AddEvent( EV_GEAR_DOWN ); pm->ps->timers[TIMER_GEARANIM] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime; // pm->ps->ONOFF |= OO_GEAR; } pm->ps->timers[TIMER_GEAR] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime + 100; }
/* ============== PM_WaterEvents Generate sound events for entering and leaving water ============== */ static void PM_WaterEvents( void ) { // FIXME? // // if just entered a water volume, play a sound // if (!pml.previous_waterlevel && pm->waterlevel) { PM_AddEvent( EV_WATER_TOUCH ); } // // if just completely exited a water volume, play a sound // if (pml.previous_waterlevel && !pm->waterlevel) { PM_AddEvent( EV_WATER_LEAVE ); } // // check for head just going under water // if (pml.previous_waterlevel != 3 && pm->waterlevel == 3) { PM_AddEvent( EV_WATER_UNDER ); } // // check for head just coming out of water // if (pml.previous_waterlevel == 3 && pm->waterlevel != 3) { PM_AddEvent( EV_WATER_CLEAR ); } }
/* ============= PM_CheckJump ============= */ static qboolean PM_CheckJump( void ) { if ( pm->ps->pm_flags & PMF_RESPAWNED ) { return qfalse; // don't allow jump until all buttons are up } if ( pm->cmd.upmove < 10 ) { // not holding jump return qfalse; } // must wait for jump to be released if ( pm->ps->pm_flags & PMF_JUMP_HELD ) { // clear upmove so cmdscale doesn't lower running speed pm->cmd.upmove = 0; return qfalse; } pml.groundPlane = qfalse; // jumping away pml.walking = qfalse; pm->ps->pm_flags |= PMF_JUMP_HELD; pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->velocity[2] = JUMP_VELOCITY; PM_AddEvent( EV_JUMP ); if ( pm->cmd.forwardmove >= 0 ) { PM_ForceLegsAnim( LEGS_JUMP ); pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; } else { PM_ForceLegsAnim( LEGS_JUMPB ); pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; } return qtrue; }
static void PM_Animate( void ) { if ( pm->cmd.buttons & BUTTON_GESTURE ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_GESTURE ); pm->ps->torsoTimer = TIMER_GESTURE; PM_AddEvent( EV_TAUNT ); } } }
static void PM_BeginWeaponReload() { //works for kar98 sniper? rest not? mmhm pmove_t *xm = *(pmove_t**)(int)pm; int clientNum = *(int*)((int)xm->ps + 172); xclient_t *xcl = &xclients[clientNum]; 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 weaponinfo = BG_GetInfoForWeapon(weapon); int *weaponstate = (int*)((int)xm->ps + 180); if(*weaponstate == WEAPON_READY || *weaponstate == WEAPON_FIRING || *weaponstate == WEAPON_RECHAMBERING) { int weapon = *(int*)((int)xm->ps + 176); if(weapon) { if(weapon <= BG_GetNumWeapons()) { int weaponinfo = BG_GetInfoForWeapon(weapon); if(!*(int*)(weaponinfo + 724)) BG_AnimScriptEvent(xm->ps, 10, 0, 1); int v2 = *(int*)((int)pml + 132); if(*(int*)(v2 + 748) && *(int*)(v2 + 500)) { if(xm->ps->pm_type <= 5) { if(*(unsigned char*)((int)xm + 10)) { int v4 = *(int*)((int)xm->ps + 980) & 0x200; BYTE1(v4) ^= 2u; LOBYTE(v4) = 13; *(int*)((int)xm->ps + 980) = v4; } } if(xcl->perks[PERK_QUICK_RELOAD]) *weaponTime = (int)(*(int*)(v2 + 500) / QUICK_RELOAD_FRACTION); else *weaponTime = *(int*)(v2 + 500); *weaponstate = WEAPON_RELOAD_START; //7 PM_AddEvent(EV_RELOAD_START); PM_SetWeaponReloadAddAmmoDelay();//sub_377B8 if(xcl->perks[PERK_QUICK_RELOAD]) *weaponDelay = (int)(*weaponDelay / QUICK_RELOAD_FRACTION); } else { PM_SetReloadingState();//sub_378BC } } } } }
static void PM_SetReloadingState() { pmove_t *xm = *(pmove_t**)(int)pm; int clientNum = *(int*)((int)xm->ps + 172); xclient_t *xcl = &xclients[clientNum]; 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 weaponinfo = BG_GetInfoForWeapon(weapon); int v2 = *(int*)((int)pml + 132); int event = EV_RELOAD_FROM_EMPTY, v3; if (*(int *)(4 * *(int *)(weaponinfo + 424) + (int)xm->ps + 524) || *(int *)(v2 + 112)) { if ( xm->ps->pm_type <= 5 ) { if (xm->cmd.wbuttons ) { v3 = *(int *)((int)xm->ps + 980) & 0x200; BYTE1(v3) ^= 2u; LOBYTE(v3) = 11; *(int *)((int)xm->ps + 980) = v3; } } if(!xcl->perks[PERK_QUICK_RELOAD]) *weaponTime = *(int *)(v2 + 488); else *weaponTime = (int)(*(int *)(v2 + 488) / QUICK_RELOAD_FRACTION); event = EV_RELOAD; } else { if ( xm->ps->pm_type <= 5 ) { if (xm->cmd.wbuttons ) { v3 = *(int *)((int)xm->ps + 980) & 0x200; BYTE1(v3) ^= 2u; LOBYTE(v3) = 12; *(int *)((int)xm->ps + 980) = v3; } } if(!xcl->perks[PERK_QUICK_RELOAD]) *weaponTime = *(int *)(v2 + 492); else *weaponTime = (int)(*(int *)(v2 + 492) / QUICK_RELOAD_FRACTION); } PM_AddEvent(event); if ( *weaponstate == 8 ) *weaponstate = 6; //WEAPON_RELOADING_INTERRUPT?? else *weaponstate = 5; //WEAPON_RELOADING //if(!reloadtime->integer) PM_SetWeaponReloadAddAmmoDelay(); if(xcl->perks[PERK_QUICK_RELOAD]) *weaponDelay = (int)(*weaponDelay / QUICK_RELOAD_FRACTION); }
/* ================== PM_StepEvent ================== */ void PM_StepEvent( vec3_t from, vec3_t to, vec3_t normal ) { float size; vec3_t delta, dNormal; VectorSubtract( from, to, delta ); VectorCopy( delta, dNormal ); VectorNormalize( dNormal ); size = DotProduct( normal, dNormal ) * VectorLength( delta ); if( size > 0.0f ) { if( size > 2.0f ) { if( size < 7.0f ) PM_AddEvent( EV_STEPDN_4 ); else if( size < 11.0f ) PM_AddEvent( EV_STEPDN_8 ); else if( size < 15.0f ) PM_AddEvent( EV_STEPDN_12 ); else PM_AddEvent( EV_STEPDN_16 ); } } else { size = fabs( size ); if( size > 2.0f ) { if( size < 7.0f ) PM_AddEvent( EV_STEP_4 ); else if( size < 11.0f ) PM_AddEvent( EV_STEP_8 ); else if( size < 15.0f ) PM_AddEvent( EV_STEP_12 ); else PM_AddEvent( EV_STEP_16 ); } } if( pm->debugLevel ) Com_Printf( "%i:stepped\n", c_pmove ); }
/* =============== PM_BeginWeaponChange =============== */ static void PM_BeginWeaponChange( int weapon ) { if ( weapon <= WP_NONE || weapon >= WP_NUM_WEAPONS ) { return; } if ( !( pm->ps->stats[STAT_WEAPONS] & ( 1 << weapon ) ) ) { return; } if ( pm->ps->weaponstate == WEAPON_DROPPING ) { return; } PM_AddEvent( EV_CHANGE_WEAPON ); pm->ps->weaponstate = WEAPON_DROPPING; pm->ps->weaponTime += 200; PM_StartTorsoAnim( TORSO_DROP ); }
static void PM_Animate( void ) { if ( pm->cmd.buttons & BUTTON_GESTURE ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_GESTURE ); pm->ps->torsoTimer = TIMER_GESTURE; PM_AddEvent( EV_TAUNT ); } #ifdef MISSIONPACK } else if ( pm->cmd.buttons & BUTTON_GETFLAG ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_GETFLAG ); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } } else if ( pm->cmd.buttons & BUTTON_GUARDBASE ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_GUARDBASE ); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } } else if ( pm->cmd.buttons & BUTTON_PATROL ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_PATROL ); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } } else if ( pm->cmd.buttons & BUTTON_FOLLOWME ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_FOLLOWME ); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } } else if ( pm->cmd.buttons & BUTTON_AFFIRMATIVE ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_AFFIRMATIVE); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } } else if ( pm->cmd.buttons & BUTTON_NEGATIVE ) { if ( pm->ps->torsoTimer == 0 ) { PM_StartTorsoAnim( TORSO_NEGATIVE ); pm->ps->torsoTimer = 600; //TIMER_GESTURE; } #endif } }
/* Alien Nuke */ qboolean Alien_nuke( gentity_t *ent, int skiparg ) { //vic->client->ps.persistant[ PERS_CREDIT ] if( ent->client->ps.persistant[ PERS_CREDIT ] < 9 ) { PM_AddEvent( EV_NOAMMO ); ent->client->ps.weaponTime += 200; trap_SendServerCommand( ent-g_entities, va( "print \"^1You must have 9 evos\n\"" ) ); return qtrue; } trap_SendServerCommand( ent-g_entities, va( "print \"^1Nade Dropped\n\"" ) ); //G_TeamCommand( PTE_HUMANS, "cp \"^1Alien Nuke Detected\" 1"); ent->s.weapon = WP_GRENADE; //G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, 0 ); FireWeapon( ent ); ent->client->ps.persistant[ PERS_CREDIT ] = 0; ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; return qtrue; }
qboolean Blaster_ball( gentity_t *ent, int skiparg ) { //vic->client->ps.persistant[ PERS_CREDIT ] if( ent->client->pers.energy < 200 ) { trap_SendServerCommand( ent-g_entities, va( "print \"^1Blaster Ball Cost 200E and do 500dmg\n\"" ) ); PM_AddEvent( EV_NOAMMO ); ent->client->ps.weaponTime += 3000; //this will block the weapon 4 seconds. return qtrue; } /*trap_SendServerCommand( ent-g_entities, va( "print \"^1Nade Dropped\n\"" ) );*/ //G_TeamCommand( PTE_HUMANS, "cp \"^1Alien Nuke Detected\" 1"); ent->s.weapon = WP_GRENADE; ent->client->pers.blasterball = 1; //G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, 0 ); LCChargeFire( ent, qtrue ); //FireWeapon( ent ); //ent->client->pers.energy -= 200; #UNCOMMENT //ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; return qtrue; }
void PM_HeloMove( void ) { vec3_t viewdir; vec3_t vehdir; vec3_t diff; vec3_t turnspeed; float targroll; bool dead = (pm->ps->stats[STAT_HEALTH] <= 0); bool verydead = (pm->ps->stats[STAT_HEALTH] <= GIB_HEALTH); int i; // int anim = 0; // Speed related stuff float throttle = pm->ps->fixed_throttle; int maxthrottle = availableVehicles[pm->vehicle].maxthrottle; // int maxforwardspeed = availableVehicles[pm->vehicle].maxspeed; // int maxrightspeed = availableVehicles[pm->vehicle].turnspeed[YAW]; // int maxliftspeed = maxforwardspeed*0.00525; // int maxspeed = sqrt(maxforwardspeed*maxforwardspeed + maxrightspeed*maxrightspeed + maxliftspeed*maxliftspeed); float curforwardspeed; float curliftspeed; float currightspeed; // float curspeed = pm->ps->speed; vec3_t forwardvel,rightvel, liftvel, deltavel; // Turret stuff vec3_t forward, up; vec3_t temp; float turret_yaw = pm->ps->turretAngle; float gun_pitch = pm->ps->gunAngle; vec3_t turretdir; float min, max; float turnModifier = 1.0f; if( verydead ) return; // clear FX pm->ps->ONOFF &= ~OO_VAPOR; // gear if( !dead && (pm->cmd.buttons & BUTTON_GEAR) ) { PM_Toggle_HeloGear(); } // gearanim if( !dead && pm->ps->timers[TIMER_GEARANIM] && pm->cmd.serverTime >= pm->ps->timers[TIMER_GEARANIM] ) { pm->ps->timers[TIMER_GEARANIM] = 0; if( pm->ps->ONOFF & OO_GEAR ) { pm->ps->ONOFF &= ~OO_GEAR; } else { pm->ps->ONOFF |= OO_GEAR; } } // update gear if( pm->updateGear ) { // sync anim if( pm->ps->ONOFF & OO_GEAR ) { PM_AddEvent( EV_GEAR_DOWN_FULL ); } else { PM_AddEvent( EV_GEAR_UP_FULL ); } pm->updateGear = false; } // get the actual turret angles AngleVectors( pm->ps->vehicleAngles, forward, 0, up ); RotatePointAroundVector( temp, up, forward, turret_yaw ); vectoangles( temp, turretdir ); turretdir[PITCH] += gun_pitch; // local vectors VectorCopy( pm->ps->vehicleAngles, vehdir ); if( pm->ps->ONOFF & OO_LANDED ) vehdir[PITCH] = vehdir[ROLL] = 0; // // Set current speeds (Do it here to allow more realistic crash) // if((pm->ps->ONOFF & OO_LANDED) && (throttle > maxthrottle)) pm->ps->fixed_throttle = throttle = 0; curforwardspeed = (vehdir[PITCH]/MAX_HELO_PITCH)*availableVehicles[pm->vehicle].maxspeed; currightspeed = (vehdir[ROLL]/MAX_HELO_ROLL)*availableVehicles[pm->vehicle].turnspeed[YAW]; curliftspeed = throttle > maxthrottle ? -(throttle-maxthrottle)*20 : throttle * 25; // Forward speed VectorCopy(vehdir, forwardvel); forwardvel[PITCH] = 0; // Don't let vehicle angels effect verticle acceleration AngleVectors(forwardvel, forwardvel, NULL, NULL ); VectorScale(forwardvel, curforwardspeed, forwardvel); // Sideways speed VectorCopy(vehdir, rightvel); rightvel[PITCH] = rightvel[ROLL] = 0; AngleVectors( rightvel, NULL, rightvel, NULL ); VectorScale( rightvel, currightspeed*2.5, rightvel ); // Lift Speed VectorCopy(vehdir, liftvel); liftvel[PITCH] = liftvel[YAW] = 0; AngleVectors( liftvel, NULL , NULL, liftvel ); VectorScale( liftvel, curliftspeed, liftvel ); // delta vel VectorAdd(forwardvel,rightvel,deltavel); VectorAdd(liftvel,deltavel,deltavel); // brake if( pm->cmd.buttons & BUTTON_BRAKE ) { PM_Helo_Brakes(); } // freelook - plane keeps current heading if( (pm->cmd.buttons & BUTTON_FREELOOK) && !dead ) { VectorCopy( vehdir, viewdir ); viewdir[0] = 0; } else { // normal - plane follows camera VectorCopy( pm->ps->viewangles, viewdir ); } // set yaw to 0 <= x <= 360 viewdir[YAW] = AngleMod( viewdir[YAW] ); vehdir[YAW] = AngleMod( vehdir[YAW] ); turretdir[YAW] = AngleMod( turretdir[YAW] ); turretdir[PITCH] = AngleMod( turretdir[PITCH] ); // Check acceleration PM_HeloAccelerate(); if( dead ) { pm->ps->vehicleAngles[PITCH] = 30*sin(pm->ps->origin[2]/25); pm->ps->vehicleAngles[ROLL] = 20*sin(pm->ps->origin[2]/50); VectorCopy(deltavel, pm->ps->velocity); // copy to velocity pm->ps->velocity[ROLL] = -DEFAULT_GRAVITY/10; // dirty trick to remember bankangle if( pm->ps->vehicleAngles[1] <= 0 ) { pm->ps->vehicleAngles[1] -= availableVehicles[pm->vehicle].turnspeed[1]*1.3 * pml.frametime; if( pm->ps->vehicleAngles[1] < -360 ) pm->ps->vehicleAngles[1] += 360; } else { pm->ps->vehicleAngles[1] += availableVehicles[pm->vehicle].turnspeed[1]*1.3 * pml.frametime; if( pm->ps->vehicleAngles[1] > 360 ) pm->ps->vehicleAngles[1] -= 360; } PM_SlideMove_Helo(); return; } for( i = PITCH; i <= ROLL; i++ ) { turnspeed[i] = availableVehicles[pm->vehicle].turnspeed[i] * pml.frametime; } // ground movement if( pm->ps->ONOFF & OO_LANDED ) { if(!(pm->ps->ONOFF & OO_LANDEDTERRAIN)) { if(pm->cmd.forwardmove > 0) { VectorCopy(vehdir, forwardvel); forwardvel[PITCH] = forwardvel[ROLL] = 0; AngleVectors(forwardvel, forwardvel, NULL, NULL ); pm->ps->speed = availableVehicles[pm->vehicle].turnspeed[PITCH]; VectorScale(forwardvel, availableVehicles[pm->vehicle].turnspeed[PITCH], forwardvel); } else if (pm->cmd.forwardmove < 0) { VectorCopy(vehdir, forwardvel); forwardvel[PITCH] = forwardvel[ROLL] = 0; AngleVectors(forwardvel, forwardvel, NULL, NULL ); pm->ps->speed = availableVehicles[pm->vehicle].turnspeed[PITCH]*10; VectorScale(forwardvel, -availableVehicles[pm->vehicle].turnspeed[PITCH], forwardvel); } // turn the hull if(pm->ps->ONOFF & OO_STALLED) turnModifier *= -1; if(pm->cmd.rightmove > 0 ) vehdir[YAW] -= turnspeed[YAW]/2 * turnModifier; else if(pm->cmd.rightmove < 0 ) vehdir[YAW] += turnspeed[YAW]/2 * turnModifier; VectorCopy(forwardvel, deltavel); } // air movement } else { // yaw diff[YAW] = viewdir[YAW] - vehdir[YAW]; if( diff[YAW] > 180 ) diff[YAW] -= 360; else if( diff[YAW] < -180 ) diff[YAW] += 360; if( diff[YAW] < -turnspeed[YAW] ) vehdir[YAW] -= turnspeed[YAW]; else if( diff[YAW] > turnspeed[YAW]) vehdir[YAW] += turnspeed[YAW]; else vehdir[YAW] = viewdir[YAW]; if( pm->ps->ONOFF & OO_SPEEDBRAKE ) { // pitch if(pm->cmd.forwardmove > 0) vehdir[PITCH] += turnspeed[PITCH]*1.25; else if(pm->cmd.forwardmove < 0) vehdir[PITCH] -= turnspeed[PITCH]*1.25; if( pm->ps->ONOFF & OO_SPEEDBRAKE && pm->cmd.forwardmove == 0) { if(vehdir[PITCH] > 0) vehdir[PITCH] -= std::min(vehdir[PITCH], turnspeed[PITCH]*1.05f); else if(vehdir[PITCH] < 0) vehdir[PITCH] += std::max(vehdir[PITCH], turnspeed[PITCH]*1.05f); } // roll if(pm->cmd.rightmove > 0) vehdir[ROLL] += turnspeed[ROLL]*2; else if(pm->cmd.rightmove < 0) vehdir[ROLL] -= turnspeed[ROLL]*2; // handle roll dependended on yaw otherwise return the vehicle ROLL to normal if( diff[YAW] > 1 ) targroll = -MAX_HELO_TARGROLL; else if( diff[YAW] < -1 ) targroll = MAX_HELO_TARGROLL; else targroll = 0; diff[ROLL] = targroll - vehdir[ROLL]; if( diff[ROLL] < -turnspeed[ROLL] ) vehdir[ROLL] -= turnspeed[ROLL]; else if( diff[ROLL] > turnspeed[ROLL] ) vehdir[ROLL] += turnspeed[ROLL]; else vehdir[ROLL] = targroll; } else { // pitch if(pm->cmd.forwardmove > 0) vehdir[PITCH] += turnspeed[PITCH]; else if(pm->cmd.forwardmove < 0) vehdir[PITCH] -= turnspeed[PITCH]; // roll if(pm->cmd.rightmove > 0) vehdir[ROLL] += turnspeed[ROLL]; else if(pm->cmd.rightmove < 0) vehdir[ROLL] -= turnspeed[ROLL]; } // limit roll and pitch vehdir[PITCH] = vehdir[PITCH] < 0 ? std::max(-MAX_HELO_PITCH, vehdir[PITCH]) : std::min (MAX_HELO_PITCH, vehdir[PITCH]); vehdir[ROLL] = vehdir[ROLL] < 0 ? std::max(-MAX_HELO_ROLL, vehdir[ROLL]) : std::min (MAX_HELO_ROLL, vehdir[ROLL]); if( (availableVehicles[pm->vehicle].caps & HC_GEAR) && (pm->ps->ONOFF & OO_GEAR) && (pm->ps->speed > availableVehicles[pm->vehicle].stallspeed * 10 * SPEED_GREEN_ARC) && !pm->ps->timers[TIMER_GEARANIM] ) { PM_AddEvent( EV_GEAR_UP ); pm->ps->timers[TIMER_GEAR] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime + 100; pm->ps->timers[TIMER_GEARANIM] = pm->cmd.serverTime + availableVehicles[pm->vehicle].gearTime; } } // Show turrets // get the angle difference for( i = PITCH; i <= YAW; i++ ) { diff[i] = pm->ps->viewangles[i] - turretdir[i]; if( diff[i] > 180 ) diff[i] -= 360; else if( diff[i] < -180 ) diff[i] += 360; } // turn the turret if( diff[YAW] < -turnspeed[TURRET_YAW] ) turret_yaw -= turnspeed[TURRET_YAW]; else if( diff[YAW] > turnspeed[TURRET_YAW] ) turret_yaw += turnspeed[TURRET_YAW]; else turret_yaw += diff[YAW]; if( turret_yaw > 180 ) turret_yaw -= 360;// limit to +- 180 min = availableWeapons[pm->ps->weaponIndex].minturns[1]; max = availableWeapons[pm->ps->weaponIndex].maxturns[1]; if( max > min ) { if( turret_yaw > max ) turret_yaw = max; else if( turret_yaw < min ) turret_yaw = min; } else { if( turret_yaw > 0 && turret_yaw < min ) turret_yaw = min; else if( turret_yaw < 0 && turret_yaw > max ) turret_yaw = max; } if( turret_yaw < 0 ) turret_yaw += 360;// clamp back to pos else if( turret_yaw > 360 ) turret_yaw -= 360; // turn the gun if( diff[PITCH] < -turnspeed[GUN_PITCH] ) gun_pitch -= turnspeed[GUN_PITCH]; else if( diff[PITCH] > turnspeed[GUN_PITCH] ) gun_pitch += turnspeed[GUN_PITCH]; else gun_pitch += diff[PITCH]; min = availableWeapons[pm->ps->weaponIndex].minturns[0]; max = availableWeapons[pm->ps->weaponIndex].maxturns[0]; if( gun_pitch > 180 ) gun_pitch -= 360;// limit to +-180 to make it easier if( gun_pitch > max ) gun_pitch = max; else if( gun_pitch < min ) gun_pitch = min; if( gun_pitch < 0 ) gun_pitch += 360;// clamp it back to pos else if( gun_pitch > 360 ) gun_pitch -= 360; // return angles VectorCopy( vehdir, pm->ps->vehicleAngles ); pm->ps->turretAngle = turret_yaw; pm->ps->gunAngle = gun_pitch; // speed if( pm->ps->ONOFF & OO_LANDED ) vehdir[0] = 0; // Copy final vel VectorCopy(deltavel, pm->ps->velocity); PM_SlideMove_Helo(); }
/* ============== PM_Weapon Generates weapon events and modifes the weapon counter ============== */ static void PM_Weapon( void ) { int addTime; int newWeapon; // don't allow attack until all buttons are up if ( pm->ps->pm_flags & PMF_RESPAWNED ) { return; } // ignore if spectator if ( pm->ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) { return; } // check for dead player if ( pm->ps->stats[STAT_HEALTH] <= 0 ) { pm->ps->weapon = WP_NONE; return; } // check for item using if ( pm->cmd.buttons & BUTTON_USE_HOLDABLE ) { if ( ! ( pm->ps->pm_flags & PMF_USE_ITEM_HELD ) ) { if ( bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag == HI_MEDKIT && pm->ps->stats[STAT_HEALTH] >= (pm->ps->stats[STAT_MAX_HEALTH] + 25) ) { // don't use medkit if at max health } else { pm->ps->pm_flags |= PMF_USE_ITEM_HELD; PM_AddEvent( EV_USE_ITEM0 + bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag ); pm->ps->stats[STAT_HOLDABLE_ITEM] = 0; } return; } } else { pm->ps->pm_flags &= ~PMF_USE_ITEM_HELD; } // make weapon function if ( pm->ps->weaponTime > 0 ) { pm->ps->weaponTime -= pml.msec; } // check for weapon change // can't change if weapon is firing, but can change // again if lowering or raising if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) { BG_DecomposeUserCmdValue( pm->cmd.stateValue, &newWeapon ); if ( pm->ps->weapon != newWeapon ) { PM_BeginWeaponChange( newWeapon ); } } if ( pm->ps->weaponTime > 0 ) { return; } // change weapon if time if ( pm->ps->weaponstate == WEAPON_DROPPING ) { PM_FinishWeaponChange(); return; } if ( pm->ps->weaponstate == WEAPON_RAISING ) { pm->ps->weaponstate = WEAPON_READY; if ( pm->ps->weapon == WP_GAUNTLET ) { PM_StartTorsoAnim( TORSO_STAND2 ); } else { PM_StartTorsoAnim( TORSO_STAND ); } return; } // check for fire if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) { pm->ps->weaponTime = 0; pm->ps->weaponstate = WEAPON_READY; return; } // start the animation even if out of ammo if ( pm->ps->weapon == WP_GAUNTLET ) { // the guantlet only "fires" when it actually hits something if ( !pm->gauntletHit ) { pm->ps->weaponTime = 0; pm->ps->weaponstate = WEAPON_READY; return; } PM_StartTorsoAnim( TORSO_ATTACK2 ); } else { PM_StartTorsoAnim( TORSO_ATTACK ); } pm->ps->weaponstate = WEAPON_FIRING; // check for out of ammo if ( ! pm->ps->ammo[ pm->ps->weapon ] ) { PM_AddEvent( EV_NOAMMO ); pm->ps->weaponTime += 500; return; } // take an ammo away if not infinite if ( pm->ps->ammo[ pm->ps->weapon ] != -1 ) { pm->ps->ammo[ pm->ps->weapon ]--; } // fire weapon PM_AddEvent( EV_FIRE_WEAPON ); switch( pm->ps->weapon ) { default: case WP_GAUNTLET: addTime = 400; break; case WP_LIGHTNING: addTime = 50; break; case WP_SHOTGUN: addTime = 1000; break; case WP_MACHINEGUN: addTime = 100; break; case WP_GRENADE_LAUNCHER: addTime = 800; break; case WP_ROCKET_LAUNCHER: addTime = 800; break; case WP_PLASMAGUN: addTime = 100; break; case WP_RAILGUN: addTime = 1500; break; case WP_BFG: addTime = 200; break; case WP_GRAPPLING_HOOK: addTime = 400; break; #ifdef MISSIONPACK case WP_NAILGUN: addTime = 1000; break; case WP_PROX_LAUNCHER: addTime = 800; break; case WP_CHAINGUN: addTime = 30; break; #endif } #ifdef MISSIONPACK if( bg_itemlist[pm->ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) { addTime /= 1.5; } else if( bg_itemlist[pm->ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_AMMOREGEN ) { addTime /= 1.3; } else #endif if ( pm->ps->powerups[PW_HASTE] ) { addTime /= 1.3; } pm->ps->weaponTime += addTime; }
/* =============== PM_Footsteps =============== */ static void PM_Footsteps( void ) { float bobmove; int old; qboolean footstep; // // calculate speed and cycle to be used for // all cyclic walking effects // pm->xyspeed = sqrt( pm->ps->velocity[0] * pm->ps->velocity[0] + pm->ps->velocity[1] * pm->ps->velocity[1] ); if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) { if ( pm->ps->powerups[PW_INVULNERABILITY] ) { PM_ContinueLegsAnim( LEGS_IDLECR ); } // airborne leaves position in cycle intact, but doesn't advance if ( pm->waterlevel > 1 ) { PM_ContinueLegsAnim( LEGS_SWIM ); } return; } // if not trying to move if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { if ( pm->xyspeed < 5 ) { pm->ps->bobCycle = 0; // start at beginning of cycle again if ( pm->ps->pm_flags & PMF_DUCKED ) { PM_ContinueLegsAnim( LEGS_IDLECR ); } else { PM_ContinueLegsAnim( LEGS_IDLE ); } } return; } footstep = qfalse; if ( pm->ps->pm_flags & PMF_DUCKED ) { bobmove = 0.5; // ducked characters bob much faster if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { PM_ContinueLegsAnim( LEGS_BACKCR ); } else { PM_ContinueLegsAnim( LEGS_WALKCR ); } // ducked characters never play footsteps /* } else if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { bobmove = 0.4; // faster speeds bob faster footstep = qtrue; } else { bobmove = 0.3; } PM_ContinueLegsAnim( LEGS_BACK ); */ } else { if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { bobmove = 0.4f; // faster speeds bob faster if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { PM_ContinueLegsAnim( LEGS_BACK ); } else { PM_ContinueLegsAnim( LEGS_RUN ); } footstep = qtrue; } else { bobmove = 0.3f; // walking bobs slow if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { PM_ContinueLegsAnim( LEGS_BACKWALK ); } else { PM_ContinueLegsAnim( LEGS_WALK ); } } } // check for footstep / splash sounds old = pm->ps->bobCycle; pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255; // if we just crossed a cycle boundary, play an apropriate footstep event if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 ) { if ( pm->waterlevel == 0 ) { // on ground will only play sounds if running if ( footstep && !pm->noFootsteps ) { PM_AddEvent( PM_FootstepForSurface() ); } } else if ( pm->waterlevel == 1 ) { // splashing PM_AddEvent( EV_FOOTSPLASH ); } else if ( pm->waterlevel == 2 ) { // wading / swimming at surface PM_AddEvent( EV_SWIM ); } else if ( pm->waterlevel == 3 ) { // no sound when completely underwater } } }
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 }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; qboolean isGiant = qfalse; bgEntity_t *pEnt; qboolean skipStep = qfalse; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( BG_InReboundHold( pm->ps->legsAnim ) ) { gravity = qfalse; } if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try } pEnt = pm_entSelf; if (pm->ps->clientNum >= MAX_CLIENTS) { if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0) { return; } } VectorCopy(start_o, down); down[2] -= STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); if (pm->ps->clientNum >= MAX_CLIENTS) { // apply ground friction, even if on ladder if (pEnt && pEnt->s.NPC_class == CLASS_ATST || (pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->type == VH_WALKER) ) {//AT-STs can step high up[2] += 66.0f; isGiant = qtrue; } else if ( pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//also can step up high up[2] += 64.0f; isGiant = qtrue; } else { up[2] += STEPSIZE; } } else { up[2] += STEPSIZE; } // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->stepSlideFix ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } /* else if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_ATST && OnSameTeam( pEnt, traceEnt) ) {//NPC AT-ST's don't step up on allies VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } */ else { VectorCopy (trace.endpos, pm->ps->origin); if ( pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } else { if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( pm->debugLevel ) { qboolean wassolid, slidesucceed; PM_TraceAll( &trace, pm->ps->origin, pm->ps->origin ); wassolid = trace.allsolid; slidesucceed = (PM_SlideMove( gravity ) == 0) ? qtrue : qfalse; PM_TraceAll( &trace, pm->ps->origin, pm->ps->origin ); if (trace.allsolid && !wassolid) Com_Printf("%i:PM_SlideMove solidified! (%f %f %f) -> (%f %f %f)\n", c_pmove, start_o[0], start_o[1], start_o[2], pm->ps->origin[0], pm->ps->origin[1], pm->ps->origin[2] ); if (slidesucceed) return; } else { if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try } } if ( pm->debugLevel ) { Com_Printf("%i:stepping\n", c_pmove); } VectorCopy(start_o, down); down[2] -= STEPSIZE; PM_TraceAll( &trace, start_o, down ); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += STEPSIZE; // test the player position if they were a stepheight higher PM_TraceAll( &trace, up, up ); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } // try slidemove from this position VectorCopy (up, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= STEPSIZE; // check legs separately if ( pm->ps->eFlags & (EF_PRONE|EF_PLAYDEAD) ) { PM_TraceLegs( &trace, NULL, pm->ps->origin, down, NULL, pm->ps->viewangles, pm->trace, pm->ps->clientNum, pm->tracemask, (pm->ps->eFlags & EF_PRONE) ? true : false ); if ( trace.allsolid ) { // legs don't step, just fuzz. VectorCopy( down_o, pm->ps->origin ); VectorCopy( down_v, pm->ps->velocity ); if ( pm->debugLevel ) { Com_Printf("%i:legs unsteppable\n", c_pmove); } return; } } pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask ); if ( !trace.allsolid ) { VectorCopy (trace.endpos, pm->ps->origin); } if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } #if 0 // if the down trace can trace back to the original position directly, don't step PM_TraceAll( &trace, pm->ps->origin, start_o ); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( float gravMod ) { vec3_t start_o, start_v; vec3_t down_o, down_v; vec3_t slideMove, stepUpMove; trace_t trace; vec3_t up, down; qboolean cantStepUpFwd, isATST = qfalse;; int stepSize = STEPSIZE; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( PM_SlideMove( gravMod ) == 0 ) { return; // we got exactly where we wanted to go first try }//else Bumped into something, see if we can step over it if ( pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_ATST) { isATST = qtrue; stepSize = 66;//hack for AT-ST stepping, slightly taller than a standing stormtrooper } else if ( pm->maxs[2] <= 0 ) {//short little guys can't go up steps... FIXME: just make this a flag for certain NPCs- especially ones that roll? stepSize = 4; } //Q3Final addition... VectorCopy(start_o, down); down[2] -= stepSize; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } if ( !pm->ps->velocity[0] && !pm->ps->velocity[1] ) {//All our velocity was cancelled sliding return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += stepSize; // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); if ( trace.allsolid || trace.startsolid || trace.fraction == 0) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); cantStepUpFwd = PM_SlideMove( gravMod ); //compare the initial slidemove and this slidemove from a step up position VectorSubtract( down_o, start_o, slideMove ); VectorSubtract( trace.endpos, pm->ps->origin, stepUpMove ); if ( fabs(stepUpMove[0]) < 0.1 && fabs(stepUpMove[1]) < 0.1 && VectorLengthSquared( slideMove ) > VectorLengthSquared( stepUpMove ) ) { //slideMove was better, use it VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, G2_NOCOLLIDE, 0); if ( !trace.allsolid ) { if ( pm->ps->clientNum && isATST && g_entities[trace.entityNum].client && g_entities[trace.entityNum].client->playerTeam == pm->gent->client->playerTeam ) {//AT-ST's don't step up on allies } else { VectorCopy( trace.endpos, pm->ps->origin ); } } if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } /* if(cantStepUpFwd && pm->ps->origin[2] < start_o[2] + stepSize && pm->ps->origin[2] >= start_o[2]) {//We bumped into something we could not step up pm->ps->pm_flags |= PMF_BLOCKED; } else {//We did step up, clear the bumped flag pm->ps->pm_flags &= ~PMF_BUMPED; } */ #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
void PM_StepSlideMove(Pmove *pm, Pml *pml, qbool gravity) { Vec3 start_o, start_v; /* Vec3 down_o, down_v; */ Trace trace; /* float down_dist, up_dist; * Vec3 delta, delta2; */ Vec3 up, down; float stepSize; float delta; copyv3 (pm->ps->origin, start_o); copyv3 (pm->ps->velocity, start_v); if(PM_SlideMove(pm, pml, gravity) == 0) return; /* we got exactly where we wanted to go first try */ copyv3(start_o, down); down[2] -= STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); setv3(up, 0, 0, 1); /* never step up when you still have up velocity */ if(pm->ps->velocity[2] > 0 && (trace.fraction == 1.0f || dotv3(trace.plane.normal, up) < 0.7f)) return; /* copyv3 (pm->ps->origin, down_o); * copyv3 (pm->ps->velocity, down_v); */ copyv3 (start_o, up); up[2] += STEPSIZE; /* test the player position if they were a stepheight higher */ pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if(trace.allsolid){ if(pm->debugLevel) comprintf("%u:bend can't step\n", cnt); return; /* can't step up */ } stepSize = trace.endpos[2] - start_o[2]; /* try slidemove from this position */ copyv3 (trace.endpos, pm->ps->origin); copyv3 (start_v, pm->ps->velocity); PM_SlideMove(pm, pml, gravity); /* push down the final amount */ copyv3 (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if(!trace.allsolid) copyv3 (trace.endpos, pm->ps->origin); if(trace.fraction < 1.0f) PM_ClipVelocity(pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP); #if 0 /* if the down trace can trace back to the original position directly, don't step */ pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if(trace.fraction == 1.0f){ /* use the original move */ copyv3 (down_o, pm->ps->origin); copyv3 (down_v, pm->ps->velocity); if(pm->debugLevel) comprintf("%u:bend\n", cnt); }else #endif /* use the step move */ delta = pm->ps->origin[2] - start_o[2]; if(delta > 2){ if(delta < 7) PM_AddEvent(pm, pml, EV_STEP_4); else if(delta < 11) PM_AddEvent(pm, pml, EV_STEP_8); else if(delta < 15) PM_AddEvent(pm, pml, EV_STEP_12); else PM_AddEvent(pm, pml, EV_STEP_16); } if(pm->debugLevel) comprintf("%u:stepped\n", cnt); }
/* ================= PM_CrashLand Check for hard landings that generate sound events ================= */ static void PM_CrashLand( void ) { float delta; float dist; float vel, acc; float t; float a, b, c, den; // decide which landing animation to use if ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP ) { PM_ForceLegsAnim( LEGS_LANDB ); } else { PM_ForceLegsAnim( LEGS_LAND ); } pm->ps->legsTimer = TIMER_LAND; // calculate the exact velocity on landing dist = pm->ps->origin[2] - pml.previous_origin[2]; vel = pml.previous_velocity[2]; acc = -pm->ps->gravity; a = acc / 2; b = vel; c = -dist; den = b * b - 4 * a * c; if ( den < 0 ) { return; } t = (-b - sqrt( den ) ) / ( 2 * a ); delta = vel + t * acc; delta = delta*delta * 0.0001; // ducking while falling doubles damage if ( pm->ps->pm_flags & PMF_DUCKED ) { delta *= 2; } // never take falling damage if completely underwater if ( pm->waterlevel == 3 ) { return; } // reduce falling damage if there is standing water if ( pm->waterlevel == 2 ) { delta *= 0.25; } if ( pm->waterlevel == 1 ) { delta *= 0.5; } if ( delta < 1 ) { return; } // create a local entity event to play the sound // SURF_NODAMAGE is used for bounce pads where you don't ever // want to take damage or play a crunch sound if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) { if ( delta > 60 ) { PM_AddEvent( EV_FALL_FAR ); } else if ( delta > 40 ) { // this is a pain grunt, so don't play it if dead if ( pm->ps->stats[STAT_HEALTH] > 0 ) { PM_AddEvent( EV_FALL_MEDIUM ); } } else if ( delta > 7 ) { PM_AddEvent( EV_FALL_SHORT ); } else { PM_AddEvent( PM_FootstepForSurface() ); } } // start footstep cycle over pm->ps->bobCycle = 0; }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove( float gravMod ) { vec3_t start_o, start_v; vec3_t down_o, down_v; vec3_t slideMove, stepUpMove; trace_t trace; vec3_t up, down; qboolean cantStepUpFwd, isGiant = qfalse;; int stepSize = STEPSIZE; VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( PM_InReboundHold( pm->ps->legsAnim ) ) { gravMod = 0.0f; } if ( PM_SlideMove( gravMod ) == 0 ) { return; // we got exactly where we wanted to go first try }//else Bumped into something, see if we can step over it if ( pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_VEHICLE && pm->gent->m_pVehicle->m_pVehicleInfo->hoverHeight > 0 ) {//Hovering vehicles don't do steps //FIXME: maybe make hovering vehicles go up steps, but not down them? return; } if ( pm->gent && pm->gent->client && (pm->gent->client->NPC_class == CLASS_ATST||pm->gent->client->NPC_class == CLASS_RANCOR) ) { isGiant = qtrue; if ( pm->gent->client->NPC_class == CLASS_RANCOR ) { if ( (pm->gent->spawnflags&1) ) { stepSize = 64;//hack for Mutant Rancor stepping } else { stepSize = 48;//hack for Rancor stepping } } else { stepSize = 70;//hack for AT-ST stepping, slightly taller than a standing stormtrooper } } else if ( pm->maxs[2] <= 0 ) {//short little guys can't go up steps... FIXME: just make this a flag for certain NPCs- especially ones that roll? stepSize = 4; } //Q3Final addition... VectorCopy(start_o, down); down[2] -= stepSize; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } if ( !pm->ps->velocity[0] && !pm->ps->velocity[1] ) {//All our velocity was cancelled sliding return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); up[2] += stepSize; // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid || trace.startsolid || trace.fraction == 0) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } if ( pm->debugLevel ) { G_DebugLine(start_o,trace.endpos,2000,0xffffff,qtrue); } //===Another slidemove forward================================================================================ // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); cantStepUpFwd = PM_SlideMove( gravMod ); //===Another slidemove forward================================================================================ if ( pm->debugLevel ) { G_DebugLine(trace.endpos,pm->ps->origin,2000,0xffffff,qtrue); } //compare the initial slidemove and this slidemove from a step up position VectorSubtract( down_o, start_o, slideMove ); VectorSubtract( trace.endpos, pm->ps->origin, stepUpMove ); if ( fabs(stepUpMove[0]) < 0.1 && fabs(stepUpMove[1]) < 0.1 && VectorLengthSquared( slideMove ) > VectorLengthSquared( stepUpMove ) ) { //slideMove was better, use it VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { qboolean skipStep = qfalse; // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->debugLevel ) { G_DebugLine(pm->ps->origin,trace.endpos,2000,0xffffff,qtrue); } if ( g_stepSlideFix->integer ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { if ( pm->debugLevel ) { G_DebugLine(down_o,trace.endpos,2000,0x0000ff,qtrue); } skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum && isGiant && g_entities[trace.entityNum].client && pm->gent && pm->gent->client && pm->gent->client->NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } else if ( pm->ps->clientNum && isGiant && g_entities[trace.entityNum].client && g_entities[trace.entityNum].client->playerTeam == pm->gent->client->playerTeam ) {//AT-ST's don't step up on allies if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } else { VectorCopy( trace.endpos, pm->ps->origin ); if ( g_stepSlideFix->integer ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } else { if ( g_stepSlideFix->integer ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !g_stepSlideFix->integer ) { if ( trace.fraction < 1.0 ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } /* if(cantStepUpFwd && pm->ps->origin[2] < start_o[2] + stepSize && pm->ps->origin[2] >= start_o[2]) {//We bumped into something we could not step up pm->ps->pm_flags |= PMF_BLOCKED; } else {//We did step up, clear the bumped flag } */ #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
void PM_StepSlideMove( qboolean gravity ) { vec3_t start_o, start_v; vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; qboolean isGiant = qfalse; bgEntity_t *pEnt; qboolean skipStep = qfalse; int NEW_STEPSIZE = STEPSIZE; const int moveStyle = PM_GetMovePhysics(); if (moveStyle == MV_CPM || moveStyle == MV_Q3 || moveStyle == MV_WSW || moveStyle == MV_RJQ3 || moveStyle == MV_RJCPM || moveStyle == MV_SLICK || moveStyle == MV_BOTCPM) { if (pm->ps->velocity[2] > 0 && pm->cmd.upmove > 0) { int jumpHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart; if (jumpHeight > 48) jumpHeight = 48; else if (jumpHeight < 22) jumpHeight = 22; NEW_STEPSIZE = 48 - jumpHeight + 22; //trap->SendServerCommand(-1, va("print \"new stepsize: %i, expected max end height: %i\n\"", NEW_STEPSIZE, NEW_STEPSIZE + (int)(pm->ps->origin[2] - pm->ps->fd.forceJumpZStart))); //This means that we can always clip things up to 48 units tall, if we are moving up when we hit it and from a bhop.. //It means we can sometimes clip things up to 70 units tall, if we hit it in right part of jump //Should it be higher..? some of the things in q3 are 56 units tall.. //NEW_STEPSIZE = 46; //Make stepsize equal to.. our current 48 - our current jumpheight ? } else NEW_STEPSIZE = 22; } VectorCopy (pm->ps->origin, start_o); VectorCopy (pm->ps->velocity, start_v); if ( BG_InReboundHold( pm->ps->legsAnim ) ) { gravity = qfalse; } if ( PM_SlideMove( gravity ) == 0 ) { return; // we got exactly where we wanted to go first try, nospeed ramp returns here maybe } pEnt = pm_entSelf; if (pm->ps->clientNum >= MAX_CLIENTS) { if (pEnt && pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->hoverHeight > 0) { return; } } VectorCopy(start_o, down); down[2] -= NEW_STEPSIZE; pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); VectorCopy (start_o, up); if (pm->ps->clientNum >= MAX_CLIENTS) { // apply ground friction, even if on ladder if (pEnt && (pEnt->s.NPC_class == CLASS_ATST || (pEnt->s.NPC_class == CLASS_VEHICLE && pEnt->m_pVehicle && pEnt->m_pVehicle->m_pVehicleInfo->type == VH_WALKER) ) ) {//AT-STs can step high up[2] += 66.0f; isGiant = qtrue; } else if ( pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//also can step up high up[2] += 64.0f; isGiant = qtrue; } else { up[2] += NEW_STEPSIZE; } } else { up[2] += NEW_STEPSIZE; } // test the player position if they were a stepheight higher pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( trace.allsolid ) { if ( pm->debugLevel ) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up, nospeed ramp returns here maybe } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy (trace.endpos, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); PM_SlideMove( gravity ); pml.clipped = qtrue; //nospeed ramp fix, if we made it to this point there wont be a nospeed ramp // push down the final amount VectorCopy (pm->ps->origin, down); down[2] -= stepSize; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if ( pm->stepSlideFix ) { if ( pm->ps->clientNum < MAX_CLIENTS && trace.plane.normal[2] < MIN_WALK_NORMAL ) {//normal players cannot step up slopes that are too steep to walk on! vec3_t stepVec; //okay, the step up ends on a slope that it too steep to step up onto, //BUT: //If the step looks like this: // (B)\__ // \_____(A) //Then it might still be okay, so we figure out the slope of the entire move //from (A) to (B) and if that slope is walk-upabble, then it's okay VectorSubtract( trace.endpos, down_o, stepVec ); VectorNormalize( stepVec ); if ( stepVec[2] > (1.0f-MIN_WALK_NORMAL) ) { skipStep = qtrue; } } } if ( !trace.allsolid && !skipStep ) //normal players cannot step up slopes that are too steep to walk on! { if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_RANCOR ) {//Rancor don't step on clients if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } else { VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } } /* else if ( pm->ps->clientNum >= MAX_CLIENTS//NPC && isGiant && trace.entityNum < MAX_CLIENTS && pEnt && pEnt->s.NPC_class == CLASS_ATST && OnSameTeam( pEnt, traceEnt) ) {//NPC AT-ST's don't step up on allies VectorCopy (start_o, pm->ps->origin); VectorCopy (start_v, pm->ps->velocity); } */ else { VectorCopy (trace.endpos, pm->ps->origin); if (pm->stepSlideFix) { if (trace.fraction < 1.0) { if (moveStyle == MV_WSW || moveStyle == MV_SLICK) { //Make Warsow Rampjump not slow down your XY speed vec3_t oldVel, clipped_velocity, newVel; float oldSpeed, newSpeed; VectorCopy(pm->ps->velocity, oldVel); oldSpeed = oldVel[0] * oldVel[0] + oldVel[1] * oldVel[1]; PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, clipped_velocity, OVERCLIP ); //WSW RAMPJUMP 3 VectorCopy(clipped_velocity, newVel); newVel[2] = 0; newSpeed = newVel[0] * newVel[0] + newVel[1] * newVel[1]; if (newSpeed > oldSpeed) VectorCopy(clipped_velocity, pm->ps->velocity); } else { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } } } else { if ( pm->stepSlideFix ) { VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); } } if ( !pm->stepSlideFix ) { if ( trace.fraction < 1.0 ) { if (moveStyle == MV_WSW || moveStyle == MV_SLICK) { vec3_t oldVel, clipped_velocity, newVel; float oldSpeed, newSpeed; VectorCopy(pm->ps->velocity, oldVel); oldSpeed = oldVel[0] * oldVel[0] + oldVel[1] * oldVel[1]; PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, clipped_velocity, OVERCLIP ); //WSW RAMPJUMP 2 VectorCopy(clipped_velocity, newVel); newVel[2] = 0; newSpeed = newVel[0] * newVel[0] + newVel[1] * newVel[1]; if (newSpeed > oldSpeed) VectorCopy(clipped_velocity, pm->ps->velocity); } else { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); } } } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { // use the original move VectorCopy (down_o, pm->ps->origin); VectorCopy (down_v, pm->ps->velocity); if ( pm->debugLevel ) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if ( delta > 2 ) { if ( delta < 7 ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11 ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15 ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel ) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ void PM_StepSlideMove(qboolean gravity) { vec3_t start_o, start_v; // vec3_t down_o, down_v; trace_t trace; // float down_dist, up_dist; // vec3_t delta, delta2; vec3_t up, down; float stepSize; VectorCopy(pm->ps->origin, start_o); VectorCopy(pm->ps->velocity, start_v); if (PM_SlideMove(gravity) == 0) { return; // we got exactly where we wanted to go first try } VectorCopy(start_o, down); down[2] -= STEPSIZE; pm->trace(&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); VectorSet(up, 0, 0, 1); // never step up when you still have up velocity if (pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) { return; } //VectorCopy (pm->ps->origin, down_o); //VectorCopy (pm->ps->velocity, down_v); VectorCopy(start_o, up); up[2] += STEPSIZE; // test the player position if they were a stepheight higher pm->trace(&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if (trace.allsolid) { if (pm->debugLevel) { Com_Printf("%i:bend can't step\n", c_pmove); } return; // can't step up } stepSize = trace.endpos[2] - start_o[2]; // try slidemove from this position VectorCopy(trace.endpos, pm->ps->origin); VectorCopy(start_v, pm->ps->velocity); PM_SlideMove(gravity); // push down the final amount VectorCopy(pm->ps->origin, down); down[2] -= stepSize; pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); if (!trace.allsolid) { VectorCopy(trace.endpos, pm->ps->origin); } if (trace.fraction < 1.0) { PM_ClipVelocity(pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP); } #if 0 // if the down trace can trace back to the original position directly, don't step pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); if (trace.fraction == 1.0) { // use the original move VectorCopy(down_o, pm->ps->origin); VectorCopy(down_v, pm->ps->velocity); if (pm->debugLevel) { Com_Printf("%i:bend\n", c_pmove); } } else #endif { // use the step move float delta; delta = pm->ps->origin[2] - start_o[2]; if (delta > 2) { if (delta < 7) { PM_AddEvent(EV_STEP_4); } else if (delta < 11) { PM_AddEvent(EV_STEP_8); } else if (delta < 15) { PM_AddEvent(EV_STEP_12); } else { PM_AddEvent(EV_STEP_16); } } if (pm->debugLevel) { Com_Printf("%i:stepped\n", c_pmove); } } }
/* ================== PM_StepSlideMove ================== */ bool PM_StepSlideMove( bool gravity, bool predictive ) { vec3_t start_o, start_v; #ifndef UNREALARENA vec3_t down_o, down_v; #endif trace_t trace; #ifndef UNREALARENA vec3_t normal; vec3_t step_v, step_vNormal; #endif vec3_t up, down; float stepSize; bool stepped = false; #ifndef UNREALARENA BG_GetClientNormal( pm->ps, normal ); #endif VectorCopy( pm->ps->origin, start_o ); VectorCopy( pm->ps->velocity, start_v ); if ( !PM_SlideMove( gravity ) ) { #ifdef UNREALARENA return stepped; // we got exactly where we wanted to go first try #else VectorCopy( start_o, down ); VectorMA( down, -STEPSIZE, normal, down ); pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); //we can step down if ( trace.fraction > 0.01f && trace.fraction < 1.0f && !trace.allsolid && pml.groundPlane ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%d: step down\n", c_pmove ); } stepped = true; } #endif } else { VectorCopy( start_o, down ); #ifdef UNREALARENA down[ 2 ] -= STEPSIZE; #else VectorMA( down, -STEPSIZE, normal, down ); #endif pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); #ifdef UNREALARENA VectorSet( up, 0.0f, 0.0f, 1.0f ); #endif // never step up when you still have up velocity #ifdef UNREALARENA if ( pm->ps->velocity[ 2 ] > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, up ) < 0.7f ) ) #else if ( DotProduct( trace.plane.normal, pm->ps->velocity ) > 0.0f && ( trace.fraction == 1.0f || DotProduct( trace.plane.normal, normal ) < 0.7f ) ) #endif { return stepped; } #ifndef UNREALARENA // never step up when flying upwards with the jetpack if ( pm->ps->velocity[ 2 ] > 0.0f && ( pm->ps->stats[ STAT_STATE2 ] & SS2_JETPACK_ACTIVE ) ) { return stepped; } VectorCopy( pm->ps->origin, down_o ); VectorCopy( pm->ps->velocity, down_v ); #endif VectorCopy( start_o, up ); #ifdef UNREALARENA up[ 2 ] += STEPSIZE; #else VectorMA( up, STEPSIZE, normal, up ); #endif // test the player position if they were a stepheight higher pm->trace( &trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, 0 ); if ( trace.allsolid ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%i:bend can't step\n", c_pmove ); } return stepped; // can't step up } #ifdef UNREALARENA stepSize = trace.endpos[ 2 ] - start_o[ 2 ]; // if the new position is falling then do nothing if ( PM_CheckFallingFromLedge( trace.endpos ) ) { VectorCopy( start_o, pm->ps->origin ); return stepped; } #else VectorSubtract( trace.endpos, start_o, step_v ); VectorCopy( step_v, step_vNormal ); VectorNormalize( step_vNormal ); stepSize = DotProduct( normal, step_vNormal ) * VectorLength( step_v ); #endif // try slidemove from this position VectorCopy( trace.endpos, pm->ps->origin ); VectorCopy( start_v, pm->ps->velocity ); #ifdef UNREALARENA PM_SlideMove( gravity, stepSize ); #else if ( PM_SlideMove( gravity ) == 0 ) { if ( pm->debugLevel > 1 ) { Log::Notice( "%d: step up\n", c_pmove ); } stepped = true; } #endif // push down the final amount VectorCopy( pm->ps->origin, down ); #ifdef UNREALARENA down[ 2 ] -= stepSize; #else VectorMA( down, -stepSize, normal, down ); #endif pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, 0 ); if ( !trace.allsolid ) { #ifdef UNREALARENA // if the new position is falling then do nothing if ( PM_CheckFallingFromLedge( trace.endpos ) ) { VectorCopy( start_o, pm->ps->origin ); return stepped; } #endif VectorCopy( trace.endpos, pm->ps->origin ); } if ( trace.fraction < 1.0f ) { PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity ); } } #ifdef UNREALARENA if ( !predictive ) { stepped = true; // use the step move float delta; delta = pm->ps->origin[ 2 ] - start_o[ 2 ]; if ( delta > 2.0f ) { if ( delta < 7.0f ) { PM_AddEvent( EV_STEP_4 ); } else if ( delta < 11.0f ) { PM_AddEvent( EV_STEP_8 ); } else if ( delta < 15.0f ) { PM_AddEvent( EV_STEP_12 ); } else { PM_AddEvent( EV_STEP_16 ); } } if ( pm->debugLevel > 1 ) { Log::Notice( "%i:stepped\n", c_pmove ); } } #else if ( !predictive && stepped ) { PM_StepEvent( start_o, pm->ps->origin, normal ); } #endif return stepped; }