/
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
 */

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

#include "crimson2.h"
#include "macro.h"
#include "log.h"
#include "mem.h"
#include "str.h"
#include "extra.h"
#include "file.h"
#include "ini.h"
#include "send.h"
#include "thing.h"
#include "index.h"
#include "edit.h"
#include "history.h"
#include "socket.h"
#include "base.h"
#include "char.h"
#include "parse.h"
#include "social.h"


INDEX     socialIndex;
LWORD     socialReadLog;

/* returns same values as strcmp */
INDEXPROC(SocialCompareProc) { /* BYTE IndexProc(void *index1, void *index2) */
  return STRICMP( Social(index1)->sName->sText, Social(index2)->sName->sText );
}
INDEXFINDPROC(SocialFindProc) { /* BYTE IndexProc(void *key, void *index) */
  if (StrAbbrev( Social(index)->sName->sText, (BYTE*)key ))
    return 0;
  else 
    return STRICMP( key, Social(index)->sName->sText );
}

/* END - INTERNAL FUNCTIONS */

void SocialInit(void) {
  BYTE  buf[256];

  IndexInit(&socialIndex, SOCIAL_INDEX_SIZE, "socialIndex(social.c)", 0);
  sprintf(buf, "Initial socialIndex allocation of %d entries\n", SOCIAL_INDEX_SIZE/sizeof(THING *));
  Log(LOG_BOOT, buf);
  socialReadLog = INILWordRead("crimson2.ini", "socialReadLog", 0);

  SocialRead();

  sprintf(buf,
    "Total Number of Socials: [%3ld]\n",
    socialIndex.iNum
   );
  Log(LOG_BOOT, buf);
}

void SocialRead(void) {
  BYTE           buf[256];
  BYTE          *trim;
  SOCIAL        *social = NULL;
  FILE          *msgFile;

  msgFile = fopen("msg/social.msg", "r");
  if (!msgFile) {
    Log(LOG_ERROR, "Unable to open msg/social.msg file\n");
    return;
  }
  fgets(buf, 256, msgFile);
  while (!feof(msgFile)) {
    if (buf[0]=='$') break;

    switch (buf[0]) {
      case '#':
        MEMALLOC(social, SOCIAL, SOCIAL_ALLOC_SIZE);
        memset(social, 0, sizeof(SOCIAL));
        trim = StrTrim(buf+1);
  social->sName = STRCREATE(trim);
        /* insert them alpabetically into the index */
  IndexInsert(&socialIndex, social, SocialCompareProc);
        if (socialReadLog) {
          sprintf(buf, "Reading Social: %s\n", social->sName->sText);
          Log(LOG_BOOT, buf);
        }
        /* read minimum position - anything not in the list will be interpreted as same */
        fgets(buf, sizeof(buf), msgFile);
        trim = StrTrim(buf);
        social->sPos = TYPEFIND(trim, posList);
        if (social->sPos==-1) {
          if (!StrExact(trim, "SAME")) {
            sprintf(buf, "Social: %s - Illegal Position, assuming SAME\n", social->sName->sText);
            Log(LOG_BOOT, buf);
          }
        }
        break;

      case 'N':
        if (!social) break; /* must have read this first */
  if (social->sNullSrc || social->sNullRoom) {
    sprintf(buf, "Duplicate N entry for social %s\n", social->sName->sText);
    Log(LOG_BOOT, buf);
    break;
  }
  social->sNullSrc  = FileStrRead(msgFile);
        social->sNullRoom = FileStrRead(msgFile);
  break;

      case 'C':
        if (!social) break; /* must have read this first */
  if (social->sCharSrc || social->sCharDst || social->sCharRoom) {
    sprintf(buf, "Duplicate C entry for social %s\n", social->sName->sText);
    Log(LOG_BOOT, buf);
    break;
  }
  social->sCharSrc  = FileStrRead(msgFile);
        social->sCharDst  = FileStrRead(msgFile);
        social->sCharRoom = FileStrRead(msgFile);
  break;

      case 'O':
        if (!social) break; /* must have read this first */
  if (social->sObjSrc || social->sObjRoom) {
    sprintf(buf, "Duplicate O entry for social %s\n", social->sName->sText);
    Log(LOG_BOOT, buf);
    break;
  }
  social->sObjSrc  = FileStrRead(msgFile);
        social->sObjRoom = FileStrRead(msgFile);
        break;

      case ';': /* its a comment */
        break;

      case '\0': /* its nothing */
      case '\r': /* its nothing */
      case '\n': /* its nothing */
        social = NULL;
        break;

      default: /* corrupt crap for example */
        Log(LOG_ERROR, "in [msg/social.msg] not sure what to make of:\n");
        Log(LOG_ERROR, buf);
        break; /* its a comment */
    }
    fgets(buf, 256, msgFile);
  }
}

SOCIAL *SocialFind(BYTE *key) {
  return IndexFind(&socialIndex, key, SocialFindProc);
}

BYTE SocialParse(THING *thing, BYTE *cmd) {
  SOCIAL *social = NULL;
  BYTE    buf[256];
  BYTE    srcKey[256];
  LWORD   srcNum;
  LWORD   srcOffset;
  THING  *found;
  THING  *search;
  LWORD   i;
  LWORD   count;

  cmd = StrOneWord(cmd, buf); 
  if (StrAbbrev("socials", buf)) {
    SendThing("^cAvailable Social Commands:\n", thing);
    SendThing("^C-+-+-+-+- +-+-+- +-+-+-+-\n\n", thing);
    count = 0;
    for (i=0; i<socialIndex.iNum; i++) {
      count++;
      if ( count%2 )
        strcpy(buf, "^g");
      else
        strcpy(buf, "^G");

      if ( count%5 )
        sprintf(buf+2, "%-15s", Social(socialIndex.iThing[i])->sName->sText);
      else 
        sprintf(buf+2, "%s\n", Social(socialIndex.iThing[i])->sName->sText);
      SendThing(buf, thing);
    }
    if ( count%5 )
      SendThing("\n", thing);
    sprintf(buf, "\n^CTotal Socials Available: ^p%ld\n", count);
    SendThing(buf, thing);
    return TRUE;
  }
  social = SocialFind(buf);
  if (!social)
    return FALSE;
  
  if (*cmd) {
    ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
    search = Base(thing)->bInside;
    found = CharThingFind(thing, srcKey, -1, search, TF_PLR|TF_MOB|TF_OBJ, &srcOffset);
  } else
    found = NULL;

  /* check minimum position */
  if ((social->sPos != -1) && (Character(thing)->cPos < social->sPos)) {
    sprintf(buf, "^wYou must at least be ^r%s^w to %s\n", posList[social->sPos].pName, social->sName->sText);
    SendThing(buf, thing);
    return TRUE;
  }

  if (!found) {
    if (!social->sNullSrc || !social->sNullRoom) {
      sprintf(buf, "^w%s must be directed at someone or something\n", social->sName->sText);
      SendThing(buf, thing);
      return TRUE;
    } else {
      SendAction(social->sNullSrc->sText,
     thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
     thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction(social->sNullRoom->sText,
     thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
     thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      return TRUE;
    }
  }
  
  else if (found->tType==TTYPE_PLR || found->tType==TTYPE_MOB) {
    if (!social->sCharSrc || !social->sCharDst || !social->sCharRoom) {
      sprintf(buf, "^w%s cant be directed against someone\n", social->sName->sText);
      SendThing(buf, thing);
      return TRUE;
    } else {
      if (social->sPos==-1 && Character(thing)->cPos!=Character(found)->cPos) {
        sprintf(buf, "^wBut they are ^r%s^w and you are %s\n", posList[Character(found)->cPos].pName, posList[Character(thing)->cPos].pName);
        SendThing(buf, thing);
        return TRUE;
      }
      SendAction(social->sCharSrc->sText,
        thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
        thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction(social->sCharDst->sText,
        thing, found, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
        thing, found, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction(social->sCharRoom->sText,
        thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
        thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      return TRUE;
    }
  }
  
  else if (found->tType==TTYPE_OBJ) {
    if (!social->sObjSrc || !social->sObjRoom) {
      sprintf(buf, "^w%s cant be directed against an object\n", social->sName->sText);
      SendThing(buf, thing);
      return TRUE;
    } else {
      SendAction(social->sObjSrc->sText,
     thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
     thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
      SendAction(social->sObjRoom->sText,
     thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      SendAction("\n",
     thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
      return TRUE;
    }
  }
  
  return TRUE;
}