Scripting engine update:
-void pointer is now compatible with any other pointer type -strings can now be directly compared using '==' and '!=' operators -added a linguistic chat message parser with some generic messages predefined - to be used for Human<->AI and AI<->AI communication Note: chat_lexer.l should be compiled using an additional -i switch for case-insensitive lexer git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@898 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
3f4119994f
commit
14cd4b60cc
|
@ -0,0 +1,178 @@
|
|||
%{
|
||||
/*
|
||||
* chat_lexer.l
|
||||
*
|
||||
* lexer for multiplayer chat messages.
|
||||
* IMPORTANT: must be compiled with -i switch (case-insensitive scanner)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "src/base.h"
|
||||
#include "src/droiddef.h"
|
||||
#include "src/structuredef.h"
|
||||
//#include "src/scriptfuncs.h"
|
||||
#include "lib/script/script.h"
|
||||
#include "src/scriptfuncs.h"
|
||||
#include "lib/script/chat_processing.h"
|
||||
|
||||
/* Get the Yacc definitions */
|
||||
#include "lib/script/chat_parser.h"
|
||||
|
||||
/* Maximum length for any TEXT value */
|
||||
#ifndef YYLMAX
|
||||
#define YYLMAX 255
|
||||
#endif
|
||||
|
||||
/* Store for any string values */
|
||||
static char aText[TEXT_BUFFERS][YYLMAX];
|
||||
static UDWORD currText=0;
|
||||
|
||||
/* Pointer to the input buffer */
|
||||
static char *pInputBuffer = NULL;
|
||||
static char *pEndBuffer = NULL;
|
||||
|
||||
static SDWORD playerIndex;
|
||||
static INTERP_VAL parameter;
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
if (pInputBuffer != pEndBuffer) { \
|
||||
buf[0] = *(pInputBuffer++); result = 1; \
|
||||
} else { \
|
||||
buf[0] = EOF; result = YY_NULL; \
|
||||
}
|
||||
|
||||
#undef chat_getc
|
||||
#define chat_getc() (pInputBuffer != pEndBuffer ? *(pInputBuffer++) : EOF)
|
||||
|
||||
%}
|
||||
|
||||
%option yylineno
|
||||
%option prefix="chat_"
|
||||
%option nounput
|
||||
|
||||
%%
|
||||
|
||||
/* Match integer numbers */
|
||||
-?[0-9]+ { chat_lval.ival = atol(chat_text); return R_INTEGER; }
|
||||
|
||||
/* Keywords - Terminals */
|
||||
"?"+ { return _T_QM; }
|
||||
"!"+ { return _T_EM; }
|
||||
"."+ { return _T_FULLSTOP; }
|
||||
":" { return _T_COLON; };
|
||||
";" { return _T_SEMICOLON; };
|
||||
"," { return _T_COMMA; };
|
||||
"a" { return _T_A; }
|
||||
"affirmative" { return _T_AFFIRMATIVE; }
|
||||
"after" { return _T_AFTER; }
|
||||
"ally" { return _T_ALLY; }
|
||||
"am" { return _T_AM; }
|
||||
"and" { return _T_AND; }
|
||||
"any" { return _T_ANY; }
|
||||
"attack" { return _T_ATTACK; }
|
||||
"attacking" { return _T_ATTACKING; }
|
||||
"beacon" { return _T_BEACON; }
|
||||
"building" { return _T_BUILDING; }
|
||||
"can't" { return _T_CANT; }
|
||||
"center" { return _T_CENTER; }
|
||||
"dead" { return _T_DEAD; }
|
||||
"derrick" { return _T_DERRICK; }
|
||||
"do" { return _T_DO; }
|
||||
"drop" { return _T_DROP; }
|
||||
"fine" { return _T_FINE; }
|
||||
"get" { return _T_GET; }
|
||||
"getting" { return _T_GETTING; }
|
||||
"go" { return _T_GO; }
|
||||
"going" { return _T_GOING; }
|
||||
"gonna" { return _T_GONNA; }
|
||||
"got" { return _T_GOT; }
|
||||
"great" { return _T_GREAT; }
|
||||
"have" { return _T_HAVE; }
|
||||
"has" { return _T_HAS; }
|
||||
"help" { return _T_HELP; }
|
||||
"i" { return _T_I; }
|
||||
"i'm" { return _T_IM; }
|
||||
"is" { return _T_IS; }
|
||||
"let's" { return _T_LETS; }
|
||||
"me" { return _T_ME; }
|
||||
"no" { return _T_NO; }
|
||||
"of course" { return _T_OFCOURSE; }
|
||||
"ok"+ { return _T_OK; }
|
||||
"place" { return _T_PLACE; }
|
||||
"possession" { return _T_POSSESSION; }
|
||||
"power" { return _T_POWER; }
|
||||
"pumping" { return _T_PUMPING; }
|
||||
"put" { return _T_PUT; }
|
||||
"roger" { return _T_ROGER; }
|
||||
"see" { return _T_SEE; }
|
||||
"some" { return _T_SOME; }
|
||||
"status" { return _T_STATUS; }
|
||||
"stop" { return _T_STOP; }
|
||||
"sure" { return _T_SURE; }
|
||||
"u" { return _T_U; }
|
||||
"units" { return _T_UNITS; }
|
||||
"vtols" { return _T_VTOLS; }
|
||||
"wait" { return _T_WAIT; }
|
||||
"where" { return _T_WHERE; }
|
||||
"yea" { return _T_YEA; }
|
||||
"yeah" { return _T_YEAH; }
|
||||
"yes" { return _T_YES; }
|
||||
"you" { return _T_YOU; }
|
||||
|
||||
/* <<EOF>> { return _T_EOF; } */
|
||||
|
||||
-?[0-9]+ {
|
||||
chat_lval.ival = atol(chat_text);
|
||||
return R_INTEGER;
|
||||
}
|
||||
|
||||
[0-9_a-zA-Z_]* {
|
||||
playerIndex = getPlayerFromString(chat_text);
|
||||
|
||||
if(playerIndex >= 0)
|
||||
{
|
||||
//console( "matched 'player'");
|
||||
chat_lval.ival = playerIndex;
|
||||
|
||||
return R_PLAYER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* [^ \t\n\<\>\[\]\(\)]+ { return T_WORD; } */
|
||||
/* [^ \t\n]+ { console( "matched 'T_WORD'"); return T_WORD; } */
|
||||
|
||||
|
||||
/* Skip white space */
|
||||
[ \t\n\x0d\x0a] ;
|
||||
|
||||
|
||||
/* Match anything that's been missed and pass it as a char */
|
||||
/* . {console( "matched 'anything else '%s'", chat_text[0]); return chat_text[0];} */
|
||||
|
||||
%%
|
||||
|
||||
/* Set the current input buffer for the lexer */
|
||||
void chatSetInputBuffer(char *pBuffer, UDWORD size)
|
||||
{
|
||||
pInputBuffer = pBuffer;
|
||||
pEndBuffer = pBuffer + size;
|
||||
|
||||
/* Reset the lexer in case it's been used before */
|
||||
chat__flush_buffer(YY_CURRENT_BUFFER);
|
||||
}
|
||||
|
||||
void chatGetErrorData(int *pLine, char **ppText)
|
||||
{
|
||||
*pLine = chat_lineno;
|
||||
*ppText = chat_text;
|
||||
}
|
||||
|
||||
int chat_wrap(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,687 @@
|
|||
%{
|
||||
/*
|
||||
* chat_parser.y
|
||||
*
|
||||
* yacc grammar for multiplayer chat messages
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "lib/framework/frameresource.h"
|
||||
#include "lib/script/script.h"
|
||||
#include "src/scripttabs.h"
|
||||
#include "lib/script/script.h"
|
||||
|
||||
#include "lib/script/chat_processing.h"
|
||||
|
||||
#define MAX_CHAT_ARGUMENTS 10
|
||||
|
||||
/* Holds information about a processed player chat message */
|
||||
CHAT_MSG chat_msg;
|
||||
|
||||
// The current script code
|
||||
static SCRIPT_CODE *psCurrScript;
|
||||
|
||||
// The current script context
|
||||
static SCRIPT_CONTEXT *psCurrContext;
|
||||
|
||||
// Parameter variable
|
||||
static INTERP_VAL scrParameter;
|
||||
|
||||
extern int chat_lex(void);
|
||||
|
||||
// Store extracted command for use in scripts
|
||||
static void chat_store_command(char *command);
|
||||
|
||||
/* Return value of the chat parsing - to be used in scripts */
|
||||
static BOOL chat_store_parameter(INTERP_VAL *parameter);
|
||||
|
||||
// Store players that were addressed in a command
|
||||
static void chat_store_player(SDWORD cmdIndex, SDWORD playerIndex);
|
||||
|
||||
// Reset a command
|
||||
static void chat_reset_command(SDWORD cmdIndex);
|
||||
|
||||
// Information extracted from message and available for scripts
|
||||
//static int numMsgParams=0; //number of parameters currently extracted/stored
|
||||
//static INTERP_VAL msgParams[MAX_CHAT_ARGUMENTS];
|
||||
|
||||
/* Store command parameter extracted from the message */
|
||||
static BOOL chat_store_parameter(INTERP_VAL *cmdParam)
|
||||
{
|
||||
SDWORD numCmdParams, numCommands;
|
||||
|
||||
//console("chat_store_parameter: new parameter");
|
||||
|
||||
/* Make sure we have no overflow */
|
||||
//if(numMsgParams >= MAX_CHAT_ARGUMENTS)
|
||||
if(chat_msg.numCommands >= MAX_CHAT_COMMANDS)
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_parameter: too many commands in a message");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
numCommands = chat_msg.numCommands;
|
||||
numCmdParams = chat_msg.cmdData[numCommands].numCmdParams;
|
||||
|
||||
/* Make sure we still have room for more parameters */
|
||||
if(numCmdParams >= MAX_CHAT_CMD_PARAMS)
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_parameter: out of parameters for command %d", numCommands);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Store parameter for command we are currently processing */
|
||||
//memcpy(&(msgParams[numMsgParams]), parameter, sizeof(INTERP_VAL));
|
||||
memcpy(&(chat_msg.cmdData[numCommands].parameter[numCmdParams]), cmdParam, sizeof(INTERP_VAL));
|
||||
|
||||
chat_msg.cmdData[numCommands].numCmdParams++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Store extracted command for use in scripts
|
||||
static void chat_store_command(char *command)
|
||||
{
|
||||
SDWORD numCmdParams, numCommands;
|
||||
|
||||
//console("chat_store_command: new command: %s", command);
|
||||
|
||||
/* Make sure we have no overflow */
|
||||
if(chat_msg.numCommands >= MAX_CHAT_COMMANDS)
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_command: too many commands in a message");
|
||||
return;
|
||||
}
|
||||
|
||||
numCommands = chat_msg.numCommands;
|
||||
numCmdParams = chat_msg.cmdData[numCommands].numCmdParams;
|
||||
|
||||
/* Make sure we still have room for more parameters */
|
||||
if(numCmdParams >= MAX_CHAT_CMD_PARAMS)
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_command: out of parameters for command %d", numCommands);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store command */
|
||||
chat_msg.cmdData[numCommands].pCmdDescription = command;
|
||||
|
||||
chat_msg.numCommands++;
|
||||
}
|
||||
|
||||
// Store players that were addressed in a command
|
||||
static void chat_store_player(SDWORD cmdIndex, SDWORD playerIndex)
|
||||
{
|
||||
SDWORD i;
|
||||
|
||||
//console("chat_store_player: player %d addressd in command %d", playerIndex, cmdIndex);
|
||||
|
||||
/* Make sure we have no overflow */
|
||||
if(cmdIndex < 0 || cmdIndex >= MAX_CHAT_COMMANDS)
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_player: command message out of bounds: %d", cmdIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
if(playerIndex == -1) //no player specified means all players addressed
|
||||
{
|
||||
/* Ally players addressed */
|
||||
for(i=0; i<MAX_PLAYERS; i++)
|
||||
{
|
||||
chat_msg.cmdData[cmdIndex].bPlayerAddressed[i] = TRUE;
|
||||
}
|
||||
}
|
||||
else if(playerIndex >= 0 && playerIndex < MAX_PLAYERS)
|
||||
{
|
||||
chat_msg.cmdData[cmdIndex].bPlayerAddressed[playerIndex] = TRUE;
|
||||
}
|
||||
else /* Wrong player index */
|
||||
{
|
||||
ASSERT(FALSE, "chat_store_player: wrong player index: %d", playerIndex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void chat_reset_command(SDWORD cmdIndex)
|
||||
{
|
||||
SDWORD i;
|
||||
|
||||
ASSERT(cmdIndex >= 0 && cmdIndex < MAX_CHAT_COMMANDS,
|
||||
"chat_reset_command: command index out of bounds: %d", cmdIndex);
|
||||
|
||||
chat_msg.cmdData[cmdIndex].numCmdParams = 0;
|
||||
|
||||
for(i=0; i<MAX_PLAYERS; i++)
|
||||
{
|
||||
chat_msg.cmdData[cmdIndex].bPlayerAddressed[i] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%name-prefix="chat_"
|
||||
|
||||
%union {
|
||||
BOOL bval;
|
||||
INTERP_TYPE tval;
|
||||
char *sval;
|
||||
UDWORD vindex;
|
||||
SDWORD ival;
|
||||
}
|
||||
|
||||
/* Start symbol */
|
||||
%start R_PHRASE
|
||||
|
||||
/* keywords */
|
||||
%token BRACKET_OPEN
|
||||
%token BRACKET_CLOSE
|
||||
%token SQ_BRACKET_OPEN
|
||||
%token SQ_BRACKET_CLOSE
|
||||
%token PIPE
|
||||
%token T_WORD
|
||||
|
||||
%token _T_QM
|
||||
%token _T_EM
|
||||
%token _T_FULLSTOP
|
||||
%token _T_COLON
|
||||
%token _T_SEMICOLON
|
||||
%token _T_COMMA
|
||||
|
||||
%token _T_A
|
||||
%token _T_AFFIRMATIVE
|
||||
%token _T_AFTER
|
||||
%token _T_ALLY
|
||||
%token _T_AM
|
||||
%token _T_AND
|
||||
%token _T_ANY
|
||||
%token _T_ATTACK
|
||||
%token _T_ATTACKING
|
||||
%token _T_BEACON
|
||||
%token _T_BUILDING
|
||||
%token _T_CANT
|
||||
%token _T_CENTER
|
||||
%token _T_DEAD
|
||||
%token _T_DERRICK
|
||||
%token _T_DO
|
||||
%token _T_DROP
|
||||
%token _T_FINE
|
||||
%token _T_GET
|
||||
%token _T_GETTING
|
||||
%token _T_GO
|
||||
%token _T_GOING
|
||||
%token _T_GONNA
|
||||
%token _T_GOT
|
||||
%token _T_GREAT
|
||||
%token _T_HAVE
|
||||
%token _T_HAS
|
||||
%token _T_HELP
|
||||
%token _T_I
|
||||
%token _T_IM
|
||||
%token _T_A
|
||||
%token _T_IS
|
||||
%token _T_LETS
|
||||
%token _T_ME
|
||||
%token _T_NO
|
||||
%token _T_OFCOURSE
|
||||
%token _T_OK
|
||||
%token _T_PLACE
|
||||
%token _T_POSSESSION
|
||||
%token _T_POWER
|
||||
%token _T_PUMPING
|
||||
%token _T_PUT
|
||||
%token _T_ROGER
|
||||
%token _T_SEE
|
||||
%token _T_SOME
|
||||
%token _T_STATUS
|
||||
%token _T_STOP
|
||||
%token _T_SURE
|
||||
%token _T_U
|
||||
%token _T_UNITS
|
||||
%token _T_VTOLS
|
||||
%token _T_WAIT
|
||||
%token _T_WHERE
|
||||
%token _T_YEA
|
||||
%token _T_YEAH
|
||||
%token _T_YES
|
||||
%token _T_YOU
|
||||
%token _T_EOF 0
|
||||
|
||||
/* Typed Keywords */
|
||||
%token <ival> R_PLAYER
|
||||
%token <ival> R_INTEGER
|
||||
|
||||
%%
|
||||
|
||||
/* The top-level rule, consists of
|
||||
* one or more sentences: commands or addressed commands
|
||||
* or unrecognized messages (handled in R_COMMAND)
|
||||
*/
|
||||
R_PHRASE: R_ADDRESSED_COMMAND
|
||||
| R_COMMAND
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands - 1, -1); /* No player list means current command is addressed to everyone */
|
||||
}
|
||||
| R_PHRASE R_ADDRESSED_COMMAND
|
||||
| R_PHRASE R_COMMAND
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands - 1, -1);
|
||||
}
|
||||
| error
|
||||
{
|
||||
//console("-unrecognized phrase");
|
||||
|
||||
/* Reset current command */
|
||||
chat_reset_command(chat_msg.numCommands);
|
||||
}
|
||||
;
|
||||
|
||||
/* A command addressed to one or more players
|
||||
*/
|
||||
R_ADDRESSED_COMMAND: R_PLAYER_LIST _T_COLON R_COMMAND /* "Red, Black: attack yellow" */
|
||||
//{console("RULE: player list: command");}
|
||||
| R_PLAYER_LIST _T_SEMICOLON R_COMMAND /* "Red, Black; attack yellow" */
|
||||
//{console("RULE: player list; command");}
|
||||
| R_PLAYER_LIST _T_COMMA R_COMMAND /* "Red, Black, attack yellow" */
|
||||
//{console("RULE: player list, command");}
|
||||
| R_PLAYER_LIST R_COMMAND /* No delimeter: "Red, Black attack yellow" */
|
||||
//{console("RULE: player list command");}
|
||||
;
|
||||
|
||||
|
||||
/* Any of the recognizable commands -
|
||||
* since there can't be any player list at this stage,
|
||||
* should address all players receiving this message by default:
|
||||
* EXAMPLE:
|
||||
* 1) "Help me!" - addresses all players receiving the message
|
||||
* 2) "Black and Red, help me!" - addresses players 'Black' and 'red' only
|
||||
*/
|
||||
R_COMMAND: R_ALLY_OFFER /* ally me */
|
||||
{
|
||||
chat_store_command("ally me"); /* Store current command */
|
||||
}
|
||||
| R_ASK_READINESS /* go? */
|
||||
{
|
||||
chat_store_command("go?");
|
||||
}
|
||||
| R_INITIATE_ACTION /* go ! */
|
||||
{
|
||||
chat_store_command("go!");
|
||||
}
|
||||
| R_DEMAND_BEACON /* drop a beacon */
|
||||
{
|
||||
chat_store_command("drop a beacon");
|
||||
}
|
||||
| R_MEET_CENTER /* go center */
|
||||
{
|
||||
chat_store_command("go center");
|
||||
}
|
||||
| R_ASK_STATUS /* status? */
|
||||
{
|
||||
chat_store_command("status?");
|
||||
}
|
||||
| R_BUILDING_UNITS /* pumping units */
|
||||
{
|
||||
chat_store_command("pumping units");
|
||||
}
|
||||
| R_STOP /* stop! */
|
||||
{
|
||||
chat_store_command("stop");
|
||||
}
|
||||
| R_WONDER_IF_HAVE_POWER /* Ask if player has power */
|
||||
{
|
||||
chat_store_command("got power?");
|
||||
}
|
||||
| R_DEMAND_HELP /* help me! */
|
||||
{
|
||||
chat_store_command("help me");
|
||||
}
|
||||
| R_REPORT_SAFETY /* i'm ok */
|
||||
{
|
||||
chat_store_command("i'm ok");
|
||||
}
|
||||
| R_AFFIRMATIVE /* roger! */
|
||||
{
|
||||
chat_store_command("roger");
|
||||
}
|
||||
| R_ALLY_PLAYER /* ally blue */
|
||||
{
|
||||
chat_store_command("ally player");
|
||||
}
|
||||
| R_ATTACK_PLAYER /* attack blue */
|
||||
{
|
||||
chat_store_command("attack player");
|
||||
}
|
||||
| R_ATTACKING_PLAYER /* attacking blue */
|
||||
{
|
||||
chat_store_command("attacking player?");
|
||||
}
|
||||
| R_PLAYER_HAS_VTOLS /* blue has VTOLS */
|
||||
{
|
||||
chat_store_command("player has vtols");
|
||||
}
|
||||
;
|
||||
|
||||
/* A reference to certain players: "yellow, help me"
|
||||
*/
|
||||
R_PLAYER_LIST: R_PLAYER
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands, $1); /* Remember this player was addressed in current command */
|
||||
}
|
||||
| R_PLAYER_LIST R_PLAYER /* without any delimeters: "yellow black red" */
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands, $2);
|
||||
}
|
||||
| R_PLAYER_LIST _T_COMMA R_PLAYER /* "yellow, black, red" */
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands, $3);
|
||||
}
|
||||
| R_PLAYER_LIST _T_AND R_PLAYER /* "yellow, black and red" */
|
||||
{
|
||||
chat_store_player(chat_msg.numCommands, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/* A Article or nothing
|
||||
*/
|
||||
R_A_OR_EMPTY: /* Empty */
|
||||
| _T_A
|
||||
;
|
||||
|
||||
/* ?????
|
||||
R_QM_REPETITION: _T_QM
|
||||
| R_QM_REPETITION _T_QM */
|
||||
;
|
||||
|
||||
/* QM or nothing */
|
||||
//R_QM_OR_EMPTY: /* Empty */
|
||||
// | _T_QM /* ????? or nothing */
|
||||
// ;
|
||||
|
||||
/* !!!!!!
|
||||
R_EM_REPETITION: _T_EM
|
||||
| R_EM_REPETITION _T_EM */
|
||||
;
|
||||
|
||||
/* EM or nothing */
|
||||
//R_EM_OR_EMPTY: /* Empty */
|
||||
// | _T_EM /* !!!!! or nothing */
|
||||
// ;
|
||||
|
||||
/* Punctuation mark */
|
||||
R_PUNCTUATION_MARK: _T_QM
|
||||
| _T_EM
|
||||
| R_PUNCTUATION_MARK _T_QM /* ?????!!!!??! */
|
||||
| R_PUNCTUATION_MARK _T_EM /* ?????!!!!??! */
|
||||
;
|
||||
|
||||
/* Full stop or end of file
|
||||
* (a 'virtual' rule)
|
||||
*/
|
||||
R_FULLSTOP_OR_EOF: /* Empty */ /* Needed for other rules */
|
||||
| _T_EOF /* End of input */
|
||||
| _T_FULLSTOP /* . */
|
||||
;
|
||||
|
||||
/* End of a declarative sentence
|
||||
* can't be a question
|
||||
*/
|
||||
R_EOD: _T_EM /* !!!! */
|
||||
| R_FULLSTOP_OR_EOF
|
||||
;
|
||||
|
||||
/* End of a question
|
||||
* can't end with an exclamation mark
|
||||
*/
|
||||
R_EOQ: _T_QM
|
||||
| R_FULLSTOP_OR_EOF
|
||||
;
|
||||
|
||||
/* (any possible) end of the sentence - similar
|
||||
* to "End of a declarative sentence",
|
||||
* but can additionally end with a question.
|
||||
*/
|
||||
R_EOS: R_EOD /* End of a declarative sentence */
|
||||
| R_PUNCTUATION_MARK /* ???!!?!?!?!? */
|
||||
;
|
||||
|
||||
/* Express attack intention */
|
||||
R_ATTACKING: _T_ATTACKING
|
||||
| _T_GOING
|
||||
| _T_GOING _T_AFTER
|
||||
;
|
||||
|
||||
/* Attack */
|
||||
R_INITIATE_ATTACK: _T_ATTACK
|
||||
| _T_GET
|
||||
;
|
||||
|
||||
R_PUT_DOWN: _T_PUT | _T_DROP | _T_PLACE; /* put */
|
||||
|
||||
R_INCREASING_NUMBER: _T_PUMPING /* pumping/getting */
|
||||
| _T_GETTING
|
||||
| _T_BUILDING
|
||||
;
|
||||
|
||||
R_YOU: _T_YOU
|
||||
| _T_U /* u */
|
||||
;
|
||||
|
||||
/* 'You' - pronoun for questions */
|
||||
R_DO_YOU: R_YOU /* like in "you got any..." */
|
||||
| _T_DO R_YOU /* do you */
|
||||
;
|
||||
|
||||
/* Used in questions */
|
||||
R_POSSESSION_Q: _T_HAVE
|
||||
| _T_GOT
|
||||
;
|
||||
|
||||
R_POSSESSES: _T_HAS
|
||||
| _T_GOT
|
||||
;
|
||||
|
||||
|
||||
R_QUANTITY: _T_ANY
|
||||
| _T_SOME
|
||||
;
|
||||
|
||||
R_DO_YOU_HAVE_ANY: R_DO_YOU R_POSSESSION_Q R_QUANTITY
|
||||
| R_DO_YOU R_POSSESSION_Q
|
||||
| R_POSSESSION_Q R_QUANTITY /* got any.. */
|
||||
| R_POSSESSION_Q /* got <substantive>? */
|
||||
| R_QUANTITY /* any <substantive>? */
|
||||
;
|
||||
|
||||
R_YES_FORMS: _T_YES
|
||||
| _T_YEA
|
||||
| _T_YEAH
|
||||
;
|
||||
|
||||
R_CONFIDENCE_EXPRESSION: _T_SURE
|
||||
| _T_OFCOURSE
|
||||
;
|
||||
|
||||
R_AGREEMENT_EXPRESSION: R_YES_FORMS
|
||||
| _T_FINE
|
||||
| _T_OK
|
||||
;
|
||||
|
||||
R_AFFIRMATIVE_FORMS: R_AGREEMENT_EXPRESSION
|
||||
| R_CONFIDENCE_EXPRESSION
|
||||
| _T_ROGER /* roger */
|
||||
| _T_AFFIRMATIVE
|
||||
;
|
||||
/*******************************************/
|
||||
/* FINAL RULES, SHOULD BE PART OF R_PHRASE */
|
||||
/*******************************************/
|
||||
|
||||
/* Ask a player to ally myself */
|
||||
R_ALLY_OFFER: _T_ALLY _T_ME R_EOS /* ally me */
|
||||
| _T_ALLY R_EOS /* "ally" at the end (otherwise breaks "ally me") */
|
||||
/* | _T_ALLY */
|
||||
;
|
||||
|
||||
/* Chech if player is willing
|
||||
* to initiate some actions
|
||||
*/
|
||||
R_ASK_READINESS: _T_GO _T_QM; /* go? */
|
||||
|
||||
/* Tell to start some action */
|
||||
R_INITIATE_ACTION: _T_GO R_EOD; /* go!! */
|
||||
|
||||
/* Tell to drop a beacon */
|
||||
R_DEMAND_BEACON: R_PUT_DOWN R_A_OR_EMPTY _T_BEACON; /* put a beacon */
|
||||
|
||||
/* Tell to meet in the center of the map */
|
||||
R_MEET_CENTER: _T_GO _T_CENTER R_EOS; /* go center */
|
||||
|
||||
/* Ask for the current status */
|
||||
R_ASK_STATUS: _T_STATUS R_EOS; /* status? */
|
||||
|
||||
/* Player is building units */
|
||||
R_BUILDING_UNITS: R_INCREASING_NUMBER _T_UNITS R_EOD; /* pumping units */
|
||||
|
||||
/* Stop command */
|
||||
R_STOP: _T_STOP R_EOD; /* stop */
|
||||
|
||||
/* Ask if player has power */
|
||||
R_WONDER_IF_HAVE_POWER: R_DO_YOU_HAVE_ANY _T_POWER R_EOQ; /* do you have power? */
|
||||
|
||||
/* Ask for help */
|
||||
R_DEMAND_HELP: _T_HELP _T_ME R_EOS /* help me!!!!! */
|
||||
| _T_HELP R_EOS /* help!?!? */
|
||||
;
|
||||
|
||||
/* Tell player i'm safe - no danger anymore */
|
||||
R_REPORT_SAFETY: _T_IM _T_OK; /* i'm ok */
|
||||
|
||||
|
||||
/* Positive order feedback */
|
||||
R_AFFIRMATIVE: R_AFFIRMATIVE_FORMS /* yes, roger etc */
|
||||
| R_AFFIRMATIVE R_AFFIRMATIVE_FORMS /* accept repetitions: "yes yes yeah" */
|
||||
| R_AFFIRMATIVE R_EOD /* can also be emotional: "yea!!! yeah! yes!!!!" */
|
||||
;
|
||||
|
||||
/* Ask to ally a player */
|
||||
R_ALLY_PLAYER: _T_ALLY R_PLAYER R_EOD /* ally blue */
|
||||
{
|
||||
/* Store for scripts */
|
||||
scrParameter.type = VAL_INT;
|
||||
scrParameter.v.ival = $2;
|
||||
if(!chat_store_parameter(&scrParameter))
|
||||
{
|
||||
chat_error("chat command: Too many parameters in the message");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
/* Ask to start attack a player */
|
||||
R_ATTACK_PLAYER: R_INITIATE_ATTACK R_PLAYER R_EOD /* attack blue */
|
||||
{
|
||||
/* Store for scripts */
|
||||
scrParameter.type = VAL_INT;
|
||||
scrParameter.v.ival = $2;
|
||||
if(!chat_store_parameter(&scrParameter))
|
||||
{
|
||||
chat_error("chat command: Too many parameters in the message");
|
||||
}
|
||||
}
|
||||
| _T_GO R_PLAYER R_EOD /* go blue */
|
||||
{
|
||||
/* Store for scripts */
|
||||
scrParameter.type = VAL_INT;
|
||||
scrParameter.v.ival = $2;
|
||||
if(!chat_store_parameter(&scrParameter))
|
||||
{
|
||||
chat_error("chat command: Too many parameters in the message");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
/* Notify i'm attacking player */
|
||||
R_ATTACKING_PLAYER: R_ATTACKING R_PLAYER R_EOD /* attacking blue */
|
||||
{
|
||||
/* Store for scripts */
|
||||
scrParameter.type = VAL_INT;
|
||||
scrParameter.v.ival = $2;
|
||||
if(!chat_store_parameter(&scrParameter))
|
||||
{
|
||||
chat_error("chat command: Too many parameters in the message");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
/* Notify about player using VTOLs */
|
||||
R_PLAYER_HAS_VTOLS: R_PLAYER R_POSSESSES _T_VTOLS R_EOD /* blue has VTOLS */
|
||||
{
|
||||
/* Store for scripts */
|
||||
scrParameter.type = VAL_INT;
|
||||
scrParameter.v.ival = $1;
|
||||
if(!chat_store_parameter(&scrParameter))
|
||||
{
|
||||
chat_error("chat command: Too many parameters in the message");
|
||||
}
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
/* Initialize Bison and start chat processing */
|
||||
BOOL chatLoad(char *pData, UDWORD size)
|
||||
{
|
||||
SDWORD cmdIndex,parseResult;
|
||||
|
||||
/* Don't parse the same message again for a different player */
|
||||
if(strcmp(pData, chat_msg.lastMessage) == 0) //just parsed this message for some other player
|
||||
{
|
||||
return TRUE; //keep all the parsed data unmodified
|
||||
}
|
||||
|
||||
/* Tell bison what to parse */
|
||||
chatSetInputBuffer(pData, size);
|
||||
|
||||
/* Reset previous chat processing */
|
||||
chat_msg.numCommands = 0;
|
||||
|
||||
/* Initialize command data */
|
||||
for(cmdIndex=0; cmdIndex<MAX_CHAT_COMMANDS; cmdIndex++)
|
||||
{
|
||||
chat_reset_command(cmdIndex);
|
||||
}
|
||||
|
||||
/* Invoke bison and parse */
|
||||
parseResult = chat_parse();
|
||||
|
||||
/* Remember last message we parsed */
|
||||
strcpy(&(chat_msg.lastMessage[0]), pData);
|
||||
|
||||
/* See if we were successfull parsing */
|
||||
if (parseResult != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* A simple error reporting routine */
|
||||
void chat_error(const char *pMessage,...)
|
||||
{
|
||||
int line;
|
||||
char *pText;
|
||||
char aTxtBuf[1024];
|
||||
va_list args;
|
||||
|
||||
va_start(args, pMessage);
|
||||
|
||||
vsprintf(aTxtBuf, pMessage, args);
|
||||
chatGetErrorData(&line, &pText);
|
||||
debug(LOG_WARNING, "multiplayer message parse error: %s at line %d, token: %d, text: '%s'",
|
||||
aTxtBuf, line, chat_char, pText);
|
||||
|
||||
va_end(args);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* chat_processing.h
|
||||
*
|
||||
* Misc definitions for chat parser
|
||||
*/
|
||||
#ifndef _chat_processing_h
|
||||
#define _chat_processing_h
|
||||
|
||||
#include "lib/framework/frame.h"
|
||||
#include "src/base.h"
|
||||
#include "src/droiddef.h"
|
||||
#include "src/structuredef.h"
|
||||
#include "lib/script/script.h"
|
||||
|
||||
#ifndef MAXSTRLEN
|
||||
#define MAXSTRLEN 255
|
||||
#endif
|
||||
|
||||
/* Max number of commands in a player chat message */
|
||||
#define MAX_CHAT_COMMANDS 10
|
||||
|
||||
/* Max number of parameters allowed in a single chat message command */
|
||||
#define MAX_CHAT_CMD_PARAMS 10
|
||||
|
||||
|
||||
/* Holds information for each recognized
|
||||
* command in a chat message */
|
||||
typedef struct _chat_command_data
|
||||
{
|
||||
char *pCmdDescription; /* String representing a certain command */
|
||||
BOOL bPlayerAddressed[MAX_PLAYERS]; /* Flag to indicate whether a command was addressed to a certain player */
|
||||
SDWORD numCmdParams; /* Number of extracted parameters associated with each command */
|
||||
INTERP_VAL parameter[MAX_CHAT_CMD_PARAMS]; /* Parameters extracted from text - to be used with scripts */
|
||||
}CHAT_CMD_DATA;
|
||||
|
||||
typedef struct _chat_command
|
||||
{
|
||||
char lastMessage[MAXSTRLEN]; /* Parse the same mesage only once - in case more than one player is trying to parse */
|
||||
SDWORD numCommands; /* Total number of commands in chat message */
|
||||
CHAT_CMD_DATA cmdData[MAX_CHAT_COMMANDS]; /* Holds information for each recognized command */
|
||||
}CHAT_MSG;
|
||||
|
||||
extern CHAT_MSG chat_msg;
|
||||
|
||||
/* Store parameter extracted from the message - for scripts */
|
||||
//extern BOOL chat_store_parameter(INTERP_VAL *parameter);
|
||||
|
||||
extern void chat_error(const char *pMessage,...);
|
||||
|
||||
extern void chatGetErrorData(int *pLine, char **ppText);
|
||||
|
||||
/* Set the current input buffer for the lexer */
|
||||
extern void chatSetInputBuffer(char *pBuffer, UDWORD size);
|
||||
|
||||
// Load message
|
||||
extern BOOL chatLoad(char *pData, UDWORD size);
|
||||
|
||||
#endif
|
|
@ -523,10 +523,7 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
goto exit_with_error;
|
||||
}
|
||||
/* get local variable */
|
||||
psVar = &(psContext->psCode->ppsLocalVarVal[CurEvent][data]);
|
||||
|
||||
//TODO: fix
|
||||
sVal.v.oval = &(psVar->v.ival);
|
||||
sVal.v.oval = &(psContext->psCode->ppsLocalVarVal[CurEvent][data]);
|
||||
|
||||
TRCPRINTF(("PUSHREF "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
|
@ -569,9 +566,9 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
// The type of the variable is stored in with the opcode
|
||||
sVal.type = (INTERP_TYPE)(InstrPointer->v.ival & OPCODE_DATAMASK);
|
||||
|
||||
// store the pointer
|
||||
psVar = interpGetVarData(psGlobals, ((INTERP_VAL *)(InstrPointer + 1))->v.ival);
|
||||
sVal.v.oval = &(psVar->v.ival);
|
||||
// store pointer to INTERP_VAL
|
||||
sVal.v.oval = interpGetVarData(psGlobals, ((INTERP_VAL *)(InstrPointer + 1))->v.ival);
|
||||
|
||||
TRCPRINTF(("PUSHREF "));
|
||||
TRCPRINTVAL(&sVal);
|
||||
TRCPRINTF(("\n"));
|
||||
|
@ -801,7 +798,7 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
// jump out of the code
|
||||
InstrPointer = pCodeEnd;
|
||||
break;
|
||||
case OP_PAUSE:
|
||||
case OP_PAUSE:
|
||||
ASSERT( InstrPointer->type == VAL_PKOPCODE,
|
||||
"wrong value type passed for OP_PAUSE: %d", InstrPointer->type);
|
||||
|
||||
|
@ -841,7 +838,7 @@ BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType, UDWORD i
|
|||
goto exit_with_error;
|
||||
}
|
||||
InstrPointer += aOpSize[opcode];
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
debug(LOG_ERROR, "interpRunScript: unknown opcode: %d, type: %d", opcode);
|
||||
ASSERT( FALSE, "interpRunScript: unknown opcode: %d, type: %d", opcode, InstrPointer->type );
|
||||
|
@ -1013,6 +1010,15 @@ BOOL interpCheckEquiv(INTERP_TYPE to, INTERP_TYPE from)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Void pointer is compatible with any other type */
|
||||
if(toRef == TRUE && fromRef == TRUE)
|
||||
{
|
||||
if(to == VAL_VOID)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (to == from)
|
||||
{
|
||||
return TRUE;
|
||||
|
|
|
@ -178,7 +178,7 @@ BOOL scriptGetVarIndex(SCRIPT_CODE *psCode, char *pID, UDWORD *pIndex)
|
|||
these aren't currently checked for, but it's a lot clearer what's going on if they're all here */
|
||||
BOOL scriptTypeIsPointer(INTERP_TYPE type)
|
||||
{
|
||||
ASSERT( ((type < ST_MAXTYPE) || (type >= VAL_REF)), "scriptTypeIsPointer: invalid type" );
|
||||
ASSERT( ((type < ST_MAXTYPE) || (type >= VAL_REF)), "scriptTypeIsPointer: invalid type: %d", type );
|
||||
// any value or'ed with VAL_REF is a pointer
|
||||
if (type >= VAL_REF) return TRUE;
|
||||
switch (type) {
|
||||
|
@ -225,7 +225,7 @@ BOOL scriptTypeIsPointer(INTERP_TYPE type)
|
|||
case ST_SOUND:
|
||||
return FALSE;
|
||||
default:
|
||||
ASSERT(FALSE, "scriptTypeIsPointer: unhandled type");
|
||||
ASSERT(FALSE, "scriptTypeIsPointer: unhandled type: %d", type );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ extern void cpPrintProgram(SCRIPT_CODE *psProg);
|
|||
extern BOOL scriptGetVarIndex(SCRIPT_CODE *psCode, char *pID, UDWORD *pIndex);
|
||||
|
||||
/* returns true if passed INTERP_TYPE is used as a pointer in INTERP_VAL, false otherwise */
|
||||
BOOL scriptTypeIsPointer(INTERP_TYPE type);
|
||||
extern BOOL scriptTypeIsPointer(INTERP_TYPE type);
|
||||
|
||||
/* Run a compiled script */
|
||||
extern BOOL interpRunScript(SCRIPT_CONTEXT *psContext, INTERP_RUNTYPE runType,
|
||||
|
|
|
@ -5253,6 +5253,14 @@ boolexp: boolexp _AND boolexp
|
|||
/* Return the code block */
|
||||
$$ = psCurrBlock;
|
||||
}
|
||||
| stringexp BOOLEQUAL stringexp
|
||||
{
|
||||
codeRet = scriptCodeBinaryOperator($1, $3, OP_EQUAL, &psCurrBlock);
|
||||
CHECK_CODE_ERROR(codeRet);
|
||||
|
||||
/* Return the code block */
|
||||
$$ = psCurrBlock;
|
||||
}
|
||||
| userexp BOOLEQUAL userexp
|
||||
{
|
||||
if (!interpCheckEquiv($1->type,$3->type))
|
||||
|
@ -5295,6 +5303,14 @@ boolexp: boolexp _AND boolexp
|
|||
/* Return the code block */
|
||||
$$ = psCurrBlock;
|
||||
}
|
||||
| stringexp NOTEQUAL stringexp
|
||||
{
|
||||
codeRet = scriptCodeBinaryOperator($1, $3, OP_NOTEQUAL, &psCurrBlock);
|
||||
CHECK_CODE_ERROR(codeRet);
|
||||
|
||||
/* Return the code block */
|
||||
$$ = psCurrBlock;
|
||||
}
|
||||
| userexp NOTEQUAL userexp
|
||||
{
|
||||
if (!interpCheckEquiv($1->type,$3->type))
|
||||
|
|
|
@ -44,6 +44,9 @@ static UDWORD currEntry=0;
|
|||
/* The block heap the stack was created in */
|
||||
static BLOCK_HEAP *psStackBlock;
|
||||
|
||||
/* Get rid of the top value without returning it */
|
||||
static inline BOOL stackRemoveTop(void);
|
||||
|
||||
|
||||
/* Check if the stack is empty */
|
||||
BOOL stackEmpty(void)
|
||||
|
@ -296,8 +299,6 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//string support
|
||||
// Get the values, checking their types
|
||||
index = currEntry;
|
||||
for (i=0; i< numParams; i++)
|
||||
|
@ -326,9 +327,28 @@ BOOL stackPopParams(SDWORD numParams, ...)
|
|||
return FALSE;
|
||||
}
|
||||
if (scriptTypeIsPointer(psVal->type))
|
||||
*((void**)pData) = psVal->v.oval;
|
||||
{
|
||||
if(psVal->type >= VAL_REF) //if it's a reference
|
||||
{
|
||||
INTERP_VAL *refVal;
|
||||
|
||||
refVal = psVal->v.oval; //oval is a pointer to INTERP_VAL in this case
|
||||
|
||||
/* doublecheck types */
|
||||
ASSERT(interpCheckEquiv(type & ~VAL_REF, refVal->type), "stackPopParams: type mismatch for a reference: %d/%d",
|
||||
type & ~VAL_REF, refVal->type); //type of provided container and type of the INTERP_VAL pointed by psVal->v.oval
|
||||
|
||||
*((void**)pData) = &(refVal->v.ival); /* get pointer to the union */
|
||||
}
|
||||
else //some pointer type
|
||||
{
|
||||
*((void**)pData) = psVal->v.oval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*((SDWORD*)pData) = psVal->v.ival;
|
||||
}
|
||||
}
|
||||
else //TODO: allow only compatible types
|
||||
{
|
||||
|
@ -595,17 +615,20 @@ BOOL stackBinaryOp(OPCODE opcode)
|
|||
psV1->v.bval = psV1->v.bval || psV2->v.bval;
|
||||
break;
|
||||
case OP_EQUAL:
|
||||
if(psV1->type == VAL_FLOAT || psV2->type == VAL_FLOAT){
|
||||
if(psV1->type == VAL_FLOAT && psV2->type == VAL_FLOAT){
|
||||
psV1->v.bval = psV1->v.fval == psV2->v.fval;
|
||||
}else if(psV1->type == VAL_STRING && psV2->type == VAL_STRING){
|
||||
psV1->v.bval = (strcasecmp(psV1->v.sval,psV2->v.sval) == 0); /* case-insensitive */
|
||||
}else{
|
||||
psV1->v.bval = psV1->v.ival == psV2->v.ival;
|
||||
}
|
||||
psV1->type = VAL_BOOL;
|
||||
break;
|
||||
case OP_NOTEQUAL:
|
||||
|
||||
if(psV1->type == VAL_FLOAT || psV2->type == VAL_FLOAT){
|
||||
if(psV1->type == VAL_FLOAT && psV2->type == VAL_FLOAT){
|
||||
psV1->v.bval = psV1->v.fval != psV2->v.fval;
|
||||
}else if(psV1->type == VAL_STRING && psV2->type == VAL_STRING){
|
||||
psV1->v.bval = (strcasecmp(psV1->v.sval,psV2->v.sval) != 0); /* case-insensitive */
|
||||
}else{
|
||||
psV1->v.bval = psV1->v.ival != psV2->v.ival;
|
||||
}
|
||||
|
@ -754,10 +777,15 @@ BOOL stackUnaryOp(OPCODE opcode)
|
|||
switch (psVal->type)
|
||||
{
|
||||
case (VAL_REF | VAL_INT):
|
||||
*((SDWORD *)psVal->v.oval) = *((SDWORD *)psVal->v.oval) + 1;
|
||||
|
||||
psVal = psVal->v.oval; //get variable
|
||||
|
||||
ASSERT(psVal->type == VAL_INT, "Invalid type for increment opcode: %d", psVal->type);
|
||||
|
||||
psVal->v.ival++;
|
||||
|
||||
/* Just get rid of the variable pointer, since already increased it */
|
||||
if (!stackPop(psVal))
|
||||
if (!stackRemoveTop())
|
||||
{
|
||||
debug( LOG_ERROR, "stackUnaryOpcode: OP_INC: could not pop" );
|
||||
return FALSE;
|
||||
|
@ -774,10 +802,15 @@ BOOL stackUnaryOp(OPCODE opcode)
|
|||
switch (psVal->type)
|
||||
{
|
||||
case (VAL_REF | VAL_INT):
|
||||
*((SDWORD *)psVal->v.oval) = *((SDWORD *)psVal->v.oval) - 1;
|
||||
|
||||
psVal = psVal->v.oval; //get variable
|
||||
|
||||
ASSERT(psVal->type == VAL_INT, "Invalid type for decrement opcode: %d", psVal->type);
|
||||
|
||||
psVal->v.ival--;
|
||||
|
||||
/* Just get rid of the variable pointer, since already decreased it */
|
||||
if (!stackPop(psVal))
|
||||
if (!stackRemoveTop())
|
||||
{
|
||||
debug( LOG_ERROR, "stackUnaryOpcode: OP_DEC: could not pop" );
|
||||
return FALSE;
|
||||
|
@ -971,6 +1004,31 @@ void stackShutDown(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get rid of the top value without returning it */
|
||||
static inline BOOL stackRemoveTop(void)
|
||||
{
|
||||
if ((psCurrChunk->psPrev == NULL) && (currEntry == 0))
|
||||
{
|
||||
debug(LOG_ERROR, "stackRemoveTop: stack empty");
|
||||
ASSERT( FALSE, "stackRemoveTop: stack empty" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* move the stack pointer down one */
|
||||
if (currEntry == 0)
|
||||
{
|
||||
/* have to move onto the previous chunk. */
|
||||
psCurrChunk = psCurrChunk->psPrev;
|
||||
currEntry = psCurrChunk->size -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
currEntry--;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the stack to an empty state */
|
||||
void stackReset(void)
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "aiexperience.h"
|
||||
#include "display3d.h" //for showRangeAtPos()
|
||||
#include "multimenu.h"
|
||||
#include "lib/script/chat_processing.h"
|
||||
|
||||
static INTERP_VAL scrFunctionResult; //function return value to be pushed to stack
|
||||
|
||||
|
@ -82,14 +83,11 @@ static INTERP_VAL scrFunctionResult; //function return value to be pushed to sta
|
|||
// If this is defined then check max number of units not reached before adding more.
|
||||
#define SCRIPT_CHECK_MAX_UNITS
|
||||
|
||||
SDWORD playerFlag[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
|
||||
char strParam1[MAXSTRLEN], strParam2[MAXSTRLEN]; //these should be used as string parameters for stackPopParams()
|
||||
static SDWORD playerFlag[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
|
||||
static char strParam1[MAXSTRLEN], strParam2[MAXSTRLEN]; //these should be used as string parameters for stackPopParams()
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
BOOL structHasModule(STRUCTURE *psStruct);
|
||||
SDWORD guessPlayerFromMessage(char **str);
|
||||
SDWORD getPlayerFromString(char *playerName);
|
||||
SDWORD getFirstWord(char *sText, char **sWord, SDWORD *readCount);
|
||||
|
||||
/******************************************************************************************/
|
||||
/* Check for objects in areas */
|
||||
|
@ -5054,14 +5052,14 @@ BOOL bVisible;
|
|||
// returns the nearest gateway bottleneck to a specified point
|
||||
BOOL scrGetNearestGateway( void )
|
||||
{
|
||||
SDWORD x,y;
|
||||
SDWORD gX,gY;
|
||||
UDWORD nearestSoFar;
|
||||
UDWORD dist;
|
||||
GATEWAY *psGateway;
|
||||
SDWORD retX,retY;
|
||||
SDWORD *rX,*rY;
|
||||
BOOL success;
|
||||
SDWORD x,y;
|
||||
SDWORD gX,gY;
|
||||
UDWORD nearestSoFar;
|
||||
UDWORD dist;
|
||||
GATEWAY *psGateway;
|
||||
SDWORD retX,retY;
|
||||
SDWORD *rX,*rY;
|
||||
BOOL success;
|
||||
|
||||
if(!stackPopParams(4, VAL_INT, &x, VAL_INT, &y, VAL_REF|VAL_INT, &rX, VAL_REF|VAL_INT, &rY))
|
||||
{
|
||||
|
@ -10166,12 +10164,9 @@ BOOL objectInRangeVis(BASE_OBJECT *psList, SDWORD x, SDWORD y, SDWORD range, SDW
|
|||
BOOL scrPursueResearch(void)
|
||||
{
|
||||
RESEARCH *psResearch;
|
||||
SDWORD player;
|
||||
UWORD cur,index,tempIndex,foundIndex;
|
||||
SDWORD foundIndex,index,player,cur,tempIndex,Stack[400];
|
||||
SWORD top;
|
||||
|
||||
UWORD Stack[400];
|
||||
|
||||
BOOL found;
|
||||
PLAYER_RESEARCH *pPlayerRes;
|
||||
|
||||
|
@ -10430,56 +10425,6 @@ BOOL scrSetPlayerName(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SDWORD guessPlayerFromMessage(char **str)
|
||||
{
|
||||
SDWORD player,count=0;
|
||||
char *endOfPlayerList;
|
||||
char playerName[255];
|
||||
SDWORD storage=0;
|
||||
BOOL bOK=FALSE;
|
||||
|
||||
ASSERT(MAX_PLAYERS <= 8, "guessPlayerFromMessage: MAX_PLAYERS too high");
|
||||
|
||||
|
||||
endOfPlayerList = *str;
|
||||
player = 0;
|
||||
|
||||
debug(LOG_SCRIPT, "now checking string='%s'",*str);
|
||||
|
||||
while( sscanf(*str, "%[^',:;?! ]%*[,';?! ]%n", playerName, &count) //didn't reach the end //first field: what to stop on; second field: what to read (skip) afterwards
|
||||
&& player >= 0 //last string was a player name
|
||||
//&& *str < copyStr + strlen(copyStr)
|
||||
)
|
||||
{
|
||||
if(count==0) /* nothing read ? */
|
||||
break;
|
||||
|
||||
debug(LOG_SCRIPT, "playerName='%s' count=%d",playerName, count);
|
||||
|
||||
*str += count;
|
||||
player = getPlayerFromString(playerName);
|
||||
|
||||
debug(LOG_SCRIPT, "player=%d",player);
|
||||
|
||||
if(player >= 0 && player < MAX_PLAYERS)
|
||||
{
|
||||
bOK = TRUE;
|
||||
endOfPlayerList = *str; //remember where target player list ends
|
||||
storage = storage | playerFlag[player]; //set player flag
|
||||
debug(LOG_SCRIPT, "storage=%d",storage);
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT, " ");
|
||||
debug(LOG_SCRIPT, "now checking string = '%s'",*str);
|
||||
}
|
||||
|
||||
*str = endOfPlayerList; //skip player list
|
||||
|
||||
return storage; //Must be 0 if no players
|
||||
}
|
||||
|
||||
SDWORD getPlayerFromString(char *playerName)
|
||||
{
|
||||
UDWORD playerIndex;
|
||||
|
@ -10488,27 +10433,27 @@ SDWORD getPlayerFromString(char *playerName)
|
|||
for( playerIndex=0; playerIndex<MAX_PLAYERS; playerIndex++ )
|
||||
{
|
||||
/* check name */
|
||||
debug(LOG_SCRIPT, "checking (%s,%s)",getPlayerName(playerIndex), playerName);
|
||||
//debug(LOG_SCRIPT, "checking (%s,%s)",getPlayerName(playerIndex), playerName);
|
||||
if (strncasecmp(getPlayerName(playerIndex),playerName, 255) == 0)
|
||||
{
|
||||
debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
//debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
return playerIndex;
|
||||
}
|
||||
|
||||
/* check color */
|
||||
debug(LOG_SCRIPT, "checking (%s,%s)",getPlayerColourName(playerIndex), playerName);
|
||||
//debug(LOG_SCRIPT, "checking (%s,%s)",getPlayerColourName(playerIndex), playerName);
|
||||
if (strncasecmp(getPlayerColourName(playerIndex),playerName, 255) == 0)
|
||||
{
|
||||
debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
//debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
return playerIndex;
|
||||
}
|
||||
|
||||
/* check player number */
|
||||
sprintf(sPlayerNumber,"%d",playerIndex);
|
||||
debug(LOG_SCRIPT, "checking (%s,%s)",sPlayerNumber, playerName);
|
||||
//debug(LOG_SCRIPT, "checking (%s,%s)",sPlayerNumber, playerName);
|
||||
if (strncasecmp(sPlayerNumber,playerName, 255) == 0)
|
||||
{
|
||||
debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
//debug(LOG_SCRIPT, "matched, returning %d", playerIndex);
|
||||
return playerIndex;
|
||||
}
|
||||
|
||||
|
@ -10517,188 +10462,6 @@ SDWORD getPlayerFromString(char *playerName)
|
|||
return -1;
|
||||
}
|
||||
|
||||
BOOL scrGetTargetPlayers(void)
|
||||
{
|
||||
char *myMsg = NULL,*freeMsg = NULL;
|
||||
char **ssval = NULL;
|
||||
SDWORD players=0;
|
||||
|
||||
if (!stackPopParams(1, VAL_REF | VAL_STRING, &ssval))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetTargetPlayers(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(*ssval == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetTargetPlayers(): passed string was not initialized");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT, "scrGetTargetPlayers: ssval='%s'", *ssval);
|
||||
|
||||
myMsg = (char*)MALLOC(255);
|
||||
freeMsg = myMsg;
|
||||
|
||||
strcpy(myMsg,*ssval);
|
||||
|
||||
debug(LOG_SCRIPT, "scrGetTargetPlayers: myMsg='%s'", myMsg);
|
||||
|
||||
players = guessPlayerFromMessage(&myMsg);
|
||||
|
||||
debug(LOG_SCRIPT, "scrGetTargetPlayers: myMsg new='%s'", myMsg);
|
||||
|
||||
strcpy(*ssval, myMsg);
|
||||
|
||||
debug(LOG_SCRIPT, "scrGetTargetPlayers: ssval='%s'", *ssval);
|
||||
|
||||
scrFunctionResult.v.ival = players;
|
||||
if (!stackPushResult(VAL_INT, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetTargetPlayers(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FREE(freeMsg);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
BOOL scrMatch(void)
|
||||
{
|
||||
char *sToParse = NULL, *sToMatch = NULL;
|
||||
char *wordNeed = NULL, *wordFound = NULL;
|
||||
SDWORD readCountParse=0,readCountMatch=0;
|
||||
SDWORD fieldAssignedParse=0,fieldAssignedMatch=0;
|
||||
BOOL ok = TRUE;
|
||||
SDWORD *nResult;
|
||||
|
||||
if (!stackPopParams(3, VAL_STRING, &strParam1, VAL_STRING, &strParam2, VAL_REF|VAL_INT, &nResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrMatch(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(strParam1 == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "scrMatch(): message to parse is null");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(strParam2 == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "scrMatch(): string to match is null");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sToParse = strParam1;
|
||||
sToMatch = strParam2;
|
||||
|
||||
debug(LOG_SCRIPT, " ");
|
||||
debug(LOG_SCRIPT, "sOrigToParse='%s'", strParam1);
|
||||
debug(LOG_SCRIPT, "sOrigToMatch='%s'", strParam2);
|
||||
|
||||
wordFound = (char*)MALLOC(255);
|
||||
wordNeed = (char*)MALLOC(255);
|
||||
|
||||
*nResult = -1;
|
||||
|
||||
while(ok)
|
||||
{
|
||||
/* get next word */
|
||||
fieldAssignedParse = getFirstWord(sToParse,&wordFound,&readCountParse);
|
||||
sToParse = sToParse + readCountParse; /* next time start with next word */
|
||||
if(readCountParse == 0) /* sscanf returns 0 when last word is read */
|
||||
sToParse = sToParse + strlen(wordFound);
|
||||
|
||||
/* get next word */
|
||||
fieldAssignedMatch = getFirstWord(sToMatch,&wordNeed,&readCountMatch);
|
||||
sToMatch = sToMatch + readCountMatch; /* next time start with next word */
|
||||
if(readCountMatch == 0) /* sscanf returns 0 when last word is read */
|
||||
sToMatch = sToMatch + strlen(wordNeed);
|
||||
|
||||
debug(LOG_SCRIPT, "wordFound '%s'", wordFound);
|
||||
debug(LOG_SCRIPT, "wordNeed '%s'", wordNeed);
|
||||
|
||||
/* failed if *one* of the strings ended */
|
||||
if((fieldAssignedParse > 0 && fieldAssignedMatch <= 0)
|
||||
|| (fieldAssignedMatch > 0 && fieldAssignedParse <= 0))
|
||||
{
|
||||
debug(LOG_SCRIPT, "exit condition FAILED");
|
||||
ok = FALSE;
|
||||
break;
|
||||
}
|
||||
else if(fieldAssignedParse <= 0 && fieldAssignedMatch <= 0) /* no more words left in either of them */
|
||||
{
|
||||
debug(LOG_SCRIPT, "exit condition SUCCESS");
|
||||
ok = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* now compare both words
|
||||
*/
|
||||
|
||||
if (strncasecmp(wordNeed,"<player>", 255) == 0) /* if we are looking for player */
|
||||
{
|
||||
debug(LOG_SCRIPT, "matching <player>");
|
||||
*nResult = getPlayerFromString(wordFound);
|
||||
|
||||
if(*nResult == -1) /* failed to match player, stop */
|
||||
{
|
||||
debug(LOG_SCRIPT, "failed to match <player>");
|
||||
ok = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug(LOG_SCRIPT, "matched <player>");
|
||||
}
|
||||
}
|
||||
else if (strncasecmp(wordNeed,wordFound,255) != 0) /* just compare words to see if they match */
|
||||
{
|
||||
debug(LOG_SCRIPT, "words did not match");
|
||||
ok = FALSE;
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT, " ");
|
||||
}
|
||||
|
||||
debug(LOG_SCRIPT, "END");
|
||||
|
||||
FREE(wordFound);
|
||||
FREE(wordNeed);
|
||||
|
||||
scrFunctionResult.v.bval = ok;
|
||||
if (!stackPushResult(VAL_BOOL, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetTargetPlayers(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SDWORD getFirstWord(char *sText, char **sWord, SDWORD *readCount)
|
||||
{
|
||||
SDWORD count=0,fieldsAssigned=0;
|
||||
|
||||
debug(LOG_SCRIPT, "--getWord: now checking string='%s'",sText);
|
||||
|
||||
ASSERT(*sWord != NULL, "getFirstWord: sWord is NULL");
|
||||
|
||||
strcpy(*sWord,""); /* clear */
|
||||
|
||||
fieldsAssigned = sscanf(sText, "%[^',:;?! ]%*[,';?! ]%n", *sWord, &count);
|
||||
|
||||
debug(LOG_SCRIPT, "--getWord: matched='%s', count=%d, fieldsAssigned=%d",*sWord, count, fieldsAssigned);
|
||||
|
||||
*readCount = count;
|
||||
|
||||
return fieldsAssigned;
|
||||
}
|
||||
|
||||
|
||||
/* Checks if a particular bit is set in an integer */
|
||||
BOOL scrBitSet(void)
|
||||
{
|
||||
|
@ -10852,3 +10615,208 @@ BOOL scrSetDebugMenuEntry(void)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Parse chat message and return number of commands that could be extracted */
|
||||
BOOL scrProcessChatMsg(void)
|
||||
{
|
||||
if (!stackPopParams(1, VAL_STRING, &strParam1))
|
||||
{
|
||||
debug(LOG_ERROR, "scrProcessChatMsg(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug(LOG_WZ, "Now preparing to parse '%s'", strParam1);
|
||||
|
||||
if (!chatLoad(strParam1, strlen(strParam1)))
|
||||
{
|
||||
ASSERT("Couldn't process chat message: %s", strParam1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
scrFunctionResult.v.ival = chat_msg.numCommands;
|
||||
if (!stackPushResult(VAL_INT, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrProcessChatMsg(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Returns number of command arguments for a certain
|
||||
* chat command that could be extracted
|
||||
*/
|
||||
BOOL scrGetNumArgsInCmd(void)
|
||||
{
|
||||
SDWORD cmdIndex;
|
||||
|
||||
if (!stackPopParams(1, VAL_INT, &cmdIndex))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetNumArgsInCmd(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check command bounds */
|
||||
if(cmdIndex < 0 || cmdIndex >= chat_msg.numCommands)
|
||||
{
|
||||
ASSERT(FALSE, "scrGetNumArgsInCmd: command inxed out of bounds: %d (num commands: %d)",
|
||||
cmdIndex, chat_msg.numCommands);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
scrFunctionResult.v.ival = chat_msg.cmdData[cmdIndex].numCmdParams;
|
||||
if (!stackPushResult(VAL_INT, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetNumArgsInCmd(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Returns a string representing a certain chat command,
|
||||
* based on the command index provided
|
||||
*/
|
||||
BOOL scrGetChatCmdDescription(void)
|
||||
{
|
||||
SDWORD cmdIndex;
|
||||
char *pChatCommand=NULL;
|
||||
|
||||
if (!stackPopParams(1, VAL_INT, &cmdIndex))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetCommandDescription(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check command bounds */
|
||||
if(cmdIndex < 0 || cmdIndex >= chat_msg.numCommands)
|
||||
{
|
||||
ASSERT(FALSE, "scrGetCommandDescription: command inxed out of bounds: %d (num commands: %d)",
|
||||
cmdIndex, chat_msg.numCommands);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Allocate memory for the comamnd string */
|
||||
pChatCommand = (char*)MALLOC(MAXSTRLEN);
|
||||
|
||||
ASSERT(pChatCommand != NULL, "scrGetCommandDescription: out of memory");
|
||||
|
||||
/* Copy command */
|
||||
strcpy(pChatCommand, chat_msg.cmdData[cmdIndex].pCmdDescription);
|
||||
|
||||
/* Make scrFunctionResult point to the valid command */
|
||||
scrFunctionResult.v.sval = pChatCommand;
|
||||
|
||||
if (!stackPushResult(VAL_STRING, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetCommandDescription(): failed to push result");
|
||||
FREE(pChatCommand);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FREE(pChatCommand);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Returns a certain parameter of a certain chat command
|
||||
* Returns FALSE if failed
|
||||
*/
|
||||
BOOL scrGetChatCmdParam(void)
|
||||
{
|
||||
SDWORD cmdIndex, argIndex;
|
||||
void *pArgument=NULL;
|
||||
INTERP_TYPE argType=VAL_VOID;
|
||||
BOOL bSuccess=TRUE; //failure on type mismatch
|
||||
|
||||
//if (!stackPopParams(3, VAL_INT, &cmdIndex, VAL_INT, &argIndex, VAL_REF | VAL_VOID, &pArgument))
|
||||
//{
|
||||
// debug(LOG_ERROR, "scrGetChatCmdParam(): stack failed");
|
||||
// return FALSE;
|
||||
//}
|
||||
|
||||
if (!stackPopParams(2, VAL_INT, &cmdIndex, VAL_INT, &argIndex))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetChatCmdParam(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(cmdIndex < 0 || cmdIndex >= chat_msg.numCommands)
|
||||
{
|
||||
ASSERT(FALSE, "scrGetChatCmdParam: command index out of bounds: %d", cmdIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(argIndex < 0 || argIndex >= chat_msg.cmdData[cmdIndex].numCmdParams )
|
||||
{
|
||||
ASSERT(FALSE, "scrGetChatCmdParam: argument index for command %d is out of bounds: %d", cmdIndex, argIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Find out the type of the argument we are going to pass to the script */
|
||||
argType = chat_msg.cmdData[cmdIndex].parameter[argIndex].type;
|
||||
|
||||
if (!stackPopParams(1, VAL_REF | argType, &pArgument))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetChatCmdParam(): stack failed or argument mismatch (expected type of argument: %d)", argType);
|
||||
bSuccess = FALSE; //return type mismatch
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
if(pArgument == NULL)
|
||||
{
|
||||
ASSERT(FALSE, "scrGetChatCmdParam: nullpointer check failed");
|
||||
bSuccess = FALSE;
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
/* Return command argument to the script */
|
||||
if(bSuccess){
|
||||
memcpy(pArgument, &(chat_msg.cmdData[cmdIndex].parameter[argIndex].v), sizeof(chat_msg.cmdData[cmdIndex].parameter[argIndex].v));
|
||||
}
|
||||
|
||||
scrFunctionResult.v.bval = bSuccess;
|
||||
if (!stackPushResult(VAL_BOOL, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrGetChatCmdParam(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Returns true if a certain command was addressed to a certain player */
|
||||
BOOL scrChatCmdIsPlayerAddressed(void)
|
||||
{
|
||||
SDWORD cmdIndex,playerInQuestion;
|
||||
|
||||
if (!stackPopParams(2, VAL_INT, &cmdIndex, VAL_INT, &playerInQuestion))
|
||||
{
|
||||
debug(LOG_ERROR, "scrChatCmdIsPlayerAddressed(): stack failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check command bounds */
|
||||
if(cmdIndex < 0 || cmdIndex >= chat_msg.numCommands)
|
||||
{
|
||||
ASSERT(FALSE, "scrChatCmdIsPlayerAddressed: command inxed out of bounds: %d (num commands: %d)",
|
||||
cmdIndex, chat_msg.numCommands);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check player bounds */
|
||||
if(playerInQuestion < 0 || playerInQuestion >= MAX_PLAYERS)
|
||||
{
|
||||
ASSERT(FALSE, "scrChatCmdIsPlayerAddressed: player inxed out of bounds: %d", playerInQuestion);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
scrFunctionResult.v.bval = chat_msg.cmdData[cmdIndex].bPlayerAddressed[playerInQuestion];
|
||||
if (!stackPushResult(VAL_INT, &scrFunctionResult))
|
||||
{
|
||||
debug(LOG_ERROR, "scrChatCmdIsPlayerAddressed(): failed to push result");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -591,8 +591,6 @@ extern BOOL scrGetStructureType(void);
|
|||
extern BOOL scrGetPlayerName(void);
|
||||
extern BOOL scrSetPlayerName(void);
|
||||
|
||||
extern BOOL scrGetTargetPlayers(void);
|
||||
extern BOOL scrMatch(void);
|
||||
extern BOOL scrBitSet(void);
|
||||
extern BOOL scrAlliancesLocked(void);
|
||||
extern BOOL scrASSERT(void);
|
||||
|
@ -600,6 +598,11 @@ extern BOOL scrShowRangeAtPos(void);
|
|||
extern BOOL scrToPow(void);
|
||||
extern BOOL scrDebugMenu(void);
|
||||
extern BOOL scrSetDebugMenuEntry(void);
|
||||
extern BOOL scrProcessChatMsg(void);
|
||||
extern BOOL scrGetChatCmdDescription(void);
|
||||
extern BOOL scrGetNumArgsInCmd(void);
|
||||
extern BOOL scrGetChatCmdParam(void);
|
||||
extern BOOL scrChatCmdIsPlayerAddressed(void);
|
||||
|
||||
|
||||
extern BOOL beingResearchedByAlly(SDWORD resIndex, SDWORD player);
|
||||
|
@ -614,6 +617,8 @@ extern VIEWDATA *HelpViewData(SDWORD sender, char *textMsg, UDWORD LocX, UDWORD
|
|||
extern MESSAGE * findHelpMsg(UDWORD player, SDWORD sender);
|
||||
extern SDWORD getNumRepairedBy(DROID *psDroidToCheck, SDWORD player);
|
||||
extern BOOL objectInRangeVis(BASE_OBJECT *psList, SDWORD x, SDWORD y, SDWORD range, SDWORD lookingPlayer);
|
||||
|
||||
extern SDWORD getPlayerFromString(char *playerName);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "intfac.h"
|
||||
#include "multimenu.h"
|
||||
#include "lib/framework/input.h" //for key constants
|
||||
#include "lib/script/chat_processing.h"
|
||||
|
||||
|
||||
/* The table of user defined types
|
||||
|
@ -947,15 +948,6 @@ FUNC_SYMBOL asFuncTable[] =
|
|||
1, { VAL_STRING },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
|
||||
{ "getTargetPlayers", scrGetTargetPlayers, VAL_INT,
|
||||
1, { VAL_REF|VAL_STRING },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "match", scrMatch, VAL_BOOL,
|
||||
3, { VAL_STRING, VAL_STRING, VAL_REF|VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "bitSet", scrBitSet, VAL_BOOL,
|
||||
2, { VAL_INT, VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
@ -1316,12 +1308,29 @@ FUNC_SYMBOL asFuncTable[] =
|
|||
2, { VAL_STRING, VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
//scripting engine chat interface functions
|
||||
{ "processChatMsg", scrProcessChatMsg, VAL_INT,
|
||||
1, { VAL_STRING },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "getChatCmdDescription", scrGetChatCmdDescription, VAL_STRING,
|
||||
1, { VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "getNumArgsInCmd", scrGetNumArgsInCmd, VAL_INT,
|
||||
1, { VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "getChatCmdParam", scrGetChatCmdParam, VAL_BOOL,
|
||||
3, { VAL_REF | VAL_VOID, VAL_INT, VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
{ "chatCmdIsPlayerAddressed", scrChatCmdIsPlayerAddressed, VAL_BOOL,
|
||||
2, { VAL_INT, VAL_INT },
|
||||
0, 0, NULL, 0, 0, NULL, NULL },
|
||||
|
||||
/* END new functions */
|
||||
|
||||
|
||||
// { "skOrderDroidLineBuild", scrSkOrderDroidLineBuild, VAL_VOID,
|
||||
// 6, { (INTERP_TYPE)ST_DROID, (INTERP_TYPE)ST_STRUCTURESTAT, VAL_INT, VAL_INT, VAL_INT, VAL_INT } },
|
||||
|
||||
/* This final entry marks the end of the function list */
|
||||
{ "FUNCTION LIST END", NULL, VAL_VOID, 0, { VAL_VOID }, 0, 0, NULL, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
@ -2155,6 +2164,10 @@ BOOL scrTabInitialise(void)
|
|||
for(i=0; i<DEBUGMENU_MAX_ENTRIES; i++)
|
||||
debugMenuEntry[i][0] = '\0';
|
||||
|
||||
/* Initialize chat message struct */
|
||||
chat_msg.numCommands = 0;
|
||||
strcpy(chat_msg.lastMessage, "");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -298,6 +298,14 @@
|
|||
RelativePath="..\src\cdspan.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\script\chat_lexer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\script\chat_parser.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\cheat.c"
|
||||
>
|
||||
|
@ -1130,6 +1138,14 @@
|
|||
RelativePath="..\src\cdspan.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\script\chat_parser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\script\chat_processing.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\cheat.h"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue