Game Development Community

Canvas.SetContent not working in EndGame function

by William Fallon · in Torque 3D Beginner · 05/10/2014 (10:43 am) · 8 replies

Hi,

I want a custom endgamegui depending on if the player died or not. I call Endgame when he dies, or when he hits the endoflevel trigger. This, the defualt code, works fine:
Canvas.setContent(EndGameGui);
But when I replace it with this:
if(%player.getState() == "Dead")
      {
          Canvas.setContent(EndGameGuiLose);
      }
      else
      {
         Canvas.setContent(EndGameGui);
      }
It doesn't work at all.


About the author

Recent Threads

  • In-Game Tutorial Text

  • #1
    05/10/2014 (1:01 pm)
    Some scripts are ran on the client side, and some are ran on the server side. Anything that changes GUI ( like Canvas.setContent ) is client side. There's two pieces to ending a game:

    function GameCore::endGame(%game, %client)
    and:
    function clientCmdGameEnd(%seq)

    The first one, endGame is called on the server side. This wraps up all the game variables, and sends a command to each client:

    commandToClient(%cl, 'GameEnd', $Game::EndGamePause);

    Which then triggers the clientCmdGameEnd function on the client side. So, your issue is that %player.getState() is a server side command, and Canvas.setContent() is a client side command, so they can't be used in the same functions.

    The solution? Check if the player is dead on the server side (in GameCore::endGame), then send a different command for ending the game depending on whether they're dead or not. Or, add a parameter to clientCmdGameEnd that dictates whether it should show win or lose screen.
    #2
    05/10/2014 (1:34 pm)
    Alright, I fixed that using your method, but I'm not quite sure if I'm calling the function right from the server endgame. You'll understand what I mean.

    In the GameCore::EndGame:
    if(%player.getState() == "Dead")
    {
         commandToClient(%cl, 'GameEndDead', $Game::EndGamePause);
    }
    else
    {
         commandToClient(%cl, 'GameEnd', $Game::EndGamePause);
    }
    And then I copied and pasted the client endgame function, and renamed it. But every time I run it, it goes to the first, original function:

    function clientCmdGameEnd(%seq)
    {
       // Stop local activity... the game will be destroyed on the server
       sfxStopAll();
       
       if ((!EditorIsActive() && !GuiEditorIsActive()))
       {
          // Copy the current scores from the player list into the
          // end game gui (bit of a hack for now).
          EndGameGuiList.clear();
          for (%i = 0; %i < PlayerListGuiList.rowCount(); %i++)
          {
             %text = PlayerListGuiList.getRowText(%i);
             %id = PlayerListGuiList.getRowId(%i);
             EndGameGuiList.addRow(%id, %text);
          }
          EndGameGuiList.sortNumerical(1, false);
    
          Canvas.setContent(EndGameGui);
       }
    }
    function clientCmdGameEndDead(%seq)
    {
       // Stop local activity... the game will be destroyed on the server
       sfxStopAll();
       
       if ((!EditorIsActive() && !GuiEditorIsActive()))
       {
          // Copy the current scores from the player list into the
          // end game gui (bit of a hack for now).
          EndGameGuiList.clear();
          for (%i = 0; %i < PlayerListGuiList.rowCount(); %i++)
          {
             %text = PlayerListGuiList.getRowText(%i);
             %id = PlayerListGuiList.getRowId(%i);
             EndGameGuiList.addRow(%id, %text);
          }
          EndGameGuiList.sortNumerical(1, false);
    
          Canvas.setContent(EndGameGuiLose);
       }
    }

    Oh, and I also tried just setting it to automatically go to Canvas.setContent(EndGameGuiLose);, and it still just keeps on running. Now I'm thinking it might be a gui problem.
    #3
    05/10/2014 (1:43 pm)
    if(%player.getState() == "Dead")

    Two problems. If you check endGame function:
    function GameCore::endGame(%game, %client)
    {
    ...

    There is no %player available in the default arguments of the function. You'll have to get it from %client. Example:
    %player = %client.player;

    Secondly, string comparisons are done with the $= operator in torquescript. It should be:
    if(%player.getState() $= "Dead")
    #4
    05/10/2014 (1:52 pm)
    Shoot, I knew that about the %client stuff, I feel stupid.

    With the strings, I'm stuck in C++, sorry.

    I fixed those two problems, but when I call the endgame function the game still shows up. Basically I'm calling the function when my character dies or when an ai touches him. When I call it, the game keeps on running.

    Any clue?

    Like I said, even when I just replaced the original Canvas.setContent(EndGameGui); (which worked), with Canvas.setContent(EndGameGuiLose);, the EndGameGuiLose does not load and the game keeps on playing.

    Thanks for so much help so far!
    #5
    05/10/2014 (2:18 pm)
    You should use cycleGame() or endMission() to stop the game. End game is more like stage 2 of shutting off the game. cycleGame() preserves the possibility of starting another map, though your game has to be configured for that before hand.

    If Canvas.setContent(EndGameGui); works and Canvas.setContent(EndGameGuiLose); doesn't then it's an issue with EndGameGuiLose. Are you able to edit that gui in the gui editor? Have you checked the console for any relevant errors?
    #6
    05/10/2014 (3:10 pm)
    The error I'm getting is this:

    GuiCanvas::setContent - Invalid control specified')

    But I can open the gui up in the editor!

    Is there someplace where I forgot to "include" the gui?

    Oh, and I can find the endGameGuiLose.gui in Torsion, too.
    #7
    05/10/2014 (4:27 pm)
    Yep, you've gotta add it to scripts/client/init.cs:

    ...
       // Load up the shell GUIs
       exec("art/gui/mainMenuGui.gui");
       exec("art/gui/joinServerDlg.gui");
       exec("art/gui/endGameGui.gui");
       exec("art/gui/StartupGui.gui");
       exec("art/gui/chooseLevelDlg.gui");
    ...
    #8
    05/10/2014 (5:40 pm)
    Okay! Thanks a lot! I'll try it tommorrow morning. I've used a lot of C++ based engines but none this built up before. I remember my ogre days hehe. It took me 2 weeks in cs in T3D to do what it took me 3 months to do in C++ in ogre. Plus I get to see the source code for free too now.