Most quake-c coders eventually see this.
A function pointer was left blank (usually one of the .void entity functions, some of which the engine calls directly) and when the code tries to call it, boom!
This case is odd:
Host_Error: NULL function in server
QuakeC crash report for server:
s1268: OR________ GLOBAL569, GLOBAL499, GLOBAL569
s1269: IFNOT______GLOBAL569, statement 1272
s1270: CALL0______DemonCheckAttack (=DemonCheckAttack())
s1271: RETURN____ GLOBAL1
s1272: FIELD_S____self (=entity 208), classname (=.classname), GLOBAL569
s1273: EQ_S______ GLOBAL569, IMMEDIATE (=monster_wizard), GLOBAL569
s1274: IFNOT______GLOBAL569, statement 1277
s1275: CALL0______WizardCheckAttack (=())
______ ai.qc : CheckAnyAttack : statement 25
______ ai.qc : ai_run : statement 93
__ wizard.qc : wiz_run1 : statement 21
Host_ShutdownServer
Client "player" dropped
gv CheckAnyAttack__
CheckAnyAttack: CheckAnyAttack()
gv WizardCheckAttack
WizardCheckAttack: ()
- gv is my alias to display global variable
Thus, a compiled function has no pointer.__Say what!
From the code (which compiled warning free in regards to this segment):
float() WizardCheckAttack =
{
// bunch of code
};
Where it gets called in ai.qc:
#ifdef quakemonsters
float()___WizardCheckAttack;
___if (self.classname == "monster_army" || self.classname == "monster_ogre" || self.classname == "monster_shambler")
______return MultiCheckAttack();
___if (self.classname == "monster_demon1" || self.classname == "monster_dog")
______return DemonCheckAttack();
___if (self.classname == "monster_wizard")
______return WizardCheckAttack();
#endifdef
What is going on here?
The compiler clearly had a value for this function pointer.
Something is scuttling the reference "return WizardCheckAttack();"
I suspect the prototype inside the #ifdef.__Which can be used to exclude quake 1 monsters from the compiled code.
To test this I'll move the prototype outside this #ifdef.
And that fixes the problem.
The #ifdef is evaluated true - a given since this is the code that is crashing.
Somehow the precompiler must ignore the prototype when it puts a value in the compiled code.
This is a new one on me.
The really odd thing - the prototype can be put in this wrapper and works fine.
#ifdef quakemonsters
float() WizardCheckAttack;
#endifdef
Further testing reveals the prototype for a global function pointer can NOT be placed in the body of a function that makes an immediate call.
Note: because this quirky inline moddb editor strips TABS, I replaced them with "___" - thus this code will not compile if used.