X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fmutators%2Fmutator%2Fspawn_near_teammate%2Fsv_spawn_near_teammate.qc;h=2243c9872cba4d3ed6d1b1f4c47e25d7cf41a2e9;hp=ee75728630e2e5623f988e1d7efaf7b31d9f37d7;hb=991de5e6922cd3c283de56c3249624f0f1bfe767;hpb=80afa8735de5af3e81d880e9980c7d9fbc3e481c diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc index ee7572863..2243c9872 100644 --- a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc +++ b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc @@ -2,6 +2,7 @@ #include +string autocvar_g_spawn_near_teammate; float autocvar_g_spawn_near_teammate_distance; int autocvar_g_spawn_near_teammate_ignore_spawnpoint; int autocvar_g_spawn_near_teammate_ignore_spawnpoint_max; @@ -10,7 +11,7 @@ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death; bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health; bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath; -REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate")); +REGISTER_MUTATOR(spawn_near_teammate, expr_evaluate(autocvar_g_spawn_near_teammate)); .entity msnt_lookat; @@ -20,20 +21,19 @@ REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate")); MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) { + if (!teamplay) return; + entity player = M_ARGV(0, entity); entity spawn_spot = M_ARGV(1, entity); vector spawn_score = M_ARGV(2, vector); - if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && player.cvar_cl_spawn_near_teammate)) + if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && CS(player).cvar_cl_spawn_near_teammate)) return; spawn_spot.msnt_lookat = NULL; - if(!teamplay) - return; - RandomSelection_Init(); - FOREACH_CLIENT(IS_PLAYER(it) && it != player && SAME_TEAM(it, player) && !IS_DEAD(it), LAMBDA( + FOREACH_CLIENT(IS_PLAYER(it) && it != player && SAME_TEAM(it, player) && !IS_DEAD(it), { if(vdist(spawn_spot.origin - it.origin, >, autocvar_g_spawn_near_teammate_distance)) continue; if(vdist(spawn_spot.origin - it.origin, <, 48)) @@ -41,7 +41,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) if(!checkpvs(spawn_spot.origin, it)) continue; RandomSelection_AddEnt(it, 1, 1); - )); + }); if(RandomSelection_chosen_ent) { @@ -56,7 +56,8 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) { - if(!teamplay) { return; } + if (!teamplay) return; + entity player = M_ARGV(0, entity); entity spawn_spot = M_ARGV(1, entity); @@ -76,7 +77,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) return; // at least 1 team has only 1 player, let's not give the bigger team too much of an advantage! // Note: when entering this, fixangle is already set. - if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && player.cvar_cl_spawn_near_teammate)) + if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && CS(player).cvar_cl_spawn_near_teammate)) { if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death) player.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death; @@ -85,16 +86,16 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) vector best_pos = '0 0 0'; float best_dist2 = FLOAT_MAX; int tested = 0; - FOREACH_CLIENT_RANDOM(IS_PLAYER(it), LAMBDA( + FOREACH_CLIENT_RANDOM(IS_PLAYER(it), { if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_max && tested >= autocvar_g_spawn_near_teammate_ignore_spawnpoint_max) break; if (PHYS_INPUT_BUTTON_CHAT(it)) continue; - if (!SAME_TEAM(player, it)) continue; - if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && it.health < autocvar_g_balance_health_regenstable) continue; + if (DIFF_TEAM(player, it)) continue; + if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && GetResource(it, RES_HEALTH) < autocvar_g_balance_health_regenstable) continue; if (IS_DEAD(it)) continue; if (time < it.msnt_timer) continue; if (time < it.spawnshieldtime) continue; - if (forbidWeaponUse(it)) continue; + if (weaponLocked(it)) continue; if (it == player) continue; tested++; // i consider a teammate to be available when he passes the checks above @@ -102,10 +103,15 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) vector horiz_vel = vec2(it.velocity); // when walking slowly sideways, we assume the player wants a clear shot ahead - spawn behind him according to where he's looking // when running fast, spawn behind him according to his direction of movement to prevent colliding with the newly spawned player + vector forward = '0 0 0'; vector right = '0 0 0'; vector up = '0 0 0'; if (vdist(horiz_vel, >, autocvar_sv_maxspeed + 50)) - fixedmakevectors(vectoangles(horiz_vel)); + { + FIXED_MAKE_VECTORS(vectoangles(horiz_vel), forward, right, up); + } else - fixedmakevectors(it.angles); // .angles is the angle of the model - usually/always 0 pitch + { + FIXED_MAKE_VECTORS(it.angles, forward, right, up); + } // test different spots close to mate - trace upwards so it works on uneven surfaces // don't spawn in front of player or directly behind to avoid players shooting each other @@ -116,22 +122,22 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) switch(i) { case 0: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 64 + v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 64 + right * 128 + up * 64, MOVE_NOMONSTERS, it); break; case 1: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 64 - v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 64 - right * 128 + up * 64, MOVE_NOMONSTERS, it); break; case 2: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin + v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin + right * 192 + up * 64, MOVE_NOMONSTERS, it); break; case 3: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - right * 192 + up * 64, MOVE_NOMONSTERS, it); break; case 4: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 128 + v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 128 + right * 64 + up * 64, MOVE_NOMONSTERS, it); break; case 5: - tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - v_forward * 128 - v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it); + tracebox(it.origin, STAT(PL_MIN, player), STAT(PL_MAX, player), it.origin - forward * 128 - right * 64 + up * 64, MOVE_NOMONSTERS, it); break; } @@ -141,7 +147,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) // 400 is about the height of a typical laser jump (in overkill) // not traceline because we need space for the whole player, not just his origin - tracebox(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), horizontal_trace_endpos - '0 0 400', MOVE_NORMAL, it); + tracebox(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), horizontal_trace_endpos - 400 * up, MOVE_NORMAL, it); vector vectical_trace_endpos = trace_endpos; //te_lightning1(NULL, horizontal_trace_endpos, vectical_trace_endpos); if (trace_startsolid) goto skip; // inside another player @@ -151,8 +157,9 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) if (tracebox_hits_trigger_hurt(horizontal_trace_endpos, STAT(PL_MIN, player), STAT(PL_MAX, player), vectical_trace_endpos)) goto skip; // make sure the spawned player will have floor ahead (or at least a wall - he shouldn't fall as soon as he starts moving) - vector floor_test_start = vectical_trace_endpos + v_up * STAT(PL_MAX, player).z + v_forward * STAT(PL_MAX, player).x; // top front of player's bbox - highest point we know is not inside solid - traceline(floor_test_start, floor_test_start + v_forward * 100 - v_up * 128, MOVE_NOMONSTERS, it); + // top front of player's bbox - highest point we know is not inside solid + vector floor_test_start = vectical_trace_endpos + up * STAT(PL_MAX, player).z + forward * STAT(PL_MAX, player).x; + traceline(floor_test_start, floor_test_start + forward * 100 - up * 128, MOVE_NOMONSTERS, it); //te_beam(NULL, floor_test_start, trace_endpos); if (trace_fraction == 1.0) goto skip; @@ -170,7 +177,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) // here, we know we found a good spot RandomSelection_Add(it, 0, string_null, vectical_trace_endpos, 1, 1); - //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + v_forward * 10); + //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + forward * 10); LABEL(skip) if (i % 2 == 1 && RandomSelection_chosen_ent) @@ -196,7 +203,7 @@ LABEL(skip) break; // don't test the other spots near this teammate, go to the next one } } - )); + }); if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath) if(best_mate)