- Added action special support to the thingdef expression evaluator. Now you

can use them like normal functions, which is probably most useful for
  ACS_ExecuteWithResult.


SVN r294 (trunk)
This commit is contained in:
Randy Heit 2006-08-16 20:56:06 +00:00
parent ed12bdc0f4
commit 7dc4be302f
4 changed files with 123 additions and 14 deletions

View file

@ -1,4 +1,7 @@
August 16, 2006 August 16, 2006
- Added action special support to the thingdef expression evaluator. Now you
can use them like normal functions, which is probably most useful for
ACS_ExecuteWithResult.
- Switched to IJG code for reading JPEG images. I have included a stripped- - Switched to IJG code for reading JPEG images. I have included a stripped-
down version of the library with the ZDoom source. (It actually uses less down version of the library with the ZDoom source. (It actually uses less
space than zlib now.) Unix users probably ought to use the system-supplied space than zlib now.) Unix users probably ought to use the system-supplied

View file

@ -1306,6 +1306,29 @@ int FindLineSpecial(const char * string)
return 0; return 0;
} }
//==========================================================================
//
// FindLineSpecialEx
//
// Like FindLineSpecial, but also returns the min and max argument count.
//
//==========================================================================
int FindLineSpecialEx (const char *string, int *min_args, int *max_args)
{
const ACSspecials *spec;
spec = is_special(string, (unsigned int)strlen(string));
if (spec != NULL)
{
*min_args = spec->MinArgs;
*max_args = MAX(spec->MinArgs, spec->MaxArgs);
return spec->Special;
}
*min_args = *max_args = 0;
return 0;
}
//========================================================================== //==========================================================================
// //
// DoSpecialFunctions // DoSpecialFunctions

View file

@ -57,6 +57,9 @@ enum
}; };
// The contents of string must be lowercase (for now, anyway)
int FindLineSpecialEx (const char *string, int *minargs, int *maxargs);
#endif #endif

View file

@ -46,6 +46,8 @@
#include "i_system.h" #include "i_system.h"
#include "m_random.h" #include "m_random.h"
#include "a_pickups.h" #include "a_pickups.h"
#include "thingdef.h"
#include "p_lnspec.h"
void InitExpressions (); void InitExpressions ();
void ClearExpressions (); void ClearExpressions ();
@ -87,6 +89,8 @@ enum ExpOp
EX_Sin, // sin (angle) EX_Sin, // sin (angle)
EX_Cos, // cos (angle) EX_Cos, // cos (angle)
EX_InvCount, // invcount (type) EX_InvCount, // invcount (type)
EX_ActionSpecial,
EX_Right,
}; };
enum ExpValType enum ExpValType
@ -251,12 +255,12 @@ struct ExpData
Type = EX_NOP; Type = EX_NOP;
Value.Type = VAL_Int; Value.Type = VAL_Int;
Value.Int = 0; Value.Int = 0;
for (int i = 0; i < 3; i++) for (int i = 0; i < 2; i++)
Children[i] = NULL; Children[i] = NULL;
} }
~ExpData () ~ExpData ()
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 2; i++)
{ {
if (Children[i]) if (Children[i])
{ {
@ -287,12 +291,14 @@ struct ExpData
if (Children[0]->Type == EX_Const) if (Children[0]->Type == EX_Const)
{ {
bool cond = (Children[0]->Value.Type == VAL_Int) ? (Children[0]->Value.Int != 0) : (Children[0]->Value.Float != 0); bool cond = (Children[0]->Value.Type == VAL_Int) ? (Children[0]->Value.Int != 0) : (Children[0]->Value.Float != 0);
ExpData *data = Children[cond ? 1 : 2]; ExpData *data = Children[1]->Children[cond];
delete Children[cond ? 2 : 1]; delete Children[1]->Children[!cond];
delete Children[1];
delete Children[0];
Type = data->Type; Type = data->Type;
Value = data->Value; Value = data->Value;
for (int i = 0; i < 3; i++) for (int i = 0; i < 2; i++)
{ {
Children[i] = data->Children[i]; Children[i] = data->Children[i];
data->Children[i] = NULL; data->Children[i] = NULL;
@ -301,7 +307,7 @@ struct ExpData
delete data; delete data;
} }
} }
else if (Type != EX_Random && Type != EX_Sin && Type != EX_Cos && Type != EX_InvCount) else if (Type != EX_Random && Type != EX_Sin && Type != EX_Cos && Type != EX_InvCount && Type != EX_ActionSpecial)
{ {
if (Children[0]->Type == EX_Const && Children[1]->Type == EX_Const) if (Children[0]->Type == EX_Const && Children[1]->Type == EX_Const)
{ {
@ -324,7 +330,7 @@ struct ExpData
return false; return false;
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 2; i++)
{ {
if (Children[i] && !Children[i]->Compare (other->Children[i])) if (Children[i] && !Children[i]->Compare (other->Children[i]))
return false; return false;
@ -335,7 +341,7 @@ struct ExpData
ExpOp Type; ExpOp Type;
ExpVal Value; ExpVal Value;
ExpData *Children[3]; ExpData *Children[2];
}; };
TArray<ExpData *> StateExpressions; TArray<ExpData *> StateExpressions;
@ -402,10 +408,13 @@ static ExpData *ParseExpressionM ()
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Cond; data->Type = EX_Cond;
data->Children[0] = tmp; data->Children[0] = tmp;
data->Children[1] = ParseExpressionM (); ExpData *choices = new ExpData;
data->Children[1] = choices;
choices->Type = EX_Right;
choices->Children[0] = ParseExpressionM ();
if (!SC_CheckString (":")) if (!SC_CheckString (":"))
SC_ScriptError ("':' expected"); SC_ScriptError ("':' expected");
data->Children[2] = ParseExpressionM (); choices->Children[1] = ParseExpressionM ();
data->EvalConst (); data->EvalConst ();
return data; return data;
} }
@ -778,8 +787,47 @@ static ExpData *ParseExpressionA ()
} }
else else
{ {
int specnum, min_args, max_args;
SC_MustGetString (); SC_MustGetString ();
// Check if this is an action special
strlwr (sc_String);
specnum = FindLineSpecialEx (sc_String, &min_args, &max_args);
if (specnum != 0)
{
int i;
if (!SC_CheckString ("("))
SC_ScriptError ("'(' expected");
ExpData *data = new ExpData, **left;
data->Type = EX_ActionSpecial;
data->Value.Int = specnum;
data->Children[0] = ParseExpressionM ();
left = &data->Children[1];
for (i = 1; i < 5 && SC_CheckString (","); ++i)
{
ExpData *right = new ExpData;
right->Type = EX_Right;
right->Children[0] = ParseExpressionM ();
*left = right;
left = &right->Children[1];
}
*left = NULL;
if (!SC_CheckString (")"))
SC_ScriptError ("')' expected");
if (i < min_args)
SC_ScriptError ("Not enough arguments to action special");
if (i > max_args)
SC_ScriptError ("Too many arguments to action special");
return data;
}
// Check if it's a variable we understand
int varid = -1; int varid = -1;
for (size_t i = 0; i < countof(ExpVars); i++) for (size_t i = 0; i < countof(ExpVars); i++)
{ {
@ -1363,10 +1411,10 @@ static ExpVal EvalExpression (ExpData *data, AActor *self)
{ {
ExpVal a = EvalExpression (data->Children[0], self); ExpVal a = EvalExpression (data->Children[0], self);
if (a.Type == VAL_Int) if (a.Type == VAL_Float)
val = a.Int ? EvalExpression (data->Children[1], self) : EvalExpression (data->Children[2], self); a.Int = (int)a.Float;
else
val = a.Float ? EvalExpression (data->Children[1], self) : EvalExpression (data->Children[2], self); val = EvalExpression (data->Children[1]->Children[!!a.Int], self);
} }
break; break;
@ -1442,6 +1490,38 @@ static ExpVal EvalExpression (ExpData *data, AActor *self)
val.Int = item->Amount; val.Int = item->Amount;
} }
break; break;
case EX_ActionSpecial:
{
int parms[5] = { 0, 0, 0, 0 };
int i = 0;
ExpData *parm = data;
while (parm != NULL && i < 5)
{
ExpVal val = EvalExpression (parm->Children[0], self);
if (val.Type == VAL_Int)
{
parms[i] = val.Int;
}
else
{
parms[i] = (int)val.Float;
}
i++;
parm = parm->Children[1];
}
val.Type = VAL_Int;
val.Int = LineSpecials[data->Value.Int] (NULL, self, false,
parms[0], parms[1], parms[2], parms[3], parms[4]);
}
break;
case EX_Right:
// This should never be a top-level expression.
assert (data->Type != EX_Right);
break;
} }
return val; return val;