OK! Next contribution. An OLC for shops to install together with Sammy's Obuild.06. Note that you must have previously installed Obuild.06. the commands to use: - sedit {save|done|<number>} if you specify an unknown number, it will create a shop with that number. - sset sset with no arguments will give the variables it can set. - sstat similar to show shop, but it also shows the messages the shopkeeper says. NOTE: the messages may not correspond exactly. If you find any problems please send them to me so that i can fix it. I want to thank the following people for having the patience of following buggy and incomplete instructions and then reporting the bugs, correct them, try again, report bugs...: Melen - melen@melen.acmenet.net William Elwartowski - ELWARTOWS_WL@A1.RSCC.CC.TN.U By the way! If you have any suggestion whatsoever that you find would improve this piece of code send it to me. INSTRUCTIONS: First, if you haven't, install Samedi's Obuild.06. It's a very nice OLC patch. ------------ structs.h in char_player_data, after default_mob, add: int shop_edit; /* PC Shop being edited *seditmod* */ ------------ shop.h and shop.c move the following code from shop.h to shop.c: const char *operator_str[] = { "[({", "])}", "|+", "&*", "^'" }; /* Constant list for printing out who we sell to */ const char *trade_letters[] = { "Good", /* First, the alignment based ones */ "Evil", "Neutral", "Magic User", /* Then the class based ones */ "Cleric", "Thief", "Warrior", "\n" } ; char *shop_bits[] = { "WILL_FIGHT", "USES_BANK", "\n" }; Immediatly before boot_the_shops in shop.c add: extern int new_shops; /* seditmod - see config.c */ then replace: if (!top_shop) CREATE(shop_index, struct shop_data, rec_count); with: if (!top_shop) { max_shop_number=rec_count+new_shops; CREATE(shop_index, struct shop_data, max_shop_number); } ------------ act.build.c add the following to the end: #include "shop.h" /* the following function is used in my act.build.c to avoid those huge arrays for command parsing. It looks for a string in an array, You can use it with the arrays in constants.c to parse bitvectors. */ int sscantype(char *names[],char *str) { int nr; int is_abbrev(char *,char *); for (nr = 0; (*names[nr] != '\n'); nr++) if (is_abbrev(str,names[nr])) return(nr); return(-1); }; extern struct room_data *world; extern struct shop_data *shop_index; extern int top_shop; extern int max_shop_number; extern char *item_types[]; extern char *trade_letters[]; #define SHOP_BUF(ch) ((ch)->player.shop_edit) /* calculate the real shop number of a certain shop */ int real_shop(int virtual) { int nr; for (nr=0;nr<top_shop;nr++) { if (SHOP_NUM(nr)==virtual) { return nr; } } return -1; } /* saves this zone's shops into their file */ int shops_to_file(int zone) { int rzone, shop_nr,index; FILE *new_file; char new_fname[64]; char backname[64]; rzone = get_zone_rnum(zone); sprintf(backname, "%s/%i.shp", SHP_PREFIX, zone); sprintf(new_fname, "%s/%i.shp.back", SHP_PREFIX, zone); if(!(new_file = fopen(new_fname, "w"))) return 1; /* Allways save as v3.0 shop files */ fprintf(new_file,"CircleMUD v3.0 Shop File~\n"); for (shop_nr=0;shop_nr<top_shop;shop_nr++) { if (SHOP_NUM(shop_nr)>=zone*100 && SHOP_NUM(shop_nr)<=zone*100+99) { fprintf(new_file,"#%d~\n",SHOP_NUM(shop_nr)); for (index = 0; SHOP_PRODUCT(shop_nr, index) != NOTHING; index++) { fprintf(new_file,"%d\n",obj_index[SHOP_PRODUCT(shop_nr,index)].virtual); }; fprintf(new_file,"-1\n"); fprintf(new_file,"%1.2f\n",SHOP_SELLPROFIT(shop_nr)); fprintf(new_file,"%1.2f\n",SHOP_BUYPROFIT(shop_nr)); for (index = 0; SHOP_BUYTYPE(shop_nr, index) != NOTHING; index++) { fprintf(new_file,"%s",item_types[SHOP_BUYTYPE(shop_nr,index)]); if (SHOP_BUYWORD(shop_nr, index)) fprintf(new_file," %s\n",SHOP_BUYWORD(shop_nr, index)); else fprintf(new_file,"\n"); }; fprintf(new_file,"-1\n"); fprintf(new_file,"%s~\n",shop_index[shop_nr].no_such_item1); fprintf(new_file,"%s~\n",shop_index[shop_nr].no_such_item2); fprintf(new_file,"%s~\n",shop_index[shop_nr].do_not_buy); fprintf(new_file,"%s~\n",shop_index[shop_nr].missing_cash1); fprintf(new_file,"%s~\n",shop_index[shop_nr].missing_cash2); fprintf(new_file,"%s~\n",shop_index[shop_nr].message_buy); fprintf(new_file,"%s~\n",shop_index[shop_nr].message_sell); fprintf(new_file,"%d\n",SHOP_BROKE_TEMPER(shop_nr)); fprintf(new_file,"%d\n",SHOP_BITVECTOR(shop_nr)); fprintf(new_file,"%d\n",mob_index[SHOP_KEEPER(shop_nr)].virtual); fprintf(new_file,"%d\n",SHOP_TRADE_WITH(shop_nr)); for (index = 0; SHOP_ROOM(shop_nr, index) != NOWHERE; index++) { fprintf(new_file,"%d\n",SHOP_ROOM(shop_nr,index)); }; fprintf(new_file,"-1\n"); fprintf(new_file,"%d\n",SHOP_OPEN1(shop_nr)); fprintf(new_file,"%d\n",SHOP_CLOSE1(shop_nr)); fprintf(new_file,"%d\n",SHOP_OPEN2(shop_nr)); fprintf(new_file,"%d\n",SHOP_CLOSE2(shop_nr)); }; }; fprintf(new_file, "$~"); fclose(new_file); remove(backname); rename(new_fname, backname); return 0; }; /* Main shop editing command */ ACMD(do_sedit) { int zone, zn; char field[MAX_INPUT_LENGTH], val_arg[MAX_INPUT_LENGTH]; int s_num,number; half_chop(argument, field, val_arg); /* shop saving command */ if(is_abbrev(field, "save")) { if(SHOP_BUF(ch) == NOWHERE) { if (ZONE_BUF(ch) == NOWHERE) { send_to_char("No shop/zone is being edited.\r\n", ch); return; } else { shops_to_file(ZONE_BUF(ch)); return; } } else if((ZONE_BUF(ch) == 0) && (GET_LEVEL(ch) == LVL_IMPL)) { shops_to_file(SHOP_NUM(SHOP_BUF(ch))/100); send_to_char("Shops saved.\r\n", ch); sprintf(buf, "olc: %s saves the shops of zone #%i", GET_NAME(ch), SHOP_NUM(SHOP_BUF(ch))/100); mudlog(buf, BRF, LVL_GOD, TRUE); return; } else if(SHOP_BUF(ch) > 0) { shops_to_file(SHOP_NUM(SHOP_BUF(ch))/100); send_to_char("Shops saved.\r\n", ch); sprintf(buf, "olc: %s saves the shops of zone #%i", GET_NAME(ch), SHOP_NUM(SHOP_BUF(ch))/100); mudlog(buf, BRF, LVL_GOD, TRUE); return; } else { send_to_char("Shops not saved.\r\n", ch); return; } } else if (is_abbrev(field,"done")) { SHOP_BUF(ch)=NOWHERE; /* editting commands */ } else { if ((number = atoi(field)) < 0) { send_to_char("A NEGATIVE number??\r\n", ch); return; } if ((s_num = real_shop(number)) >= 0) { SHOP_BUF(ch)=s_num; send_to_char("OK.\r\n",ch); return; } else if (number==0) { send_to_char("You must indicate a non-zero shop number.\r\n",ch); return; } else { send_to_char("There is no shop with that number.\r\n",ch); send_to_char("Creating new one.\r\n",ch); } zn = get_zon_num(number/100); zone = get_zone_perms(ch, zn); if(zone == -1) return; /* now we create the new shop. */ if (top_shop==max_shop_number) { send_to_char("You must reboot to allocate new slots for shops.\r\n",ch); } else { SHOP_BUF(ch)=top_shop; SHOP_NUM(top_shop)=number; /* No shopkeeper by default */ SHOP_KEEPER(top_shop)=-1; /* Shops open all day by default */ SHOP_OPEN1(top_shop)=0; SHOP_OPEN2(top_shop)=0; SHOP_CLOSE1(top_shop)=28; SHOP_CLOSE2(top_shop)=0; /* Creating the array for rooms. One room. The present room. */ CREATE(shop_index[top_shop].in_room, int, 2); SHOP_ROOM(top_shop,0)=world[ch->in_room].number; SHOP_ROOM(top_shop,1)=NOWHERE; /* Creating the products index. Currently empty. */ CREATE(shop_index[top_shop].producing,int,1); SHOP_PRODUCT(top_shop,0)=NOTHING; /* Creating the bought types index. Empty for starters. */ CREATE(shop_index[top_shop].type, struct shop_buy_data,1); SHOP_BUYTYPE(top_shop,0)=NOTHING; SHOP_BUYWORD(top_shop,0)=NULL; top_shop++; } }; }; /* Set the values of the current shop */ char *sset_params[]= { "products", "rooms", "owner", "buyat", "sellat", "open", "bank", "buytypes", "bnonex" , "snonex", "wrongsold", "scantafford", "pcantafford", "buyitem", "sellitem", "fight", "\n" }; ACMD(do_sset) { int cmmd,v_num,r_num,encontrei=0; float profit; char field[MAX_INPUT_LENGTH], val_arg[MAX_INPUT_LENGTH]; int *new_rooms; int aux,o1,o2,c1,c2,i,index; struct shop_buy_data *new_types; half_chop(argument,field,val_arg); if (SHOP_BUF(ch)==NOWHERE) { send_to_char("But you aren't editing any shop!?\r\n",ch); return; } do { /* is it a trade with flag? */ if ((cmmd=sscantype(trade_letters,field))>=0) { TOGGLE_BIT(SHOP_TRADE_WITH(SHOP_BUF(ch)),cmmd); send_to_char("OK.\r\n",ch); break; } else { /* check wich command it is */ for (cmmd=0;!(*(sset_params[cmmd])=='\n' || is_abbrev(field,sset_params[cmmd]));cmmd++); switch (cmmd) { case 0: /* command products */ half_chop(val_arg,field,val_arg); if (is_abbrev(field,"add")) { if (!is_number(val_arg)) { send_to_char("You must specify a object number.\r\n",ch); return; } else { v_num=atoi(val_arg); if ((r_num=real_object(v_num))<0) { send_to_char("That object number does not exist.\r\n",ch); return; }; }; for (cmmd=0;SHOP_PRODUCT(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++); CREATE(new_rooms,int,cmmd+2); for (cmmd=0;SHOP_PRODUCT(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++) new_rooms[cmmd]=SHOP_PRODUCT(SHOP_BUF(ch),cmmd); free(shop_index[SHOP_BUF(ch)].producing); new_rooms[cmmd]=r_num; new_rooms[cmmd+1]=NOTHING; shop_index[SHOP_BUF(ch)].producing=new_rooms; sprintf(buf,"Ok. The shop now produces %s.\r\n", obj_proto[r_num].short_description); } else if (is_abbrev(field,"delete")) { if (!is_number(val_arg)) { send_to_char("You must specify a object number.\r\n",ch); return; }; v_num=atoi(val_arg); r_num=real_object(v_num); for (cmmd=0;SHOP_PRODUCT(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++) if (SHOP_PRODUCT(SHOP_BUF(ch),cmmd)==r_num) encontrei=1; if (!encontrei) { send_to_char("That object number is not valid for this shop.\r\n",ch); return; }; CREATE(new_rooms,int, cmmd+1); aux=0; for(cmmd=0;SHOP_PRODUCT(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++) if (SHOP_PRODUCT(SHOP_BUF(ch),cmmd)!=r_num) new_rooms[aux++]=SHOP_PRODUCT(SHOP_BUF(ch),cmmd); free(shop_index[SHOP_BUF(ch)].producing); new_rooms[aux]=NOWHERE; shop_index[SHOP_BUF(ch)].producing=new_rooms; }; send_to_char("OK.\r\n",ch); break; case 1: /* command room */ half_chop(val_arg,field,val_arg); if (is_abbrev(field,"add")) { if (!is_number(val_arg)) { send_to_char("You must specify a room number.\r\n",ch); return; } else { v_num=atoi(val_arg); if ((r_num=real_room(v_num))<0) { send_to_char("That room number does not exist.\r\n",ch); return; }; }; for (cmmd=0;SHOP_ROOM(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++); CREATE(new_rooms,int,cmmd+2); for (cmmd=0;SHOP_ROOM(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++) new_rooms[cmmd]=SHOP_ROOM(SHOP_BUF(ch),cmmd); free(shop_index[SHOP_BUF(ch)].in_room); new_rooms[cmmd]=v_num; new_rooms[cmmd+1]=NOWHERE; shop_index[SHOP_BUF(ch)].in_room=new_rooms; } else if (is_abbrev(field,"delete")) { if (!is_number(val_arg)) { send_to_char("You must specify a room number.\r\n",ch); return; }; v_num=atoi(val_arg); for (cmmd=0;SHOP_ROOM(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++) if (SHOP_ROOM(SHOP_BUF(ch),cmmd)==v_num) encontrei=1; if (!encontrei) { send_to_char("That room number is not valid for this shop.\r\n",ch); return; }; CREATE(new_rooms,int, cmmd+1); r_num=0; for(cmmd=0;SHOP_ROOM(SHOP_BUF(ch),cmmd)!=NOWHERE;cmmd++) if (SHOP_ROOM(SHOP_BUF(ch),cmmd)!=v_num) new_rooms[r_num++]=SHOP_ROOM(SHOP_BUF(ch),cmmd); free(shop_index[SHOP_BUF(ch)].in_room); new_rooms[r_num]=NOWHERE; shop_index[SHOP_BUF(ch)].in_room=new_rooms; }; send_to_char("OK.\r\n",ch); break; case 2: /* command owner */ half_chop(val_arg,field,val_arg); v_num=atoi(field); if ((r_num=real_mobile(v_num))<0) { send_to_char("That mobile does not exist!\r\n",ch); return; } else { send_to_char("OK.\r\n",ch); SHOP_KEEPER(SHOP_BUF(ch))=r_num; break; } case 3: /* sell profit */ half_chop(val_arg,field,val_arg); profit=atof(field); if (profit<1) { send_to_char("The sell profit must be more than 1.\r\n",ch); return; } send_to_char("OK.\r\n",ch); SHOP_SELLPROFIT(SHOP_BUF(ch))=profit; break; case 4: /* buy profit */ half_chop(val_arg,field,val_arg); profit=atof(field); if (profit>1) { send_to_char("The buy profit must be less than 1.\r\n",ch); return; } if (profit<0) { send_to_char("Profits can't be negative.\r\n",ch); return; } send_to_char("OK!\r\n",ch); SHOP_BUYPROFIT(SHOP_BUF(ch))=profit; break; case 5: i=sscanf(val_arg,"[%d-%d,%d-%d]",&o1,&c1,&o2,&c2); if (i<4) { send_to_char("The correct format is: [<open>-<close>,<open>-<close>]\r\n",ch); return; } send_to_char("Ok.\r\n",ch); SHOP_OPEN1(SHOP_BUF(ch))=o1; SHOP_CLOSE1(SHOP_BUF(ch))=c1; SHOP_OPEN2(SHOP_BUF(ch))=o2; SHOP_CLOSE2(SHOP_BUF(ch))=c2; break; case 6: TOGGLE_BIT(SHOP_BITVECTOR(SHOP_BUF(ch)),WILL_START_FIGHT); break; case 7: /* command buytypes */ half_chop(val_arg,field,val_arg); if (is_abbrev(field,"add")) { half_chop(val_arg,field,val_arg); for (cmmd=0;SHOP_BUYTYPE(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++); for (index = 0, r_num = NOTHING; *item_types[index] != '\n'; index++) if (is_abbrev(field, item_types[index])) r_num = index; if (r_num==NOTHING) { send_to_char("That is an invalid type!\r\n",ch); return; }; CREATE(new_types,struct shop_buy_data,cmmd+2); for (cmmd=0;SHOP_BUYTYPE(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++) { BUY_TYPE(new_types[cmmd])=SHOP_BUYTYPE(SHOP_BUF(ch),cmmd); BUY_WORD(new_types[cmmd])=SHOP_BUYWORD(SHOP_BUF(ch),cmmd); } BUY_TYPE(new_types[cmmd])=r_num; if (*val_arg) BUY_WORD(new_types[cmmd])=str_dup(val_arg); else BUY_WORD(new_types[cmmd])=NULL; BUY_TYPE(new_types[cmmd+1])=NOTHING; BUY_WORD(new_types[cmmd+1])=NULL; free(shop_index[SHOP_BUF(ch)].type); shop_index[SHOP_BUF(ch)].type=new_types; } else if (is_abbrev(field,"delete")) { if (!is_number(val_arg)) { send_to_char("You must specify a type order number.\r\n",ch); return; }; v_num=atoi(val_arg); for(cmmd=0;SHOP_BUYTYPE(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++); if (v_num>cmmd) { send_to_char("That order number does not exist.\n\r",ch); return; } CREATE(new_types,struct shop_buy_data, cmmd+1); aux=0; for(cmmd=0;SHOP_BUYTYPE(SHOP_BUF(ch),cmmd)!=NOTHING;cmmd++) if (cmmd!=v_num) { BUY_TYPE(new_types[aux])=SHOP_BUYTYPE(SHOP_BUF(ch),cmmd); BUY_WORD(new_types[aux])=SHOP_BUYWORD(SHOP_BUF(ch),cmmd); aux++; } free(shop_index[SHOP_BUF(ch)].type); BUY_TYPE(new_types[aux])=NOTHING; shop_index[SHOP_BUF(ch)].type=new_types; } else { send_to_char("Error in subcommand.\r\n",ch); return; }; send_to_char("OK.\r\n",ch); break; case 8: if (shop_index[SHOP_BUF(ch)].no_such_item1) free(shop_index[SHOP_BUF(ch)].no_such_item1); shop_index[SHOP_BUF(ch)].no_such_item1=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 9: if (shop_index[SHOP_BUF(ch)].no_such_item2) free(shop_index[SHOP_BUF(ch)].no_such_item2); shop_index[SHOP_BUF(ch)].no_such_item2=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 10: if (shop_index[SHOP_BUF(ch)].missing_cash1) free(shop_index[SHOP_BUF(ch)].missing_cash1); shop_index[SHOP_BUF(ch)].missing_cash1=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 11: if (shop_index[SHOP_BUF(ch)].missing_cash2) free(shop_index[SHOP_BUF(ch)].missing_cash2); shop_index[SHOP_BUF(ch)].missing_cash2=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 12: if (shop_index[SHOP_BUF(ch)].do_not_buy) free(shop_index[SHOP_BUF(ch)].do_not_buy); shop_index[SHOP_BUF(ch)].do_not_buy=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 13: if (shop_index[SHOP_BUF(ch)].message_buy) free(shop_index[SHOP_BUF(ch)].message_buy); shop_index[SHOP_BUF(ch)].message_buy=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 14: if (shop_index[SHOP_BUF(ch)].message_sell) free(shop_index[SHOP_BUF(ch)].message_sell); shop_index[SHOP_BUF(ch)].message_sell=str_dup(val_arg); send_to_char("OK.\r\n",ch); return; break; case 15: TOGGLE_BIT(SHOP_BITVECTOR(SHOP_BUF(ch)),WILL_BANK_MONEY); break; default: send_to_char("Unknown command.\r\n",ch); send_to_char("Syntax: sset <option>\r\n",ch); send_to_char("Where option can be:\r\n",ch); send_to_char(" products\r\n",ch); send_to_char(" rooms\r\n",ch); send_to_char(" owner - number of the shopkeeper\r\n",ch); send_to_char(" sellat - profit when selling\r\n",ch); send_to_char(" buyat - profit when buying\r\n",ch); send_to_char(" open\r\n",ch); send_to_char(" bank\r\n",ch); send_to_char(" buytypes\r\n",ch); send_to_char(" messages:\r\n",ch); send_to_char(" bnonex - the shop doesn't have the product\r\n",ch); send_to_char(" snonex - the player doesn't have the product\r\n",ch); send_to_char(" wrongsold - the shop doesn't buy that item\r\n",ch); send_to_char(" scantafford - shop can't afford product\r\n",ch); send_to_char(" pcantafford - player can't afford product\r\n",ch); send_to_char(" buyitem - when shop buying\r\n",ch); send_to_char(" sellitem - when player buying item\r\n",ch); send_to_char("\r\n",ch); break; } } half_chop(val_arg,field,val_arg); } while (val_arg[0]); } void list_messages(struct char_data *ch,int shop_nr) { strcpy(buf,"The messages of the shop are:\r\n"); sprintf(buf,"%sbuy non exist. : %s\n\r",buf,shop_index[shop_nr].no_such_item1); sprintf(buf,"%ssell non exist.: %s\n\r",buf,shop_index[shop_nr].no_such_item2); sprintf(buf,"%swrong type: %s\r\n",buf,shop_index[shop_nr].do_not_buy); sprintf(buf,"%sshp can't afford: %s\r\n",buf,shop_index[shop_nr].missing_cash1); sprintf(buf,"%splr can't afford: %s\r\n",buf,shop_index[shop_nr].missing_cash2); sprintf(buf,"%sbuying: %s\r\n",buf,shop_index[shop_nr].message_buy); sprintf(buf,"%sselling: %s\r\n",buf,shop_index[shop_nr].message_sell); send_to_char(buf,ch); } ACMD(do_sstat) { void list_detailed_shop(struct char_data * ch, int shop_nr); if (SHOP_BUF(ch)) { list_detailed_shop(ch,SHOP_BUF(ch)); list_messages(ch,SHOP_BUF(ch)); } else { send_to_char("You must be editing a shop to show it's stats.\r\n",ch); } } -------------- config.c add somewhere: /* maximum number of new shops allowed buy seditor */ int new_shops = 10; /* seditmod */ -------------- interpreter.c in the ACMD() section add the lines: ACMD(do_sedit); /*seditmod*/ ACMD(do_sset); /*seditmod*/ ACMD(do_sstat); /*seditmod*/ in the Master Command Table(TM) add: { "sedit" , POS_DEAD , do_sedit , LVL_GOD, 0 }, /* seditmod */ { "sset" , POS_DEAD , do_sset , LVL_GOD, 0 }, /* seditmod */ { "sstat" , POS_DEAD , do_sstat , LVL_GOD, 0 }, /* seditmod */ I think that's all. If you install it ok, could you please tell me, so that i can upload it to the ftp site and send it to Sam? Sorry for the inconvenience. Sincerely, (sp?) Luis Carvalho
This archive was generated by hypermail 2b30 : 12/07/00 PST