Ejemplo n.º 1
0
// ticks the game forward in time
void GameInfo::Ticker()
{
  tic++;

  // TODO read/write demo ticcmd's here

  // do main actions
  switch (state)
    {
    case GS_INTRO:
      if (--pagetic <= 0)
	AdvanceIntro();
      break;

    case GS_LEVEL:
      if (!paused && currentcluster)
	currentcluster->Ticker();

      if (!dedicated)
	{
	  hud.Ticker();
	  automap.Ticker();
	}
      break;

    case GS_INTERMISSION:
      wi.Ticker();
      break;

    case GS_FINALE:
      F_Ticker();
      break;

    case GS_NULL:
    default:
      // do nothing
      break;
    }


  MapInfo *m;
  PlayerInfo *p;

  if (state != GS_LEVEL)
    return;

  // manage players
  for (player_iter_t t = Players.begin(); t != Players.end(); )
    {
      p = t->second;
      t++; // because "old t" may be invalidated

      if (p->playerstate == PST_REMOVE)
	{
	  // the player is removed from the game (invalidates "old t")
	  if (!p->mp)
	    RemovePlayer(p->number); // first the maps throw out the removed player, then the game proper.

	  // TODO purge the removed players from the frag maps of other players?
	}
      else
	p->Ticker();
    }

  if (!server)
    return;

  //
  for (player_iter_t t = Players.begin(); t != Players.end(); t++)
    {
      p = t->second;

      if (p->playerstate == PST_NEEDMAP)
	{
	  LConnection *conn = p->connection;
	  if (conn && !conn->isGhostAvailable(p))
	    {
	      // remote player, is it already being ghosted? if not, wait.
	      CONS_Printf(" server waiting for client ghost\n");
	      continue;
	    }

	  // assign the player to a map
	  CONS_Printf("Map request..");

	  if (p->requestmap == 0)
	    {
	      m = initial_map; // first map in game
	      p->entrypoint = initial_ep;
	    }
	  else
	    m = FindMapInfo(p->requestmap);

	  if (!m)
	    {
	      // game ends
	      currentcluster->Finish(p->requestmap, p->entrypoint);
	      StartFinale(NULL);
	      break;
	    }
	  else if (!m->found)
	    m = currentcluster->maps[0]; // TODO or give an error?

	  // cluster change?
	  if (currentcluster->number != m->cluster)
	    {
	      // TODO minor thing: if several players exit maps on the same tick,
	      // and someone besides the first one causes a cluster change, some
	      // maps could be loaded in vain...

	      // cluster change!
	      currentcluster->Finish(p->requestmap, p->entrypoint);

	      MapCluster *next = FindCluster(m->cluster);
	      StartFinale(next);
	      currentcluster = next;

	      break; // this is important! no need to check the other players.
	    }

	  p->Reset(!currentcluster->keepstuff, true);

	  // normal individual mapchange
	  if (!m->Activate(p))
	    I_Error("Darn!\n");

	  if (conn)
	    {
	      CONS_Printf(" server sending rpc\n");
	      // nonlocal player enters a new map, notify client
	      // send the EnterMap rpc only to the owning connection
	      NetEvent *e = TNL_RPC_CONSTRUCT_NETEVENT(p, s2cEnterMap, (m->mapnumber));
	      conn->postNetEvent(e);
	    }
	}
    }
}
Ejemplo n.º 2
0
void G_Ticker(void)
{
    int i, buf;
    ticcmd_t *cmd = NULL;

//
// do player reborns if needed
//
    for (i = 0; i < MAXPLAYERS; i++)
        if (playeringame[i] && players[i].playerstate == PST_REBORN)
            G_DoReborn(i);

//
// do things to change the game state
//
    while (gameaction != ga_nothing)
    {
        switch (gameaction)
        {
            case ga_loadlevel:
                G_DoLoadLevel();
                break;
            case ga_newgame:
                G_DoNewGame();
                break;
            case ga_loadgame:
                G_DoLoadGame();
                break;
            case ga_savegame:
                G_DoSaveGame();
                break;
            case ga_playdemo:
                G_DoPlayDemo();
                break;
            case ga_screenshot:
                V_ScreenShot("HTIC%02i.%s");
                gameaction = ga_nothing;
                break;
            case ga_completed:
                G_DoCompleted();
                break;
            case ga_worlddone:
                G_DoWorldDone();
                break;
            case ga_victory:
                F_StartFinale();
                break;
            default:
                break;
        }
    }


//
// get commands, check consistancy, and build new consistancy check
//
    //buf = gametic%BACKUPTICS;
    buf = (gametic / ticdup) % BACKUPTICS;

    for (i = 0; i < MAXPLAYERS; i++)
        if (playeringame[i])
        {
            cmd = &players[i].cmd;

            memcpy(cmd, &netcmds[i], sizeof(ticcmd_t));

            if (demoplayback)
                G_ReadDemoTiccmd(cmd);
            if (demorecording)
                G_WriteDemoTiccmd(cmd);

            if (netgame && !(gametic % ticdup))
            {
                if (gametic > BACKUPTICS
                    && consistancy[i][buf] != cmd->consistancy)
                {
                    I_Error("consistency failure (%i should be %i)",
                            cmd->consistancy, consistancy[i][buf]);
                }
                if (players[i].mo)
                    consistancy[i][buf] = players[i].mo->x;
                else
                    consistancy[i][buf] = rndindex;
            }
        }

//
// check for special buttons
//
    for (i = 0; i < MAXPLAYERS; i++)
        if (playeringame[i])
        {
            if (players[i].cmd.buttons & BT_SPECIAL)
            {
                switch (players[i].cmd.buttons & BT_SPECIALMASK)
                {
                    case BTS_PAUSE:
                        paused ^= 1;
                        if (paused)
                        {
                            S_PauseSound();
                        }
                        else
                        {
                            S_ResumeSound();
                        }
                        break;

                    case BTS_SAVEGAME:
                        if (!savedescription[0])
                        {
                            if (netgame)
                            {
                                M_StringCopy(savedescription,
                                             DEH_String("NET GAME"),
                                             sizeof(savedescription));
                            }
                            else
                            {
                                M_StringCopy(savedescription,
                                             DEH_String("SAVE GAME"),
                                             sizeof(savedescription));
                            }
                        }
                        savegameslot =
                            (players[i].cmd.
                             buttons & BTS_SAVEMASK) >> BTS_SAVESHIFT;
                        gameaction = ga_savegame;
                        break;
                }
            }
        }
    // turn inventory off after a certain amount of time
    if (inventory && !(--inventoryTics))
    {
        players[consoleplayer].readyArtifact =
            players[consoleplayer].inventory[inv_ptr].type;
        inventory = false;
        cmd->arti = 0;
    }
//
// do main actions
//
//
// do main actions
//
    switch (gamestate)
    {
        case GS_LEVEL:
            P_Ticker();
            SB_Ticker();
            AM_Ticker();
            CT_Ticker();
            break;
        case GS_INTERMISSION:
            IN_Ticker();
            break;
        case GS_FINALE:
            F_Ticker();
            break;
        case GS_DEMOSCREEN:
            D_PageTicker();
            break;
    }
}