From: Adam Beytin <mbeytin@umd5.umd.edu>
Subject: Death count snippet

Death count, it keeps track of how many times a player/mob has died or
killed.  The player part is easy, but the mob part is tough.  It creates a
file called ripcount in world/mob dir.  tampering with this file will give
problems, and if it is somehow messed up, I suggest you remove it and then
run the game, it will rewrite it.
The file is rewritten out at every normal shutdown/reboot. I didn't put
anything in here about a board or whatever listing this stuff, but you may
want to.  If you do put in something like that, I'd like to hear about it.
My email is mbeytin@umd5.umd.edu.


comm.c: writes the file

void check_idle_passwords(void);
void heartbeat(int pulse);
void death_count_write(void);           <- add these lines
extern int top_of_mobt;                 <-
extern struct char_data *mob_proto;     <-


/* extern fcnts */

.......

  game_loop(mother_desc);

  log("Saving mob death counts.");      <- add this line
  death_count_write();                  <- add this line

  log ("Closing all sockets.");

....... (at the end of the file, put this function)

void death_count_write(void) {
  FILE *fl;
  int nr;
  fl = fopen("world/mob/ripcount", "w");

  for (nr = 0;nr <= top_of_mobt;nr++)
    fprintf(fl, "%d %ld %ld\n", nr, mob_proto[nr].points.deaths,
        mob_proto[nr].points.kills);

  fclose(fl);
}


db.c:  loads the file

void reset_time(void);
void clear_char(struct char_data * ch);
void death_count_load(void);            <- add this line

/* external functions */

.......

  log("Loading mobs and generating index.");
  index_boot(DB_BOOT_MOB);
  death_count_load();                   <- add this line

  log("Loading objs and generating index.");

....... (at the end of the file, add this function)

void death_count_load(void) {
  FILE *fl;
  char line[256];
  int rnum;
  long int death, kill;

  if (!(fl = fopen("world/mob/ripcount", "r"))) {
    if (errno != ENOENT) {
      perror("fatal error opening deathcount file");
      exit(1);
    } else {
      log("no deathcount file, creating a new one");
      fl = fopen("world/mob/ripcount", "w");
      fprintf(fl, "0 0 0\n1 0 0");
      fclose(fl);
      if (!(fl = fopen("world/mob/ripcount", "r"))) {
        perror("fatal error opening ripcount file");
        exit(1);
      }
    }
  }

  while (!feof(fl)) {
    get_line(fl, line);
    sscanf(line, "%d %ld %ld", &rnum, &death, &kill);
    mob_proto[rnum].points.deaths = death;
    mob_proto[rnum].points.kills = kill;
  }
}


act.wizard.c:  adds to do_set and do_stat_char

extern struct zone_data *zone_table;
extern struct player_index_element *player_table;
extern struct char_data *mob_proto;                <- add this line

extern int top_of_zone_table;

....... (put this in do_stat_character wherever it will fit)

  if (IS_NPC(k)) {
    sprintf(buf, "Deaths: [%ld], Kills: [%ld]\r\n",
        mob_proto[k->nr].points.deaths, mob_proto[k->nr].points.kills);
    send_to_char(buf, ch);
  } else if (GET_LEVEL(k) < LVL_IMMORT) {
    sprintf(buf, "Deaths: [%ld], Kills: [%ld]\r\n", GET_DEATHS(k),
        GET_KILLS(k));
    send_to_char(buf, ch);
  }

....... (if "cha" isn't last on list before "\n", put deaths right before
         "\n")

   { "nodelete",        LVL_GOD,        PC,     BINARY },
   { "cha",             LVL_GRGOD,      BOTH,   NUMBER },
   { "deaths",          LVL_IMPL,       BOTH,   NUMBER }, <- add this line
   { "kills",           LVL_IMPL,       BOTH,   NUMBER }, <- add this line
   { "\n", 0, BOTH, MISC }

....... (if case 47 isn't last thing before default, make the case #
         directly after the last number)

    break;
  case 48:                                    <- add this line
    i = atoi(val_arg);                        <- add this line
    if (i < 0) {                              <- add this line
      send_to_char("You can't have negative deaths.\r\n", ch); <- add this
      return;                                 <- add this line
    }                                         <- add this line
    if (IS_NPC(vict))                         <- add this line
      mob_proto[ch->nr].points.deaths = i;    <- add this line
    else                                      <- add this line
      GET_DEATHS(vict) = i;                   <- add this line
    break;                                    <- add this line
  case 49:                                    <- add this line
    i = atoi(val_arg);                        <- add this line
    if (i < 0) {                              <- add this line
      send_to_char("You can't have negative kills.\r\n", ch); <- add this
      return;                                 <- add this line
    }                                         <- add this line
    if (IS_NPC(vict))                         <- add this line
      mob_proto[ch->nr].points.kills = i;     <- add this line
    else                                      <- add this line
      GET_KILLS(vict) = i;                    <- add this line
    break;                                    <- add this line

  default:


act.informative.c:  displays current death/kills in score

extern struct title_type titles[NUM_CLASSES][LVL_SUP + 1];
extern struct command_info cmd_info[];
extern struct char_data *mob_proto;           <- add this line

extern char *credits;

....... (put this in do_score wherever it will fit)

  if (IS_NPC(ch))
    sprintf(buf, "%sYou have died %ld times and killed %ld creatures.\r\n",
        buf, mob_proto[ch->nr].points.deaths,
        mob_proto[ch->nr].points.kills);
  else if (GET_LEVEL(ch) < LVL_LRIMMORT)
    sprintf(buf, "%sYou have died %ld times and killed %ld creatures.\r\n",
        buf, GET_DEATHS(ch), GET_KILLS(ch));


fight.c:  changes death count on killed (note, does not work with rawkill)

extern int auto_save;           /* see config.c */
extern int max_exp_gain;        /* see config.c */
extern struct char_data *mob_proto;           <- add this line

/* External procedures */

....... (replace die() function with this)

void die(struct char_data * ch)
{
  gain_exp(ch, -(GET_EXP(ch) >> 1));
  if (IS_NPC(ch))
    mob_proto[ch->nr].points.deaths += 1;
  else {
    REMOVE_BIT(PLR_FLAGS(ch), PLR_KILLER | PLR_THIEF);
    GET_DEATHS(ch) += 1;
  }
  raw_kill(ch);
}

.......

      sprintf(local_buf,"%ld", (long)local_gold);
    }
    if (IS_NPC(ch))                            <- add this line
      mob_proto[ch->nr].points.kills += 1;     <- add this line
    else                                       <- add this line
      GET_KILLS(ch) += 1;                      <- add this line
    die(victim);


structs.h:  defines death count
   int  bank_gold;      /* Gold the char has in a bank account     */
   int  exp;            /* The experience of the player            */
   long int  deaths;    /* The number of times the player has died */
                     ^^^add this line^^^
   long int  kills;     /* The number of times the player has killed */
                     ^^^add this line^^^

   sbyte hitroll;       /* Any bonus or penalty to the hit roll    */


utils.h:  defines death count var (GET_DEATHS(ch))
#define GET_HITROLL(ch)   ((ch)->points.hitroll)
#define GET_DAMROLL(ch)   ((ch)->points.damroll)
#define GET_DEATHS(ch)    ((ch)->points.deaths)        <- add this line
#define GET_KILLS(ch)     ((ch)->points.kills)         <- add this line

#define GET_POS(ch)       ((ch)->char_specials.position)



