• Ever wanted an RSS feed of all your favorite gaming news sites? Go check out our new Gaming Headlines feed! Read more about it here.

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
It's understandable that it could happen in the first place, but not that the typo remained there for half a decade before being noticed. I mean, the devs surely must have noticed at some point that the game footage people were capturing of the game's AI was off compared to what they'd put in the game.

Unless the difference isn't that big, which I guess remains to be seen.

It's the nature of complex systems. This could be just a single component in a larger complex algorithm. It could be something buried deep within subsystem that don't manifest in obvious ways. It could be that the uninitialized value looks legitimate enough that it's essentially invisible to debugging.

Also, consider that once something is released, it is basically subject to thousand monkeys at typewriter style debugging. And with all the people undoubtedly looking all around the files, it still took half a decade for it to be found.

Asking people to go through and spell check ini files is pretty much impossible. Not least of which because sometimes spelling errors are intentional.

This is all super believable.
 

Deleted member 2507

User requested account closure
Banned
Oct 25, 2017
3,188
Not least of which because sometimes spelling errors are intentional.
I'm pretty damn sure some games i've played have had stuff labeled weirdly internally. Typos, swapped designations (Command&Conquer 1 has two units whose internal designations match the other unit better for reasons unknown), funny internal names for things, perfectly working code for balanced game feature commented out intentionally for no fathomable reason (parts of Skyrim's vampire script), modified copied version of a thing using slightly altered designation...
Parts of these probably rise from changes during development, others perhaps from mistakes that were easier to reproduce than to fix, or perhaps they originated as tests and corrections were never carried out because it isn't really important.

I wouldn't be surprised that for outsiders these might look mistakes but they're given orders not to do anything about them because they're (supposedly) correct. Anyone who knows why stuff is weirdly labelled can double check things from both ends, but others probably cannot. Thus, a single typo is very easy to overlook.

In case of Colonial Marines, it really doesn't help the game has been very rushed and development outsourced. QA was probably nearly non-existent, even if they had figured out the AI had issues, devs probably didn't have time to figure out the issue.
 

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
I suppose this is one of the problems of putting this kind of stuff in config rather than actual code...

Putting things like this in "actual code" is a very poor programming practice. Loading stuff externally from config files is done for several reasons. It affords a degree of flexibility that would otherwise make game development a nightmare.
 
Last edited:

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
In case of Colonial Marines, it really doesn't help the game has been very rushed and development outsourced. QA was probably nearly non-existent, even if they had figured out the AI had issues, devs probably didn't have time to figure out the issue.

That's another thing. It seems like such a simple fix when you know the solution. People in this topic are examining the problem backwards. They're working from the solution out. You tackle bugs differently. The symptom is that "the AI is poor" and that could literally be thousands upon thousands of different problems, especially in a complex program. Again, this could also be made more difficult to diagnose if an uninitialized value looks legitimate to quick observation, too.
 

Qassim

Member
Oct 25, 2017
1,528
United Kingdom
Putting things like this in "actual code" is a very poor programming practice. Loading stuff externally from config files is done for several reasons. It affords a degree of flexibility that would otherwise make game development a nightmare.

You don't need to tell me, I'm very aware, I wasn't suggesting it's wrong at all (otherwise I'd be somewhat of a hypocrite.. configuration loading and support is one of the first things I set up in my projects) - and professionally work in a process which results in most new features and functionality added to the applications I work on being driven by config.

Just that it's a balance worth considering when you decide WHAT to put in config, what are the risks of taking something out of an environment which will check your references before allowing you to proceed to one that doesn't? The risk here being that you break your game in ways that aren't necessarily super obvious and might make debugging harder. But balanced against all the other development benefits, it's probably one worth taking.
 

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
You don't need to tell me, I'm very aware, I wasn't suggesting it's wrong at all (otherwise I'd be somewhat of a hypocrite.. configuration loading and support is one of the first things I set up in my projects).

Just that it's a balance worth considering when you decide WHAT to put in config, what are the risks of taking something out of an environment which will check your references before allowing you to proceed to one that doesn't? The risk here being that you break your game in ways that aren't necessarily super obvious and might make debugging harder. But balanced against all the other development benefits, it's probably one worth taking.

You can make the exact same mistake in actual code. I posted a page ago about how I did that with a printf statement inside my executable, not from an external file. Again, this looks like a key error in some sort of container list. That's not the type of thing which would be checked, really. Depends on how the key is used.
 

Qassim

Member
Oct 25, 2017
1,528
United Kingdom
You can make the exact same mistake in actual code. I posted a page ago about how I did that with a printf statement inside my executable, not from an external file. Again, this looks like a key error in some sort of container list. That's not the type of thing which would be checked, really. Depends on how the key is used.

I only glanced over the config but got reminded by a real world issue I came across. In a largish java application, someone dynamically (and poorly) loading classes based on an array of strings in a config file using reflection, it wasn't a commonly hit bit of code - but it resulted in the application being shipped with a typo in the config and an uncaught exception bringing the application down.

There was actually no need to dynamically load these classes.. especially not based on values in config.. so it was all pulled out and done properly. This issue in the OP is obviously largely irrelevant to this - you're right, it just triggered a funny memory :)
 

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
I only glanced over the config but got reminded by a real world issue I came across. In a largish java application, someone dynamically (and poorly) loading classes based on an array of strings in a config file using reflection, it wasn't a commonly hit bit of code - but it resulted in the application being shipped with a typo in the config and an uncaught exception bringing the application down.

There was actually no need to dynamically load these classes.. especially not based on values in config.. so it was all pulled out and done properly. This issue in the OP is obviously largely irrelevant to this - you're right, it just triggered a funny memory :)

Hey I've done some stupid things in the name of meta programming. I think it's a phase most programmers go through. Pretty sure there is a galaxy-brain meme about it in fact lol.

Then you get to the end point, and you have things like an actual NES emulator written entirely in LUA that performs like shit lmao.
 

Jerykk

Banned
Dec 26, 2017
1,184
This may have been intentional. There's a chance that playtesters thought the original AI was too hard to handle with a gamepad, so Gearbox took a lazy solution and just disabled tethering via the CFG.
 

Jedi2016

Member
Oct 27, 2017
15,622
It's boggling how no one caught this before now. Even if they didn't know what was causing it, surely someone noticed that the AI wasn't behaving the way they'd programmed it?

I'm curious to try this now.
 

Deleted member 2507

User requested account closure
Banned
Oct 25, 2017
3,188
It's boggling how no one caught this before now. Even if they didn't know what was causing it, surely someone noticed that the AI wasn't behaving the way they'd programmed it?

I'm curious to try this now.
The game had very troubled development, did it not? I would guess devs may have been aware of things being wrong but lacking time and resources to figure it out (and/or perhaps will too, wouldn't blame 'em if it was troubled production).

As Krejlooc notes, figuring out the cause isn't very simple. It is obvious in hindsight, but then again hindsight's 20/20.
 

JimJamJones

The Fallen
Oct 25, 2017
2,286
So I reinstalled this just because of this nonsense.

The AI is still dumb as nails, but it's definitely better than before. The game is so damn awful on so many levels. AVP 2010 is still the GOAT.
 

chrisypoo

Member
Oct 27, 2017
3,457
This wasn't just a programming error but a sign of something else.
Yeah, it seems that the project was just horribly mismanaged, so I guess that's the real answer here; whoever directed this game shouldn't be directing anything anymore. I even tried looking up who the director was and couldn't find a clear cut answer, what a weirdly managed development project.
 

Deleted member 18347

User requested account closure
Banned
Oct 27, 2017
2,572
So I reinstalled this just because of this nonsense.

The AI is still dumb as nails, but it's definitely better than before. The game is so damn awful on so many levels. AVP 2010 is still the GOAT.
Yeah their movement still looks weird, but at least they do a much better job at tracking targets.

Unfortunate how they couldn't figure out this typo before release. Maybe with a bit more time.
 

Wereroku

Member
Oct 27, 2017
6,204
The guy that wrote the .ini file is probably the guy that had to find his own error. He thought the word was spelled correctly the whole time so he didn't do shit about it.
Also the human brain will autocorrect spelling errors without us even noticing unless it is exceptionally bad. That's why even highly acclaimed authors and scientist's use editor's for important submissions.
 

Deleted member 18347

User requested account closure
Banned
Oct 27, 2017
2,572
Wat.


This whole situation is insane.
Before

Here's how the xenomorphs behave to begin with. As Chris said in his review, they're all over the place, they're sluggish, and all around they come across as kinda dopey.


After

Now look at how they behave after fixing the typo. In my experience, they're not only considerably more aggressive, they're also much better at tracking the player. As an experiment, I tried just running away from one, a maneuver which would normally confound a xenomorph, and it stayed right on my tail.


via PCGamer
 

Green Marine

Member
Oct 25, 2017
324
El Paso
This is second only to riverboat casino in the pantheon of Gearbox stories. That initial E3 demo might still be the most disingenuous "vertical slice" ever.
 

eso76

Prophet of Truth
Member
Dec 8, 2017
8,107
Oh. Who knows what tinkering with that string that says
GraphicsAndLighting=_Ultrae
does.


(I'm kidding, don't go looking for that)
 

Okii

Banned
Oct 25, 2017
3,189
So like, what's the excuse for the console versions? I assume they don't use inis. Maybe I shouldn't assume...

Those parameters are still in the console version and most likely misspelled there too, no way of editing it like PC without a traditional INI file and access to it, so the only hope is to hope (pray?) for a patch (lol).
 

Eolz

Banned
Oct 25, 2017
7,601
FR
I know what it's like to work with programmers that can't spell. This kind of stuff is frighteningly common. It isn't an unusual thing to see programmers that proudly display their ineptitude for language and communication, because apparently logical thinking and effective expression are incompatible.
This. Remarkably common, but at least it's getting fixed usually.
This case is pretty embarrassing, even though it doesn't fix the whole game obviously.
 

klauskorp

Member
Oct 27, 2017
596
Minnesota
That's funny. I can't even fault anyone for that - shit happens, and it sucks. It's easy to make simple mistakes.

I haven't ever worked on anything that's anywhere near as complicated as a game is, so I know nothing about working with anything so complex. That being said, something I don't understand is why no exceptions were thrown and caught down the road. In the dumb, simple code I write, if I try to call a function that doesn't exist, I get an error. Does it have to do with the function call being in an external file? Or is it something else I can't think of?
 

Razor Mom

Member
Jan 2, 2018
2,546
United Kingdom
So I reinstalled this just because of this nonsense.

The AI is still dumb as nails, but it's definitely better than before. The game is so damn awful on so many levels. AVP 2010 is still the GOAT.
AVP'10 is such a fucking good game. Like at the time I really enjoyed it but it's held up incredibly, it plays great for the most part, it's beautiful, atmospheric, and does so much so well. With the right direction and time, those guys could have made one hell of a colonial marines style game.
 

Abstrusity

Member
Oct 27, 2017
2,656
It's like that one time when I replaced a semicolon, just one, near the very end of a project my friend worked on for months, with a greek question mark because I saw it on the internet.

I bought him beer and pizza as an apology. He smoked two packs of cigarettes in a single day because of it.
 

Ramala

Member
Oct 28, 2017
6,042
Santa Monica, LA
I wish people would stop saying Gearbox developed the game. They oversaw development. Sega published. TimeGate actuallymade the game. I'm not excusing Gearbox but honestly their internal teams would never make something this bad.
 

BradGrenz

Banned
Oct 27, 2017
1,507

Yeah, just tried for myself. In the vanilla version I was given the mission in the beginning to kill the first Xeno. I was confused because after popping out of the wall he literally ran away. I had to track him down with the motion tracker to find and kill it. Before I figured that out I was wondering why I couldn't just finish cutting the other soldier down since the alien had scampered.

Why was this never fixed by Gearbox? What a story.

For all we know someone spent weeks looking for a bug in the source code and never realized the problem wasn't there to begin with.
 

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
That's funny. I can't even fault anyone for that - shit happens, and it sucks. It's easy to make simple mistakes.

I haven't ever worked on anything that's anywhere near as complicated as a game is, so I know nothing about working with anything so complex. That being said, something I don't understand is why no exceptions were thrown and caught down the road. In the dumb, simple code I write, if I try to call a function that doesn't exist, I get an error. Does it have to do with the function call being in an external file? Or is it something else I can't think of?

Let me show you one way something like this could have an unintended effect without causing a crash, let's assume the following program:

Code:
#include <stdio.h>
#include <tchar.h>
#include <map>
#include <string>

//Function number 1
int FunctionToCall1()
{
   printf("Called function 1");
   return 1;
}

int FunctionToCall2()
{
   printf("Called function 2");
   return 1;
}

//Create a typedefinition for a function pointer
typedef int(*Func)(void);

int _tmain(int argc, _TCHAR* argv[])
{
   //create a map with strings for keys, values being function pointers
   std::map<std::string, Func> FuncMap;

   //Map "Test1" string to call Function1;
   FuncMap["Test1"] = &FunctionToCall1;

   //Map "Test2" string to call Function1;
   FuncMap["Test2"] = &FunctionToCall1;

   //Map "Test3" string to call Function2;
   FuncMap["Test3"] = &FunctionToCall2;

   //Create an iterator to traverse through out map of function pointers
   auto it = FuncMap.begin();
 
   //advance iterator twice
   ++it;
   ++it;

   //run function that iterator is pointing to
   it->second();
 
   return 0;
}

kUAdasx.png


We populate our map with 3 keys, "Test1," "Test2," and "Test3". Thus our map is 3 values big. The output of this program will be "Called function 2" because our iterator first points to "Test1" in the map, then advances to "Test2" then advances to "Test3." When we call the iterator, we are pointing to the map key "Test3" which points to FunctionToCall2. This all works as intended. Now let's throw a monkey in the works:

Code:
#include <stdio.h>
#include <tchar.h>
#include <map>
#include <string>

//Function number 1
int FunctionToCall1()
{
   printf("Called function 1");
   return 1;
}

int FunctionToCall2()
{
   printf("Called function 2");
   return 1;
}

//Create a typedefinition for a function pointer
typedef int(*Func)(void);

int _tmain(int argc, _TCHAR* argv[])
{
   //create a map with strings for keys, values being function pointers
   std::map<std::string, Func> FuncMap;

   //Map "Test1" string to call Function1;
   FuncMap["Test1"] = &FunctionToCall1;

   //Map "Test2" string to call Function1;
   FuncMap["Test2"] = &FunctionToCall1;

   //Map "Test3" string to call Function2;
   FuncMap["Test3"] = &FunctionToCall2;

   printf("%i\n", (int)FuncMap["Test1s"]);

   //Create an iterator to traverse through out map of function pointers
   auto it = FuncMap.begin();
 
   //advance iterator twice
   ++it;
   ++it;

   //run function that iterator is pointing to
   it->second();
 
   return 0;
}

hFAfatp.png


We still populate the map with 3 keys, "Test1," Test2," and "Test3" and our map is still 3 values big. But after populating the list, we make an errant call to read the key "Test1s" instead of "Test1." Our program looks through the map and doesn't see "Test1s" anywhere in the list of keys, so it creates one. Our map is ordered by default, so this new key is inserted after Test1 and before Test2. Our map is now 4 values big, "Test1" which points to FunctionToCall1, "Test1s" which points to nothing (0), "Test2" which points to FunctionToCall1, and "Test3" which points to FunctionToCall2.

When we create our iterator and advance is two iterations, instead of pointing to Test3 like it did before, now it points to Test2. When we execute our function pointer stored in this key, we call the wrong function. This is not undefined behavior, the program still compiles and runs without throwing any errors or even any warnings. It's just that our output is now "Called Function1" instead of "Called Function2."

Just one of many, many ways this could mess everything up without actually causing any compiler error.
 

klauskorp

Member
Oct 27, 2017
596
Minnesota
Let me show you one way something like this could have an unintended effect without causing a crash, let's assume the following program:

-snip-

Just one of many, many ways this could mess everything up without actually causing any compiler error.

Huh. Thank you for the explanation. If this were Stack Overflow, I'd vote you up. That's shockingly close to making sense to me - someone that hasn't touched a language that uses pointers in years.