Forum

How to replay a map x number of times?

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

How to replay a map x number of times?

Postby OneManClan » Sat Mar 27, 2010 5:03 am

Hi all,

At the Weekly AGR Sessions (AGR = O vs D style mod), there are no preset teams, and if the teams are too unbalanced (defined as Red:40 Blue:00 in less than 10 minutes), Blue is considered to have 'forfeited' the game, and the map is restarted. There are a maximum of 3 Restarts before we move on to the next Map.

Currently I'm doing this manually, but I'd like to automate it. I tried making a global variable 'float NumRestart;' in defs and then in the scoring section:
Code: Select all
// OMC_restart
// this code is after the Red Team has Scored

               if (team1score == 0 && team2score == 30 && time < 10 )
               bprint(#PRINT_HIGH, "\n Alert! Blue is about to forfeit the game! \n");
               else
               if (team1score == 0 && team2score == 40 && time < 13 )
               {
                  if (AGR_Restart < 3)
                  {
                              
                  localcmd("restart\n");
                  AGR_Restart = AGR_Restart + 1;
                  }
                  else
                  AGR_Restart = 0;
               }   



But this didn't do anything. Not sure where the prob lies..

Q1: Where should I initialise Num_Restart to '0'?

Q2: When a new map loads, is the .dat file read again? Are all variables reset every map, or do global variables 'survive'?

Q3:How can I make the Num_Restart variable keep track of how many times a map has been replayed?

thanks,


OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby Spike » Sat Mar 27, 2010 9:06 am

mvdsv has no restart console command, if I remember correctly.
on map changes, your (qw)progs.dat is flushed entirely and all globals are essentually reset.
You can make persistant variables using the server's localinfo, cvars, the serverflags field (you only get one though) or the parms of a player (which isn't really that sane a thing to do) - QW prefers localinfo.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby r00k » Sun Mar 28, 2010 8:00 am

Hmm not sure if this is relevant (it's 3am atm)
this is how i recycle the same map in Cax....
Code: Select all
   if ((ca_gametype & CA_ROTATE_NEXTMAP) && (boss.abort == FALSE))
   {      
      boss.maprecycle = boss.maprecycle - 1;
      if (boss.maprecycle < 1)
      {         
         boss.busy = TRUE;
         execute_changelevel();
         gameover = TRUE;
      }
      else
      {         
         mc=ftos(boss.maprecycle);
         if (boss.maprecycle > 1)
         {
            announce3 ("Next map change after ",mc," more matches.");
         }
         else
         {
            if (boss.maprecycle == 1)
               announce ("Next map change after 1 more match.");
         }
         gameover = FALSE;            
      }
   }
   else
   gameover = FALSE;   
   


This is called at the end of the game...
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby OneManClan » Tue Mar 30, 2010 3:56 am

Spike wrote:mvdsv has no restart console command, if I remember correctly.
on map changes, your (qw)progs.dat is flushed entirely and all globals are essentually reset.

I see.

Spike wrote:You can make persistant variables using the server's localinfo, cvars, the serverflags field (you only get one though) or the parms of a player (which isn't really that sane a thing to do) - QW prefers localinfo.

Thanks Spike, I'll use localinfo then (see below).

r00k wrote:Hmm not sure if this is relevant (it's 3am atm)
this is how i recycle the same map in Cax....


Thanks r00k, I don't understand what 'boss' entity is, and how it stores the .maprecycle variable between map changes. Also I can't see where the command is to actually change the map.

In any case, here's my latest attempt:

Code: Select all
//=========
// AGR Restart version 2
               
                  temp = infokey(world, "agr_restart");
                  AGR_Restart = stof(temp);
               

                  if (team1score == 0 && team2score == 30 && time < 600 )
                     {
                     // this prints, but loops / gets printed every frame, I'm workin' on it.
                     bprint(#PRINT_HIGH, "\n Alert! Blue is about to forfeit the game! \n");
                     
                     }
                     
                  else
                  
                  if (team1score == 0 && team2score == 40 && time < 780)
                  {
                     if (AGR_Restart < 3)
                     {
                  // this should restart the map - but doesn't do anything..
                     MapNameSt = world.model;
                     
                     localcmd("map ");
                     localcmd(MapNameSt);
                     localcmd("\n");
                     sprint(self, #PRINT_HIGH, MapNameSt);
                     sprint(self, #PRINT_HIGH, "\n");
                  
                  
                     AGR_Restart = AGR_Restart + 1;
                     }
                     else
                     AGR_Restart = 0;
                  
                  
                     // update the variable 'agr_restart' on the server
                     temp = ftos(AGR_Restart);
                     localcmd("localinfo ");
                     localcmd("agr_restart");
                     localcmd(" ");
                     localcmd(temp);
                     localcmd("\n");




I sprinted world.model and it contains the whole path, eg 'map/2fort5r'. Could *this* be the issue? I tried to change maps on the server via: "map /map/2fort5r' but it didn't work, because it tried to find the map at 'map/map/ '

Do I have to process the string 'MapNameSt' to remove the complete path and only have the mapname?


OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby Spike » Tue Mar 30, 2010 10:21 am

Use the mapname global instead of world.model.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby OneManClan » Wed Mar 31, 2010 7:18 am

Spike wrote:Use the mapname global instead of world.model.


Brilliant, it works!!! :)

thanks heaps!


OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby OneManClan » Wed Mar 31, 2010 4:58 pm

Ok, the 'warning' bit works, the map changing bit works, the localinfo variable is getting modified with every map change, BUT there's an issue with resetting the localinfo to 0, because the function is currently run every frame, so once it gets set to '0', the 'restart' bit runs, and increments it back to one instantly. Here's the complete function (currently run every frame).

Code: Select all
void() AGR_RestartCheck =

{
   local float AGR_Restart;
   local string temp;

   temp = infokey(world, "agr_restart");
   AGR_Restart = stof(temp);
   
   
   // this bit works. LoopStop is a global used to stop this bprint being looped over and over, its hacky and newb, and I welcome a more 'pro' solution
    if (team1score == 0 && team2score == 30 && time < 600 && LoopStop!=24)
        {
       
      bprint(#PRINT_HIGH, "\n Alert! Blue is about to forfeit the game! \n");
               
      // once LoopStop is assigned the value 24, this stops the looping
        LoopStop = 24;
        return;
        }
       
        else
       
         if (team1score == 0 && team2score == 40 && time < 780)
            {

            // We restart 3 times max
               if (AGR_Restart < 3)
               {
               
               // Need something here to pause the game before the level change
               
               bprint(#PRINT_HIGH, "\n Blue has forfeited the game! \n");
            
               // this bit works now!!
               localcmd("map ");
               localcmd(mapname);
               localcmd("\n");
                 
               // increment the variable which keeps track of the number of restarts
               AGR_Restart = AGR_Restart + 1;
               }
               
               else
            
               // once Restarts >= 3 we reset AGR_Restart to zero, but NOW it is less than 3, the above code runs, and AGR_Restart is instantly given a value of 1 ( 0 + 1)!
               AGR_Restart = 0;
                 
                 
                // update the variable 'agr_restart' on the server
                temp = ftos(AGR_Restart);
                localcmd("localinfo ");
                localcmd("agr_restart");
                localcmd(" ");
                localcmd(temp);
                localcmd("\n");
         }
     
      // after the third restart agr_restart was made '0', but that just made it 'less than 3' so the game restarted again, and agr_restart went from 0 to 1..

               
};


Where / how do I reset 'AGR_Restart = 0;' without having the loop run in the next frame?

:?

OneManClan
Last edited by OneManClan on Wed Mar 31, 2010 5:39 pm, edited 1 time in total.
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby Spike » Wed Mar 31, 2010 5:17 pm

You should not spam map commands either. Make a global initialised to 0, test it just before triggering the map command and if its 1, just leave the function. otherwise set the global to 1 and then do what you currently do.


Incidentilly, FTE has no single-instance restriction. And nor does DP if you want to try using that for QW.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby OneManClan » Wed Mar 31, 2010 6:26 pm

Spike wrote:You should not spam map commands either.


How do you mean 'map commands' The 'map change' command happens once. Are you referring to the bprint warnings?

Spike wrote:Make a global initialised to 0, test it just before triggering the map command and if its 1, just leave the function. otherwise set the global to 1 and then do what you currently do.



Sorry, I don't follow:

Code: Select all

float GlobNum = 0; // global

..

// in the loop
//The global is initialised to '0' in the beginning so this doesn't 'return':
if (GlobNum == 1) return;

// but now we make it a '1', so on the next iteration of the loop it will run. But how is this better?
else GlobNum = 1;
{... function}


I think I missed something..


Spike wrote:Incidentilly, FTE has no single-instance restriction. And nor does DP if you want to try using that for QW.


I don't know what you mean by 'single-instance restriction', so I don't know what you mean here.



OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby frag.machine » Wed Mar 31, 2010 9:32 pm

Code: Select all
// somewhere in the top of your QC file...
float  doitonce = 0;

(...)

void() AGR_RestartCheck =
{
  (...)
  if (doitonce == 0)
  {
    // do your one-time stuff here...
    (...)
    // let's prevent this happening again!
    doitonce = 1;
  }
  (...)
}
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby OneManClan » Thu Apr 01, 2010 1:33 am

Gotcha, thanks, the 'doitonce' idea works for the initial 'warning but the problem is with the place I reset the variable which keeps track of restarts to '0'.

Let's assume we have had 3 restarts, and now we want to continue the game without restarting. AGR_Restart (the variable stored in a localinfo setting) is currently '3':

PSEUDO CODE:
Code: Select all

// AGR_Restart (currently 3) isn't true so we skip the mapchange the first iteration

if (AGR_Restart < 3)

   {
   RestartSameMap():
   AGR_Restart = AGR_Restart + 1;
   }

   else

   AGR_Restart = 0;

   // we just reset AGR_Restart to '0', BUT this means on the next iteration RestartSameMap WILL be executed, and AGR_Restart incremented from '0' to '1'

   UpdateVariableInLocalinfo(agr_restart);
   





I think the place where I'm resetting AGR_Restart to '0' is wrong.



OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby OneManClan » Thu Apr 01, 2010 4:35 pm

UPDATE:

OneManClan wrote:I think the place where I'm resetting AGR_Restart to '0' is wrong.


So I put the 'reset' code in another function, outside the run-every-frame loop , and after fiddling here and there - it works!!

Thanks for the feedback!!


OneManClan
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest