]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/spawnsystem_mutator
authorMario <mario.mario@y7mail.com>
Tue, 28 Jan 2014 06:16:50 +0000 (17:16 +1100)
committerMario <mario.mario@y7mail.com>
Tue, 28 Jan 2014 06:16:50 +0000 (17:16 +1100)
mutators.cfg
qcsrc/server/autocvars.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator_spawn_near_teammate.qc

index e88fbc0afcc039cb3107c73ae778fdfce08239f2..c762ef9dec047aaa26cebd9320da67e40aad6aef 100644 (file)
@@ -77,6 +77,11 @@ set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs"
 // =====================
 set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate"
 set g_spawn_near_teammate_distance 640 "max distance to consider a spawn to be near a team mate"
+set g_spawn_near_teammate_ignore_spawnpoint 0 "ignore spawnpoints and spawn right at team mates"
+set g_spawn_near_teammate_ignore_spawnpoint_delay 2.5 "how long to wait before its OK to spawn at a player after someone just spawned at this player"
+set g_spawn_near_teammate_ignore_spawnpoint_delay_death 0 "how long to wait before its OK to spawn at a player after death"
+set g_spawn_near_teammate_ignore_spawnpoint_check_health 1 "only allow spawn at this player if their health is full"
+set g_spawn_near_teammate_ignore_spawnpoint_closetodeath 1 "spawn as close to death location as possible"
 
 
 // ========================
@@ -156,3 +161,4 @@ set g_campcheck 0 "damages campers every few seconds"
 set g_campcheck_interval 10
 set g_campcheck_damage 100
 set g_campcheck_distance 1800
+
index fc9181d56c473061faf366bf2b1c697f3bd969de..85daa81b36a5c927bbfe9f50378f3ab6d737dea3 100644 (file)
@@ -1269,3 +1269,9 @@ float autocvar_g_campcheck_damage;
 float autocvar_g_campcheck_distance;
 float autocvar_g_campcheck_interval;
 float autocvar_g_jump_grunt;
+float autocvar_g_spawn_near_teammate_distance;
+float autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
+float autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+float autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
index 72872233fe3607ca22e8b0cb5779ad22e4f3932a..5dc6f2e39346ff99098d6fe4a3a0768012b3db0a 100644 (file)
@@ -911,7 +911,7 @@ void readlevelcvars(void)
                { if(cvar(mut_cvar) && dependence) { MUTATOR_ADD(mut_name); } }
 
        CHECK_MUTATOR_ADD("g_dodging", mutator_dodging, 1);
-       CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, 1);
+       CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, teamplay);
        CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
        CHECK_MUTATOR_ADD("g_touchexplode", mutator_touchexplode, 1);
        CHECK_MUTATOR_ADD("g_minstagib", mutator_minstagib, 1);
index 4d0746dec28fe6c9235937e86597fc06ee1f5ff5..54df3a97cdcaa22f101fedaf9c8c80bcde358438 100644 (file)
@@ -1,8 +1,13 @@
-float autocvar_g_spawn_near_teammate_distance;
 .entity msnt_lookat;
 
+.float msnt_timer;
+.vector msnt_deathloc;
+
 MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
 {
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint)
+               return 0;
+
        entity p;
 
        spawn_spot.msnt_lookat = world;
@@ -36,10 +41,105 @@ MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
 
 MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
 {
-       if(spawn_spot.msnt_lookat)
+       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint)
+       {
+               if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death)
+                       self.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
+
+               entity team_mate, best_mate = world;
+               vector best_spot = '0 0 0';
+               float pc = 0, best_dist = 0, dist = 0;
+               FOR_EACH_PLAYER(team_mate)
+               {
+                       if((autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health >= 0 && team_mate.health >= autocvar_g_balance_health_regenstable) || autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health == 0)
+                       if(team_mate.deadflag == DEAD_NO)
+                       if(team_mate.msnt_timer < time)
+                       if(SAME_TEAM(self, team_mate))
+                       if(time > team_mate.spawnshieldtime) // spawn shielding
+                       if(team_mate.freezetag_frozen == 0)
+                       if(team_mate != self)
+                       {
+                               tracebox(team_mate.origin, PL_MIN, PL_MAX, team_mate.origin - '0 0 100', MOVE_WORLDONLY, team_mate);
+                               if(trace_fraction != 1.0)
+                               if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
+                               {
+                                       pc = pointcontents(trace_endpos + '0 0 1');
+                                       if(pc == CONTENT_EMPTY)
+                                       {
+                                               if(vlen(team_mate.velocity) > 5)
+                                                       fixedmakevectors(vectoangles(team_mate.velocity));
+                                               else
+                                                       fixedmakevectors(team_mate.angles);
+
+                                               for(pc = 0; pc != 5; ++pc) // test 5 diffrent spots close to mate
+                                               {
+                                                       switch(pc)
+                                                       {
+                                                               case 0:
+                                                                       tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 128, MOVE_NORMAL, team_mate);
+                                                                       break;
+                                                               case 1:
+                                                                       tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_right * 128 , MOVE_NORMAL, team_mate);
+                                                                       break;
+                                                               case 2:
+                                                                       tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
+                                                                       break;
+                                                               case 3:
+                                                                       tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
+                                                                       break;
+                                                               case 4:
+                                                                       tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_forward * 128, MOVE_NORMAL, team_mate);
+                                                                       break;
+                                                       }
+
+                                                       if(trace_fraction == 1.0)
+                                                       {
+                                                               traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NORMAL, team_mate);
+                                                               if(trace_fraction != 1.0)
+                                                               {
+                                                                       if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
+                                                                       {
+                                                                               dist = vlen(trace_endpos - self.msnt_deathloc);
+                                                                               if(dist < best_dist || best_dist == 0)
+                                                                               {
+                                                                                       best_dist = dist;
+                                                                                       best_spot = trace_endpos;
+                                                                                       best_mate = team_mate;
+                                                                               }
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               setorigin(self, trace_endpos);
+                                                                               self.angles = team_mate.angles;
+                                                                               self.angles_z = 0; // never spawn tilted even if the spot says to
+                                                                               self.fixangle = TRUE; // turn this way immediately
+                                                                               team_mate.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+                                                                               return 0;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
+               if(best_dist)
+               {
+                       setorigin(self, best_spot);
+                       self.angles = best_mate.angles;
+                       self.angles_z = 0; // never spawn tilted even if the spot says to
+                       self.fixangle = TRUE; // turn this way immediately
+                       best_mate.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+               }
+       }
+       else if(spawn_spot.msnt_lookat)
        {
                self.angles = vectoangles(spawn_spot.msnt_lookat.origin - self.origin);
                self.angles_x = -self.angles_x;
+               self.angles_z = 0; // never spawn tilted even if the spot says to
+               self.fixangle = TRUE; // turn this way immediately
                /*
                sprint(self, "You should be looking at ", spawn_spot.msnt_lookat.netname, "^7.\n");
                sprint(self, "distance: ", vtos(spawn_spot.msnt_lookat.origin - self.origin), "\n");
@@ -50,10 +150,17 @@ MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
        return 0;
 }
 
+MUTATOR_HOOKFUNCTION(msnt_PlayerDies)
+{
+       self.msnt_deathloc = self.origin;
+       return 0;
+}
+
 MUTATOR_DEFINITION(mutator_spawn_near_teammate)
 {
        MUTATOR_HOOK(Spawn_Score, msnt_Spawn_Score, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, msnt_PlayerSpawn, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerDies, msnt_PlayerDies, CBC_ORDER_ANY);
 
        return 0;
 }