void Game::shootSV(int playerID, int nuzzleID, float imp, CVector3f p1, CVector3f p2) { Player* player = players[playerID]; if (player == 0) return; int ident = (int)imp; CVector3f oldP2; if(player->weapon->weaponID == WEAPON_SHOTGUN) { switch(ident) { case 1: oldP2 = rotateAboutAxis(p2, 10.0f, CVector3f(0.0f, 0.0f, 1.0f)); break; case 2: oldP2 = rotateAboutAxis(p2, 5.0f, CVector3f(0.0f, 0.0f, 1.0f)); break; case 3: oldP2 = rotateAboutAxis(p2, 0.0f, CVector3f(0.0f, 0.0f, 1.0f)); break; case 4: oldP2 = rotateAboutAxis(p2, -5.0f, CVector3f(0.0f, 0.0f, 1.0f)); break; case 5: oldP2 = rotateAboutAxis(p2, -10.0f, CVector3f(0.0f, 0.0f, 1.0f)); break; }; normalize(oldP2); } if(player->weapon->weaponID == WEAPON_SHOTGUN) { imp = 3.5f; } #ifdef _PRO_ CVector3f dir = p2; if (player->weapon->projectileType == PROJECTILE_DIRECT && player->weapon->weaponID == WEAPON_FLAME_THROWER) { if(gameVar.sv_ftExpirationTimer > 0) { float mult = (1.0f-player->secondsFired/gameVar.sv_ftExpirationTimer) * gameVar.sv_ftMaxRange; if (mult < gameVar.sv_ftMinRange) mult = gameVar.sv_ftMinRange; p2 = p2 * mult;//nuvem's awesome idea, ft range decreases the longer it's fired if(gameVar.sv_explodingFT && player->secondsFired/gameVar.sv_ftExpirationTimer > 1) { scene->server->nukePlayer(playerID); } } else p2 = p2 * gameVar.sv_ftMaxRange; } else p2 = p2 * 128; p2 = rotateAboutAxis(p2, rand(-imp, imp), CVector3f(0,0,1)); p2 = rotateAboutAxis(p2, rand(0.0f, 360.0f), dir); p2[2] *= .5f; p2 += p1; #endif CVector3f normal; if (player->weapon->weaponID == WEAPON_SHOTGUN) { //--- Clamp shot CVector3f dir = p2 - p1; normalize(dir); float clampShot; float variation = 0.01f; if(gameVar.sv_serverType == SERVER_TYPE_PRO) { //clampShot = gameVar.sv_shottyRange; CVector3f sinThetaVector = cross(dir,oldP2); float sinTheta = sinThetaVector.length(); clampShot = gameVar.sv_shottyDropRadius/sinTheta; } else { switch(ident) { case 1: clampShot = gameVar.sv_shottyRange*(0.333f+rand(-variation, variation)); break; case 2: clampShot = gameVar.sv_shottyRange*(0.667f+rand(-variation, variation)); break; case 3: clampShot = gameVar.sv_shottyRange; break; case 4: clampShot = gameVar.sv_shottyRange*(0.667f+rand(-variation, variation)); break; case 5: clampShot = gameVar.sv_shottyRange*(0.333f+rand(-variation, variation)); break; }; } p2 = p1 + dir * clampShot; } bool isCollision = false; if (map->rayTest(player->currentCF.position, p1, normal)) { p1 += normal * .01f; } // On test s'il y a une collision, sinon, f**k it on envoit pas ça if (map->rayTest(p1, p2, normal)) { isCollision = true; } if (player->weapon->weaponID == WEAPON_PHOTON_RIFLE || player->weapon->weaponID == WEAPON_FLAME_THROWER) { if (player->weapon->weaponID == WEAPON_PHOTON_RIFLE) { player->p1 = p1; player->p2 = p2; player->incShot = 30; } CVector3f p3 = p2; // On test premièrement si on touche un autre joueur! Player * hitPlayer = 0; for (int i=0;i<MAX_PLAYER;i++) { if (players[i]) { if (i != player->playerID) { #ifdef _PRO_ if (players[i]->status == PLAYER_STATUS_ALIVE && (players[i]->teamID != player->teamID || gameType == GAME_TYPE_DM || gameType == GAME_TYPE_SND || gameVar.sv_friendlyFire || gameVar.sv_reflectedDamage)) #else if (players[i]->status == PLAYER_STATUS_ALIVE && (players[i]->teamID != player->teamID || gameType == GAME_TYPE_DM || gameVar.sv_friendlyFire)) #endif { // Ray to sphere test if (segmentToSphere(p1, p3, players[i]->currentCF.position, (player->weapon->weaponID == WEAPON_FLAME_THROWER)?.50f:.25f)) { isCollision = true; hitPlayer = players[i]; normal = p3 - p1; p3 = p2; // Full length normalize(normal); // On décrémente sa vie hitPlayer->hitSV(gameVar.weapons[player->weapon->weaponID], player, gameVar.weapons[player->weapon->weaponID]->damage); } } } } } // On envoit le résultat à TOUT les joueurs y compris celui qui l'a tiré net_svcl_player_shoot playerShootSV; playerShootSV.hitPlayerID = -1; playerShootSV.playerID = player->playerID; playerShootSV.nuzzleID = nuzzleID; playerShootSV.p1[0] = (short)(p1[0] * 100); playerShootSV.p1[1] = (short)(p1[1] * 100); playerShootSV.p1[2] = (short)(p1[2] * 100); playerShootSV.p2[0] = (short)(p2[0] * 100); playerShootSV.p2[1] = (short)(p2[1] * 100); playerShootSV.p2[2] = (short)(p2[2] * 100); playerShootSV.normal[0] = (char)(normal[0] * 120); playerShootSV.normal[1] = (char)(normal[1] * 120); playerShootSV.normal[2] = (char)(normal[2] * 120); playerShootSV.weaponID = player->weapon->weaponID; bb_serverSend((char*)&playerShootSV,sizeof(net_svcl_player_shoot),NET_SVCL_PLAYER_SHOOT,0); } else { // On test premièrement si on touche un autre joueur! Player * hitPlayer = 0; for (int i=0;i<MAX_PLAYER;i++) { if (players[i]) { if (i != player->playerID) { if (players[i]->status == PLAYER_STATUS_ALIVE) { // Ray to sphere test if (segmentToSphere(p1, p2, players[i]->currentCF.position, .25f)) { isCollision = true; hitPlayer = players[i]; normal = p2 - p1; normalize(normal); } } } } } // On envoit le résultat à TOUT les joueurs y compris celui qui l'a tiré net_svcl_player_shoot playerShootSV; if (hitPlayer) { playerShootSV.hitPlayerID = hitPlayer->playerID; playerShootSV.weaponID = player->weapon->weaponID; // On décrémente sa vie hitPlayer->hitSV(gameVar.weapons[playerShootSV.weaponID], players[player->playerID]); } else { playerShootSV.hitPlayerID = -1; } playerShootSV.playerID = player->playerID; playerShootSV.nuzzleID = nuzzleID; playerShootSV.p1[0] = (short)(p1[0] * 100); playerShootSV.p1[1] = (short)(p1[1] * 100); playerShootSV.p1[2] = (short)(p1[2] * 100); playerShootSV.p2[0] = (short)(p2[0] * 100); playerShootSV.p2[1] = (short)(p2[1] * 100); playerShootSV.p2[2] = (short)(p2[2] * 100); playerShootSV.normal[0] = (char)(normal[0] * 120); playerShootSV.normal[1] = (char)(normal[1] * 120); playerShootSV.normal[2] = (char)(normal[2] * 120); playerShootSV.weaponID = player->weapon->weaponID; bb_serverSend((char*)&playerShootSV,sizeof(net_svcl_player_shoot),NET_SVCL_PLAYER_SHOOT,0); } }