This snippet will allow you to set mobs as bounty collectors where players can set and collect bounties on other players. It is currently set up for my mud where pkill status is determined by clan, ie in a clan = pkill. If your mud is set up different then you'll have to make some minor changes in if checks in do_bounty. They are noted with comments so easy to find. Without further ado, here are the install instructions: Changes to existing files: -------------------------- *** merc.h *** Assign ACT_BOUNTY to a free act flag. To the vnum define section add: #define OBJ_VNUM_SEVERED_HEAD 12 Replace the 12 with whatever vnum is convenient for you. Under this line: typedef struct weather_data WEATHER_DATA; Add: typedef struct bounty_data BOUNTY_DATA; Under this section: struct buf_type { BUFFER * next; bool valid; sh_int state; /* error state of the buffer */ sh_int size; /* size in k */ char * string; /* buffer's string */ }; Add: /* * Bounty stuff -- by Gomi no sensei */ struct bounty_data { BOUNTY_DATA *next; bool valid; char * name; int amount; }; Under this line: extern OBJ_DATA * object_list; Add: extern BOUNTY_DATA * bounty_list; Under this line: #define MUSIC_FILE "music.txt" Add: #define BOUNTY_FILE "bounty.txt" Under this line: void update_handler args( ( void ) ); Add: /* bounty.c */ bool is_bountied args( (CHAR_DATA *ch) ); *** recycle.h *** Add this at the bottom: /* bounty recycling */ #define BD BOUNTY_DATA BD *new_bounty args( (void) ); void free_bounty args( (BOUNTY_DATA *b) ); #undef BD *** db.c *** Under this line: void load_bans args( ( void ) ); Add: void load_bounties args( ( void ) ); Under this line: load_songs(); Add: load_bounties(); *** fight.c *** Right before the call to raw_kill() in damage() add: /* Make the head for a bountied PC */ if(!IS_NPC(victim) && !IS_NPC(ch) && is_bountied(victim)) { char buf[MAX_STRING_LENGTH]; char *name; OBJ_DATA *obj; name = str_dup(victim->name); obj = create_object(get_obj_index(OBJ_VNUM_SEVERED_HEAD),0); obj->extra_flags |= ITEM_NODROP|ITEM_NOUNCURSE; sprintf(buf, "%s %s", "head", name); free_string( obj->name ); obj->name = str_dup( buf); sprintf( buf, obj->short_descr, name ); free_string( obj->short_descr ); obj->short_descr = str_dup( buf ); sprintf( buf, obj->description, name ); free_string( obj->description ); obj->description = str_dup( buf ); obj_to_char(obj,ch); free_string(name); } *** handler.c *** In the act_bit_name function right under this line: if (act_flags & ACT_UPDATE_ALWAYS) strcat(buf," update_always"); Add: if (act_flags & ACT_BOUNTY) strcat(buf," bounty"); *** recycle.c *** Right before this line: /* stuff for setting ids */ Add: /* stuff for recycling bounties */ BOUNTY_DATA *bounty_free; BOUNTY_DATA *new_bounty(void) { static BOUNTY_DATA b_zero; BOUNTY_DATA *b; if (bounty_free == NULL) b = alloc_perm(sizeof(*b)); else { b = bounty_free; bounty_free = bounty_free->next; } *b = b_zero; VALIDATE(b); return b; } void free_bounty(BOUNTY_DATA *b) { if (!IS_VALID(b)) return; free_string( b->name ); INVALIDATE(b); b->next = bounty_free; bounty_free = b; } *** tables.c *** In the appropriate place in the act_flags table add: { "bounty", X, TRUE }, Replace X with whatever flag you used for ACT_BOUNTY Finally, just add do_bounty to interp.h and interp.c as normal and do a clean make (rm *.o followed by make). The severed head object I use is below, add it to limbo.are somewhere. To make a mob a bounty collector, just flag him with ACT_BOUNTY in the area file and voila, he will accept and pay out bounties. I've also included a help file entry that explains the whole bounty system. You don't have to email me or give me credit or anything, though I don't mind if you do. If you find any bugs please email me so I can fix 'em. Gomi no sensei slaughterdog@yahoo.com AKA Kyless on The Mind's Eye (mindeye.mudservices.com 7777) ---------------cut here for the head---------------------------------------- The vnum can be whatever you need, I just happened to use 12. Make sure you have OBJ_VNUM_SEVERED_HEAD properly defined in merc.h. #12 head~ the head of %s~ The severed head of %s is lying here.~ meat~ trash 0 A 0 0 0 0 0 0 50 0 D ---------------cut here for the help entry---------------------------------- -1 'BOUNTY SYSTEM'~ The bounty system allows player killers to set bounties on one another and to collect said bounties. To place a bounty on a player, first you must both be player killers. If that condition is met, then you can go ahead and find a Bounty Collector. A Bounty Collector is a particular mobile similar to a shopkeeper, though instead of buying and selling goods he provides a service. For a small fee the Collector will add a player's name and a price on his head to the Dead Books, a list of all the individuals who someone was willing to pay to have killed. To protect your privacy, the Collector will allow you to set a bounty on a player regardless of whether they are visible, invisible, online, or offline. For an additional surcharge, the price on a particular player's head can be raised. Finally, for a significant fee, a player's name can be erased from the Dead Books, so be sure your target isn't richer than you. If you wish to collect on a bounty rather than place one, the Collector can help there as well. The Collector maintains the Dead Books and will let you refer to them as needed to obtain a list of the bountied. A would-be bounty hunter then must track down and kill his target. All that remains to do following that is to provide proof to the Collector, namely the victim's head. Conveniently, the victim's head will be automatically transferred to the bounty hunter's inventory upon his killing of the victim. This saves the player from repeating the grisly actions that his character must perform in order to obtain the head. Return to the Collector with the proof of the deed and he will provide payment. It's better not to ask what the Collector does with the heads. For further information, see the help file on the BOUNTY command. Originally designed by Gomi no Sensei AKA Kyless of The Mind's Eye. ~ -1 BOUNTY~ Syntax: bounty bounty collect <player> bounty remove <player> bounty <player> <amount> BOUNTY is the command used in conjunction with a Bounty Collector to place and collect bounties. With no argument, BOUNTY provides a list of all the currently bountied individuals. BOUNTY collect lets you collect the bounty on a player's head, assuming you have the required proof. BOUNTY remove lets a person remove a bounty placed on somebody's head. BOUNTY with a player's name and amount places a bounty of that amount on the player. For further information see HELP BOUNTY SYSTEM. ~ ---------------cut here for bounty.c---------------------------------------- /*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ****************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ****************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include "merc.h" #include "interp.h" #include "recycle.h" /* Global variables */ BOUNTY_DATA *bounty_list; /* Command functions needed */ DECLARE_DO_FUN(do_say ); /* Function definitions */ int clan_lookup args( (const char *name) ); /* And some local defines */ #define BOUNTY_PLACE_CHARGE 3 #define BOUNTY_REMOVE_CHARGE 100 #define BOUNTY_ADD_CHARGE 5 #define MIN_BOUNTY 1000 void save_bounties() { FILE *fp; BOUNTY_DATA *bounty; bool found = FALSE; fclose(fpReserve); if ( ( fp = fopen( BOUNTY_FILE, "w" ) ) == NULL ) { perror( BOUNTY_FILE ); } for( bounty = bounty_list; bounty != NULL; bounty = bounty->next) { found = TRUE; fprintf(fp,"%-12s %d\n",bounty->name,bounty->amount); } fclose(fp); fpReserve = fopen( NULL_FILE, "r" ); if(!found) unlink(BOUNTY_FILE); } void load_bounties() { FILE *fp; BOUNTY_DATA *blist; if ( ( fp = fopen( BOUNTY_FILE, "r" ) ) == NULL ) return; blist = NULL; for( ; ; ) { BOUNTY_DATA *bounty; if ( feof(fp) ) { fclose(fp); return; } bounty = new_bounty(); bounty->name = str_dup(fread_word(fp)); bounty->amount = fread_number(fp); fread_to_eol(fp); if(bounty_list == NULL) bounty_list = bounty; else blist->next = bounty; blist = bounty; } } bool is_bountied(CHAR_DATA *ch) { BOUNTY_DATA *bounty; bool found = FALSE; if(IS_NPC(ch)) return FALSE; for(bounty = bounty_list; bounty != NULL; bounty = bounty->next) { if( !str_cmp(ch->name,bounty->name) ) found = TRUE; } return found; } void do_bounty(CHAR_DATA *ch, char *argument) { FILE *fp; CHAR_DATA *vch; BOUNTY_DATA *bounty; BOUNTY_DATA *prev=NULL; char arg[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; char strsave[MAX_STRING_LENGTH]; char *word; bool found = FALSE; bool clanned = FALSE; int cash, amount, surcharge; if( IS_NPC(ch) ) return; /* Check for the bounty collector */ for(vch = ch->in_room->people; vch ; vch = vch->next_in_room) { if(IS_NPC(vch) && IS_SET(vch->act, ACT_BOUNTY)) break; } if(vch == NULL) { send_to_char("You cannot do that here.\n\r",ch); return; } /* Only clanned chars/pkillers can place bounties. */ if( !is_clan(ch) ) { do_say(vch,"You must be in a clan to place or collect a bounty."); return; } argument = one_argument(argument, arg); one_argument(argument, arg2); if(arg[0] == '\0') { do_say(vch,"These are the bounties I will honor:"); send_to_char(" Name Bounty\n\r",ch); send_to_char(" ============ ===============\n\r",ch); for(bounty = bounty_list;bounty != NULL;bounty=bounty->next) { sprintf(buf," %-12s %d\n\r",bounty->name,bounty->amount); send_to_char(buf,ch); } return; } if( arg2[0] == '\0' || (str_cmp(arg,"remove") && str_cmp(arg,"collect") && !is_number(arg2)) ) { send_to_char("Syntax: bounty\n\r",ch); send_to_char(" bounty remove <player>\n\r",ch); send_to_char(" bounty collect <player>\n\r",ch); send_to_char(" bounty <player> <amount>\n\r",ch); return; } /* For collecting bounties. */ if( !str_cmp(arg,"collect") ) { OBJ_DATA *obj; for(bounty = bounty_list; bounty != NULL; prev=bounty, bounty=bounty->next) { if( !str_cmp(capitalize(arg2),capitalize(bounty->name)) ) break; } if( bounty == NULL ) { do_say(vch,"That individual is not in the books."); return; } for(obj = ch->carrying; obj != NULL; obj = obj->next) { if( is_name(arg2,obj->name) && (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_HEAD) ) break; } if( obj == NULL ) { do_say(vch,"I'm afraid I'll need proof of the death."); return; } extract_obj(obj); do_say(vch,"Very well, here is your payment."); ch->pcdata->bank_gold += bounty->amount; /* * OK, we've got a valid bounty and they've * been paid. Time to remove the bounty. */ if(prev == NULL) bounty_list = bounty_list->next; else prev->next = bounty->next; free_bounty(bounty); save_bounties(); return; } /* For buying off bounties. */ if( !str_cmp(arg,"remove") ) { for(bounty = bounty_list; bounty != NULL; prev=bounty, bounty=bounty->next) { if( !str_cmp(arg2,bounty->name) ) break; } if( bounty == NULL ) { do_say(vch,"That individual is not in the books."); return; } surcharge = BOUNTY_REMOVE_CHARGE; amount = bounty->amount+(bounty->amount*surcharge/100); cash = ch->gold + (ch->silver/100) + ch->pcdata->bank_gold + (ch->pcdata->bank_silver/100); if(cash < amount) { do_say(vch,"You cannot afford to remove that bounty."); return; } if(ch->pcdata->bank_silver < (amount*100)) { amount -= (ch->pcdata->bank_silver/100); ch->pcdata->bank_silver %= 100; } else { ch->pcdata->bank_silver -= amount*100; amount = 0; } if(ch->pcdata->bank_gold < amount) { amount -= ch->pcdata->bank_gold; ch->pcdata->bank_silver = 0; } else { ch->pcdata->bank_gold -= amount; amount = 0; } if(ch->silver < (amount*100)) { amount -= (ch->silver/100); ch->silver %= 100; } else { ch->silver -= amount*100; amount = 0; } if(ch->gold < amount) { amount -= ch->gold; ch->gold = 0; } else { ch->gold -= amount; amount = 0; } /* * OK, we've got a valid bounty and they can * pay. Time to remove the bounty. */ if(prev == NULL) bounty_list = bounty_list->next; else prev->next = bounty->next; free_bounty(bounty); do_say(vch,"The name has been removed from the books."); save_bounties(); return; } /* * This code allows you to bounty those * offline as well as those not visible. */ fclose(fpReserve); sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(arg)); if ( ( fp = fopen( strsave, "r" ) ) == NULL ) { do_say(vch,"I am afraid there is no such person."); fpReserve = fopen( NULL_FILE, "r" ); return; } strcpy(arg,capitalize(arg)); while( !found ) { char *clanName; word = feof(fp) ? "End" : fread_word( fp ); if( !str_cmp(word, "Clan") ) { found = TRUE; clanName = fread_string(fp); clanned = clan_lookup(clanName) ? TRUE : FALSE; free_string(clanName); } else if( !str_cmp(word, "End") ) { found = TRUE; } else { fread_to_eol( fp ); } } fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); /* Only clanned chars can be bountied */ if( !clanned ) { do_say(vch,"You cannot place bounties on non-clanned characters."); return; } /* Minimum bounty, change as desired */ if( (amount = atoi(arg2)) < MIN_BOUNTY) { sprintf(buf,"I do not accept bounties under %d gold.",MIN_BOUNTY); do_say(vch,buf); return; } /* * Char's cash total in gold, bounties * are always set in gold. Notice the */ cash = ch->gold + (ch->silver/100) + ch->pcdata->bank_gold + (ch->pcdata->bank_silver/100); /* * Does the bounty already exist? * Let's find out. */ for(bounty = bounty_list;bounty != NULL;bounty = bounty->next) { if( !str_cmp(bounty->name,arg) ) break; } /* * Either create a new bounty * or add to an existing one. * Notice the charge added to * place a bounty and the * additional one to add to a * bounty. Don't want to make * it too cheap. Again, change * as desired. */ if(bounty == NULL) { surcharge = BOUNTY_PLACE_CHARGE; if(cash < (amount+(amount*surcharge/100))) { do_say(vch,"You cannot afford to place that bounty."); return; } bounty = new_bounty(); bounty->name = str_dup(arg); bounty->amount = amount; bounty->next = bounty_list; bounty_list = bounty; amount += amount*surcharge/100; } else { sprintf(buf,"There is a %d%% surcharge to add to an existing bounty.",BOUNTY_ADD_CHARGE); do_say(vch,buf); surcharge = BOUNTY_PLACE_CHARGE + BOUNTY_ADD_CHARGE; amount += amount*surcharge/100; if(cash < amount) { do_say(vch,"You cannot afford to place that bounty."); return; } bounty->amount += amount; } save_bounties(); /* * Now make them pay, start with bank * then go to cash on hand. Also use * up that annoying silver first. */ if(ch->pcdata->bank_silver < (amount*100)) { amount -= (ch->pcdata->bank_silver/100); ch->pcdata->bank_silver %= 100; } else { ch->pcdata->bank_silver -= amount*100; amount = 0; } if(ch->pcdata->bank_gold < amount) { amount -= ch->pcdata->bank_gold; ch->pcdata->bank_silver = 0; } else { ch->pcdata->bank_gold -= amount; amount = 0; } if(ch->silver < (amount*100)) { amount -= (ch->silver/100); ch->silver %= 100; } else { ch->silver -= amount*100; amount = 0; } if(ch->gold < amount) { amount -= ch->gold; ch->gold = 0; } else { ch->gold -= amount; amount = 0; } do_say(vch,"Your bounty has been recorded in the books."); }