version 1.59 | | version 1.60 |
---|
| | |
/* | | /* |
* static char *rcsid_monster_c = | | * static char *rcsid_monster_c = |
* "$Id: monster.c,v 1.59 2003/01/08 08:39:20 mwedel Exp $"; | | * "$Id: monster.c,v 1.60 2003/01/27 07:34:34 mwedel Exp $"; |
*/ | | */ |
| | |
/* | | /* |
| | |
#include <skills.h> | | #include <skills.h> |
#endif | | #endif |
| | |
| | #if 0 |
/* | | /* |
* When parsing a message-struct, the msglang struct is used | | * When parsing a message-struct, the msglang struct is used |
* to contain the values. | | * to contain the values. |
| | |
char ***keywords; /* For each message, an array of strings to match */ | | char ***keywords; /* For each message, an array of strings to match */ |
} msglang; | | } msglang; |
| | |
| | #endif |
| | |
#define MIN_MON_RADIUS 3 /* minimum monster detection radius */ | | #define MIN_MON_RADIUS 3 /* minimum monster detection radius */ |
| | |
| | |
} | | } |
} | | } |
| | |
| | #if 0 |
static void free_messages(msglang *msgs) { | | static void free_messages(msglang *msgs) { |
int messages, keywords; | | int messages, keywords; |
| | |
| | |
} | | } |
} | | } |
| | |
| | #endif |
| | |
| | /* This replaces all the msglang stuff about which seems to be a lot of |
| | * unneeded complication - since the setup of that data is never re-used |
| | * (say 'hi' to monster, then 'yes', it would re-do the entire parse-message) |
| | * it seems to me to make more sense to just have simple function that returns |
| | * the 'text' portion of the message that it matches - this savees us a bunch |
| | * of malloc's and free's, as well as that setup. |
| | * This function takes the message to be parsed in 'msg', the text to |
| | * match in 'match', and returns the portion of the message. This |
| | * returned portion is in a malloc'd buf that should be freed. |
| | * Returns NULL if no match is found. |
| | */ |
| | static char *find_matching_message(char *msg, char *match) |
| | { |
| | char *cp=msg, *cp1, *cp2, regex[MAX_BUF], *cp3, gotmatch=0; |
| | |
| | while (1) { |
| | if (strncmp(cp, "@match ", 7)) { |
| | LOG(llevDebug,"find_matching_message: Invalid message %s", msg); |
| | return NULL; |
| | } |
| | else { |
| | /* Find the end of the line, and copy the regex portion into it */ |
| | cp2 = strchr(cp+7, '\n'); |
| | strncpy(regex, cp+7, (cp2 - cp -7 )); |
| | regex[cp2 - cp -7] = 0; |
| | |
| | /* Find the next match command */ |
| | cp1 = strstr(cp+6, "\n@match"); |
| | |
| | /* Got a match - handle * as special case - proper regex would be .*, |
| | * but lots of messages don't use that form. |
| | */ |
| | if (regex[0] == '*') gotmatch=1; |
| | else { |
| | char *pipe, *pnext=NULL; |
| | /* need to parse all the | seperators. Our re_cmp isn't |
| | * realy a fully blown regex parser. |
| | */ |
| | for (pipe=regex; pipe != NULL; pipe = pnext) { |
| | pnext = strchr(pipe, '|'); |
| | if (pnext) { |
| | *pnext = 0; |
| | pnext ++; |
| | } |
| | if (re_cmp(match, pipe)) { |
| | gotmatch = 1; |
| | break; |
| | } |
| | } |
| | } |
| | if (gotmatch) { |
| | if (cp1) { |
| | cp3 = malloc(cp1 - cp2 + 1); |
| | strncpy(cp3, cp2+1, cp1 - cp2); |
| | cp3[cp1 - cp2] = 0; |
| | } |
| | else { /* if no next match, just want the rest of the string */ |
| | cp3 = strdup_local(cp2 + 1); |
| | } |
| | return cp3; |
| | } |
| | if (cp1) cp = cp1 + 1; |
| | else return NULL; |
| | } |
| | } |
| | /* Should never get reached */ |
| | } |
| | |
| | /* This function looks for an object or creature that is listening. |
| | * I've disabled the bit that has only the first npc monster listen - |
| | * we'll see how this works out. only the first npc listens, which |
| | * is sort of bogus since it uses the free_arr which has a preference |
| | * to certain directions. |
| | */ |
void communicate(object *op, char *txt) { | | void communicate(object *op, char *txt) { |
object *npc; | | object *npc; |
int i; | | int i; |
| | sint16 x, y; |
| | mapstruct *mp; |
| | |
int flag=1; /*hasn't spoken to a NPC yet*/ | | int flag=1; /*hasn't spoken to a NPC yet*/ |
for(i = 0; i <= SIZEOFFREE2; i++) | | for(i = 0; i <= SIZEOFFREE2; i++) { |
if (!out_of_map(op->map, op->x+freearr_x[i], op->y+freearr_y[i])) | | mp = op->map; |
for(npc = get_map_ob(op->map,op->x+freearr_x[i],op->y+freearr_y[i]); | | x = op->x + freearr_x[i]; |
npc != NULL; npc = npc->above) { | | y = op->y + freearr_y[i]; |
| | |
| | if (get_map_flags(mp, &mp, x, y, &x, &y) & P_OUT_OF_MAP) continue; |
| | |
| | for(npc = get_map_ob(mp,x,y); npc != NULL; npc = npc->above) { |
if (npc->type == MAGIC_EAR) | | if (npc->type == MAGIC_EAR) |
(void) talk_to_wall(npc, txt); /* Maybe exit after 1. success? */ | | (void) talk_to_wall(npc, txt); /* Maybe exit after 1. success? */ |
else if(flag) { | | else if(flag && npc->msg) { |
| | #if 0 |
if (talk_to_npc(op, npc,txt)) | | if (talk_to_npc(op, npc,txt)) |
flag=0; /* Can be crowded */ | | flag=0; /* Can be crowded */ |
| | #else |
| | talk_to_npc(op, npc,txt); |
| | #endif |
| | } |
} | | } |
} | | } |
} | | } |
| | |
int talk_to_npc(object *op, object *npc, char *txt) { | | int talk_to_npc(object *op, object *npc, char *txt) { |
msglang *msgs; | | |
int i,j; | | |
object *cobj; | | object *cobj; |
/* GROS: Handle for plugin say event */ | | |
if(npc->event_hook[EVENT_SAY] != NULL) | | |
{ | | |
CFParm CFP; | | CFParm CFP; |
int k, l, m; | | int k, l, m; |
| | char *cp, buf[MAX_BUF]; |
| | |
| | /* Move this commone area up here - shouldn't cost much extra cpu |
| | * time, and makes the function more readable */ |
k = EVENT_SAY; | | k = EVENT_SAY; |
l = SCRIPT_FIX_ALL; | | l = SCRIPT_FIX_ALL; |
m = 0; | | m = 0; |
CFP.Value[0] = &k; | | CFP.Value[0] = &k; |
CFP.Value[1] = op; | | CFP.Value[1] = op; |
CFP.Value[2] = npc; | | |
CFP.Value[3] = NULL; | | |
CFP.Value[4] = txt; | | CFP.Value[4] = txt; |
CFP.Value[5] = &m; | | CFP.Value[5] = &m; |
CFP.Value[6] = &m; | | CFP.Value[6] = &m; |
CFP.Value[7] = &m; | | CFP.Value[7] = &m; |
CFP.Value[8] = &l; | | CFP.Value[8] = &l; |
| | |
| | /* GROS: Handle for plugin say event */ |
| | if(npc->event_hook[EVENT_SAY] != NULL) |
| | { |
| | CFP.Value[2] = npc; |
| | CFP.Value[3] = NULL; |
CFP.Value[9] = npc->event_hook[k]; | | CFP.Value[9] = npc->event_hook[k]; |
CFP.Value[10]= npc->event_options[k]; | | CFP.Value[10]= npc->event_options[k]; |
if (findPlugin(npc->event_plugin[k])>=0) | | if (findPlugin(npc->event_plugin[k])>=0) |
| | |
} | | } |
/* GROS - Here we let the objects inside inventories hear and answer, too. */ | | /* GROS - Here we let the objects inside inventories hear and answer, too. */ |
/* This allows the existence of "intelligent" weapons you can discuss with */ | | /* This allows the existence of "intelligent" weapons you can discuss with */ |
for(cobj=npc->inv;cobj!=NULL;) | | for(cobj=npc->inv;cobj!=NULL; cobj = cobj->below) |
{ | | { |
if(cobj->event_hook[EVENT_SAY] != NULL) | | if(cobj->event_hook[EVENT_SAY] != NULL) |
{ | | { |
CFParm CFP; | | |
int k, l, m; | | |
k = EVENT_SAY; | | |
l = SCRIPT_FIX_ALL; | | |
m = 0; | | |
CFP.Value[0] = &k; | | |
CFP.Value[1] = op; | | |
CFP.Value[2] = cobj; | | CFP.Value[2] = cobj; |
CFP.Value[3] = npc; | | CFP.Value[3] = npc; |
CFP.Value[4] = txt; | | |
CFP.Value[5] = &m; | | |
CFP.Value[6] = &m; | | |
CFP.Value[7] = &m; | | |
CFP.Value[8] = &l; | | |
CFP.Value[9] = cobj->event_hook[k]; | | CFP.Value[9] = cobj->event_hook[k]; |
CFP.Value[10]= cobj->event_options[k]; | | CFP.Value[10]= cobj->event_options[k]; |
if (findPlugin(cobj->event_plugin[k])>=0) | | if (findPlugin(cobj->event_plugin[k])>=0) |
| | |
return 0; | | return 0; |
} | | } |
} | | } |
cobj = cobj->below; | | |
} | | } |
| | |
/* GROS: Then we parse the target inventory */ | | |
/*if (npc!=NULL) | | |
for(cobj=npc->inv;cobj!=NULL;cobj=cobj->next) | | |
{ | | |
printf("Name is %s\n", cobj->name); | | |
if(npc->event_hook[EVENT_SAY] != NULL) | | |
{ | | |
CFParm CFP; | | |
int k, l, m; | | |
k = EVENT_SAY; | | |
l = SCRIPT_FIX_ALL; | | |
m = 0; | | |
CFP.Value[0] = &k; | | |
CFP.Value[1] = op; | | |
CFP.Value[2] = cobj; | | |
CFP.Value[3] = NULL; | | |
CFP.Value[4] = txt; | | |
CFP.Value[5] = &m; | | |
CFP.Value[6] = &m; | | |
CFP.Value[7] = &m; | | |
CFP.Value[8] = &l; | | |
CFP.Value[9] = cobj->event_hook[k]; | | |
CFP.Value[10]= cobj->event_options[k]; | | |
if (findPlugin(cobj->event_plugin[k])>=0) | | |
{ | | |
((PlugList[findPlugin(cobj->event_plugin[k])].eventfunc) (&CFP)); | | |
return 0; | | |
} | | |
} | | |
}*/ | | |
if(npc->msg == NULL || *npc->msg != '@') | | if(npc->msg == NULL || *npc->msg != '@') |
return 0; | | return 0; |
if((msgs = parse_message(npc->msg)) == NULL) | | |
return 0; | | cp = find_matching_message(npc->msg, txt); |
#if 0 /* Turn this on again when enhancing parse_message() */ | | if (cp) { |
if(debug) | | sprintf(buf,"%s says:",query_name(npc)); |
dump_messages(msgs); | | |
#endif | | |
for(i=0; msgs->messages[i]; i++) | | |
for(j=0; msgs->keywords[i][j]; j++) | | |
if(msgs->keywords[i][j][0] == '*' || re_cmp(txt,msgs->keywords[i][j])) { | | |
char buf[MAX_BUF]; | | |
sprintf(buf,"%s says:",query_name(npc)); /* We want more unique NPCS */ | | |
/* "The <unique name> says ...." looks bad */ | | |
new_info_map(NDI_NAVY|NDI_UNIQUE, npc->map,buf); | | new_info_map(NDI_NAVY|NDI_UNIQUE, npc->map,buf); |
new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map, msgs->messages[i]); | | new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map, cp); |
free_messages(msgs); | | free(cp); |
return 1; | | return 1; |
} | | } |
free_messages(msgs); | | |
return 0; | | return 0; |
} | | } |
| | |
int talk_to_wall(object *npc, char *txt) { | | int talk_to_wall(object *npc, char *txt) { |
msglang *msgs; | | char *cp; |
int i,j; | | |
| | |
if(npc->msg == NULL || *npc->msg != '@') | | if(npc->msg == NULL || *npc->msg != '@') |
return 0; | | return 0; |
if((msgs = parse_message(npc->msg)) == NULL) | | |
| | cp = find_matching_message(npc->msg, txt); |
| | if (!cp) |
return 0; | | return 0; |
if(settings.debug >= llevDebug) | | |
dump_messages(msgs); | | new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map,cp); |
for(i=0; msgs->messages[i]; i++) | | |
for(j=0; msgs->keywords[i][j]; j++) | | |
if(msgs->keywords[i][j][0] == '*' || re_cmp(txt,msgs->keywords[i][j])) { | | |
if (msgs->messages[i] && *msgs->messages[i] != 0) | | |
new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map,msgs->messages[i]); | | |
free_messages(msgs); | | |
use_trigger(npc); | | use_trigger(npc); |
| | free(cp); |
return 1; | | return 1; |
} | | } |
free_messages(msgs); | | |
return 0; | | |
} | | |
| | |
/* find_mon_throw_ob() - modeled on find_throw_ob | | /* find_mon_throw_ob() - modeled on find_throw_ob |
* This is probably overly simplistic as it is now - We want | | * This is probably overly simplistic as it is now - We want |