/
Crimson2/alias/
Crimson2/area.tmp/
Crimson2/area.tmp/AnomalySpaceDock/
Crimson2/area.tmp/AnomalyStation/
Crimson2/area.tmp/AntHill/
Crimson2/area.tmp/ArcticTerrarium/
Crimson2/area.tmp/BuilderCity/
Crimson2/area.tmp/Dungeon/
Crimson2/area.tmp/MiningDock/
Crimson2/area.tmp/PipeSystem/
Crimson2/area.tmp/RattArea/
Crimson2/area.tmp/RobotFactory/
Crimson2/area.tmp/SilverDale/
Crimson2/area.tmp/StarshipFearless/
Crimson2/area.tmp/StationConduits/
Crimson2/area.tmp/TerrariumAlpha/
Crimson2/area.tmp/TerrariumBeta/
Crimson2/area.tmp/TestArea/
Crimson2/area.tmp/Void/
Crimson2/area/
Crimson2/area/AnomalySpaceDock/
Crimson2/area/AnomalyStation/
Crimson2/area/MiningDock/
Crimson2/area/PipeSystem/
Crimson2/area/SilverDale/
Crimson2/area/StationConduits/
Crimson2/area/Void/
Crimson2/board/
Crimson2/clone/
Crimson2/lib/
Crimson2/mole/
Crimson2/mole/mole_src/HELP/
Crimson2/player/
Crimson2/util/
Crimson2/wldedit/
Crimson2/wldedit/res/
/* Crimson2 Mud Server
 * All source written/copyright Ryan Haksi 1995 *
 * This source code is proprietary. Use in whole or in part without
 * explicity permission by the author is strictly prohibited
 *
 * Current email address(es): cryogen@infoserve.net
 * Phone number: (604) 591-5295
 *
 * C4 Script Language written/copyright Cam Lesiuk 1995
 * Email: clesiuk@engr.uvic.ca
 */

/*****************************************************************
 *                                                               *
 *                                                               *
 *                     M O B    S T U F F                        *
 *                                                               *
 *                                                               *
 *****************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "crimson2.h"
#include "macro.h"
#include "mem.h"
#include "queue.h"
#include "log.h"
#include "str.h"
#include "ini.h"
#include "extra.h"
#include "property.h"
#include "code.h"
#include "file.h"
#include "thing.h"
#include "reset.h"
#include "exit.h"
#include "index.h"
#include "world.h"
#include "area.h"
#include "edit.h"
#include "history.h"
#include "socket.h"
#include "send.h"
#include "base.h"
#include "char.h"
#include "affect.h"
#include "mobile.h"
#include "player.h"
#include "parse.h"
#include "cmd_wld.h"
#include "cmd_mob.h"


MOBTEMPLATE *MobGetMobile(THING *thing, BYTE **cmd) {
  MOBTEMPLATE *mobile = NULL;
  LWORD        virtual = -1;

  sscanf(*cmd, " %ld", &virtual);
  if (virtual>=0) {
    *cmd = StrOneWord(*cmd, NULL);
    mobile = MobileOf(virtual);
    if (!mobile) {
      SendThing("Sorry, no MOBILE with that virtual number exists\n", thing);
      return NULL;
    }
  } 

  return mobile;
}


CMDPROC(CmdMStat) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         buf[512];
  BYTE         truncateStr[256];
  EXTRA       *extra;
  PROPERTY    *property;

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* show them the stats on the WORLD */
  /* first line, # Name & Type */
  sprintf(buf, "^g#:^G[^w%ld^G] ^gOnline^G[^c%ld^G] ^gName:^G[^c", mobile->mVirtual, mobile->mOnline);
  SendThing(buf, thing);
  SendThing(mobile->mSDesc->sText, thing);
  SendThing("^G]\n^gKeywords:^G[^c", thing);
  SendThing(mobile->mKey->sText, thing);
  SendThing("^G]\n^gLDesc:\n^c", thing);
  SendThing(mobile->mLDesc->sText, thing);
  SendThing("\n^gDescription:^b\n", thing);
  SendThing(mobile->mDesc->sText, thing);

  /* 2nd line - flags */
  SendThing("^gAct: ^G[^c", thing);
  SendThing(FlagSprintf(buf, mobile->mAct, mActList, ' ', 512), thing);
  SendThing("^G]\n", thing);
  SendThing("^gAffect: ^G[^c", thing);
  SendThing(FlagSprintf(buf, mobile->mAffect, affectList, ' ', 512), thing);
  SendThing("^G]\n", thing);

  sprintf(buf, "^gAura:^G[^c%hd^G] ", mobile->mAura);
  SendThing(buf, thing);
  sprintf(buf, "^gLevel:^G[^c%hd^G] ", mobile->mLevel);
  SendThing(buf, thing);
  sprintf(buf, "^gHitBonus:^G[^c%hd^G] ", mobile->mHitBonus);
  SendThing(buf, thing);
  sprintf(buf, "^gArmor:^G[^c%hd^G] ", mobile->mArmor);
  SendThing(buf, thing);
  sprintf(buf, "^gHP:^G[^c%hd^gD^c%hd+%hd^G] ", mobile->mHPDiceNum, mobile->mHPDiceSize, mobile->mHPBonus);
  SendThing(buf, thing);
  sprintf(buf, "^gDamage:^G[^c%hd^gD^c%hd+%hd^G]\n", mobile->mDamDiceNum, mobile->mDamDiceSize, mobile->mDamBonus);
  SendThing(buf, thing);

  sprintf(buf, "^gMoney:^G[^c%ld^G] ", mobile->mMoney);
  SendThing(buf, thing);
  sprintf(buf, "^gExp:^G[^c%ld^G] ", mobile->mExp);
  SendThing(buf, thing);
  SendThing("^gPos:^G[^c", thing);
  SendThing(TYPESPRINTF(buf, mobile->mPos, posList, 512), thing);
  SendThing("^G] ^gType:^G[^c", thing);
  SendThing(TYPESPRINTF(buf, mobile->mType, mTypeList, 512), thing);
  SendThing("^G] ^gSex:^G[^c", thing);
  SendThing(TYPESPRINTF(buf, mobile->mSex, sexList, 512), thing);
  SendThing("^G]\n", thing);

#ifdef BLAH
  /* Show Resists */
  SendThing("\nResistances:\n", thing);
  sprintf(buf, 
          "^gPuncture  [^c%3hd^G]",
          CharGetResist(thing, FD_PUNCTURE));
  SendThing(buf, thing);
  sprintf(buf, 
          "            ^gSlash [^c%3hd^G]",
          CharGetResist(thing, FD_SLASH));
  SendThing(buf, thing);
  sprintf(buf, 
          "               ^gConcussive[^c%3hd^G]\n",
          CharGetResist(thing, FD_CONCUSSIVE));
  SendThing(buf, thing);
  sprintf(buf, 
          "^gHeat      [^c%3hd^G]",
          CharGetResist(thing, FD_HEAT));
  SendThing(buf, thing);
  sprintf(buf, 
          "            ^gEMR   [^c%3hd^G]",
          CharGetResist(thing, FD_EMR));
  SendThing(buf, thing);
  sprintf(buf, 
          "               ^gLaser     [^c%3hd^G]\n",
          CharGetResist(thing, FD_LASER));
  SendThing(buf, thing);
  sprintf(buf, 
          "^gPsychic   [^c%3hd^G]",
          CharGetResist(thing, FD_PSYCHIC));
  SendThing(buf, thing);
  sprintf(buf, 
          "            ^gAcid  [^c%3hd^G]",
          CharGetResist(thing, FD_ACID));
  SendThing(buf, thing);
  sprintf(buf, 
          "               ^gPoison    [^c%3hd^G]\n",
          CharGetResist(thing, FD_POISON));
  SendThing(buf, thing);
#endif

  for (extra = mobile->mExtra; extra; extra=extra->eNext) {
    sprintf(buf,
            "^gExtra: ^c%-31s = ",
            StrTruncate(truncateStr,extra->eKey->sText,  30));
    SendThing(buf, thing);
    StrTruncate(truncateStr,extra->eDesc->sText, 30);
    StrOneLine(truncateStr);
    sprintf(buf, "%s\n", truncateStr);
    SendThing(buf, thing);
  }
  for (property = mobile->mProperty; property; property=property->pNext) {
    sprintf(buf,
            "^gProp.: ^c%-31s = ",
            StrTruncate(truncateStr,property->pKey->sText,  30));
    SendThing(buf, thing);
    StrTruncate(truncateStr,property->pDesc->sText, 30);
    StrOneLine(truncateStr);
    sprintf(buf, "%s\n", truncateStr);
    SendThing(buf, thing);
  }
}

CMDPROC(CmdMList) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         truncateStr[256];
  BYTE         buf[256];
  LWORD        i;
  THING       *world;
  LWORD        area;

  world = WldGetWorld(thing, NULL);
  area = Wld(world)->wArea;

  /* List the rooms */
  for (i=0; i<areaList[area].aMobIndex.iNum; i++) {
    mobile = MobTemplate(areaList[area].aMobIndex.iThing[i]);
    sprintf(buf, "^w%5ld ^c%-19s", mobile->mVirtual, StrTruncate(truncateStr,mobile->mSDesc->sText, 19));
    SendThing(buf, thing);
    if (i%3 == 2) {
      SendThing("\n", thing);
    } else
      SendThing(" ", thing);
  }
  if (i%3)
    SendThing("\n", thing); /* last line allways gets a return */
  sprintf(buf, "^g%ld ^bMobile Templates listed.\n", i);
  SendThing(buf, thing);
}



CMDPROC(CmdMCreate) {
  WLD         *world;
  MOBTEMPLATE *mobile;
  LWORD        area;
  BYTE         buf[256];
  LWORD        i;
  INDEX       *index;

  cmd = StrOneWord(cmd, NULL);
  world = Wld(WldGetWorld(thing, &cmd));
  if (!world)
    return;
  area = world->wArea;
  if (areaList[area].aMobIndex.iNum == (areaList[area].aVirtualMax - areaList[area].aVirtualMin + 1)) {
    SendThing("^gBad news.... This Area is completely full of MobTemplates allready\n", thing);
    return;
  }

  MEMALLOC(mobile, MOBTEMPLATE, MOBILE_ALLOC_SIZE);
  memset( (void*)mobile, 0, sizeof(MOBTEMPLATE)); /* init to zeros */

  mobile->mKey         = STRCREATE("blank mobile");
  mobile->mSDesc       = STRCREATE("Type ^wMNAME^c to give this Mob a better name.");
  mobile->mLDesc       = STRCREATE("Type ^wMLDESC^c to give this Mob a better LDesc.");
  mobile->mDesc        = STRCREATE("Type ^wMDESC^c to give this Mob a better Description.\n");
  mobile->mLevel       = 1;
  mobile->mHPDiceNum   = 1;
  mobile->mHPDiceSize  = 4;
  mobile->mDamDiceNum  = 1;
  mobile->mDamDiceSize = 2;
  mobile->mPos         = POS_STANDING;
  mobile->mAct         = MACT_STAY_AREA;

  /* update total num of MobTemplates in the game */
  mobileNum++;

  /* give the MobTemplate the first available virtual number */
  mobile->mVirtual = areaList[area].aVirtualMin;
  index = &areaList[area].aMobIndex;
  i=0;
  while( (i<=index->iNum-1) && (mobile->mVirtual>=MobTemplate(index->iThing[i])->mVirtual) ){
    if (mobile->mVirtual==MobTemplate(index->iThing[i])->mVirtual)
      mobile->mVirtual++;
    else 
      i++;
  }
  /* insert it into index */
  IndexInsert(index, Thing(mobile), MobileCompareProc);

  BITSET(areaList[Wld(world)->wArea].aSystem, AS_MOBUNSAVED);
  sprintf(buf, "^bYou have just created MobTemplate #^g[%5ld]\n", mobile->mVirtual);
  SendThing(buf, thing);
}




CMDPROC(CmdMName) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* Edit the requisite string */
  SendHint("^;HINT: Names should not end on a blank line\n", thing);
  SendHint("^;HINT: The next thing you should do is use ^<MLDESC ^;to add a long description\n", thing);
  sprintf(strName, "Mobile #%ld - Name", mobile->mVirtual);
  EDITSTR(thing, mobile->mSDesc, 256, strName, EP_ONELINE|EP_ENDNOLF);
  EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}



CMDPROC(CmdMKey) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* Edit the requisite string */
  SendHint("^;HINT: Keywords should be only a single line\n", thing);
  sprintf(strName, "Mobile #%ld - Keywords", mobile->mVirtual);
  EDITSTR(thing, mobile->mKey, 256, strName, EP_ONELINE|EP_ENDNOLF);
  EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}



CMDPROC(CmdMLDesc) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* Edit the requisite string */
  SendHint("^;HINT: Names should not end on a blank line\n", thing);
  SendHint("^;HINT: The next thing you should do is use ^<MDESC ^;to add a description\n", thing);
  sprintf(strName, "Mobile #%ld - LDesc", mobile->mVirtual);
  EDITSTR(thing, mobile->mLDesc, 256, strName, EP_ENDNOLF);
  EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}



CMDPROC(CmdMDesc) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* Edit the requisite string */
  SendHint("^;HINT: Descriptions must end with a blank line\n", thing);
  sprintf(strName, "Mobile #%ld - Detailed Description", mobile->mVirtual);
  EDITSTR(thing, mobile->mDesc, 4096, strName, EP_ENDLF);
  EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}

CMDPROC(CmdMExtra) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  if (!*cmd)
    EditExtra(thing, "MEXTRA <#>", "", NULL, NULL);
  mobile = MobGetMobile(thing, &cmd);

  if (!mobile)
    return;

  sprintf(strName, "^cMobile ^w#%ld^c/", mobile->mVirtual);
  if (EditExtra(thing, "MEXTRA <#>", cmd, strName, &mobile->mExtra))
    EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}

CMDPROC(CmdMProperty) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         strName[256];

  cmd = StrOneWord(cmd, NULL);
  if (!*cmd)
    EditProperty(thing, "MPROPERTY <#>", "", NULL, NULL);
  mobile = MobGetMobile(thing, &cmd);

  if (!mobile)
    return;

  sprintf(strName, "^cMobile ^w#%ld^c/", mobile->mVirtual);
  if (EditProperty(thing, "MPROPERTY <#>", cmd, strName, &mobile->mProperty))
    EDITFLAG(thing, &areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}

CMDPROC(CmdMSet) {    /* void CmdProc(THING *thing, BYTE* cmd) */
  BYTE         buf[512];
  LWORD        i;
  MOBTEMPLATE *mobile;
  MOBTEMPLATE  mobTemplate;

  SETLIST mobSetList[] = {
    { "AURA",         SET_NUMERIC(     mobTemplate, mobTemplate.mAura )          },
    { "LEVEL",        SET_NUMERIC(     mobTemplate, mobTemplate.mLevel )         },
    { "HITBONUS",     SET_NUMERIC(     mobTemplate, mobTemplate.mHitBonus )      },
    { "ARMOR",        SET_NUMERIC(     mobTemplate, mobTemplate.mArmor )         },
    { "EXPERIENCE",   SET_NUMERIC(     mobTemplate, mobTemplate.mExp )           },
    { "HPDICENUM",    SET_NUMERIC(     mobTemplate, mobTemplate.mHPDiceNum )     },
    { "HPDICESIZE",   SET_NUMERIC(     mobTemplate, mobTemplate.mHPDiceSize )    },
    { "HPBONUS",      SET_NUMERIC(     mobTemplate, mobTemplate.mHPBonus )       },
    { "DAMDICENUM",   SET_NUMERIC(     mobTemplate, mobTemplate.mDamDiceNum )    },
    { "DAMDICESIZE",  SET_NUMERIC(     mobTemplate, mobTemplate.mDamDiceSize )   },
    { "DAMBONUS",     SET_NUMERIC(     mobTemplate, mobTemplate.mDamBonus )      },
    { "MONEY",        SET_NUMERIC(     mobTemplate, mobTemplate.mMoney )         },
    { "EXP",          SET_NUMERIC(     mobTemplate, mobTemplate.mExp )           },
    { "SEX",          SET_TYPE(        mobTemplate, mobTemplate.mSex, sexList )  },
    { "TYPE",         SET_TYPE(        mobTemplate, mobTemplate.mType,mTypeList )},
    { "POSITION",     SET_TYPE(        mobTemplate, mobTemplate.mPos, posList )  },
    { "ACT",          SET_FLAG(        mobTemplate, mobTemplate.mAct, mActList ) },
    { "AFFECT",       SET_FLAG(        mobTemplate, mobTemplate.mAffect, affectList ) },

    /* Skill/Numeric/Properties */
    { "%SPEED",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%PERCEPTION",  SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%GUARD",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%AMBUSH",      SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RESCUE",      SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%PURSUE",      SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%TRACK",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RPUNCTURE",   SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RSLASH",      SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RCONCUSSIVE", SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RHEAT",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%REMR",        SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RLASER",      SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RPSYCHIC",    SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RACID",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%RPOISON",     SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%WILLPOWER",   SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%DODGE",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%PICKPOCKET",  SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%STEAL",       SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%PEEK",        SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },
    { "%CARRYMAX",    SET_PROPERTYINT( mobTemplate, mobTemplate.mProperty ) },

    { "%WEAPONSDESC", SET_PROPERTYSTR( mobTemplate, mobTemplate.mProperty ) },

    { "" }
  };

  cmd = StrOneWord(cmd, NULL);
  if (!*cmd) { /* if they didnt type anything, give 'em a list */
    SendThing("^pUsuage:\n^P=-=-=-=\n", thing);
    SendThing("^cMSET <Mob#> <stat> <value>\n", thing);
    EditSet(thing, cmd, NULL, NULL, mobSetList);
    return;
  }

  mobile = MobGetMobile(thing, &cmd);
  if (!mobile) {
    SendThing("^bThere doesnt appear to be a mob with that virtual number\n", thing);
    return;
  }
  if (!*cmd) {
    sprintf(buf, "mstat %ld", mobile->mVirtual);
    CmdMStat(thing, buf);
    return;
  }

  i = EditSet(thing, cmd, mobile, mobile->mSDesc->sText, mobSetList);
  if (i==-1) {
    SendThing("^wOh, good one.... I bet you made that stat up on the spot, didnt you?\n", thing);
    SendThing("^wType MSET with no arguments for a list of changeable stats\n", thing);
    return;
  } else if (i == 1)
    BITSET(areaList[AreaOf(mobile->mVirtual)].aSystem, AS_MOBUNSAVED);
}


CMDPROC(CmdMCompile) {    /* void CmdProc(THING *thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         buf[256];
  PROPERTY    *property;
  LWORD        i;
  LWORD        area;
  BYTE         printLine;

  cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
  /* Check for Compile all command */
  if (StrExact(cmd, "all")) {
    if (!Base(thing)->bInside || Base(thing)->bInside->tType != TTYPE_WLD) {
      SendThing("^wYou cant do that here\n", thing);
      return;
    }
    area = Wld(Base(thing)->bInside)->wArea;
    for (i=0; i<areaList[area].aMobIndex.iNum; i++) {
      printLine=0;
      for (property = MobTemplate(areaList[area].aMobIndex.iThing[i])->mProperty; property; property=property->pNext) {
        
        if (property->pKey->sText[0]=='@') {
          if (!printLine) {
            printLine=1;
            sprintf(buf, 
              "^yMCOMPILE: ^c#%ld - ^b%s ", 
              MobTemplate(areaList[area].aMobIndex.iThing[i])->mVirtual, 
              MobTemplate(areaList[area].aMobIndex.iThing[i])->mSDesc->sText);

            SendThing(buf, thing);
          }
          sprintf(buf,"^G(%s) ", property->pKey->sText);
          SendThing(buf, thing);
          CodeCompileProperty(property,thing);
        }
      }
      if (printLine)
        SendThing("\n",thing);
    }
    return;
  }
  
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile) {
    SendThing("^GUSUAGE: ^gMCOMPILE <Mob Template #>\n", thing);
    SendThing("^G or\n", thing);
    SendThing("^GUSUAGE: ^gMCOMPILE all\n", thing);
    return;
  }

  sprintf(buf, "^yCOMPILE: ^c#%ld - ^b%s\n", mobile->mVirtual, mobile->mSDesc->sText);
  SendThing(buf, thing);
  
  for (property = mobile->mProperty; property; property=property->pNext) {
    SendThing("^gProp.: ^c", thing);
    SendThing(property->pKey->sText, thing);
    SendThing("\n", thing);
    if (property->pKey->sText[0]=='@') {
      CodeCompileProperty(property,thing);
    }
  }
  
}


CMDPROC(CmdMDecomp) {    /* void CmdProc(THING *thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  BYTE         buf[256];
  PROPERTY    *property;
  LWORD        i;
  LWORD        area;
  BYTE         printLine;

  cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
  /* Check for Compile all command */
  if (StrExact(cmd, "all")) {
    if (!Base(thing)->bInside || Base(thing)->bInside->tType != TTYPE_WLD) {
      SendThing("^wYou cant do that here\n", thing);
      return;
    }
    area = Wld(Base(thing)->bInside)->wArea;
    for (i=0; i<areaList[area].aMobIndex.iNum; i++) {
      printLine=0;
      for (property = MobTemplate(areaList[area].aMobIndex.iThing[i])->mProperty; property; property=property->pNext) {
        
        if (property->pKey->sText[0]=='@') {
          if (!printLine) {
            printLine=1;
            sprintf(buf, 
              "^yMDECOMP: ^c#%ld - ^b%s ", 
              MobTemplate(areaList[area].aMobIndex.iThing[i])->mVirtual, 
              MobTemplate(areaList[area].aMobIndex.iThing[i])->mSDesc->sText);

            SendThing(buf, thing);
          }
          sprintf(buf,"^G(%s) ", property->pKey->sText);
          SendThing(buf, thing);
          CodeDecompProperty(property,thing);
        }
      }
      if (printLine)
        SendThing("\n",thing);
    }
    return;
  }
  
  mobile = MobGetMobile(thing, &cmd);

  if (!mobile) {
    SendThing("^GUSUAGE: ^gMDECOMP <Mob Template #>\n", thing);
    SendThing("^G or\n", thing);
    SendThing("^GUSUAGE: ^gMDECOMP all\n", thing);
    return;
  }

  sprintf(buf, "^yDECOMP: ^c#%ld - ^b%s\n", mobile->mVirtual, mobile->mSDesc->sText);
  SendThing(buf, thing);
  
  for (property = mobile->mProperty; property; property=property->pNext) {
    SendThing("^gProp.: ^c", thing);
    SendThing(property->pKey->sText, thing);
    SendThing("\n", thing);
    if (property->pKey->sText[0]=='@') {
      CodeDecompProperty(property,thing);
    }
  }
  
}


CMDPROC(CmdMLoad) { /* void CmdProc(THING thing, BYTE* cmd) */
  MOBTEMPLATE *mobile;
  THING       *create;

  cmd = StrOneWord(cmd, NULL);
  mobile = MobGetMobile(thing, &cmd);
  if (!mobile)
    return;

  /* load one */
  create = MobileCreate(mobile, Base(thing)->bInside);
  SendAction("^wYou create a $N\n", 
             thing, create, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
  SendAction("^w$n creates a $N\n", 
             thing, create, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}


CMDPROC(CmdMSave) { /* void CmdProc(THING thing, BYTE* cmd) */
  THING *world;
  BYTE   buf[256];
  WORD   area;
  SOCK  *sock;

  world = WldGetWorld(thing, &cmd);
  if (!world)
    return;
  area = Wld(world)->wArea;

  if (!BIT(areaList[Wld(world)->wArea].aSystem, AS_MOBUNSAVED)) {
    SendThing("There are no unsaved changes!\n", thing);
  } else {
    BITFLIP(areaList[area].aSystem, AS_MOBUNSAVED);
    MobileWrite(area);
    sock = BaseControlFind(thing);
    sprintf(buf, "%s.mob saved by %s. (%ld mobiles)\n", areaList[area].aFileName->sText, sock->sHomeThing->tSDesc->sText, areaList[area].aMobIndex.iNum);
    Log(LOG_AREA, buf);
    sprintf(buf, "%s.mob saved. (^w%ld mobiles^V)\n", areaList[area].aFileName->sText, areaList[area].aMobIndex.iNum);
    SendThing(buf, thing);
  }
}