New trigger to control spawning of trainz from portals

ffccnn

Member
The need for this trigger is coming from a thread started by Sniper297. I decided to open this thread specific for the trigger so it won't get buried somewhere in Sniper's stuff. Please take a look to more details in his thread at http://forums.auran.com/trainz/showthread.php?97264-AI-traffic-train-performance-revisited.

I think I have a good understanding of what is required and I came out with these requirements/specs.
Specs to include in version 1:
  1. A new trigger will be created named PortalTrigger.
  2. This trigger will execute one of two actions, either turn ON or turn OFF spawning trainz at some selected portals.
  3. The trigger will not be attached to a particular portal control. However, for this to work a portal control must be able to understand the requests sent from the trigger. As a result, there will be a new portal control perhaps a clone one out of an existing portal control.
  4. The trigger will be activated by a specific train which will be selected by the player from a list of available trainz in Surveyor.
  5. The configuration of the trigger in Surveyor will allow the player
  • to set the trigger’s function (turn on or turn off spawning),
  • to select the player’s train,
  • to add any available portal to the list of controlled portals,
  • to remove any of the portals previously selected.
  1. When session starts, all portals added to the trigger will be disabled (not spawning trainz). As the player train enters the turn-on-trigger all portals belonging to the trigger will be enabled (start spawning trainz at whatever sequence was scheduled in the portal control). As the player train moves on and eventually hits the turn-off-trigger all portals belonging to the trigger will be disabled.
Specs to include in version 2:
  1. The trigger will be activated by either of two options, by any train or by any train out of a list of selected trainz. Note that choosing the 2[SUP]nd[/SUP] option and selected only one train is the same as selecting a train in version 1.
  2. The trigger will change color in Surveyor depending on whether the trigger is set to turn ON or turn OFF spawning. This will help greatly in Surveyor see at a glance what each trigger’s action will be in Driver.
  1. I think this is a doable solution. I estimate that the coding of the trigger and building its model in Blender can be done in 1 week (spare time). The modified portal control may be CPC since it is the one I am familiar with. The problem is whether we get permission to make it public. The actual code changes in the control may not be too many, I hope.

    Feedback is very important at this time. Please post your comments/changes/suggestions before the implementation begins.

    Cheers,

    --José
 
I don't think we're looking for a trigger object, the default trigger works for CPC Emit Train on Trigger and the same trigger is used for Trigger Multiple Signals. Likewise the Trigger Multiple Signals rule doesn't need a specific signal type, and the CPC Emit Train on Trigger works on any portal. Unless it's easier to program it into a new portal and trigger I think all that's needed is a rule similar to CPC Emit Train on Trigger which would shut it off instead of activating it. When I stop and analyze the whole thing what CPC Emit Train on Trigger actually does is START the portal when it's triggered, after that the portal continues to run the way it normally would if it was set up to just spawn trains by the normal method. CPC has an option to disable it by default so it won't start until the trigger is activated, so the trick is how to reset it to disabled again with another trigger.
 
OK, I got the new trigger working. Sniper, if you'd like to try it I'll PM you the scrip files.

In the meantime, let's see how it looks like.

The first shot is the cloned CPC which required very trivial changes that I will ask Pguy to add the changes instead of dealing with another CPC. Note that for testing it I made an insane configuration of one train every minute and zero delay between trains, so the demo doesn't take too long, the demo? Oh yes, it's coming...


Uploaded with ImageShack.us

Here is the new trigger, yeah! this one is for turning ON spawning of train at the portal. Note that my train is called 'Test Portal Trigger' and I selected the same portal that is being controlled by the cloned CPC. Very friendly GUI by the way.


Uploaded with ImageShack.us


This is the other trigger to turn OFF spawning trains from the portal, same train name and same portal as above.


Uploaded with ImageShack.us


where is the demo?:( patience my friend, it is uploading to YT.


cheers,

--José
 
It might be the good solution, two triggers for on/off. Will it work for Unportal too? It's important too, that it repeat action endless not only once.

Maybe is good to say this.
If you use portals with 'Produce new trains' in any intervals e.g. 2, 5,10,15,20,...50 min..etc,, or Unportal with 'Time between Trains in', or CPC rule with 'Time between trains' , the bad bahaviour with unpredictable emiting is shown with the time in any session in any route. It doesn't matter if you play session nonstop or you save them. The problem by using this rules is shown in 06,09,10 and 12 edition. It's the limitation of TS, it work for some time (1-2 hours), then anomalies are shown. Only accurate solution for emiting the trains is Quick portal manager, but it work only with portals, it don't recognize CPC (trigger) or Unportal rule (trackmark).
Btw, author of CPC and Un-Portal is sforget, pguy made QPM.
 
Last edited:
Here is the demo: http://youtu.be/zXeA39_7FHs

Note the message window displaying when the portal is enabled/disabled.
Observe also how the portal responded to the commands appropriately to spawn or not the trains.
Now we have the means to control which portals can be spawning trainz as the player's train moves around the map.
By laying down any number of the new triggers at proper places we can have complete control of the number of trainz on the route.



Thanks to Celje for pointing out who owns the CPC. Later, I will post the required changes. BTW, Unportal should also be modified to respond to the new commands.

cheers,

--José
 
ffccnn

I edit my post 6 min later after yours, please read it.
Thank you for demo i will try it tomorow it's late night here in Europe.

regards
 
Last edited:
PUBLIC APPEAL

Dear Sforget:

Could you please make these changes to your Central Portal Control? please, please, please....

file mpc.gs, class MPCPortal:


int CurrentTrain;
bool isEnabled = false;

public void SetEnabled(bool enabled)
{
isEnabled = enabled;
}

public bool IsEnabled(void)
{
return isEnabled;
}

public void SetPortal (BasePortal m_Portal)
.............

same file, class MPC, add these 3 methods after your method void ModuleInitHandler(Message msg):

void doEnablePortal(string portalName, bool enabled)
{
int i;
if(Controlled_Portals and Controlled_Portals.size())
{
for(i = 0; i < Controlled_Portals.size(); i++)
{
BasePortal portal = Controlled_Portals.GetPortal();
if(portal and (portalName == portal.GetLocalisedName()))
{
Controlled_Portals.SetEnabled(enabled);
break;
}
}
}
}

void EnablePortal(Message msg)
{
// Interface.Print("MPC.EnablePortal -- Enabling portal '" + msg.minor + "'");
doEnablePortal(msg.minor, true);
msg.src = null;
}

void DisablePortal(Message msg)
{
// Interface.Print("MPC.DisablePortal -- Disabling portal '" + msg.minor + "'");
doEnablePortal(msg.minor, false);
msg.src = null;
}

void EmitTrain(Message Msg)
......................


In method ModuleInitHandler() the changes are:

void ModuleInitHandler(Message msg)
{
if (RunningDriver)
return;
if (World.GetCurrentModule() == World.DRIVER_MODULE)
{
int i;
RunningDriver = true;
AddHandler(me, "MPCPortal-Emit-Train", "", "EmitTrain");
AddHandler(me, "Enable-Portal", "", "EnablePortal");
AddHandler(me, "Disable-Portal", "", "DisablePortal");
if (Controlled_Portals and Controlled_Portals.size())
{
......................................



In method EmitTrain() the changes are:


void EmitTrain(Message Msg)
{
string IndexStr = Msg.minor;
int Index = Str.ToInt(IndexStr);
if (Index >= Controlled_Portals.size())
{
return;
}
if (World.GetTrainList().size() < MaxTrains)
{
if (Index >=0 and Index < Controlled_Portals.size())
{
if(Controlled_Portals[Index].IsEnabled())
{
Controlled_Portals[Index].EmitNextTrain();
}
}
}
else if (MaxTrains and (World.GetTrainList().size() > MaxTrains) and RemoveExcess)
...............


thank you very much,

--José

PD: I lost the nice formatting (proper indentation) when I do coding, any ways that's the required changes.
 
Last edited:
much better......


Code:
class MPCPortal
{
  BasePortal Portal;
  string PortalName;
  ConsistHelperInfo[] Consists;
  int Timer = 15;
  int TimerDev = 5;
  bool EmitRandom = true;
  bool EmitImmediatly = true;
  bool WaitForTrig = false;
  int CurrentTrain;
    [B]bool isEnabled = false;
[/B]    
[B]    public void SetEnabled(bool enabled)
    {
        isEnabled = enabled;
    }
    
    public bool IsEnabled(void)
    {
        return isEnabled;
    }

[/B]  public void SetPortal (BasePortal m_Portal)
  {

..................................

class MPC isclass ScenarioBehavior
{
...
  void ModuleInitHandler(Message msg)
  {
    if (RunningDriver)
      return;
    if (World.GetCurrentModule() == World.DRIVER_MODULE)
    {
      int i;
      RunningDriver = true;
      AddHandler(me, "MPCPortal-Emit-Train", "", "EmitTrain");
[B]      AddHandler(me, "Enable-Portal", "", "EnablePortal");
      AddHandler(me, "Disable-Portal", "", "DisablePortal");
[/B]      if (Controlled_Portals and Controlled_Portals.size())
      {
        for (i=0; i<Controlled_Portals.size(); i++)
        {
          if (!Controlled_Portals[i].WaitForTrigger())
          {
            if (Controlled_Portals[i].GetEmitImmediatly())
              PostMessage(me, "MPCPortal2-Emit-Train", (string)i, 0.0);
            else if (Controlled_Portals[i].GetTimer() > 0)
              PostMessage(me, "MPCPortal2-Emit-Train", (string)i, Controlled_Portals[i].GetEmitTimer());
            Sleep(0.3);
          }
        }
      }
    }
  }
  
[B]    void doEnablePortal(string portalName, bool enabled)
    {
        int i;
        if(Controlled_Portals and Controlled_Portals.size())
        {
            for(i = 0; i < Controlled_Portals.size(); i++)
            {
                BasePortal portal = Controlled_Portals[i].GetPortal();
                if(portal and (portalName == portal.GetLocalisedName()))
                {
                    Controlled_Portals[i].SetEnabled(enabled);
                    break;
                }
            }
        }
    }
  
    void EnablePortal(Message msg)
    {
  //      Interface.Print("MPC.EnablePortal -- Enabling portal '" + msg.minor + "'");
        doEnablePortal(msg.minor, true);
        msg.src = null;
    }

    void DisablePortal(Message msg)
    {
//        Interface.Print("MPC.DisablePortal -- Disabling portal '" + msg.minor + "'");
        doEnablePortal(msg.minor, false);
        msg.src = null;
    }

[/B]  void EmitTrain(Message Msg)
  {
    string IndexStr = Msg.minor;
    int Index = Str.ToInt(IndexStr);
    if (Index >= Controlled_Portals.size())
    {
      return;
    }
    if (World.GetTrainList().size() < MaxTrains)
    {
      if (Index >=0 and Index < Controlled_Portals.size())
      {
[B]        if(Controlled_Portals[Index].IsEnabled())
        {
[/B]            Controlled_Portals[Index].EmitNextTrain();
[B]        }[/B]
      }
    }
    else if (MaxTrains and (World.GetTrainList().size() > MaxTrains) and RemoveExcess)
    {
 
Back
Top