]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote branch 'origin/master' into samual/updatecommands
authorSamual <samual@xonotic.org>
Sun, 4 Dec 2011 15:51:47 +0000 (10:51 -0500)
committerSamual <samual@xonotic.org>
Sun, 4 Dec 2011 15:51:47 +0000 (10:51 -0500)
25 files changed:
defaultXonotic.cfg
qcsrc/client/Defs.qc
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/ctf.qc [deleted file]
qcsrc/client/hud.qc
qcsrc/client/main.qh
qcsrc/client/progs.src
qcsrc/client/projectile.qc
qcsrc/client/scoreboard.qc
qcsrc/client/shownames.qc
qcsrc/client/tturrets.qc
qcsrc/client/waypointsprites.qc
qcsrc/common/constants.qh
qcsrc/server/assault.qc
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc
qcsrc/server/defs.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/mutator_spawn_near_teammate.qc [new file with mode: 0644]
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/sv_main.qc

index 8d5cecd54149ee384e085b0edcd762c307273f95..0ea94f7c686cb905751b5f8b397c960efb50fe2c 100644 (file)
@@ -614,6 +614,8 @@ seta g_freezetag_frozen_force 0.6 "How much to multiply the force on a frozen pl
 
 set g_spawn_furthest 0.5 "this amount of the spawns shall be far away from any players"
 set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay"
+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"
 // respawn delay
 set g_respawn_delay 2 "number of seconds you have to wait before you can respawn again"
 set g_respawn_waves 0 "respawn in waves (every n seconds), intended to decrease overwhelming base attacks"
index a1a32404dd48ec7d57bdeb83eca8b624433f58fd..901380c1bb28e130df82c992a1a33a27f289892d 100644 (file)
@@ -28,7 +28,7 @@ entity                world;
 float          time;
 float          frametime;
 
-float          player_localentnum;     //the entnum
+float          player_localentnum;     //the entnum of the VIEW entity
 float          player_localnum;        //the playernum
 float          maxclients;     //a constant filled in by the engine. gah, portability eh?
 
index cf696a3228cf2d7b646601b95384442d446e3d95..0f28e4bac5f7658d5c3faba9d716112e88793328 100644 (file)
@@ -46,6 +46,11 @@ void CSQC_Init(void)
 
        float i;
 
+#ifdef COMPAT_XON050_ENGINE
+       // old engine lacks implementation of player_localnum
+       player_localnum = player_localentnum - 1;
+#endif
+
        binddb = db_create();
        tempdb = db_create();
        ClientProgsDB = db_load("client.db");
@@ -483,7 +488,7 @@ void Ent_ClientData()
        if(f & 2)
        {
                newspectatee_status = ReadByte();
-               if(newspectatee_status == player_localentnum)
+               if(newspectatee_status == player_localnum + 1)
                        newspectatee_status = -1; // observing
        }
        else
@@ -517,6 +522,8 @@ void Ent_ClientData()
                        prev_health = -1;
        }
        spectatee_status = newspectatee_status;
+
+       // non-COMPAT_XON050_ENGINE: we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
 }
 
 void Ent_Nagger()
@@ -963,7 +970,7 @@ void Net_ReadRace()
                                strunzone(grecordholder[pos-1]);
                        grecordholder[pos-1] = strzone(ReadString());
                        grecordtime[pos-1] = ReadInt24_t();
-                       if(grecordholder[pos-1] == GetPlayerName(player_localentnum -1))
+                       if(grecordholder[pos-1] == GetPlayerName(player_localnum))
                                race_myrank = pos;
                        break;
                case RACE_NET_SERVER_STATUS:
index ca9841b53293760a08bef6df2d4a72369ddc8327..d9f6df7ee77281fdf2e52b650d25680dec5f72a9 100644 (file)
@@ -371,6 +371,7 @@ void CSQC_UpdateView(float w, float h)
        vector v;
        vector vf_size, vf_min;
        float a;
+
        hud = getstati(STAT_HUD);
 
        if(checkextension("DP_CSQC_MINFPS_QUALITY"))
@@ -407,9 +408,11 @@ void CSQC_UpdateView(float w, float h)
 
        WaypointSprite_Load();
 
+#ifdef COMPAT_XON050_ENGINE
        if(spectatee_status)
                myteam = GetPlayerColor(spectatee_status - 1);
        else
+#endif
                myteam = GetPlayerColor(player_localentnum - 1);
 
        ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
diff --git a/qcsrc/client/ctf.qc b/qcsrc/client/ctf.qc
deleted file mode 100644 (file)
index 5bf6639..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-#ifdef CTF_EXAMPLE
-
-// NOTE: This file contains lots of debugging stuff
-// it is not really used... can be seen as another sample...
-
-string STR_PLAYER = "player";
-#define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; )
-
-string ctf_temp_1;
-float order_page;
-
-void menu_close()
-{
-       menu_visible = false;
-       menu_show = menu_show_error;
-       menu_action = menu_sub_null;
-       
-       /*if(ctf_temp_1)
-         strunzone(ctf_temp_1);*/
-       
-       localcmd("\nin_bindmap 0 0;");
-}
-
-void order_menu_render()
-{
-       vector ps, po;
-       float i, p, n;
-       string frags, color;
-       ps = '0 200 0';
-       po = '0 8 0';
-
-       color = getplayerkeyvalue(player_localentnum-1, "topcolor");
-       
-       if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) {
-               drawstring(ps, _("----- Order Menu -----"), '8 8 0', '1 1 0', 1, 0); ps += po;
-               drawstring(ps, sprintf(_("Order: %s"), ctf_temp_1), '8 8 0', '1 1 0', 1, 0); ps += po;
-               drawcolorcodedstring(ps, _("1) ^3previous page"), '8 8 0', 1, 0); ps += po;
-               drawcolorcodedstring(ps, _("2) ^3next page"), '8 8 0', 1, 0); ps += po;
-               for((n = 2), (p = i = 0); i < maxclients && n > 0; ++i) {
-                       frags = getplayerkeyvalue(i, "frags");
-                       if(!frags || (i+1) == player_localentnum)
-                               continue;
-                       if(frags == "-666" || getplayerkeyvalue(i, "topcolor") != color) // FIXME use GetPlayerTeam
-                               continue;
-                       ++p;
-                       if(p > (8*order_page))
-                       {
-                               // only render current page
-                               ++n;
-                               if(n == 10)
-                                       n = 0;
-                               drawcolorcodedstring(ps, strcat(ftos(n), ") ", GetPlayerName(i), " : ", ftos(getstatf(STAT_CTF_STATE))), '8 8 0', 1, 0); ps += po;
-                       }
-               }
-               drawstring(ps, _("ESC) Exit Menu"), '8 8 0', '1 1 0', 1, 0); ps += po;
-       } else {
-               menu_close();
-       }
-}
-
-float order_menu_action(float bInputType, float nPrimary, float nSecondary)
-{
-       string arg;
-       float p, i, n, chose;
-       string frags, color;
-       if(bInputType != 0) // key down wanted
-               return FALSE;
-       
-       arg = chr2str(nSecondary);
-       chose = stof(chr2str(nPrimary));
-       //str2chr
-       if(arg == "1") {
-               color = getplayerkeyvalue(player_localentnum-1, "topcolor");
-               ++order_page;
-               for(p = i = 0; i < maxclients; ++i) {
-                       frags = getplayerkeyvalue(i, "frags");
-                       if(!frags || (i+1) == player_localentnum)
-                               continue;
-                       if(frags == "-666" || getplayerkeyvalue(i, "topcolor") != color) // FIXME use GetPlayerTeam
-                               continue;
-                       ++p;
-               }
-               if(p <= (8*order_page)) // no ppl on page
-                       order_page = 0;
-       } else if(arg == "2") {
-               color = getplayerkeyvalue(player_localentnum-1, "topcolor");
-               --order_page;
-               if(order_page < 0) {
-                       for(p = i = 0; i < maxclients; ++i) {
-                               frags = getplayerkeyvalue(i, "frags");
-                               if(!frags || (i+1) == player_localentnum)
-                                       continue;
-                               if(frags == "-666" || getplayerkeyvalue(i, "topcolor") != color) // FIXME use GetPlayerTeam
-                                       continue;
-                               ++p;
-                       }
-                       order_page = floor(p/8);
-               }
-       } else if(chose >= 3 && chose <= 9 || arg == "0") { // the 10 needs extra checking, assuming that stof(astring) returns 0
-               if(chose == 0)
-                       chose = 10;
-               n = 2;
-               color = getplayerkeyvalue(player_localentnum-1, "topcolor");
-               for(p = i = 0; i < maxclients && n > 0; ++i) {
-                       frags = getplayerkeyvalue(i, "frags");
-                       if(!frags || (i+1) == player_localentnum)
-                               continue;
-                       if(frags == "-666" || getplayerkeyvalue(i, "topcolor") != color) // FIXME use GetPlayerTeam
-                               continue;
-                       ++p;
-                       if(p > (8*order_page))
-                       {
-                               // only render current page
-                               ++n;
-                               if(n == chose) {
-                                       n = 0;
-                                       break;
-                               }
-                       }
-               }
-               if(n == 0) {
-                       //print(sprintf(_("Issuing order to: %d\n"), i+1));
-                       //print(strcat("cmd order #", ftos(i+1), " ", ctf_temp_1, ";\n"));
-                       localcmd(strcat("\ncmd order #", ftos(i+1), " ", ctf_temp_1, ";"));
-               } else {
-                       print(sprintf(_("Couldn't find player %d\n"), chose));
-               }
-               return TRUE;
-       } else if(nSecondary == K_ESCAPE) {
-               strunzone(ctf_temp_1);
-               menu_close();
-       } else {
-               //print(sprintf(_("Menu action %s does not exist.\n"), arg));
-               return FALSE;
-       }
-       return TRUE;
-}
-
-void order_menu_show()
-{
-       order_page = 0;
-       menu_show = order_menu_render;
-       menu_action = order_menu_action;
-}
-
-
-void ctf_menu_render()
-{
-       vector ps, po;
-       ps = '0 200 0';
-       po = '0 8 0';
-       
-       if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) {
-               drawstring(ps, _("----- Command Menu -----"), '8 8 0', '1 1 0', 1, 0); ps += po;
-               drawstring(ps, _("Issue orders:"), '8 8 0', '1 1 0', 1, 0); ps += po;
-               drawstring(ps, _(" 1) Attack"), '8 8 0', '1 1 0', 1, 0);
-               drawstring(ps + '80 0 0', " \x0F", '8 8 0', '1 1 1', 1, 0); ps += po;
-               drawstring(ps, strcat(_(" 2) Defend"), " \x0E"), '8 8 0', '1 1 0', 1, 0); ps += po;
-               ps += po;
-               drawstring(ps, _("3) Resign from command."), '8 8 0', '1 1 0', 1, 0); ps += po;
-               drawstring(ps, _("ESC) Exit Menu"), '8 8 0', '1 1 0', 1, 0); ps += po;
-       } else {
-               menu_close();
-       }
-}
-
-float ctf_menu_action(float bInputType, float nPrimary, float nSecondary)
-{
-       string arg;
-       if(bInputType != 0) // key down wanted
-               return FALSE;
-       
-       arg = chr2str(nSecondary);
-
-       if(arg == "1") {
-               ctf_temp_1 = strzone("attack");
-               order_menu_show();
-       } else if(arg == "2") {
-               ctf_temp_1 = strzone("defend");
-               order_menu_show();
-       } else if(arg == "3") {
-               localcmd("\ncmd order resign;");
-               menu_close();
-       } else if(nSecondary == K_ESCAPE) {
-               menu_close();
-       } else {
-               //print(strcat("Menu action ", arg, " does not exist.\n"));
-               return FALSE;
-       }
-       return TRUE;
-}
-
-void ctf_menu_show()
-{
-       if(getstati(STAT_CTF_STATE) < 0)
-               return;
-       menu_show = ctf_menu_render;
-       menu_action = ctf_menu_action;
-       menu_visible = TRUE;
-       //menu_default_binds();
-}
-
-void ctf_view()
-{
-       float stat;
-       stat = getstati(STAT_CTF_STATE);
-       if(stat == CTF_STATE_ATTACK) {
-               drawpic('0 0 0', "gfx/ctf_ic_atk.tga", '64 64 0', '1 1 1', 1, 0);
-       } else if(stat == CTF_STATE_DEFEND) {
-               drawpic('0 0 0', "gfx/ctf_ic_def.tga", '64 64 0', '1 1 1', 1, 0);
-       } else if(stat == CTF_STATE_COMMANDER) {
-               drawstring('0 0 0', _("You're commander!"), '8 8 0', '1 1 1', 1, 0);
-       } else if(stat < 0) {
-       } else {
-               drawstring('0 0 0', _("Awaiting orders..."), '8 8 0', '1 1 1', 0.5, 0);
-       }
-}
-
-#endif
index efa2d317beccd9bc14618a9c02c81fa589244986..86b49761e5ca59cd34e978073f82e79ad9ddf395 100644 (file)
@@ -432,33 +432,34 @@ float GetAmmoTypeForWep(float i)
 void HUD_Weapons(void)
 {
        // declarations
-       float weapons_stat = getstati(STAT_WEAPONS); 
+       float weapons_stat = getstati(STAT_WEAPONS);
        float i, f, a, j, factor;
-       float screen_ar, center_x, center_y; 
-       float weapon_count, weapon_id, weapon_alpha; 
-       float row, column, rows, columns; 
+       float screen_ar, center_x, center_y;
+       float weapon_count, weapon_id, weapon_alpha;
+       float row, column, rows, columns;
        float aspect = autocvar_hud_panel_weapons_aspect;
-       
+
        float show_accuracy, panel_weapon_accuracy;
-       
+
        float timeout = autocvar_hud_panel_weapons_timeout;
        float timein_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.375 : 0);
        float timeout_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.75 : 0);
-       
+
        float ammo_type, ammo_full, ammo_alpha;
        float barsize_x, barsize_y, baroffset_x, baroffset_y;
-       
+
        float when = autocvar_hud_panel_weapons_complainbubble_time;
        float fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime;
-       
+
        vector weapon_pos, weapon_size;
        local noref vector old_panel_size; // fteqcc sucks
        vector color, ammo_color;
-       
+
        // check to see if we want to continue
-  if(hud != HUD_NORMAL) { return; }
-  
+       if(hud != HUD_NORMAL) { return; }
+
        if(!autocvar__hud_configure)
+       {
                if((!autocvar_hud_panel_weapons) || (spectatee_status == -1))
                        return;
                else if(timeout && time >= weapontime + timeout + timeout_effect_length)
@@ -466,13 +467,14 @@ void HUD_Weapons(void)
                        weaponprevtime = time;
                        return;
                }
+       }
        else
                hud_configure_active_panel = HUD_PANEL_WEAPONS;
 
        // update generic hud functions
        HUD_Panel_UpdateCvars(weapons);
        HUD_Panel_ApplyFadeAlpha();
-       
+
        // calculate fading effect to weapon images for when the panel is idle
        if(autocvar_hud_panel_weapons_fade)
        {
@@ -511,7 +513,7 @@ void HUD_Weapons(void)
 
                weaponorder_cmp_str = string_null;
        }
-       
+
        // determine which weapons are going to be shown
        if (autocvar_hud_panel_weapons_onlyowned)
        {
@@ -520,25 +522,25 @@ void HUD_Weapons(void)
                        if (weapons_stat == 0) // create some fake weapons anyway
                                for(i = 0; i <= WEP_LAST-WEP_FIRST; i += floor((WEP_LAST-WEP_FIRST)/5))
                                        weapons_stat |= power2of(i);
-                                       
+
                        if(menu_enabled != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
                }
-               
+
                // do we own this weapon?
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
                        if(weapons_stat & weaponorder[i].weapons)
                                ++weapon_count;
-               
+
                // add it anyway if weaponcomplain is shown
                if((!autocvar__hud_configure) 
                        && (autocvar_hud_panel_weapons_complainbubble 
                                && time - complain_weapon_time < when + fadetime))
                                        ++weapon_count;
-                       
+
                // might as well commit suicide now, no reason to live ;)
                if (weapon_count == 0) { return; }
-               
+
                // reduce size of the panel
                if (panel_size_y > panel_size_x)
                {
@@ -623,12 +625,12 @@ void HUD_Weapons(void)
                }
        }
 
-       // draw the background, then change the virtual size of it to better fit other items inside 
+       // draw the background, then change the virtual size of it to better fit other items inside
        HUD_Panel_DrawBg(1);
        if(panel_bg_padding)
        {
                panel_pos += '1 1 0' * panel_bg_padding;
-               panel_size -= '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
        }
 
        // after the sizing and animations are done, update the other values
@@ -636,7 +638,7 @@ void HUD_Weapons(void)
        rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
        columns = ceil(weapon_count/rows);
        weapon_size = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows);
-       
+
        // calculate position/size for visual bar displaying ammount of ammo status
        if (autocvar_hud_panel_weapons_ammo)
        {
@@ -670,10 +672,10 @@ void HUD_Weapons(void)
                // retrieve information about the current weapon to be drawn
                self = weaponorder[i];
                weapon_id = self.impulse;
-               
+
                // skip if this weapon doesn't exist
                if (!self || self.impulse < 0) { continue; }
-               
+
                // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
                if (autocvar_hud_panel_weapons_onlyowned
                        && !((weapons_stat & self.weapons) 
@@ -681,7 +683,7 @@ void HUD_Weapons(void)
                                && time - complain_weapon_time < when + fadetime 
                                && autocvar_hud_panel_weapons_complainbubble)))
                                        continue;
-                                       
+
                // figure out the drawing position of weapon
                weapon_pos = (panel_pos 
                        + eX * column * weapon_size_x 
@@ -723,19 +725,19 @@ void HUD_Weapons(void)
                                case 1: // weapon number
                                        drawstring(weapon_pos, ftos(weapon_id), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
-                                       
+
                                case 2: // bind
                                        drawstring(weapon_pos, getcommandkey(ftos(weapon_id), strcat("impulse ", ftos(weapon_id))), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
-                                       
+
                                case 3: // weapon name
                                        drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
-                                       
+
                                default: // nothing
                                        break;
                        }
-                       
+
                        // draw ammo status bar
                        if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO)
                        {
@@ -769,7 +771,7 @@ void HUD_Weapons(void)
                {
                        drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
                }
-               
+
                // draw the complain message
                if(time - complain_weapon_time < when + fadetime && self.weapon == complain_weapon && autocvar_hud_panel_weapons_complainbubble)
                {
@@ -2692,7 +2694,11 @@ void HUD_Score(void)
        string sign;
        vector distribution_color;
        entity tm, pl, me;
+#ifdef COMPAT_XON050_ENGINE
        me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1];
+#else
+       me = playerslots[player_localentnum - 1];
+#endif
 
        if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
                string timer, distrtimer;
@@ -3567,7 +3573,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
 {
        mod_active = 1; // race should never hide the mod icons panel
        entity me;
-       me = playerslots[player_localentnum - 1];
+       me = playerslots[player_localnum];
        float t, score;
        float f; // yet another function has this
        score = me.(scores[ps_primary]);
@@ -3675,7 +3681,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
                drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
                drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
        } else if(race_status == 2) {
-               if(race_status_name == GetPlayerName(player_localentnum -1) || !race_myrank || race_myrank < rank)
+               if(race_status_name == GetPlayerName(player_localnum) || !race_myrank || race_myrank < rank)
                        drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                else
                        drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
@@ -4121,7 +4127,11 @@ void HUD_InfoMessages(void)
                        if(spectatee_status == -1)
                                s = _("^1Observing");
                        else
+#ifdef COMPAT_XON050_ENGINE
                                s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(spectatee_status - 1));
+#else
+                               s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(player_localentnum - 1));
+#endif
                        drawInfoMessage(s)
 
                        if(spectatee_status == -1)
@@ -4144,7 +4154,7 @@ void HUD_InfoMessages(void)
                        else if(gametype == GAME_LMS)
                        {
                                entity sk;
-                               sk = playerslots[player_localentnum - 1];
+                               sk = playerslots[player_localnum];
                                if(sk.(scores[ps_primary]) >= 666)
                                        s = _("^1Match has already begun");
                                else if(sk.(scores[ps_primary]) > 0)
@@ -4883,7 +4893,11 @@ void HUD_Main (void)
                        drawfill(eY * i * hud_configure_realGridSize_y, eY + eX * vid_conwidth, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL);
        }
 
+#ifdef COMPAT_XON050_ENGINE
     current_player = (spectatee_status > 0) ? spectatee_status : player_localentnum;
+#else
+    current_player = player_localentnum;
+#endif
 
        // draw the dock
        if(autocvar_hud_dock != "" && autocvar_hud_dock != "0")
index 57028bf3e9d836229a0fc6fe10a20d594eecbb8b..ec25ab98b90b01f7c4960bdc79f31d0105009ded 100644 (file)
@@ -17,14 +17,6 @@ float menu_visible;
 var void() menu_show;
 var float(float bInputType, float nPrimary, float nSecondary) menu_action;
 
-// --------------------------------------------------------------------------
-// CTF
-
-#ifdef CTF_EXAMPLE
-void() ctf_menu_show;
-string ctf_temp_1;
-#endif
-
 // --------------------------------------------------------------------------
 // Onslaught
 
index e8ba3990e04eabb0e461edca098cd99a4a7a6c0f..f87bfb002cf8fef981fb47ab78cacf36be1e3e2f 100644 (file)
@@ -42,8 +42,6 @@ sortlist.qc
 miscfunctions.qc
 teamplay.qc
 
-ctf.qc
-
 teamradar.qc
 hud_config.qc
 hud.qc
index e17d7ba3ddeb9df27c09c4d43c56b2508fcc79bb..e8274c8cd95d44a9ca61904e43ea20b3627c883c 100644 (file)
@@ -75,7 +75,7 @@ void Projectile_Draw()
                        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
                if(!(self.move_flags & FL_ONGROUND))
                        if(self.velocity != '0 0 0')
-                               self.angles = vectoangles(self.velocity);
+                               self.move_angles = self.angles = vectoangles(self.velocity);
        }
        else
        {
index d4c2043e6c66fb05c99ab17090b82a702492d7af..3124b4b9b4d68056f968c4ca87f15c993edf8c99 100644 (file)
@@ -894,7 +894,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
                {
                        if(pl.team != tm.team)
                                continue;
-                       HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
+                       HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
                        pos_y += 1.25 * hud_fontsize_y;
                        ++i;
                }
@@ -903,7 +903,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
                {
                        if(pl.team == COLOR_SPECTATOR)
                                continue;
-                       HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
+                       HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
                        pos_y += 1.25 * hud_fontsize_y;
                        ++i;
                }
@@ -1147,7 +1147,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
                        continue;
                n = grecordholder[i];
                p = race_PlaceName(i+1);
-               if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
+               if(grecordholder[i] == GetPlayerName(player_localnum))
                        drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
                else if(!mod(i, 2) && scoreboard_highlight)
                        drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
@@ -1296,7 +1296,7 @@ void HUD_DrawScoreboard()
                if(pl.team != COLOR_SPECTATOR)
                        continue;
                pos_y += 1.25 * hud_fontsize_y;
-               HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs);
+               HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
                ++specs;
        }
 
index 21e8bcd420799ac3688e938abcefcc780cf67fd4..d5e24888d34a79e03d2de8db4a8c19ca22c8219f 100644 (file)
@@ -13,7 +13,11 @@ void Draw_ShowNames(entity ent)
        if(!autocvar_hud_shownames)
                return;
        
+#ifdef COMPAT_XON050_ENGINE
        if((ent.sv_entnum == player_localentnum) || (ent.sv_entnum == spectatee_status)) // ent is me or person i'm spectating
+#else
+       if(ent.sv_entnum == player_localentnum) // ent is me or person i'm spectating
+#endif
                if not (autocvar_hud_shownames_self && autocvar_chase_active) 
                        return;
 
index f4a53ca199563b18495dce544fce2af04a7537df..89f1be7fa826d008d2cf2795408a3385ee37e375 100644 (file)
@@ -264,7 +264,7 @@ void turret_draw2d()
         return;
 
        string spriteimage = self.netname;
-       float t = (GetPlayerColor(player_localentnum - 1) + 1); 
+       float t = (GetPlayerColor(player_localnum) + 1);        
        float a = self.alpha * autocvar_hud_panel_fg_alpha;
        vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
 
index ac85f8c65638bfda0385f1a7718cfe35ba4c998f..6d9b0ee8bd7fee0f2112cf77686f6a25111dce6b 100644 (file)
@@ -403,7 +403,7 @@ void Draw_WaypointSprite()
 
        InterpolateOrigin_Do();
 
-       t = GetPlayerColor(player_localentnum - 1) + 1;
+       t = GetPlayerColor(player_localnum) + 1;
 
        spriteimage = "";
 
index d838f09e2bc52ca2d936353ab40fcd9e63283a3b..7e5e99edbf9a5a2c64476c7e526c305a70284c6f 100644 (file)
@@ -574,3 +574,9 @@ float HUD_MENU_ENABLE               = 0;
 #define SERVERFLAG_ALLOW_FULLBRIGHT 1
 #define SERVERFLAG_TEAMPLAY 2
 #define SERVERFLAG_PLAYERSTATS 4
+
+// spawnpoint prios
+#define SPAWN_PRIO_NEAR_TEAMMATE_FOUND    200
+#define SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM 100
+#define SPAWN_PRIO_RACE_PREVIOUS_SPAWN     50
+#define SPAWN_PRIO_GOOD_DISTANCE           10
index 45fa5c77d43aabc688d325e9f8f6edd191cc2c7f..425bbf77933892791bf46b5c96219b50daec758e 100644 (file)
@@ -47,6 +47,13 @@ void assault_objective_use() {
        self = oldself;
 }
 
+vector target_objective_spawn_evalfunc(entity player, entity spot, vector current)
+{
+       if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE)
+               return '-1 0 0';
+       return current;
+}
+
 void spawnfunc_target_objective() {
        if(!g_assault)
        {
@@ -57,6 +64,7 @@ void spawnfunc_target_objective() {
        self.use = assault_objective_use;
        assault_objective_reset();
        self.reset = assault_objective_reset;
+       self.spawn_evalfunc = target_objective_spawn_evalfunc;
 }
 
 
index 609516634c3282858329786bc0c7aeabdabcb6e1..f1bd5b024d75b924f2068bebc1f16b7ba5bced58 100644 (file)
@@ -1065,7 +1065,6 @@ float autocvar_skill_auto;
 #define autocvar_slowmo cvar("slowmo")
 float autocvar_snd_soundradius;
 float autocvar_spawn_debug;
-float autocvar_spawn_debugview;
 float autocvar_speedmeter;
 float autocvar_sv_accelerate;
 var float autocvar_sv_accuracy_data_share = 1;
index 40039ead81f107743a38a78b3a58be2ea38ba6cd..c21fc78719d81260e7b01d99391f7ef1ea64b806 100644 (file)
@@ -123,7 +123,7 @@ void spawnpoint_use()
 // Returns:
 //   _x: prio (-1 if unusable)
 //   _y: weight
-vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoint)
+vector Spawn_Score(entity spot, float mindist, float teamcheck)
 {
        float shortest, thisdist;
        float prio;
@@ -151,55 +151,37 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi
                        return '-1 0 0';
        }
 
+       shortest = vlen(world.maxs - world.mins);
+       FOR_EACH_PLAYER(player) if (player != self)
+       {
+               thisdist = vlen(player.origin - spot.origin);
+               if (thisdist < shortest)
+                       shortest = thisdist;
+       }
+       if(shortest < mindist)
+               prio += SPAWN_PRIO_GOOD_DISTANCE;
+
+       spawn_score = prio * '1 0 0' + shortest * '0 1 0';
+       spawn_spot = spot;
+
        // filter out spots for assault
        if(spot.target != "") {
                entity ent;
-               float good, found;
+               float found;
 
                found = 0;
-               good = 0;
                for(ent = world; (ent = find(ent, targetname, spot.target)); )
                {
                        ++found;
-                       if(ent.classname == "target_objective")
+                       if(ent.spawn_evalfunc)
                        {
-                               if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE)
-                                       continue;
-                       }
-                       else if(ent.classname == "trigger_race_checkpoint")
-                       {
-                               if(!anypoint) // spectators may spawn everywhere
-                               {
-                                       if(g_race_qualifying)
-                                       {
-                                               // spawn at first
-                                               if(ent.race_checkpoint != 0)
-                                                       continue;
-                                               if(spot.race_place != race_lowest_place_spawn)
-                                                       continue;
-                                       }
-                                       else
-                                       {
-                                               if(ent.race_checkpoint != self.race_respawn_checkpoint)
-                                                       continue;
-                                               // try reusing the previous spawn
-                                               if(ent == self.race_respawn_spotref || spot == self.race_respawn_spotref)
-                                                       prio += 1;
-                                               if(ent.race_checkpoint == 0)
-                                               {
-                                                       float pl;
-                                                       pl = self.race_place;
-                                                       if(pl > race_highest_place_spawn)
-                                                               pl = 0;
-                                                       if(pl == 0 && !self.race_started)
-                                                               pl = race_highest_place_spawn; // use last place if he has not even touched finish yet
-                                                       if(spot.race_place != pl)
-                                                               continue;
-                                               }
-                                       }
-                               }
+                               entity oldself = self;
+                               self = ent;
+                               spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
+                               self = oldself;
+                               if(spawn_score_x < 0)
+                                       return spawn_score;
                        }
-                       ++good;
                }
 
                if(!found)
@@ -207,95 +189,42 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi
                        dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
                        return '-1 0 0';
                }
-
-               if(good < found) // at least one was bad
-                       return '-1 0 0';
        }
 
-       player = playerlist;
-       shortest = vlen(world.maxs - world.mins);
-       for(player = playerlist; player; player = player.chain)
-               if (player != self)
-               {
-                       thisdist = vlen(player.origin - spot.origin);
-                       if (thisdist < shortest)
-                               shortest = thisdist;
-               }
-       return prio * '1 0 0' + shortest * '0 1 0';
+       MUTATOR_CALLHOOK(Spawn_Score);
+       return spawn_score;
+}
+
+void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
+{
+       entity spot;
+       for(spot = firstspot; spot; spot = spot.chain)
+               spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
 }
 
-float spawn_allbad;
-float spawn_allgood;
-entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck, float anypoint)
+entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
 {
        entity spot, spotlist, spotlistend;
-       spawn_allgood = TRUE;
-       spawn_allbad = TRUE;
 
        spotlist = world;
        spotlistend = world;
 
+       Spawn_ScoreAll(firstspot, mindist, teamcheck);
+
        for(spot = firstspot; spot; spot = spot.chain)
        {
-               spot.spawnpoint_score = Spawn_Score(spot, playerlist, teamcheck, anypoint);
-
-               if(autocvar_spawn_debugview)
-               {
-                       setmodel(spot, "models/runematch/rune.mdl");
-                       if(spot.spawnpoint_score_y < mindist)
-                       {
-                               spot.colormod = '1 0 0';
-                               spot.scale = 1;
-                       }
-                       else
-                       {
-                               spot.colormod = '0 1 0';
-                               spot.scale = spot.spawnpoint_score_y / mindist;
-                       }
-               }
-
                if(spot.spawnpoint_score_x >= 0) // spawning allowed here
                {
-                       if(spot.spawnpoint_score_y < mindist)
-                       {
-                               // too short distance
-                               spawn_allgood = FALSE;
-                       }
-                       else
-                       {
-                               // perfect
-                               spawn_allbad = FALSE;
-
-                               if(spotlistend)
-                                       spotlistend.chain = spot;
-                               spotlistend = spot;
-                               if(!spotlist)
-                                       spotlist = spot;
-
-                               /*
-                               if(teamcheck >= 0)
-                               if(spot.team != teamcheck)
-                                       error("invalid spawn added");
-
-                               print("added ", etos(spot), "\n");
-                               */
-                       }
+                       if(spotlistend)
+                               spotlistend.chain = spot;
+                       spotlistend = spot;
+                       if(!spotlist)
+                               spotlist = spot;
                }
        }
        if(spotlistend)
                spotlistend.chain = world;
 
-       /*
-               entity e;
-               if(teamcheck >= 0)
-                       for(e = spotlist; e; e = e.chain)
-                       {
-                               print("seen ", etos(e), "\n");
-                               if(e.team != teamcheck)
-                                       error("invalid spawn found");
-                       }
-       */
-
        return spotlist;
 }
 
@@ -322,8 +251,7 @@ Finds a point to respawn
 entity SelectSpawnPoint (float anypoint)
 {
        float teamcheck;
-       entity firstspot_new;
-       entity spot, firstspot, playerlist;
+       entity spot, firstspot;
 
        spot = find (world, classname, "testplayerstart");
        if (spot)
@@ -354,8 +282,6 @@ entity SelectSpawnPoint (float anypoint)
                // if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then
 
 
-       // get the list of players
-       playerlist = findchain(classname, "player");
        // get the entire list of spots
        firstspot = findchain(classname, "info_player_deathmatch");
        // filter out the bad ones
@@ -366,38 +292,22 @@ entity SelectSpawnPoint (float anypoint)
        }
        else
        {
-               firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 100, teamcheck, anypoint);
-               if(!firstspot_new)
-                       firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, -1, teamcheck, anypoint);
-               firstspot = firstspot_new;
+               float mindist;
+               if (arena_roundbased && !g_ca)
+                       mindist = 800;
+               else
+                       mindist = 100;
+               firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, teamcheck);
 
                // there is 50/50 chance of choosing a random spot or the furthest spot
                // (this means that roughly every other spawn will be furthest, so you
                // usually won't get fragged at spawn twice in a row)
-               if (arena_roundbased && !g_ca)
-               {
-                       firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck, anypoint);
-                       if(firstspot_new)
-                               firstspot = firstspot_new;
-                       spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
-               }
-               else if (random() > autocvar_g_spawn_furthest)
+               if (random() > autocvar_g_spawn_furthest)
                        spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
                else
                        spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
        }
 
-       if(autocvar_spawn_debugview)
-       {
-               print("spot mindistance: ", vtos(spot.spawnpoint_score), "\n");
-
-               entity e;
-               if(teamcheck >= 0)
-                       for(e = firstspot; e; e = e.chain)
-                               if(e.team != teamcheck)
-                                       error("invalid spawn found");
-       }
-
        if (!spot)
        {
                if(autocvar_spawn_debug)
@@ -1086,12 +996,6 @@ void PutClientInServer (void)
 
                race_PostSpawn(spot);
 
-               if(autocvar_spawn_debug)
-               {
-                       sprint(self, strcat("spawnpoint origin:  ", vtos(spot.origin), "\n"));
-                       remove(spot);   // usefull for checking if there are spawnpoints, that let drop through the floor
-               }
-
                //stuffcmd(self, "chase_active 0");
                //stuffcmd(self, "set viewsize $tmpviewsize \n");
 
@@ -1130,8 +1034,15 @@ void PutClientInServer (void)
                        activator = world;
                self = oldself;
 
+               spawn_spot = spot;
                MUTATOR_CALLHOOK(PlayerSpawn);
 
+               if(autocvar_spawn_debug)
+               {
+                       sprint(self, strcat("spawnpoint origin:  ", vtos(spot.origin), "\n"));
+                       remove(spot);   // usefull for checking if there are spawnpoints, that let drop through the floor
+               }
+
                self.switchweapon = w_getbestweapon(self);
                self.cnt = -1; // W_LastWeapon will not complain
                self.weapon = 0;
index 2292f60332c40958868d927b838499e175e6a57e..4896526ad77441ba49927a1824faa65740fb522a 100644 (file)
@@ -667,3 +667,6 @@ float serverflags;
 .float misc_bulletcounter;     // replaces uzi & hlac bullet counter.
 
 void PlayerUseKey();
+
+typedef vector(entity player, entity spot, vector current) spawn_evalfunc_t;
+.spawn_evalfunc_t spawn_evalfunc;
index 965c2743b590878c0e0e4c7bc8f2eef42e82c760..e4ee39e9174a2f7e6b2435c3ddc08f01c2552c2f 100644 (file)
@@ -1086,6 +1086,8 @@ void readlevelcvars(void)
                MUTATOR_ADD(mutator_rocketflying);
        if(cvar("g_vampire"))
                MUTATOR_ADD(mutator_vampire);
+       if(cvar("g_spawn_near_teammate"))
+               MUTATOR_ADD(mutator_spawn_near_teammate);
 
        if(cvar("sv_allow_fullbright"))
                serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
index 73b23bbd3f224201ecffa53725fe544a3b225573..e668c1da1ea222bf13f1e300442a81ab078d8b29 100644 (file)
@@ -45,6 +45,7 @@ MUTATOR_HOOKABLE(MakePlayerObserver);
        // called when a player becomes observer, after shared setup
 
 MUTATOR_HOOKABLE(PlayerSpawn);
+       entity spawn_spot; // spot that was used, or world
        // called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
 
 MUTATOR_HOOKABLE(ClientDisconnect);
@@ -188,3 +189,12 @@ MUTATOR_HOOKABLE(SV_ParseClientCommand);
                        return 0;
                }
        */
+
+MUTATOR_HOOKABLE(Spawn_Score);
+       // called when a spawnpoint is being evaluated
+       // return 1 to make the spawnpoint unusable
+       // INPUT
+       entity self; // player wanting to spawn
+       entity spawn_spot; // spot to be evaluated
+       // IN+OUT
+       vector spawn_score; // _x is priority, _y is "distance"
diff --git a/qcsrc/server/mutators/mutator_spawn_near_teammate.qc b/qcsrc/server/mutators/mutator_spawn_near_teammate.qc
new file mode 100644 (file)
index 0000000..4d0746d
--- /dev/null
@@ -0,0 +1,59 @@
+float autocvar_g_spawn_near_teammate_distance;
+.entity msnt_lookat;
+
+MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
+{
+       entity p;
+
+       spawn_spot.msnt_lookat = world;
+
+       if(!teamplay)
+               return 0;
+
+       RandomSelection_Init();
+       FOR_EACH_PLAYER(p) if(p != self) if(p.team == self.team) if(!p.deadflag)
+       {
+               float l = vlen(spawn_spot.origin - p.origin);
+               if(l > autocvar_g_spawn_near_teammate_distance)
+                       continue;
+               if(l < 48)
+                       continue;
+               if(!checkpvs(spawn_spot.origin, p))
+                       continue;
+               RandomSelection_Add(p, 0, string_null, 1, 1);
+       }
+
+       if(RandomSelection_chosen_ent)
+       {
+               spawn_spot.msnt_lookat = RandomSelection_chosen_ent;
+               spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND;
+       }
+       else if(self.team == spawn_spot.team)
+               spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
+
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
+{
+       if(spawn_spot.msnt_lookat)
+       {
+               self.angles = vectoangles(spawn_spot.msnt_lookat.origin - self.origin);
+               self.angles_x = -self.angles_x;
+               /*
+               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");
+               sprint(self, "angles: ", vtos(self.angles), "\n");
+               */
+       }
+
+       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);
+
+       return 0;
+}
index 1ae28abe54ff961700c030d9e305119aa51bd5ec..ba7edaeecb2f2dadeb5f13001d3e9c0ff9af12f9 100644 (file)
@@ -7,3 +7,5 @@ MUTATOR_DECLARATION(mutator_nix);
 MUTATOR_DECLARATION(mutator_dodging);
 MUTATOR_DECLARATION(mutator_rocketflying);
 MUTATOR_DECLARATION(mutator_vampire);
+
+MUTATOR_DECLARATION(mutator_spawn_near_teammate);
index a07454ffa3566066f5778023661a1959267c0683..d249030db4969147c6b522f9e5c731816321d695 100644 (file)
@@ -197,6 +197,7 @@ mutators/mutator_nix.qc
 mutators/mutator_dodging.qc
 mutators/mutator_rocketflying.qc
 mutators/mutator_vampire.qc
+mutators/mutator_spawn_near_teammate.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
index f6ca98682c3d91eb7b4af582118c06dfed317e41..911106a30560358e6ae03054ab21526dc0e6ad8a 100644 (file)
@@ -635,7 +635,7 @@ void trigger_race_checkpoint_verify()
                        // race only (middle of the race)
                        g_race_qualifying = 0;
                        self.race_place = 0;
-                       if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE))
+                       if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE))
                                error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for respawning in race) - bailing out"));
 
                        if(i == 0)
@@ -643,7 +643,7 @@ void trigger_race_checkpoint_verify()
                                // qualifying only
                                g_race_qualifying = 1;
                                self.race_place = race_lowest_place_spawn;
-                               if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE))
+                               if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE))
                                        error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out"));
                                
                                // race only (initial spawn)
@@ -651,7 +651,7 @@ void trigger_race_checkpoint_verify()
                                for(p = 1; p <= race_highest_place_spawn; ++p)
                                {
                                        self.race_place = p;
-                                       if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE))
+                                       if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE))
                                                error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for initially spawning in race) - bailing out"));
                                }
                        }
@@ -663,7 +663,7 @@ void trigger_race_checkpoint_verify()
                self.race_checkpoint = race_NextCheckpoint(0);
                g_race_qualifying = 1;
                self.race_place = race_lowest_place_spawn;
-               if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE))
+               if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE))
                        error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out"));
        }
        else
@@ -764,6 +764,38 @@ void trigger_race_checkpoint_verify()
        self = oldself;
 }
 
+vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector current)
+{
+       if(g_race_qualifying)
+       {
+               // spawn at first
+               if(self.race_checkpoint != 0)
+                       return '-1 0 0';
+               if(spot.race_place != race_lowest_place_spawn)
+                       return '-1 0 0';
+       }
+       else
+       {
+               if(self.race_checkpoint != player.race_respawn_checkpoint)
+                       return '-1 0 0';
+               // try reusing the previous spawn
+               if(self == player.race_respawn_spotref || spot == player.race_respawn_spotref)
+                       current_x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN;
+               if(self.race_checkpoint == 0)
+               {
+                       float pl;
+                       pl = player.race_place;
+                       if(pl > race_highest_place_spawn)
+                               pl = 0;
+                       if(pl == 0 && !player.race_started)
+                               pl = race_highest_place_spawn; // use last place if he has not even touched finish yet
+                       if(spot.race_place != pl)
+                               return '-1 0 0';
+               }
+       }
+       return current;
+}
+
 void spawnfunc_trigger_race_checkpoint()
 {
        vector o;
@@ -811,6 +843,7 @@ void spawnfunc_trigger_race_checkpoint()
        }
 
        self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
+       self.spawn_evalfunc = trigger_race_checkpoint_spawn_evalfunc;
 
        InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
 }
index 6e4b0ccb7a47e6a9e9ba20c9801af2996bff260d..c4cc090c3b289adcfd77a8fd71ba6733f13c6a93 100644 (file)
@@ -231,15 +231,6 @@ void StartFrame (void)
        RuneMatchGivePoints();
        bot_serverframe();
 
-       if(autocvar_spawn_debugview)
-       {
-               RandomSelection_Init();
-               for(self = world; (self = find(self, classname, "player")); )
-                       RandomSelection_Add(self, 0, string_null, 1, 0);
-               self = RandomSelection_chosen_ent;
-               SelectSpawnPoint(0);
-       }
-
        FOR_EACH_PLAYER(self)
                self.porto_forbidden = max(0, self.porto_forbidden - 1);
 }