API Question Sub-scopes in scenario files

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
I'm trying to use a sub-scope in my vessel's clbkLoadSaveStateEx ().

I can write the scope to the scenario fine but i'm having trouble reading it. Specifically my while loop fails to terminate at the end of the scope.

This is the code.

Code:
		// Read cockpit parameters
		if (!_strnicmp (cbuf, "COCKPIT", 7))
		{
			while (!_strnicmp (cbuf, "END COCKPIT", 11) == false) cockpit->ParseScenarioLine (cbuf);
		}

What did i screw-up this time?

Note:

I've also tried "while (cbuf != "END COCKPIT")" and various permutations there of
 
Last edited:

Blake

Addon Developer
Addon Developer
Joined
Mar 9, 2009
Messages
232
Reaction score
118
Points
58
Location
Lehi, Utah
You're negating _strnicmp (which returns an int) and then comparing to false.

Try this:

Code:
// Read cockpit parameters
if (_strnicmp (cbuf, "COCKPIT", 7) == 0)
{
	while (_strnicmp (cbuf, "END COCKPIT", 11) != 0)
	{
		cockpit->ParseScenarioLine (cbuf);
	}
}
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
You're negating _strnicmp (which returns an int) and then comparing to false.

The perils of excessive copy/pasta :facepalm:

Still having the same problem though.

Code:
		// Read cockpit parameters
		if (_strnicmp (cbuf, "COCKPIT", 7) == 0)
		{
			while (_strnicmp (cbuf, "END COCKPIT", 11) != 0) cockpit->ParseScenarioLine (cbuf);
		}
 

Blake

Addon Developer
Addon Developer
Joined
Mar 9, 2009
Messages
232
Reaction score
118
Points
58
Location
Lehi, Utah
I'm assuming the ParseScenario line is updating cbuf?
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
cbuf is being advanced by oapiReadScenario_nextline().
 

Blake

Addon Developer
Addon Developer
Joined
Mar 9, 2009
Messages
232
Reaction score
118
Points
58
Location
Lehi, Utah
I don't see where that is called within the inner while loop, somewhere inside that loop cbuf needs to be populated and I don't see where ParseScenarioLine does that--at least according to the docs.
 
Last edited:

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
oapiReadScenario_nextline() is orbiters scenario reading functio it is what populates the buffer.

The idea is...

When you hit the line "Cockpit" pass the contents of the character buffer "cbuf" to the cockpit parser until you hit "end cockpit"
 

Blake

Addon Developer
Addon Developer
Joined
Mar 9, 2009
Messages
232
Reaction score
118
Points
58
Location
Lehi, Utah
oapiReadScenario_nextline() is orbiters scenario reading functio it is what populates the buffer.

The idea is...

When you hit the line "Cockpit" pass the contents of the character buffer "cbuf" to the cockpit parser until you hit "end cockpit"

Right, so someplace inside your 'while' loop you need a call to oapiReadScenario_nextline(). I don't see that being called, which means the while loop is forever comparing the same cbuf data.

Code:
...
	while (_strnicmp (cbuf, "END COCKPIT", 11) != 0)
	{
		if (!oapiReadScenario_nextline(...))
		{
			break;
		}

		cockpit->ParseScenarioLine (cbuf);
	}

something like that.
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
The function is already being called within the brackets of "while (oapiReadScenario_nextline (scn, cbuf))" wouldn't calling it again result in a recursive loop?
 

meson800

Addon Developer
Addon Developer
Donator
Joined
Aug 6, 2011
Messages
405
Reaction score
2
Points
18
The function is already being called within the brackets of "while (oapiReadScenario_nextline (scn, cbuf))" wouldn't calling it again result in a recursive loop?
No, at least not in the literal sense.

I assume your code looks something like:
Code:
while (oapiReadScenario_nextline (scn, cbuf))
{
  //some stuff

  // Read cockpit parameters
  if (_strnicmp (cbuf, "COCKPIT", 7) == 0)
  {
    while (_strnicmp (cbuf, "END COCKPIT", 11) != 0)
      cockpit->ParseScenarioLine (cbuf);
  }

//oapiReadScenario is [b]only[/b] executed after the next curly brace atm
}

As Blake has said, the current code (the internal while loop) will loop forever, as the buffer is never being updated, and the solution is to place a oapiReadScenario inside the if statement.

This will call oapiReadScenario from inside the large while loop, but only until it reaches END COCKPIT. This is acceptable behavior, unless any other subsystem needs to read information inside the cockpit section. After the cockpit subsystem is done being loaded, control is transferred back to the while loop, which continues to load lines like normal.

If a config file looked like:
Code:
COCKPIT
COFFEE_MAKER = 1
COFFEE_RESERVES = 150
RCS_SWITCH = 2
END COCKPIT

ELECTRIC
TOTAL_VOLTAGE = 5
TOTAL_AMPS = 15
END ELECTRIC

then the revised code would call oapiReadScenario in the following way:
Code:
read "COCKPIT": inside main loop
read "COFFEE_MAKER = 1": inside cockpit loop
read "COFFEE_RESERVES = 150": inside cockpit loop
...
read "END_COCKPIT": inside cockpit loop
read "ELECTRIC": inside main loop
...

Your current system can be a little confusing, but it works.

Depending on how you might want to expand the loading code, you might consider splitting the actual subsystem loading into separate functions, having a while loop look only for certain tokens that define subsections, and hand off loading to a subsystem loading function.
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
Depending on how you might want to expand the loading code, you might consider splitting the actual subsystem loading into separate functions, having a while loop look only for certain tokens that define subsections, and hand off loading to a subsystem loading function.

That's what I'm trying to do actually but it isn't working.
 

meson800

Addon Developer
Addon Developer
Donator
Joined
Aug 6, 2011
Messages
405
Reaction score
2
Points
18
That's what I'm trying to do actually but it isn't working.

First, I would end your sub-sections with just a single END token, as that makes readScenario_nextline return false, which makes the whole thing easier. Here's the example scenario file lines:
Code:
COCKPIT
COFFEE_MAKER = 1
COFFEE_RESERVES = 150
RCS_SWITCH = 2
END
ELECTRIC
TOTAL_VOLTAGE = 5
TOTAL_AMPS = 15
END

Ok, here's some sample code of how I would set it up. Hopefully it helps :lol:

For each subsection, assume that the FILEHANDLE begins inside a subsection (this is because it is handled in the main loop later)
Code:
bool readCockpitSubsystemScenario(FILEHANDLE scn)
{
  char* cbuf;
  while (oapiReadScenario_nextline(scn,cbuf))
  {
    if (_strnicmp (cbuf, "COFFEE", 6) == 0)
      //init coffee stuff
    if (_strnicmp (cbuf, "RCS_SWITCH", 10) == 0)
      //setup RCS switch
    //etc
  }
  return true; //if everything setup correctly
}

And an example electric subsystem:
Code:
bool readElectricSubsystemScenario(FILEHANDLE scn)
{
  char* cbuf;
  while (oapiReadScenario_nextline(scn,cbuf))
  {
    if (_strnicmp (cbuf, "TOTAL", 5) == 0)
      //init other stuff
  }
  return true; // if everything setup correctly
}

Then, your main loop's only job is to read the first token not read by another subsystem and determine which subsystem to load
Main loop:
Code:
while (oapiReadScenario_nextline (scn, cbuf))
{
  if (_strnicmp (cbuf, "COCKPIT", 7) == 0)
  {
     readCockpitSubsystemScenario(scn);
    //handle failed cockpit loading by checking return value of function, or other method
  }

  if (_strnicmp (cbuf, "ELECTRIC", 7) == 0)
  {
    readElectricSubsystemScenario(scn);
      //handle failed electric loading by checking return value of function, or other method
  }
}
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
Thank you, that appears to have done it.

But wont re-running oapiReadScenario cause issues if two sub-systems have similarly named variables? As far as I can tell "LoadCockpitState ()" is not restricting itself to those lines between "Cockpit" and "End".
 

meson800

Addon Developer
Addon Developer
Donator
Joined
Aug 6, 2011
Messages
405
Reaction score
2
Points
18
But wont re-running oapiReadScenario cause issues if two sub-systems have similarly named variables? As far as I can tell "LoadCockpitState ()" is not restricting itself to those lines between "Cockpit" and "End".
No, each loadState function will limit it between whenever it was given the FILEHANDLE (which should be the start of its section) and END. That's because oapiReadScenario_nextline will return false when it reads an END token, so each LoadState function will return when it hits the end of its section.
 

Hlynkacg

Aspiring rocket scientist
Addon Developer
Tutorial Publisher
Donator
Joined
Dec 27, 2010
Messages
1,870
Reaction score
3
Points
0
Location
San Diego
So FILEHANDLE includes a starting line? not just a pointer to the *.scn?
 

meson800

Addon Developer
Addon Developer
Donator
Joined
Aug 6, 2011
Messages
405
Reaction score
2
Points
18
Yes, FILEHANDLE stores the position inside the file.
 

orb

New member
News Reporter
Joined
Oct 30, 2009
Messages
14,020
Reaction score
4
Points
0
FILEHANDLE is a pointer to an iostream object (fstream), but it can't be simply referenced as that in modules, because its implementation depends on the version of used C++ libraries, which is usually different than these used by Orbiter.
 
Top