home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / d / d-linux.zip / dm-dist / reception.c < prev    next >
C/C++ Source or Header  |  1991-03-01  |  14KB  |  532 lines

  1. /* ************************************************************************
  2. *  file: reception.c, Special module for Inn's.           Part of DIKUMUD *
  3. *  Usage: Procedures handling saving/loading of player objects            *
  4. *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
  5. ************************************************************************* */
  6.  
  7. #include <stdio.h>
  8. #include <sys/time.h>
  9.  
  10. #include "structs.h"
  11. #include "comm.h"
  12. #include "handler.h"
  13. #include "db.h"
  14. #include "interpreter.h"
  15. #include "utils.h"
  16. #include "spells.h"
  17.  
  18. #define OBJ_SAVE_FILE "pcobjs.obj"
  19. #define OBJ_FILE_FREE "\0\0\0"
  20.  
  21. extern struct room_data *world;
  22. extern struct index_data *mob_index;
  23. extern struct index_data *obj_index;
  24.  
  25. /* Extern functions */
  26.  
  27. void store_to_char(struct char_file_u *st, struct char_data *ch);
  28. void do_tell(struct char_data *ch, char *argument, int cmd);
  29. int str_cmp(char *arg1, char *arg2);
  30. void clear_char(struct char_data *ch);
  31.  
  32.  
  33. struct obj_cost {
  34.     int total_cost;
  35.     int no_carried;
  36.     bool ok;
  37. };
  38.  
  39.  
  40. /* ************************************************************************
  41. * Routines used for the "Offer"                                           *
  42. ************************************************************************* */
  43.  
  44. void add_obj_cost(struct char_data *ch, struct char_data *re,
  45.                   struct obj_data *obj, struct obj_cost *cost)
  46. {
  47.     char buf[MAX_STRING_LENGTH];
  48.  
  49.     /* Add cost for an item and it's conents, and next->contents */
  50.  
  51.     if (obj) {
  52.         if ((obj->item_number > -1) && (cost->ok)) {
  53.             cost->total_cost += MAX(0, obj->obj_flags.cost_per_day);
  54.             cost->no_carried++;
  55.             add_obj_cost(ch, re, obj->contains, cost);
  56.             add_obj_cost(ch, re, obj->next_content, cost);
  57.         } else
  58.             if (cost->ok) {
  59.                 act("$n tells you 'I refuse storing $p'",FALSE,re,obj,ch,TO_VICT);
  60.                 cost->ok = FALSE;
  61.             }
  62.  
  63.     }
  64. }
  65.  
  66.  
  67. bool recep_offer(struct char_data *ch,    struct char_data *receptionist,
  68.     struct obj_cost *cost)
  69. {
  70.     int i;
  71.     char buf[MAX_STRING_LENGTH];
  72.  
  73.     cost->total_cost = 100; /* Minimum cost */
  74.     cost->no_carried = 0;
  75.     cost->ok = TRUE; /* Use if any "-1" objects */
  76.  
  77.     add_obj_cost(ch, receptionist, ch->carrying, cost);
  78.  
  79.     for(i = 0; i<MAX_WEAR; i++)
  80.         add_obj_cost(ch, receptionist, ch->equipment[i], cost);
  81.  
  82.     if (!cost->ok)
  83.         return(FALSE);
  84.     
  85.     if (cost->no_carried == 0) {
  86.         act("$n tells you 'But you are not carrying anything?'",FALSE,receptionist,0,ch,TO_VICT);
  87.         return(FALSE);
  88.     }
  89.  
  90.     if (cost->no_carried > MAX_OBJ_SAVE) {
  91.         sprintf(buf,"$n tells you 'Sorry, but I can't store any more than %d items.",
  92.             MAX_OBJ_SAVE);
  93.         act(buf,FALSE,receptionist,0,ch,TO_VICT);
  94.         return(FALSE);
  95.     }
  96.  
  97.     sprintf(buf, "$n tells you 'It will cost you %d coins per day'", cost->total_cost);
  98.     act(buf,FALSE,receptionist,0,ch,TO_VICT);
  99.  
  100.     if (cost->total_cost > GET_GOLD(ch)) {
  101.         if (GET_LEVEL(ch) < 21)
  102.             act("$n tells you 'Which I can see you can't afford'",
  103.               FALSE,receptionist,0,ch,TO_VICT);
  104.         else {
  105.             act("$n tells you 'Well, since you're a God, I guess it's okay'",
  106.               FALSE,receptionist,0,ch,TO_VICT);
  107.             cost->total_cost = 0;
  108.         }
  109.     }
  110.  
  111.     if ( cost->total_cost > GET_GOLD(ch) )
  112.         return(FALSE);
  113.     else
  114.         return(TRUE);
  115. }
  116.  
  117.  
  118. /* ************************************************************************
  119. * General save/load routines                                              *
  120. ************************************************************************* */
  121.  
  122. /* pos == 0 is first position in file! */
  123. void update_file(FILE *fl, int pos, struct obj_file_u *st)
  124. {
  125.     if (fseek(fl, sizeof(struct obj_file_u)*(pos), 0)) {
  126.         perror("Seeking in file update (update_file, reception.c)");
  127.         exit(1);
  128.     }
  129.     if (fwrite(st, sizeof(struct obj_file_u), 1, fl) < 1) {
  130.         perror("Error updating file (update_file, reception.c).");
  131.         exit(1);
  132.     }
  133.  
  134.     /* WHY OH WHY?!??!? I can't tell, but I doesn't work without */
  135.   /* Something with update mode and reads after writes         */
  136.     if (fseek(fl, sizeof(struct obj_file_u)*(pos+1), 0)) {
  137.         perror("Seeking in file update (update_file, reception.c)");
  138.         exit(1);
  139.     }
  140.  
  141. }
  142.  
  143.  
  144. /* ************************************************************************
  145. * Routines used to load a characters equipment from disk                  *
  146. ************************************************************************* */
  147.  
  148. void obj_store_to_char(struct char_data *ch, struct obj_file_u *st)
  149. {
  150.     struct obj_data *obj;
  151.     int i, j;
  152.  
  153.     void obj_to_char(struct obj_data *object, struct char_data *ch);
  154.  
  155.     for(i=0; i<MAX_OBJ_SAVE; i++) {
  156.         if (st->objects[i].item_number > -1) {
  157.       if (real_object(st->objects[i].item_number) > -1) {
  158.                 obj = read_object(st->objects[i].item_number, VIRTUAL);
  159.  
  160.                 obj->obj_flags.value[0] = st->objects[i].value[0];
  161.                 obj->obj_flags.value[1] = st->objects[i].value[1];
  162.                 obj->obj_flags.value[2] = st->objects[i].value[2];
  163.                 obj->obj_flags.value[3] = st->objects[i].value[3];
  164.  
  165.                 obj->obj_flags.extra_flags = st->objects[i].extra_flags;
  166.                 obj->obj_flags.weight      = st->objects[i].weight;
  167.                 obj->obj_flags.timer       = st->objects[i].timer;
  168.                 obj->obj_flags.bitvector   = st->objects[i].bitvector;
  169.  
  170.                 for(j=0; j<MAX_OBJ_AFFECT; j++)
  171.                     obj->affected[j] = st->objects[i].affected[j];
  172.  
  173.                 obj_to_char(obj, ch);
  174.             }
  175.         }
  176.     }
  177. }
  178.  
  179.  
  180. void load_char_objs(struct char_data *ch)
  181. {
  182.     FILE *fl;
  183.     int pos, i, j;
  184.     bool found = FALSE;
  185.     float timegold;
  186.     struct obj_file_u st;
  187.  
  188.  
  189.     /* r+b is for Binary Reading/Writing */
  190.     if (!(fl = fopen(OBJ_SAVE_FILE, "r+b")))
  191.     {
  192.         perror("Opening object file for Loading PC's objects");
  193.         exit(1);
  194.     }
  195.  
  196.     pos = 0;
  197.  
  198.     while (!feof(fl) && !found) {
  199.         pos += fread(&st, sizeof(struct obj_file_u), 1, fl);
  200.         found = !str_cmp(st.owner, GET_NAME(ch));
  201.     }
  202.  
  203.     if (found) {
  204.  
  205.         obj_store_to_char(ch, &st);
  206.         
  207.         timegold = (int) ((st.total_cost*(time(0) - st.last_update)) / (SECS_PER_REAL_DAY));
  208.  
  209.         GET_GOLD(ch) -= timegold;
  210.  
  211.         if (GET_GOLD(ch) < 0)
  212.             GET_GOLD(ch) = 0;
  213.  
  214.  
  215.         if (fseek(fl, sizeof(struct obj_file_u)*(pos-1), 0)) {
  216.             perror("seeking in PC objects file.");
  217.             exit(1);
  218.         }
  219.         strcpy(st.owner, OBJ_FILE_FREE);
  220.         if (fwrite(&st, sizeof(struct obj_file_u), 1, fl) < 1) {
  221.             log("Error updating name to be set as unused.");
  222.             exit(1);
  223.         }
  224.  
  225.     } else {
  226.         log("Char has no data in file!");
  227.     }
  228.  
  229.     fclose(fl);
  230.  
  231.     /* Save char, to avoid strange data if crashing */
  232.     save_char(ch, NOWHERE);
  233.  
  234. }
  235.  
  236.  
  237. /* ************************************************************************
  238. * Routines used to save a characters equipment from disk                  *
  239. ************************************************************************* */
  240.  
  241. /* Puts object in store, at first item which has no -1 */
  242. void put_obj_in_store(struct obj_data *obj, struct obj_file_u *st)
  243. {
  244.     int i, j;
  245.     bool found = FALSE;
  246.  
  247.     for (i=0; (i<MAX_OBJ_SAVE) && !found; i++)
  248.         if (st->objects[i].item_number == -1) {
  249.             st->objects[i].item_number = obj_index[obj->item_number].virtual;
  250.             st->objects[i].value[0] = obj->obj_flags.value[0];
  251.             st->objects[i].value[1] = obj->obj_flags.value[1];
  252.             st->objects[i].value[2] = obj->obj_flags.value[2];
  253.             st->objects[i].value[3] = obj->obj_flags.value[3];
  254.  
  255.             st->objects[i].extra_flags = obj->obj_flags.extra_flags;
  256.             st->objects[i].weight  = obj->obj_flags.weight;
  257.             st->objects[i].timer  = obj->obj_flags.timer;
  258.             st->objects[i].bitvector  = obj->obj_flags.bitvector;
  259.             for(j=0; j<MAX_OBJ_AFFECT; j++)
  260.                 st->objects[i].affected[j] = obj->affected[j];
  261.             found = TRUE;
  262.         }
  263.  
  264.     if (!found) {
  265.         log("No empty space to store object. (put_obj_in_store, reception.c)");
  266.         exit(1);
  267.     }
  268. }
  269.  
  270.  
  271.  
  272. /* Destroy inventory after transferring it to "store inventory" */
  273. void obj_to_store(struct obj_data *obj, struct obj_file_u *st,
  274.                   struct char_data * ch)
  275. {
  276.     static char buf[240];
  277.  
  278.     if (obj) {
  279.         obj_to_store(obj->contains, st, ch);
  280.         obj_to_store(obj->next_content, st, ch);
  281.  
  282.         if ((obj->obj_flags.timer < 0) && (obj->obj_flags.timer != OBJ_NOTIMER)) {
  283.             sprintf(buf, "You're told: 'The %s is just old junk, I'll throw it away for you.'\n\r",
  284.               fname(obj->name));
  285.             send_to_char(buf, ch);
  286.         } else {
  287.             put_obj_in_store(obj, st);
  288.             if (obj->in_obj)
  289.                 obj_from_obj(obj);
  290.             extract_obj(obj);
  291.         }
  292.     }
  293. }
  294.  
  295.  
  296.  
  297. /* write the vital data of a player to the player file */
  298. void save_obj(struct char_data *ch, struct obj_cost *cost)
  299. {
  300.     struct obj_file_u st, dummy;
  301.     FILE *fl;
  302.     int pos, i, j;
  303.     bool found = FALSE;
  304.  
  305.  
  306.     for(j=0; j<MAX_OBJ_SAVE; j++) {
  307.         st.objects[j].item_number = -1; /* Set as not used */
  308.         st.objects[j].value[0] = 0;
  309.         st.objects[j].value[1] = 0;
  310.         st.objects[j].value[2] = 0;
  311.         st.objects[j].value[3] = 0;
  312.         st.objects[j].extra_flags = 0;
  313.         st.objects[j].weight = 0;
  314.         st.objects[j].timer = 0;
  315.  
  316.         st.objects[j].bitvector = 0;
  317.         for (i=0; i<MAX_OBJ_AFFECT; i++) {
  318.             st.objects[j].affected[i].location = 0;
  319.             st.objects[j].affected[i].modifier = 0;
  320.         }
  321.  
  322.     }
  323.  
  324.  
  325.     strcpy(st.owner, GET_NAME(ch));
  326.     st.gold_left = GET_GOLD(ch);
  327.     st.total_cost = cost->total_cost;
  328.     st.last_update = time(0);
  329.  
  330.     obj_to_store(ch->carrying, &st, ch);
  331.     ch->carrying = 0;
  332.  
  333.     for(i=0; i<MAX_WEAR; i++)
  334.         if (ch->equipment[i]) {
  335.             obj_to_store(ch->equipment[i], &st, ch);
  336.             unequip_char(ch, i);
  337.         }
  338.  
  339.     if (!(fl = fopen(OBJ_SAVE_FILE, "a+b")))
  340.     {
  341.         perror("saving PC's objects");
  342.         exit(1);
  343.     }
  344.  
  345.  
  346.     if (fseek(fl, 0, 0)) /* Move to beginning of file */
  347.     {
  348.         perror("seeking to start of PC objects file.");
  349.         exit(1);
  350.     }
  351.  
  352.     pos = 0;
  353.  
  354.     while (!feof(fl) && !found) {
  355.         pos+=fread(&dummy, sizeof(struct obj_file_u), 1, fl);
  356.         found = (dummy.owner[0] == '\0');
  357.     }
  358.  
  359.     if (feof(fl))
  360.         update_file(fl, pos, &st);
  361.     else {
  362.         if (!found) {
  363.             perror("Really strange...\n\r");
  364.             exit(1);
  365.         }
  366.  
  367.         update_file(fl, pos-1, &st);
  368.     }
  369.  
  370.     fclose(fl);
  371. }
  372.  
  373.  
  374.  
  375. /* ************************************************************************
  376. * Routines used to update object file, upon boot time                     *
  377. ************************************************************************* */
  378.  
  379. void update_obj_file(void)
  380. {
  381.     FILE *fl, *char_file;
  382.     struct obj_file_u st;
  383.     struct char_file_u ch_st;
  384.     struct char_data tmp_char;
  385.     int pos, no_read, player_i;
  386.     long days_passed, secs_lost;
  387.     char buf[MAX_STRING_LENGTH];
  388.  
  389.     int find_name(char *name);
  390.     extern struct player_index_element *player_table;
  391.  
  392.     if (!(char_file = fopen(PLAYER_FILE, "r+"))) {
  393.         perror("   Opening player file for reading. (reception.c, update_obj_file)");
  394.         exit(1);
  395.     }
  396.  
  397.     /* r+b is for Binary Reading/Writing */
  398.     if (!(fl = fopen(OBJ_SAVE_FILE, "r+b")))
  399.     {
  400.         perror("   Opening object file for updating");
  401.         exit(1);
  402.     }
  403.  
  404.  
  405.     pos = 0;
  406.  
  407.     while (!feof(fl)) {
  408.         no_read = fread(&st, sizeof(struct obj_file_u), 1, fl);
  409.         pos += no_read;
  410.  
  411.         if ((!feof(fl)) && (no_read > 0) && st.owner[0]) {
  412.             sprintf(buf, "   Processing %s[%d].", st.owner, pos);
  413.             log(buf);
  414.             days_passed = ((time(0) - st.last_update) / SECS_PER_REAL_DAY);
  415.             secs_lost = ((time(0) - st.last_update) % SECS_PER_REAL_DAY);
  416.  
  417.             if (days_passed > 0) {
  418.                 if ((st.total_cost*days_passed) > st.gold_left) {
  419.  
  420.                     if ((player_i = find_name(st.owner)) < 0) {
  421.                         perror("   Character not in list. (update_obj_file)");
  422.                         exit(1);
  423.                     }
  424.  
  425.                     fseek(char_file, (long) (player_table[player_i].nr *
  426.                         sizeof(struct char_file_u)), 0);
  427.  
  428.                     fread(&ch_st, sizeof(struct char_file_u), 1, char_file);
  429.  
  430.                     sprintf(buf, "   Dumping %s from object file.", ch_st.name);
  431.                     log(buf);
  432.  
  433.                     ch_st.points.gold = 0;
  434.                     ch_st.load_room = NOWHERE;
  435.                     fseek(char_file, (long) (player_table[player_i].nr *
  436.                         sizeof(struct char_file_u)), 0);
  437.                     fwrite(&ch_st, sizeof(struct char_file_u), 1, char_file);
  438.  
  439.                     strcpy(st.owner, OBJ_FILE_FREE);
  440.                     update_file(fl, pos-1, &st);
  441.  
  442.                 } else {
  443.  
  444.                     sprintf(buf, "   Updating %s", st.owner);
  445.                     log(buf);
  446.                     st.gold_left  -= (st.total_cost*days_passed);
  447.                     st.last_update = time(0)-secs_lost;
  448.                     update_file(fl, pos-1, &st);
  449.                 }
  450.             }
  451.         }
  452.     }
  453.  
  454.     fclose(fl);
  455.     fclose(char_file);
  456. }
  457.  
  458.  
  459. /* ************************************************************************
  460. * Routine Receptionist                                                    *
  461. ************************************************************************* */
  462.  
  463.  
  464.  
  465. int receptionist(struct char_data *ch, int cmd, char *arg)
  466. {
  467.     char buf[240];
  468.     struct obj_cost cost;
  469.     struct char_data *recep = 0;
  470.     struct char_data *temp_char;
  471.     sh_int save_room;
  472.     sh_int action_tabel[9] = {23,24,36,105,106,109,111,142,147};
  473.  
  474.     void do_action(struct char_data *ch, char *argument, int cmd);
  475.     int number(int from, int to);
  476.  
  477.     if (!ch->desc)
  478.         return(FALSE); /* You've forgot FALSE - NPC couldn't leave */
  479.  
  480.     for (temp_char = world[ch->in_room].people; (temp_char) && (!recep);
  481.         temp_char = temp_char->next_in_room)
  482.         if (IS_MOB(temp_char))
  483.             if (mob_index[temp_char->nr].func == receptionist)
  484.                 recep = temp_char;
  485.  
  486.     if (!recep) {
  487.         log("Ingen receptionist.\n\r");
  488.         exit(1);
  489.     }
  490.  
  491.     if (IS_NPC(ch))
  492.         return(FALSE);
  493.  
  494.     if ((cmd != 92) && (cmd != 93)) {
  495.         if (!number(0, 30))
  496.             do_action(recep, "", action_tabel[number(0,8)]);
  497.         return(FALSE);
  498.     }
  499.  
  500.     if (!AWAKE(recep)) {
  501.         act("$e isn't able to talk to you...", FALSE, recep, 0, ch, TO_VICT);
  502.         return(TRUE);
  503.     }
  504.  
  505.     if (!CAN_SEE(recep, ch)) 
  506.     {
  507.         act("$n says, 'I don't deal with people I can't see!'", FALSE, recep, 0, 0, TO_ROOM);
  508.         return(TRUE);
  509.     }
  510.  
  511.     if (cmd == 92) { /* Rent  */
  512.         if (recep_offer(ch, recep, &cost)) {
  513.  
  514.             act("$n stores your stuff in the safe, and helps you into your chamber.",
  515.                 FALSE, recep, 0, ch, TO_VICT);
  516.             act("$n helps $N into $S private chamber.",FALSE, recep,0,ch,TO_NOTVICT);
  517.  
  518.             save_obj(ch, &cost);
  519.             save_room = ch->in_room;
  520.             extract_char(ch);
  521.             ch->in_room = world[save_room].number;
  522.             save_char(ch, ch->in_room);
  523.         }
  524.         
  525.     } else {         /* Offer */
  526.         recep_offer(ch, recep, &cost);
  527.         act("$N gives $n an offer.", FALSE, ch, 0, recep, TO_ROOM);
  528.     }
  529.     
  530.     return(TRUE);
  531. }
  532.