Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web

Browse additional code for the DG Script System

In addition to new triggers and commands, there are other things that can be found for the system. New sub-variables for objects, rooms & character variables, more commands for the interpreter itself, as well as many other things.

Sub-Variables


It seems a little silly to have just charisma, so I added the ability to get ANY of the statistics. However, once you see the 2 lines of code needed for this code, you will realize that adding new ones is a snap. Here is a list of simple ones you can add:
Hitpoints/Max Hitpoints (also works for move and mana)
Weight
Height
Age

For objects try:
Cost
Weight

Here are a couple of more complex ones:

      else if (!str_cmp(field, "master"))
       if (!c->master)
        strcpy(str, "NULL");
       else
        sprintf(str, "%c%ld", UID_CHAR, GET_ID(c->master));

      else if (!str_cmp(field, "nextinroom"))
       if (!c->next_in_room)
        strcpy(str, "NULL");
       else
        sprintf(str, "%c%ld", UID_CHAR, GET_ID(c->next_in_room));

      else if (!str_cmp(field, "nextinworld"))
       if (!c->next)
        strcpy(str, "NULL");
       else
        sprintf(str, "%c%ld", UID_CHAR, GET_ID(c->next));

       /* Note, these will return a UID_VAR, like %actor% or
          %victim% */

      else if (!str_cmp(field, "hisher"))
        sprintf(str, "%s", HSHR(c));

      else if (!str_cmp(field, "heshe"))
        sprintf(str, "%s", HSSH(c));

      else if (!str_cmp(field, "himher"))
        sprintf(str, "%s", HMHR(c));


Other Commands


In this section, we have Chris Jacobson's While/Switch parser for the system. Here is his code and documentation (slightly re-written to be compatible with this version of the DG Script System...his is not quite the same)

Heres a REVISED "patch-by-hand" for DG scripts. Tested and all, works wonders!

Another note is that GET_TRIG_DEPTH is NO LONGER updated here, it is useless IMHO, and using BREAK would (excuse the unintended pun) break it anyways, because if used from nested loops, since it searches for "done" rather than "end", it doesn't search for "end"s inbetween.

NOTE: this changes the overall design of my original WHILE patch to end with DONE and not END, so unpatch your previous version (if you have one) before patching this one. This allows for CORRECTLY breaking from WHILE/SWITCH from within nested IFs, the way C works. I.e, you can do:

while (%x% < 5)
  eval x (%x% + 1)
  if (%x% == 2)
    if (yet something else again)
      break
    end
  end
done

The way these changes work in scripts:
while 
...
done

switch 
  case 
    ...
    break
  case 
  case 
    ...
    break
  default
    ...
done

"break" can be used to drop out the current "while" or "switch", or end the script if it isn't in a while/switch.

With while loops, if more than 30 loops occur, it will automatically cause a WAIT for 1 second. If more than 100 loops occur since the script has started executing /from the beginning/ (if it WAITs it will still remember how many loops), it will mudlog-warn the MUD.

- Chris Jacobson

PS. No credit needed, just dont go telling your builders you wrote this yerself :-P

-------------------------

*-> in dg_scripts.h:
* add the macro:
#define GET_TRIG_LOOPS(t)               ((t)->loops)

* in trig_data, add:
        int             loops;

* in cmdlist_element, add:
        struct cmdlist_element *original;

*-> dg_script.c
* add
/*
 * scans for a case/default instance
 * returns the line containg the correct case instance, or the last
 * line of the trigger if not found.
 */
struct cmdlist_element *find_case(trig_data *trig, struct cmdlist_element *cl,
                void *go, struct script_data *sc, int type, char *cond) {
  struct cmdlist_element *c;
  char *p;

  if (!(cl->next))
    return cl;

  for (c = cl->next; c->next; c = c->next) {
    for (p = c->cmd; *p && isspace(*p); p++);

    if (!strn_cmp("while ", p, 6) || !strn_cmp("switch", p, 6))
      c = find_done(c);
    else if (!strn_cmp("case ", p, 5)) {
      sprintf(buf, "(%s) == (%s)", cond, p + 5);
      if (process_if(buf, go, sc, trig, type)) {
        return c;
      }
    } else if (!strn_cmp("default", p, 7))
      return c;
    else if (!strn_cmp("done", p, 3))
      return c;
  }
  return c;
}


/*
 * scans for end of while/switch-blocks.
 * returns the line containg 'end', or the last
 * line of the trigger if not found.
 */
struct cmdlist_element *find_done(struct cmdlist_element *cl)
{
  struct cmdlist_element *c;
  char *p;

  if (!(cl->next))
    return cl;

  for (c = cl->next; c->next; c = c->next) {
    for (p = c->cmd; *p && isspace(*p); p++);

    if (!strn_cmp("while ", p, 6) || !strn_cmp("switch ", p, 7))
      c = find_done(c);
    else if (!strn_cmp("done", p, 3))
      return c;
  }
  return c;
}


*> script_driver:
* in the beginning, add these variables:
        struct cmdlist_element *temp;
        unsigned long loops = 0;

* replace:
        if (mode == TRIG_NEW)
                GET_TRIG_DEPTH(trig) = 1;
* with:
  if (mode == TRIG_NEW) {
    GET_TRIG_LOOPS(trig) = 0;
    GET_TRIG_DEPTH(trig) = 1;
  }

* replace "} else if (!strn_cmp("end", p, 3)) { ... }" with:
    } else if (!strn_cmp("while ", p, 6)) {
      temp = find_done(cl);
      if (process_if(p + 6, go, sc, trig, type)) {
        temp->original = cl;
      } else {
        cl = temp;
        loops = 0;
      }
    } else if (!strn_cmp("switch ", p, 7)) {
      cl = find_case(trig, cl, go, sc, type, p + 7);
    } else if (!strn_cmp("end", p, 3)) {
      GET_TRIG_DEPTH(trig)--;
    } else if (!strn_cmp("done", p, 4)) {
      if (cl->original && process_if(cl->original->cmd + 6, go, sc, trig, type)) {
        cl = cl->original;
        loops++;
        GET_TRIG_LOOPS(trig)++;
        if (loops == 30) {
          process_wait(go, trig, type, "wait 1", cl);
          depth--;
          return ret_val;
        }
        if (GET_TRIG_LOOPS(trig) == 100) {
          mudlogf(NRM, LVL_BUILDER, TRUE, "SCRIPTERR: Trigger VNum %d has
looped 100 times!!!", GET_TRIG_VNUM(trig));
        }
      }
    } else if (!strn_cmp("break", p, 5)) {
      cl = find_done(cl);
    } else if (!strn_cmp("case", p, 4)) {
      ;       // Do nothing, this allows multiple cases to a single instance
    }



Return to the Death's Gate Script page