My bet is on this one, from parse_object() in missionparse.cpp
if ( optional_string("+AI Class:")) {
objp->ai_class = match_and_stuff(F_NAME, Ai_class_names, Num_ai_classes, "AI class");
Assert(objp->ai_class > -1 );
} else {
objp->ai_class = Ship_info[objp->ship_class].ai_class;
}
Of all the options, objp->ai_class = match_and_stuff(F_NAME, Ai_class_names, Num_ai_classes, "AI class"); seems the one most directly relevant to taking some external data and hooking it into the ship. But how to implement it is another question, at least for know-nothings like me.
Assuming this one works, we need to set up some code that will first reference the ai.tbl and retrieve the valid options in it(Coward, Captain, General, etc.), then compare them with the value actually entered as an argument of the sexp to ensure it is valid (returning an Int3() or whatever otherwise). Then I'm going to guess the (F_NAME, Ai_class_names, Num_ai_classes, "AI class") bits of objp->ai_class = match_and_stuff(F_NAME, Ai_class_names, Num_ai_classes, "AI class"); will have to be modified somewhat. Also, somewhere along the way Fred will have to know to retrieve the info from ai.tbl just so that the Fredder will only be given the valid options to begin with.
The one thing about this bit of code is that parse_object() ultimately ends with creating an object, not modifying it, so I don't know what difference that might make, if any.