ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
(Generate patch)

Comparing deliantra/server/server/monster.C (file contents):
Revision 1.2 by root, Sat Aug 26 23:36:34 2006 UTC vs.
Revision 1.3 by root, Tue Aug 29 05:03:55 2006 UTC

1/* 1/*
2 * static char *rcsid_monster_c = 2 * static char *rcsid_monster_c =
3 * "$Id: monster.C,v 1.2 2006/08/26 23:36:34 root Exp $"; 3 * "$Id: monster.C,v 1.3 2006/08/29 05:03:55 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
1495 return; 1495 return;
1496 } 1496 }
1497 } 1497 }
1498} 1498}
1499 1499
1500/* This replaces all the msglang stuff about which seems to be a lot of
1501 * unneeded complication - since the setup of that data is never re-used
1502 * (say 'hi' to monster, then 'yes', it would re-do the entire parse-message)
1503 * it seems to me to make more sense to just have simple function that returns
1504 * the 'text' portion of the message that it matches - this savees us a bunch
1505 * of malloc's and free's, as well as that setup.
1506 * This function takes the message to be parsed in 'msg', the text to
1507 * match in 'match', and returns the portion of the message. This
1508 * returned portion is in a malloc'd buf that should be freed.
1509 * Returns NULL if no match is found.
1510 * The player is passed too, so that quest-related messages can be checked too.
1511 */
1512static char *find_matching_message(object* pl, const char *msg, const char *match)
1513{
1514 const char *cp=msg, *cp1, *cp2;
1515 char *cp3, regex[MAX_BUF], gotmatch=0;
1516
1517 while (1) {
1518 if (strncmp(cp, "@match ", 7)) {
1519 LOG(llevDebug,"find_matching_message: Invalid message %s", msg);
1520 return NULL;
1521 }
1522 else {
1523 /* Find the end of the line, and copy the regex portion into it */
1524 cp2 = strchr(cp+7, '\n');
1525 strncpy(regex, cp+7, (cp2 - cp -7 ));
1526 regex[cp2 - cp -7] = 0;
1527
1528 /* Find the next match command */
1529 cp1 = strstr(cp+6, "\n@match");
1530
1531 /* Got a match - handle * as special case - proper regex would be .*,
1532 * but lots of messages don't use that form.
1533 */
1534 if (regex[0] == '*') gotmatch=1;
1535 else {
1536 char *pipe, *pnext=NULL;
1537 /* need to parse all the | seperators. Our re_cmp isn't
1538 * realy a fully blown regex parser.
1539 */
1540 for (pipe=regex; pipe != NULL; pipe = pnext) {
1541 pnext = strchr(pipe, '|');
1542 if (pnext) {
1543 *pnext = 0;
1544 pnext ++;
1545 }
1546 if (re_cmp(match, pipe)) {
1547 gotmatch = 1;
1548 break;
1549 }
1550 }
1551 }
1552 if (gotmatch) {
1553 if (cp1) {
1554 cp3 = (char*) malloc(cp1 - cp2 + 1);
1555 strncpy(cp3, cp2+1, cp1 - cp2);
1556 cp3[cp1 - cp2] = 0;
1557 }
1558 else { /* if no next match, just want the rest of the string */
1559 cp3 = strdup_local(cp2+1);
1560 }
1561 return cp3;
1562 }
1563 gotmatch = 0;
1564 if (cp1) cp = cp1 + 1;
1565 else return NULL;
1566 }
1567 }
1568 /* Should never get reached */
1569}
1570
1571/* This function looks for an object or creature that is listening.
1572 * I've disabled the bit that has only the first npc monster listen -
1573 * we'll see how this works out. only the first npc listens, which
1574 * is sort of bogus since it uses the free_arr which has a preference
1575 * to certain directions.
1576 *
1577 * There is a rare even that the orig_map is used for - basically, if
1578 * a player says the magic word that gets him teleported off the map,
1579 * it can result in the new map putting the object count too high,
1580 * which forces the swap out of some other map. In some cases, the
1581 * map the player was just on now gets swapped out - thus, the
1582 * object on that map are no longer in memory. So check to see if the
1583 * players map changes, and if so, don't process any further.
1584 * If it does change, most likely we don't care about the results
1585 * of further conversation. Also, depending on the value of i,
1586 * the conversation would continue on the new map, which probably isn't
1587 * what is really wanted either.
1588 */
1589void communicate(object *op, const char *txt) {
1590 object *npc;
1591 int i, mflags;
1592 sint16 x, y;
1593 mapstruct *mp, *orig_map = op->map;
1594
1595 int flag=1; /*hasn't spoken to a NPC yet*/
1596 for(i = 0; i <= SIZEOFFREE2; i++) {
1597
1598 mp = op->map;
1599 x = op->x + freearr_x[i];
1600 y = op->y + freearr_y[i];
1601
1602 mflags = get_map_flags(mp, &mp, x, y, &x, &y);
1603 if (mflags & P_OUT_OF_MAP) continue;
1604
1605 for(npc = get_map_ob(mp,x,y); npc != NULL; npc = npc->above) {
1606 if (npc->type == MAGIC_EAR) {
1607 (void) talk_to_wall(op, npc, txt); /* Maybe exit after 1. success? */
1608 if (orig_map != op->map) {
1609 LOG(llevDebug,"Warning: Forced to swap out very recent map - MAX_OBJECTS should probably be increased\n");
1610 return;
1611 }
1612 }
1613 else if (flag) {
1614#if 0
1615 if (talk_to_npc(op, npc,txt))
1616 flag=0; /* Can be crowded */
1617#else
1618 talk_to_npc(op, npc,txt);
1619#endif
1620 if (orig_map != op->map) {
1621 LOG(llevDebug,"Warning: Forced to swap out very recent map - MAX_OBJECTS should probably be increased\n");
1622 return;
1623 }
1624 }
1625 }
1626 }
1627}
1628
1629static int do_talk_npc(object* op, object* npc, object* override, const char* txt)
1630{
1631 char* cp;
1632 char buf[MAX_BUF];
1633
1634 if(override->msg == NULL || *override->msg != '@')
1635 return 0;
1636
1637 cp = find_matching_message(op, override->msg, txt);
1638 if (cp) {
1639 sprintf(buf,"%s says:",query_name(npc));
1640 new_info_map(NDI_NAVY|NDI_UNIQUE, npc->map,buf);
1641 new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map, cp);
1642 quest_apply_items(override,op->contr);
1643 free(cp);
1644 return 1;
1645 }
1646 return 0;
1647}
1648
1649int talk_to_npc(object *op, object *npc, const char *txt) {
1650 object *cobj;
1651
1652 /* Move this commone area up here - shouldn't cost much extra cpu
1653 * time, and makes the function more readable */
1654 /* Lauwenmark: Handle for plugin say event */
1655 if (op==npc) return 0;
1656 if (execute_event(npc, EVENT_SAY,op,NULL,txt,SCRIPT_FIX_ALL)!=0)
1657 return 0;
1658 /* Lauwenmark - Here we let the objects inside inventories hear and answer, too. */
1659 /* This allows the existence of "intelligent" weapons you can discuss with */
1660 for(cobj=npc->inv;cobj!=NULL; cobj = cobj->below)
1661 {
1662 if (execute_event(cobj, EVENT_SAY,op,NULL,txt,SCRIPT_FIX_ALL)!=0)
1663 return 0;
1664 }
1665 for ( cobj = npc->inv; cobj; cobj = cobj->below )
1666 if ( quest_is_override_compatible( cobj, op ) )
1667 if ( do_talk_npc( op, npc, cobj, txt ) )
1668 return 1;
1669 return do_talk_npc( op, npc, npc, txt );
1670}
1671
1672static int do_talk_wall(object* pl, object* npc, object* override, const char* txt)
1673{
1674 char* cp;
1675 if(override->msg == NULL || *override->msg != '@')
1676 return 0;
1677
1678 cp = find_matching_message(pl, override->msg, txt);
1679 if (!cp)
1680 return 0;
1681
1682 new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map,cp);
1683 use_trigger(npc);
1684 quest_apply_items(npc, pl->contr);
1685 free(cp);
1686
1687 return 1;
1688}
1689
1690int talk_to_wall(object* pl, object *npc, const char *txt) {
1691
1692 object* inv;
1693
1694 for ( inv = npc->inv; inv; inv = inv->below)
1695 if ( quest_is_override_compatible(inv, pl ) )
1696 if ( do_talk_wall( pl, npc, inv, txt ) )
1697 return 1;
1698
1699 return do_talk_wall( pl, npc, npc, txt );;
1700}
1701
1702/* find_mon_throw_ob() - modeled on find_throw_ob 1500/* find_mon_throw_ob() - modeled on find_throw_ob
1703 * This is probably overly simplistic as it is now - We want 1501 * This is probably overly simplistic as it is now - We want
1704 * monsters to throw things like chairs and other pieces of 1502 * monsters to throw things like chairs and other pieces of
1705 * furniture, even if they are not good throwable objects. 1503 * furniture, even if they are not good throwable objects.
1706 * Probably better to have the monster throw a throwable object 1504 * Probably better to have the monster throw a throwable object

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines