Inside3D!
     

How to replay a map x number of times?

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Sat Mar 27, 2010 5:03 am    Post subject: How to replay a map x number of times? Reply with quote

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:

// 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
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Sat Mar 27, 2010 9:06 am    Post subject: Reply with quote

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.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Sun Mar 28, 2010 8:00 am    Post subject: Reply with quote

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

   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...
Back to top
View user's profile Send private message
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Tue Mar 30, 2010 3:56 am    Post subject: Reply with quote

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:
//=========
// 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
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Tue Mar 30, 2010 10:21 am    Post subject: Reply with quote

Use the mapname global instead of world.model.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Wed Mar 31, 2010 7:18 am    Post subject: Reply with quote

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


Brilliant, it works!!! Smile

thanks heaps!


OneManClan
Back to top
View user's profile Send private message
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Wed Mar 31, 2010 4:58 pm    Post subject: Reply with quote

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:
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?

Confused

OneManClan


Last edited by OneManClan on Wed Mar 31, 2010 5:39 pm; edited 1 time in total
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Wed Mar 31, 2010 5:17 pm    Post subject: Reply with quote

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.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Wed Mar 31, 2010 6:26 pm    Post subject: Reply with quote

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:


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
Back to top
View user's profile Send private message
frag.machine



Joined: 25 Nov 2006
Posts: 728

PostPosted: Wed Mar 31, 2010 9:32 pm    Post subject: Reply with quote

Code:

// 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;
  }
  (...)
}

_________________
frag.machine - Q2K4 Project
http://fragmachine.quakedev.com/
Back to top
View user's profile Send private message Visit poster's website
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Thu Apr 01, 2010 1:33 am    Post subject: Reply with quote

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:


// 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
Back to top
View user's profile Send private message
OneManClan



Joined: 28 Feb 2009
Posts: 62

PostPosted: Thu Apr 01, 2010 4:35 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group