/***************************************************************************
* 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 Envy Diku Mud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* 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 *
* *
* Code Adapted and Improved by Abandoned Realms Mud *
* and Aabahran: The Forsaken Lands Mud by Virigoth *
* *
* Continued Production of this code is available at www.flcodebase.com *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <malloc.h>
#include "merc.h"
#include "recycle.h"
#include "bounty.h"
#include "cabal.h"
#include "interp.h"
#include "jail.h"
#include "save_mud.h"
/***************************************************************/
/*Following are bounty orientanted routines for Forsaken Lands */
/*mud created by Virigoth circa 2002. Copyrighted for Forsaken*/
/*Lands mud June 1, 2002. Do not use or copy without explicit */
/*permission of author. (Voytek Plawny aka Virigoth) */
/***************************************************************/
extern PACT_DATA* pact_list;
/* global bounty list */
BOUNTY_DATA* bounty_list = NULL;
/* attatches an objec to a bounty bid and puts it in a bounty room */
void obj_to_bbid( OBJ_DATA* obj, BBID_DATA* bbid ){
if (obj == NULL || bbid == NULL)
return;
else if (obj->in_room )
obj_from_room( obj );
else if (obj->carried_by)
obj_from_char( obj );
else if (obj->in_obj )
obj_from_obj ( obj );
else if (obj->bbid )
obj_from_bbid( obj );
if (bbid->obj == NULL){
bbid->obj = obj;
bbid->obj->next_bidobj = NULL;
}
else{
obj->next_bidobj = bbid->obj;
bbid->obj = obj;
}
obj_to_room( obj, get_room_index( ROOM_VNUM_BOUNTY ));
obj->bbid = bbid;
}
/* removes an object from bounty room and the bid list */
void obj_from_bbid( OBJ_DATA* obj ){
BBID_DATA* bbid = obj->bbid;
if (bbid == NULL){
bug("obj_from_bbid: obj has no bounty bid.", 0);
return;
}
if (obj->in_room && obj->in_room->vnum == ROOM_VNUM_BOUNTY )
obj_from_room( obj );
if ( obj == bbid->obj )
bbid->obj = obj->next_bidobj;
else{
OBJ_DATA *prev;
for ( prev = bbid->obj; prev; prev = prev->next_bidobj ){
if ( prev->next_bidobj == obj ){
prev->next_bidobj = obj->next_bidobj;
break;
}
}
if ( prev == NULL ){
bug( "Obj_from_bbid: obj not found.", 0 );
return;
}
}
obj->next_bidobj = NULL;
obj->bbid = NULL;
}
/* creates/destroys bounty bids, we do not use lists for this */
BBID_DATA* new_bbid(void){
BBID_DATA* pBb = (BBID_DATA*) malloc( sizeof( *pBb ));
/* reset initial things */
pBb->next = NULL;
pBb->bounty = NULL;
pBb->name = str_dup("");
pBb->level = 0;
pBb->pCabal = NULL;
pBb->cp = 0;
pBb->gp = 0;
pBb->obj = NULL;
return pBb;
};
void free_bbid( BBID_DATA* pBb ){
if (pBb == NULL)
return;
free_string( pBb->name );
pBb->next = NULL;
free( pBb );
}
/* creates destroys bounties */
BOUNTY_DATA *bounty_free;
BOUNTY_DATA *new_bounty(){
BOUNTY_DATA *pB;
if (bounty_free == NULL)
pB = alloc_perm(sizeof(*pB));
else
{
pB = bounty_free;
bounty_free = bounty_free->next;
}
pB->next = NULL;
pB->bids = NULL;
pB->time_stamp = 0;
pB->name = str_empty;
VALIDATE(pB);
return pB;
}
void free_bounty(BOUNTY_DATA *bounty)
{
if (!IS_VALID(bounty))
return;
if (!IS_NULLSTR(bounty->name))
free_string( bounty->name);
/* free bids */
while (bounty->bids){
BBID_DATA* pBb = bounty->bids;
bounty->bids = pBb->next;
free_bbid( pBb );
}
INVALIDATE( bounty );
bounty->next = bounty_free;
bounty_free = bounty;
}
/* adds a bounty onto the bounty list */
void add_bounty( BOUNTY_DATA* pb ){
CHAR_DATA* victim;
if (bounty_list == NULL){
bounty_list = pb;
pb->next = NULL;
}
else{
/* we always insert the bountys from oldest to newest */
BOUNTY_DATA* last = bounty_list;
for (last = bounty_list; last->next != NULL; last = last->next);
pb->time_stamp = UMAX(last->time_stamp + 1, pb->time_stamp );
last->next = pb;
pb->next = NULL;
}
/* check if the target of this bounty is about */
if ( (victim = char_file_active( pb->name)) != NULL){
victim->pcdata->pbounty = pb;
}
}
/* removes a bounty from the bounty list */
bool rem_bounty( BOUNTY_DATA* pb ){
BOUNTY_DATA* prev = bounty_list;
if (bounty_list == NULL){
bug("rem_bounty: bounty_list null.", 0);
return FALSE;
}
if (prev == pb )
bounty_list = pb->next;
else{
while (prev->next && prev->next != pb){
prev = prev->next;
}
}
if (prev == NULL){
bug("rem_bounty: bounty note found.", 0);
return FALSE;
}
prev->next = pb->next;
pb->next = NULL;
return TRUE;
}
/* removes a single bid from a bounty */
void bid_from_bounty( BBID_DATA* bbid ){
BOUNTY_DATA* bounty = bbid->bounty;
if (bounty == NULL){
bug("bid_from_bounty: bid not on bounty.", 0);
return;
}
if (bounty->bids == bbid ){
bounty->bids = bbid->next;
bbid->next = NULL;
}
else{
BBID_DATA* prev = bounty->bids;
for (; prev; prev = prev->next){
if (prev->next == bbid){
prev->next = bbid->next;
break;
}
}
if ( prev == NULL ){
bug( "bid_from_bounty: bid not found.", 0 );
return;
}
}
bbid->bounty = NULL;
bbid->next = NULL;
}
/* adds a single bounty bid onto a bounty */
BBID_DATA* bid_to_bounty( BBID_DATA* bbid, BOUNTY_DATA* bounty ){
if (bbid == NULL || bounty == NULL)
return NULL;
else if (bbid->bounty)
bid_from_bounty( bbid );
if (bounty->bids == NULL){
bounty->bids = bbid;
bbid->next = NULL;
}
else{
BBID_DATA* last = bounty->bids;
while (last->next)
last = last->next;
last->next = bbid;
bbid->next = NULL;
}
bbid->bounty = bounty;
return bbid;
}
/* returns bid from given bounty with given name */
BBID_DATA* get_bbid( BOUNTY_DATA* bounty, char* name ){
BBID_DATA* bbid;
int num = 0;
int count = 0;
if (bounty == NULL || IS_NULLSTR( name ))
return NULL;
else{
bbid = bounty->bids;
num = atoi( name );
}
for (; bbid; bbid = bbid->next){
if (num && ++count == num)
return bbid;
else if (LOWER(name[0]) == LOWER(bbid->name[0]) && !str_cmp(name, bbid->name))
return bbid;
}
return NULL;
}
/* returns a bounty if found based on victim name */
BOUNTY_DATA* get_bounty( char* name ){
BOUNTY_DATA* bounty = bounty_list;
for (; bounty; bounty = bounty->next){
if (LOWER(name[0]) == LOWER(bounty->name[0]) && !str_cmp(name, bounty->name))
return bounty;
}
return NULL;
}
/* adds/compounds a single bid based on victim's name */
BBID_DATA* add_bounty_bid( BBID_DATA* new_bbid, char* name){
BOUNTY_DATA* bounty;
BBID_DATA* bbid;
if (new_bbid == NULL || IS_NULLSTR( name ))
return NULL;
/* we check if there is en existing bounty */
if ( (bounty = get_bounty( name )) == NULL){
bounty = new_bounty();
bounty->next = NULL;
bounty->name = str_dup( name );
bounty->time_stamp = mud_data.current_time;
bounty->bids = new_bbid;
add_bounty( bounty );
return bounty->bids;
}
else if ( (bbid = get_bbid( bounty, new_bbid->name )) != NULL){
OBJ_DATA* obj, *obj_next;
/* we add the info from new bid onto existing one */
bounty->time_stamp = mud_data.current_time;
bbid->level = new_bbid->level;
bbid->pCabal = new_bbid->pCabal;
bbid->cp += new_bbid->cp;
bbid->gp += new_bbid->gp;
/* add objects */
for (obj = new_bbid->obj; obj; obj = obj_next){
obj_next = obj->next_bidobj;
obj_from_bbid( obj );
obj_to_bbid( obj, bbid );
}
return bbid;
}
else
return bid_to_bounty( new_bbid, bounty );
return NULL;
}
/* creates a linked list of ordered bounties by gold/cp/obj */
BOUNTY_DATA* make_bounty_list( BOUNTY_DATA* bounties, bool fGold, bool fObj){
BBID_DATA* bbid;
BOUNTY_DATA* bounty;
BOUNTY_DATA* new_bount;
/* run through all bounties */
for (bounty = bounty_list; bounty; bounty = bounty->next){
int val = 0;
new_bount = new_bounty();
/* get the total bid value for this bounty */
new_bount->name = str_dup(bounty->name);
new_bount->next = NULL;
for (bbid = bounty->bids; bbid; bbid = bbid->next){
if (fGold)
val += bbid->gp;
else if (fObj){
OBJ_DATA* obj;
int max_obj = 1;
int tot_level = 0;
for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
max_obj++;
tot_level += obj->level;
}
val = val + (tot_level / max_obj);
}
else
val += bbid->cp;
}
/* at this point val has a total comparison for this bounty */
/* we cheat and put it in new bounties time stamp */
new_bount->time_stamp = val;
/* ordered insert */
if (bounties == NULL){
bounties = new_bount;
bounties->next = NULL;
}
else{
BOUNTY_DATA* prev = bounties;
BOUNTY_DATA* cur = bounties;
while( cur ){
if (val > cur->time_stamp)
break;
else{
prev = cur;
cur = cur->next;
}
}
if (prev == cur){
new_bount->next = bounties;
bounties = new_bount;
}
else{
new_bount->next = prev->next;
prev->next = new_bount;
}
}
}
return bounties;
}
/* show top 10 bounties */
void show_top_10( CHAR_DATA* ch ){
const int max_10 = 10;
char gold[max_10] [MIL];
char cp[max_10] [MIL];
char obj[max_10] [MIL];
BOUNTY_DATA* bounty;
BOUNTY_DATA* bounties = NULL;
int count = 0;
for (count = 0; count < max_10; count++){
gold[count][0] = '\0';
obj[count][0] = '\0';
cp[count][0] = '\0';
}
/* we perform three similiar operations to build a linked list
with sorted entries according to: gold, cp, and objects
After each build we enter the top 10 entries into the array
destroy the list and do the next top 10
*/
/* GOLD */
bounties = make_bounty_list( bounties, TRUE, FALSE );
count = 0;
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else
strcpy(gold[count++], bounty->name );
}
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/* CP */
bounties = make_bounty_list( bounties, FALSE, FALSE );
count = 0;
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else
strcpy(cp[count++], bounty->name );
}
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/*OBJ */
bounties = make_bounty_list( bounties, FALSE, TRUE );
count = 0;
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else
strcpy(obj[count++], bounty->name );
}
/* free the linked list */
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/* print the top out */
send_to_char("TOP 10 BOUNTIES:\n\r", ch);
send_to_char("Place Gold Cabal Pts. Object Lvl.\n\r", ch);
send_to_char("----------------------------------------\n\r", ch);
for (count = 0; count < max_10; count++){
sendf( ch, "%2d. %-10s %-10s %-10s\n\r",
count + 1,
gold[count] [0] ? gold[count] : "",
cp[count] [0] ? cp[count] : "",
obj[count] [0] ? obj[count] : "");
}
}
void do_top10( CHAR_DATA* ch, char* argument ){
show_top_10( ch );
}
/* get a cost of buyout on a bounty *
* FORMULA for PLACE:
140 + 60 * (10 - position)
*
* position = place in top10, hence:
* - Person not in top10 : 140
* - Person in 9th place : 200
* - Person in 6th place : 380
* - Person in 4th place : 500
*
* 3rd-1st cannot be bought out.
* position is determined as best of three categories.
*
* FORMULA for GOLD:
* highest_gold_bid / 10000
*
* FORMULA for OBJECTS:
* total object level * 2
*
* The highest worth out of Obj/Gold/Cp/Place is returned
*/
int get_buyout_cost( BOUNTY_DATA* pBounty ){
const int max_10 = 10;
BOUNTY_DATA* bounty;
BOUNTY_DATA* bounties = NULL;
BBID_DATA* bbid;
OBJ_DATA* obj;
int count = 0;
int place = 99;
int gold_cost = 0;
int obj_cost = 0;
int place_cost = 0;
int cp_cost = 0;
int cost = 0;
/* get the highest place first */
/* GOLD */
bounties = make_bounty_list( bounties, TRUE, FALSE );
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else if (!str_cmp(bounty->name, pBounty->name) && count < place){
place = count;
break;
}
count++;
}
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/* CP */
bounties = make_bounty_list( bounties, FALSE, FALSE );
count = 0;
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else if (!str_cmp(bounty->name, pBounty->name) && count < place){
place = count;
break;
}
count++;
}
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/*OBJ */
bounties = make_bounty_list( bounties, FALSE, TRUE );
count = 0;
for (bounty = bounties; bounty; bounty = bounty->next){
if (count >= max_10)
break;
else if (!str_cmp(bounty->name, pBounty->name) && count < place){
place = count;
break;
}
count++;
}
/* free the linked list */
while (bounties){
BOUNTY_DATA* b = bounties;
bounties = b->next;
free_bounty( b );
}
/* we have the lowest spot on top 10, if its 0, 1, or 2 we return negative */
if (place < 3)
return -1;
else if (place == 99)
place_cost = 140;
else
place_cost = 140 + 60 * (10 - place);
/* get the other costs */
for (bbid = pBounty->bids; bbid; bbid = bbid->next){
int tot_level = 0;
if (bbid->gp / 10000 > gold_cost)
gold_cost = bbid->gp / 10000;
if (bbid->cp > cp_cost)
cp_cost = bbid->cp;
for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
tot_level += obj->level;
}
if (tot_level * 2 > obj_cost)
obj_cost = tot_level * 2;
}
/* return highest */
cost = place_cost;
if (gold_cost > cost)
cost = gold_cost;
if (obj_cost > cost)
cost = obj_cost;
if (cp_cost > cost)
cost = cp_cost;
return cost;
}
/* shows a bounty to a character with all its bids */
void show_bounty( CHAR_DATA* ch, BOUNTY_DATA* bounty, bool fGold, bool fObj ){
BUFFER* buffer;
BBID_DATA* bbid;
BBID_DATA* bbids = NULL;
char buf[MSL];
long tot_gp = 0;
long tot_cp = 0;
int count = 0;
/* we create a temorary linked list of bounty data's by ordered inserts */
for (bbid = bounty->bids; bbid; bbid = bbid->next){
BBID_DATA* new_bid = new_bbid();
int val = 0;
new_bid->name = str_dup( bbid->name );
new_bid->level = ++count;
new_bid->pCabal = bbid->pCabal;
new_bid->cp = bbid->cp;
new_bid->gp = bbid->gp;
new_bid->obj = bbid->obj; //we do not copy objects since we only need info to print later
if (fGold)
val = new_bid->gp;
else if (fObj){
OBJ_DATA* obj;
int max_obj = 1;
int tot_level = 0;
for (obj = new_bid->obj; obj; obj = obj->next_bidobj ){
max_obj++;
tot_level += obj->level;
}
val = tot_level / max_obj;
}
else
val = new_bid->cp;
/* we have a value for comparison and new bbid, find insertion point */
if (bbids == NULL){
bbids = new_bid;
bbids->next = NULL;
}
else{
BBID_DATA* prev = bbids;
BBID_DATA* cur = bbids;
while( cur ){
int key = 0;
if (fGold)
key = cur->gp;
else if (fObj){
OBJ_DATA* obj;
int max_obj = 1;
int tot_level = 0;
for (obj = cur->obj; obj; obj = obj->next_bidobj ){
max_obj++;
tot_level += obj->level;
}
key = tot_level / max_obj;
}
else
key = cur->cp;
/* we now have a key and value to compare */
if (val > key)
break;
else{
prev = cur;
cur = cur->next;
}
}
if (prev == cur){
new_bid->next = bbids;
bbids = new_bid;
}
else{
new_bid->next = prev->next;
prev->next = new_bid;
}
}
}
/* at this point we have a linked list bbids full of sorted bids, we show them. */
buffer = new_buf();
sprintf( buf, "Bids set for %s's head listed in order of %s.\n\r",
bounty->name,
fObj ? "AVERAGE OBJECT RANK" : fGold ? "GOLD AMOUNT" : "CABAL POINTS");
add_buf( buffer, buf );
for (bbid = bbids; bbid; bbid = bbid->next){
OBJ_DATA* obj;
tot_cp += bbid->cp;
tot_gp += bbid->gp;
sprintf( buf, "%2d: Gp: %-10ld Cp: %-10d\n\r", bbid->level, bbid->gp, bbid->cp);
add_buf( buffer, buf );
if (bbid->obj){
add_buf(buffer, " ");
for (obj = bbid->obj; obj; obj = obj->next_bidobj){
sprintf(buf, "%-12.12s, ", obj->short_descr);
add_buf( buffer, buf );
}
add_buf( buffer, "\n\r");
}
}
sprintf(buf, "This bounty will expire in %ld days.\n\r",
(BOUNTY_LIFETIME - mud_data.current_time + bounty->time_stamp) / 86400);
add_buf( buffer, buf );
page_to_char(buf_string(buffer),ch);
free_buf(buffer);
/* free the linked list */
while (bbids){
bbid = bbids;
bbids = bbid->next;
bbid->obj = NULL; //we do not free objets since we only linked to them
free_bbid( bbid );
}
}
void show_bbid( CHAR_DATA* ch, BBID_DATA* bbid ){
OBJ_DATA* obj;
char buf[MSL];
if (ch == NULL || bbid == NULL)
return;
sendf(ch,
"Gold : %-10ld %s%s: %-10d\n\r",
bbid->gp,
ch->pCabal ? capitalize(ch->pCabal->currency) : "CP",
ch->pCabal ? bbid->cp == 1 ? "" : "s" : "",
bbid->cp);
if (bbid->obj == NULL){
return;
}
else{
int count = 0;
sprintf(buf, "Objects:\n\r");
for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
sprintf( buf + strlen( buf ), "%d. %s\n\r",
++count,
obj->short_descr);
}
send_to_char( buf, ch );
send_to_char("\n\r", ch );
}
}
/* MAIN BOUNTY FUNCTION TO CREATE BOUNTY BIDS */
/* Syntax:
bounty cp <amount> : set amount of cabal points on your bid
bounty gold <amount> : set amount of gold on your bid
bounty add <object> : add object to the bid
bounty rem <object> : remove object from the bid
bounty place <name> : place current bounty bid onto character <name>
bounty <name> : show your bids on character <name>
bounty : show current bid
*/
void do_bounty( CHAR_DATA* ch, char* argument ){
char arg[MIL];
int val;
if (IS_NPC(ch))
return;
else
argument = one_argument( argument, arg );
if (IS_NULLSTR( arg )){
if (ch->pcdata->pbbid){
send_to_char("Your current bounty bid is composed of:\n\r", ch );
show_bbid(ch, ch->pcdata->pbbid);
}
send_to_char("Bounty <cp/gold/add/rem/place/buyout> (\"help bounty\" for details).\n\r", ch );
return;
}
else if (!str_prefix( arg, "cp")){
if (ch->pCabal == NULL){
send_to_char("You are not in a cabal!\n\r", ch );
return;
}
if (ch->pcdata->pbbid == NULL)
ch->pcdata->pbbid = new_bbid();
if ( (val = atoi( argument )) < 30){
sendf(ch, "You must place at last 30 %ss.\n\r", ch->pCabal->currency );
return;
}
else if (val > GET_CP(ch)){
int dif = val - GET_CP( ch );
sendf( ch, "You are short %d %s%s.\n\r", dif, ch->pCabal->currency, dif == 1 ? "" : "s" );
return;
}
else{
ch->pcdata->pbbid->cp = val;
sendf( ch, "Your bounty now includes %d %s%s.\n\r", ch->pcdata->pbbid->cp,
ch->pCabal->currency,
ch->pcdata->pbbid->cp == 1 ? "" : "s" );
}
return;
}
else if (!str_prefix( arg, "gold")){
if (ch->pcdata->pbbid == NULL)
ch->pcdata->pbbid = new_bbid();
/* get minimum bid for this character */
if ( (val = atoi( argument )) < 10000){
send_to_char("You must place at least 10k gold.\n\r", ch );
return;
}
else if (val > ch->in_bank){
int dif = val - ch->in_bank;
sendf( ch, "You are short %d gold in your bank account.", dif);
return;
}
else{
ch->pcdata->pbbid->gp = val;
sendf( ch, "Your bounty now includes %ld gold.\n\r", ch->pcdata->pbbid->gp );
}
return;
}
else if (!str_prefix( arg, "add")){
OBJ_DATA* obj, *pObj;
int count = 0;
if (IS_NULLSTR( argument )){
send_to_char("Add what object to the bounty?\n\r", ch );
return;
}
else if ( (obj = get_obj_carry( ch, argument, ch )) == NULL){
send_to_char("You do not seem to be carrying that object.\n\r", ch );
return;
}
else if (!IS_LIMITED( obj )){
send_to_char("That object is too common to be placed as a bounty.\n\r", ch );
return;
}
else if (obj->bbid != NULL){
send_to_char("That object already seems to be part of your bounty.\n\r", ch );
return;
}
else if (!can_drop_obj(ch, obj )){
send_to_char("You must be able to part with the item first.\n\r", ch );
return;
}
else if (obj->pIndexData->vnum == OBJ_VNUM_CLONE){
send_to_char("Placing a counterfit item as a bounty is a sure way to die.\n\r", ch);
return;
}
else if (obj->contains && !IS_OBJ_STAT(obj, ITEM_SOCKETABLE)) {
send_to_char("You may not place objects that are containers, or loaded.\n\r", ch );
return;
}
if (ch->pcdata->pbbid == NULL)
ch->pcdata->pbbid = new_bbid();
/* count how many objects on this bid */
for (pObj = ch->pcdata->pbbid->obj; pObj; pObj = pObj->next_bidobj )
count++;
if (count + 1 > 5){
send_to_char("You may place a maximum of five objects as a bounty.\n\r", ch );
return;
}
/* we attach the object into this bid data BUT DO NOT remove it from character, "place" command will do all that */
if (ch->pcdata->pbbid->obj == NULL){
obj->next_bidobj = NULL;
ch->pcdata->pbbid->obj = obj;
}
else{
obj->next_bidobj = ch->pcdata->pbbid->obj;
ch->pcdata->pbbid->obj = obj;
}
obj->bbid = ch->pcdata->pbbid;
sendf( ch, "You have added %s to the bounty.\n\r", obj->short_descr);
/* we store the count in bbid->level to be used in "place" command */
ch->pcdata->pbbid->level = count + 1;
return;
}
else if (!str_prefix( arg, "rem")){
OBJ_DATA* obj;
if (ch->pcdata->pbbid == NULL || ch->pcdata->pbbid->obj == NULL){
send_to_char("You have not placed any objects as a bounty.\n\r", ch);
return;
}
else if (IS_NULLSTR( argument )){
send_to_char("Remove what object from the bounty?\n\r", ch );
return;
}
else if ( (obj = get_obj_carry( ch, argument, ch )) == NULL){
send_to_char("You do not seem to be carrying that object.\n\r", ch );
return;
}
else if (obj->bbid == NULL){
send_to_char("That object is has not been placed as a bounty.\n\r", ch );
return;
}
else if (obj->bbid != ch->pcdata->pbbid){
send_to_char("That object has not been placed into the bounty you are working on.\n\r", ch );
return;
}
obj_from_bbid( obj );
ch->pcdata->pbbid->level --;
sendf( ch, "You have removed %s from the bounty.\n\r", obj->short_descr);
return;
}
/* none of the commands matched, try to place the bounty */
else if (!str_prefix( arg, "place")){
CHAR_DATA* victim;
CHAR_DATA* mob;
DESCRIPTOR_DATA* d;
BBID_DATA* bbid, *oldBbid;
BOUNTY_DATA* oldBounty;
int coffers = 0, cost = 0;
bool fPurge = FALSE;
long min_gp = 0, min_cp = 0;
for (mob = ch->in_room->people; mob; mob = mob->next_in_room ){
if (IS_NPC(mob) && IS_SET(mob->act, ACT_CONTRACTER))
break;
}
if (mob == NULL){
send_to_char("There is no one here to record your bounty.\n\r", ch);
return;
}
else if (ch->pcdata->pbbid == NULL){
do_bounty( ch, "" );
return;
}
else if (IS_NULLSTR( argument)){
send_to_char("Place this bounty on who?\n\r", ch );
return;
}
else
bbid = ch->pcdata->pbbid;
/* try to get the victim of this bounty */
if ( (victim = char_file_active (argument)) == NULL){
if ( (d = bring( ch->in_room, argument )) != NULL){
victim = d->character;
fPurge = TRUE;
victim->pcdata->roomnum *= -1;
}
else{
send_to_char ("That character does not exist.\n\r", ch);
return;
}
}
/* we now have the victm of this bounty, do some checks */
if (IS_NPC(victim)){
send_to_char("Why would you want to place a bounty on a mobile?\n\r", ch );
return;
}
else if (mud_data.current_time < victim->pcdata->last_bounty + BOUNTY_WAITTIME){
send_to_char("Their bounty has been recently claimed. Try again later.\n\r", ch);
if (fPurge)
purge( victim );
return;
}
/* calculate minimums */
min_gp = 100 * victim->level + (victim->pcdata->kpc / UMAX(1, victim->pcdata->dpc)) * 10000;
min_cp = UMAX(30, min_gp / 1000);
/* find old bid if any */
if ( (oldBounty = get_bounty( victim->name )) != NULL
&& (oldBbid = get_bbid( oldBounty, ch->name )) != NULL){
min_gp -= oldBbid->gp;
min_cp -= oldBbid->cp;
}
min_gp = UMAX(5000, min_gp );
min_cp = UMAX(30, min_cp );
if (victim->level < 15)
send_to_char("You may not place bounties on victims of rank lower then 15th.\n\r", ch );
else if (ch == victim)
send_to_char("You cannot place bounties on yourself.\n\r", ch );
else if (mud_data.mudport != TEST_PORT && ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE))
send_to_char("Your job is to collect the bounties, not place them.\n\r", ch );
else if (victim->pCabal && IS_CABAL(victim->pCabal, CABAL_ROUGE))
act("$N seems to ignore your request.", ch, NULL, mob, TO_CHAR);
else if (mud_data.mudport != TEST_PORT && (IS_IMMORTAL( ch ) || IS_IMMORTAL(victim)) )
send_to_char("Gods are above such petty behavior. Event logged.\n\r", ch );
else if (bbid->obj && victim->level < 40 && victim->pCabal == NULL)
send_to_char("In order to place equipment as a bounty your victim must be of rank 40+ or cabaled.\n\r", ch );
/* minimum gold */
else if (bbid->gp && bbid->gp < min_gp){
sendf(ch, "The minimum gold bid on %s is %ld gold.\n\r", victim->name, min_gp);
}
else if (ch->pCabal && bbid->cp && bbid->cp < min_cp){
sendf(ch, "The minimum %s bid on %s is %ld %ss.\n\r",
ch->pCabal->currency,
victim->name,
min_cp,
ch->pCabal->currency);
}
else if (ch->in_bank < bbid->gp)
send_to_char("You do not have enough gold in the bank.\n\r", ch );
else if (ch->pCabal && GET_CP( ch ) < bbid->cp )
sendf( ch, "You do not have enough %s%s.", ch->pCabal->currency, bbid->cp == 1 ? "" : "s" );
else if (bbid->obj == NULL && bbid->cp == 0 && bbid->gp == 0)
send_to_char("Your bid does has no value.\n\r", ch );
else{
/* we can now create a real bid, and transfer stuff over */
BBID_DATA* new_bid;
BOUNTY_DATA* bounty = NULL;
OBJ_DATA* obj, *obj_next;
/* check if we can add objects into this bid */
if (bbid->obj
&& (bounty = get_bounty( victim->name)) != NULL
&& (new_bid = get_bbid( bounty, ch->name)) != NULL){
int count = 0;
for (obj = new_bid->obj; obj; obj = obj->next_bidobj )
count ++;
if (count + bbid->level > 5){
if (5 - count >= 0)
sendf(ch, "You have previously placed %d items as a bounty and may place only %d more.\n\r", count, 5 - count);
else
send_to_char("You may only place up to 5 items as a bounty.\n\r", ch );
if (fPurge)
purge( victim );
return;
}
}
new_bid = new_bbid();
new_bid->name = str_dup( ch->name );
new_bid->level = ch->level;
new_bid->pCabal = ch->pCabal;
new_bid->cp = ch->pCabal ? bbid->cp : 0;
new_bid->gp = bbid->gp;
/* subtract gold, cp's */
/* check if cabal can cover half */
cost = bbid->cp;
if (ch->pCabal && IS_CABAL(get_parent(ch->pCabal), CABAL_ROYAL)){
CABAL_DATA* pCab = get_parent(ch->pCabal);
if (GET_CAB_CP(pCab) - 500 > bbid->cp / 2){
coffers = bbid->cp / 2;
cost = bbid->cp / 2;
}
if (coffers){
char buf[MIL];
sprintf( buf, "%s has been given %d %s%s from our coffers.",
PERS2( ch ),
coffers,
pCab->currency,
coffers == 1 ? "" : "s");
cabal_echo( pCab, buf );
CP_CAB_GAIN( pCab, -coffers );
}
}
CP_GAIN( ch, -cost, TRUE );
ch->in_bank -= new_bid->gp;
for (obj = bbid->obj; obj; obj = obj_next){
obj_next = obj->next_bidobj;
obj_from_bbid( obj );
obj_from_char( obj );
obj_to_bbid( obj, new_bid );
}
/* the new_bid now contains all the info, we get rid of the old one */
free_bbid( ch->pcdata->pbbid );
ch->pcdata->pbbid = NULL;
/* we now add the bid for the victim */
if ( (new_bid = add_bounty_bid( new_bid, victim->name )) == NULL){
send_to_char("There was a problem setting your bounty.\n\r", ch );
return;
}
else
save_bounties();
/* send a message to the victim */
if (victim->pCabal && IS_CABAL(get_parent(victim->pCabal), CABAL_SPIES) ){
if (!fPurge)
sendf( victim, "[%s] contacts in the underworld report %s's bounty on your head.\n\r",
victim->pCabal->who_name, ch->name);
else{
char buf[MIL];
SET_BIT(victim->pcdata->messages, MSG_BOUNTY );
sprintf( buf, "[%s] contacts in the underworld report %s's bounty on your head.\n\r",
victim->pCabal->who_name, ch->name);
do_hal(victim->name, "A bounty has been set upon your head.", buf, NOTE_NOTE);
}
}
sendf( ch, "Your current bounty for %s:\n\r", PERS2( victim ));
show_bbid( ch, new_bid );
send_to_char( "\n\r", ch );
if (mob){
act("$N nods ever so slightly and turns $S back on you.", ch, NULL, mob, TO_CHAR);
act("$N nods ever so slightly and turns $S back on $n.", ch, NULL, mob, TO_ROOM);
}
}
if (fPurge )
purge( victim );
}
else if (!str_prefix( arg, "clear")){
if (ch->pcdata->pbbid == NULL){
send_to_char("You are not working on a bounty.\n\r", ch );
return;
}
else{
OBJ_DATA* obj, *obj_next;
for (obj = ch->pcdata->pbbid->obj; obj; obj = obj_next){
obj_next = obj->next_bidobj;
obj_from_bbid( obj );
}
free_bbid( ch->pcdata->pbbid);
ch->pcdata->pbbid = NULL;
send_to_char("Bounty data cleared.\n\r", ch );
}
return;
}
/* BUYOUT */
else if (!str_prefix( arg, "buyout")){
BOUNTY_DATA* bounty;
CABAL_DATA* pCab = get_parent(ch->pCabal);
CABAL_DATA* pRouge = NULL;
PACT_DATA* pp;
int cost = 0, coffers = 0;
char buf[MIL];
if (pCab == NULL){
send_to_char("You must be a member of a cabal.\n\r", ch);
return;
}
else if (!IS_CABAL(pCab, CABAL_ALLIANCE)){
send_to_char("You lack the contacts neccessary.\n\r", ch);
return;
}
/* check for an alliance with a rouge cabal */
for (pp = pact_list; pp; pp = pp->next){
if (pp->complete != PACT_COMPLETE)
continue;
if ( pp->type != PACT_ALLIANCE )
continue;
if (pp->benefactor == pCab && IS_CABAL(pp->creator, CABAL_ROUGE)){
pRouge = pp->creator;
break;
}
else if(IS_CABAL(pp->benefactor, CABAL_ROUGE) && pp->creator == pCab){
pRouge = pp->benefactor;
break;
}
}
if (pRouge == NULL){
send_to_char("You lack the contacts neccessary.\n\r", ch);
return;
}
else if ( (bounty = ch->pcdata->pbounty) == NULL){
send_to_char("There are no bounties associated with you.\n\r", ch );
return;
}
/* get the cost */
cost = get_buyout_cost( bounty );
if (cost < 1){
send_to_char("You may not buy out your bounty.\n\r", ch);
return;
}
if (IS_CABAL(pCab, CABAL_ROYAL) && GET_CAB_CP(pCab) - 500 > cost / 2){
cost = cost / 2;
coffers = cost;
}
if (IS_NULLSTR(argument)){
if (coffers){
sendf(ch, "The bribe will cost you %d %s%s with %d being covered by [%s] coffers.\n\r",
cost,
pCab->currency,
cost == 1 ? "" : "s",
coffers,
pCab->who_name);
}
else{
sendf(ch, "The bribe will cost %d %s%s.\n\r",
cost,
pCab->currency,
cost == 1 ? "" : "s");
}
send_to_char("Use \"bounty buyout confirm\" to end the transaction.\n\r", ch);
}
else{
if (GET_CP( ch ) < cost){
send_to_char("You lack the funds neccessary.\n\r", ch);
return;
}
else if (coffers && GET_CAB_CP(pCab) < coffers){
send_to_char("Your cabal lacks the funds neccessary.\n\r", ch);
return;
}
/* remove the bounty */
rem_bounty( ch->pcdata->pbounty );
free_bounty( ch->pcdata->pbounty );
save_bounties();
ch->pcdata->pbounty = NULL;
/* mark time for re-biounty wait */
ch->pcdata->last_bounty = mud_data.current_time;
sprintf( buf, "%s has graciously donated %d %ss to our cause.",
PERS2( ch ),
cost + coffers,
pCab->currency);
cabal_echo( pRouge, buf );
if (coffers){
sprintf( buf, "%s has been given %d %s%s from our coffers.",
PERS2( ch ),
coffers,
pCab->currency,
coffers == 1 ? "" : "s");
cabal_echo( pCab, buf );
CP_CAB_GAIN( pCab, -coffers );
}
CP_GAIN( ch, -cost, TRUE );
CP_CAB_GAIN(pRouge, coffers + cost );
save_char_obj( ch );
}
return;
}
/* check if we have any bounties on this person */
else if (!IS_NULLSTR( arg )){
BOUNTY_DATA* bounty = get_bounty( arg );
BBID_DATA* bbid;
if (bounty == NULL || (bbid = get_bbid( bounty, ch->name )) == NULL){
sendf( ch, "You have not placed any bounties for their death.\n\r");
return;
}
else{
sendf( ch, "Your current bounty for %s:\n\r", bounty->name );
show_bbid( ch, bbid );
sendf(ch, "This bounty will expire in %ld days.\n\r",
(BOUNTY_LIFETIME - mud_data.current_time + bounty->time_stamp) / 86400);
}
return;
}
else
do_bounty( ch, "" );
}
/* returns a single bid from a bounty to its owner */
void return_bbid( BBID_DATA* bbid, char* name ){
CHAR_DATA* owner;
DESCRIPTOR_DATA* d;
ROOM_INDEX_DATA* to_room;
OBJ_DATA* obj, *obj_next;
bool fPurge = FALSE;
int count = 0;
if (bbid == NULL || IS_NULLSTR(name))
return;
/* get transfer room first */
if ( (to_room = get_room_index(ROOM_VNUM_LIMBO)) == NULL){
bug("return_bbid: could not get limbo room.", 0);
return;
}
else if ( (owner = char_file_active (name)) == NULL){
if ( (d = bring( to_room, name )) != NULL){
owner = d->character;
fPurge = TRUE;
owner->pcdata->roomnum *= -1;
}
else{
owner = NULL;
}
}
/* at this point we stop if pfile no longer exists */
if (owner == NULL){
return;
}
/* transfer items from bid */
for (obj = bbid->obj; obj; obj = obj_next){
obj_next = obj->next_bidobj;
obj_from_bbid( obj );
if (!can_take(owner, obj)){
extract_obj( obj );
continue;
}
else{
obj_to_char( obj, owner );
count++;
}
}
/* return gold */
owner->in_bank += bbid->gp;
CP_GAIN(owner, bbid->cp, TRUE );
if (fPurge && count)
SET_BIT(owner->pcdata->messages, MSG_BOUNTY_RETURN);
else if (count){
sendf( owner, "`@Your bounty on %s has been returned.``\n\r",
bbid->bounty->name);
}
if (fPurge)
purge( owner );
}
/* returns an entire bounty to their owners */
void return_bounty( BOUNTY_DATA* bounty, BBID_DATA* exempt ){
BBID_DATA* bbid, *bbid_next;
for (bbid = bounty->bids; bbid; bbid = bbid_next){
bbid_next = bbid->next;
if (exempt && bbid == exempt)
continue;
return_bbid(bbid, bbid->name );
}
}
/* writes a single bounty bid to a file */
void fwrite_bbid( FILE* fp, BBID_DATA* bbid ){
OBJ_DATA* obj;
fprintf( fp, "#BBID %s~ %d %d %d %ld\n",
bbid->name,
bbid->pCabal ? bbid->pCabal->vnum : 0,
bbid->level,
bbid->cp,
bbid->gp );
/* write objects if any */
for (obj = bbid->obj; obj; obj = obj->next_bidobj ){
fwrite_obj(NULL, obj, fp, 0, 0, FALSE);
}
/* terminate */
fprintf( fp, "#End\n" );
}
/* reads a single bounty bid from file */
void fread_bbid( FILE* fp, BBID_DATA* bbid ){
ROOM_INDEX_DATA* bounty_room;
OBJ_DATA* obj;
char letter;
char* word;
bbid->name = fread_string( fp );
bbid->pCabal = get_cabal_vnum( fread_number( fp ) );
bbid->level = fread_number( fp );
bbid->cp = fread_number( fp );
bbid->gp = fread_number( fp );
/* make sure we can get the bounty room */
if ( (bounty_room = get_room_index( ROOM_VNUM_BOUNTY)) == NULL){
bug("fread_bbid: could not get bounty room.", 0);
exit( 1 );
}
/* start the loop to read objects */
for (;;){
letter = fread_letter( fp );
if ( letter != '#' ){
bug( "read_bbid: # not found.", 0 );
exit( 1 );
}
word = feof( fp ) ? "End" : fread_word( fp );
if ( !str_cmp(word, "End"))
break;
else if (!str_cmp(word, "O") || !str_cmp(word, "OBJECT")){
if ( (obj = fread_obj( NULL, fp, bounty_room )) == NULL){
bug("fread_bbid: could not load object.", 0);
}
else{
obj_to_bbid( obj, bbid );
}
continue;
}
}
}
/* writes a single bounty */
void fwrite_bounty( FILE* fp, BOUNTY_DATA* bounty ){
BBID_DATA* bbid;
struct stat Stat; //File statistics
char pFile [MIL];
/* check if this player file exists */
/* Get info/pointer to file entry*/
sprintf(pFile, PLAYER_DIR"%s", bounty->name);
if ( -1 == stat( pFile, &Stat))
return;
fprintf( fp, "#BOUNTY %s~ %ld\n", bounty->name, bounty->time_stamp );
/* save bids */
for (bbid = bounty->bids; bbid; bbid = bbid->next ){
fwrite_bbid( fp, bbid );
}
/* terminate */
fprintf( fp, "#End\n" );
}
/* reads a single bounty */
void fread_bounty( FILE* fp, BOUNTY_DATA* bounty ){
char letter;
char* word;
bounty->name = fread_string( fp );
bounty->time_stamp = fread_number( fp );
/* read in the individual bids */
for (;;){
letter = fread_letter( fp );
if ( letter != '#' ){
bug( "read_bounty: # not found.", 0 );
exit( 1 );
}
word = feof( fp ) ? "End" : fread_word( fp );
if ( !str_cmp(word, "End"))
break;
else if (!str_cmp(word, "BBID")){
BBID_DATA* bbid = new_bbid();
fread_bbid( fp, bbid );
bid_to_bounty( bbid, bounty );
}
}
}
/* saves all the bounties */
void save_bounties( ){
FILE *fp;
BOUNTY_DATA* bounty = bounty_list;
char path[128];
fclose( fpReserve );
sprintf( path, "%s%s", SAVEBOUNTY_DIR, SAVEBOUNTY_FILE);
if ( ( fp = fopen( path, "w" ) ) == NULL ){
fp = fopen( NULL_FILE, "r" );
fclose (fp);
perror( path );
return;
}
/* loop through bounties and save */
for (; bounty; bounty = bounty->next ){
fwrite_bounty( fp, bounty );
}
fprintf( fp, "#END\n" );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
}
/* checks bounties after loading in order to free the timed out ones */
void fix_bounties(){
BOUNTY_DATA* bounty = bounty_list, *bounty_next;
/* loop through bounties and check */
for (; bounty; bounty = bounty_next ){
bounty_next = bounty->next;
/* check if this bounty should be released */
if (mud_data.current_time - bounty->time_stamp > BOUNTY_LIFETIME){
return_bounty( bounty, NULL );
rem_bounty( bounty );
free_bounty( bounty );
}
}
save_bounties();
}
/* reads all bounties */
void load_bounties(){
BOUNTY_DATA* bounty;
FILE *fp;
char path[128];
char letter;
char* word;
fclose( fpReserve );
sprintf( path, "%s%s", SAVEBOUNTY_DIR, SAVEBOUNTY_FILE);
if ( ( fp = fopen( path, "r" ) ) == NULL ){
fp = fopen( NULL_FILE, "r" );
fclose (fp);
perror( path );
return;
}
for (;;){
letter = fread_letter( fp );
if ( letter != '#' ){
bug( "load_bounties: # not found.", 0 );
exit( 1 );
}
word = feof( fp ) ? "END" : fread_word( fp );
if ( !str_cmp(word, "END"))
break;
else if (!str_cmp(word, "BOUNTY")){
bounty = new_bounty();
fread_bounty( fp, bounty );
add_bounty( bounty );
}
}
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
fix_bounties();
}
/* handles all the misc. tasks after a bountied victim is killed */
void fulfill_bounty( CHAR_DATA *ch, CHAR_DATA *victim, char* name){
CHAR_DATA* bidder;
DESCRIPTOR_DATA* d;
OBJ_DATA* obj, *obj_next;
BBID_DATA* bbid;
CABAL_DATA* pAlly = NULL;
AFFECT_DATA* paf;
const int cab_share = 75; //percent taken by cabal, if not allied kill
long gold = 0;
int cp = 0;
int cp_cab = 0;
int count = 0;
int corp_count= 0;
bool fPurge = FALSE;
char buf[MSL];
char to[MSL];
/* safety */
if (IS_NPC(ch) || IS_NPC(victim))
return;
else if (victim->pcdata->pbounty == NULL){
bug("fulfill_bounty: victim with no bounty.\n\r", 0 );
return;
}
/* try to get the bid by name */
if ( (bbid = get_bbid( victim->pcdata->pbounty, name)) == NULL){
if ( (bbid = victim->pcdata->pbounty->bids) == NULL){
bug("fulfill_bounty: bounty with no bids.", 0);
return;
}
}
/* set transfer for cp/gp, if this is not an allied kill, then cabal takes cab_share% to coffers */
gold = pAlly ? bbid->gp : cab_share * bbid->gp / 100;
cp_cab = pAlly ? 0 : cab_share * bbid->cp / 100;
cp = bbid->cp - cp_cab;
/* transfer bounty items to killer */
for (obj = bbid->obj; obj; obj = obj_next){
obj_next = obj->next_bidobj;
obj_from_bbid( obj );
if (!can_take(ch, obj)){
sendf( ch, "You could not use %s.\n\rIt has been sold to help widowed families of %s%s%s.\n\r",
obj->short_descr,
ch->pCabal ? "[" : "",
ch->pCabal ? ch->pCabal->who_name : victim->name,
ch->pCabal ? "]" : "");
extract_obj( obj );
continue;
}
else{
obj_to_char( obj, ch );
count++;
}
}
if (ch->pCabal){
/* do cp event bounty to reward */
cp_event( ch, victim, NULL, CP_EVENT_BOUNTY);
if (cp_cab > 0){
sprintf( buf, "%d %s%s %s been directed to our coffers from %s's bounty.",
cp_cab,
ch->pCabal->currency,
cp_cab == 1 ? "" : "s",
cp_cab == 1 ? "has" : "have",
PERS2(victim));
cabal_echo( get_parent( ch->pCabal ), buf);
CP_CAB_GAIN( ch->pCabal, cp_cab );
}
if (cp)
CP_GAIN( ch, cp, TRUE );
}
/* transfer best three rares to the killer */
corp_count = get_random_rares( ch, victim, 3, FALSE );
/* if the bountier exists and is of rank > 40 he gets the rest of rares up to 18 */
if ( (bidder = char_file_active (bbid->name)) == NULL){
if ( (d = bring( ch->in_room, bbid->name )) != NULL){
bidder = d->character;
fPurge = TRUE;
bidder->pcdata->roomnum *= -1;
}
else{
bidder = NULL;
}
}
if (bidder && bidder->level >= 40){
int bidder_count = get_random_rares(bidder, victim, 18, FALSE );
if (fPurge && bidder_count)
SET_BIT(bidder->pcdata->messages, MSG_BOUNTY_REWARD);
else if (bidder_count)
sendf( ch, "`@You have recived %d items as a result of %s's death to a bounty hunter.``\n\r",
bidder_count, victim->name);
}
if (fPurge && bidder)
purge( bidder );
ch->in_bank += gold;
if (gold || count || corp_count)
sendf( ch, "You've recived %ld gold, %d items from the bounty and %d items from the corpse.\n\r",
gold, count, corp_count );
/* we create a single note to all the people that bid on this bounty */
to[0] = '\0';
for (bbid = victim->pcdata->pbounty->bids; bbid; bbid = bbid->next){
strcat(to, bbid->name);
strcat(to, " ");
}
sprintf( buf, warn_table[WARN_BOUNTY].subj, victim->name );
do_hal( to, buf, warn_table[WARN_BOUNTY].text, NOTE_NOTE);
/* get rid of contract */
if ( (paf = affect_find( ch->affected, gen_contract)) != NULL){
paf->modifier = TRUE;
affect_remove( ch, paf );
}
/* return rest of the bids */
return_bounty( victim->pcdata->pbounty, bbid);
/* we clear the bounty for the victim */
rem_bounty( victim->pcdata->pbounty );
free_bounty( victim->pcdata->pbounty );
save_bounties();
victim->pcdata->pbounty = NULL;
/* mark time for re-biounty wait */
victim->pcdata->last_bounty = mud_data.current_time;
/* increae the count of bounties collected */
mud_data.bounties++;
/* if this is a cabaled killer from bounty cabal, increase bounty count */
if (ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE))
ch->pcdata->member->kills++;
save_mud();
}
/* handles selection and collection of bounty */
/* SYNTAX:
collect <name> : collects first avaliable bounty
collect <name> <number> : collects the selected bounty
collect list <name> : list all bids by cp
collect gold <name> : list by gold
collect obj <name> : list by obj
collect list <name> <number> : list the bid in detail
*/
void do_bounty_collect( CHAR_DATA *ch, char *argument ){
AFFECT_DATA* paf = NULL;
CHAR_DATA *victim;
OBJ_DATA *obj;
char arg[MIL];
char buf[MSL];
argument = one_argument( argument, arg);
if ((ch->pCabal == NULL || !IS_CABAL(ch->pCabal, CABAL_ROUGE))
&& ( (paf = affect_find(ch->affected, gen_contract)) == NULL
|| !paf->has_string
|| IS_NULLSTR(paf->string)) ){
send_to_char("Huh?\n\r", ch );
return;
}
else if (IS_NULLSTR( arg )){
send_to_char("Seek scrolls of \"help collect\" for details.\n\r", ch );
return;
}
/* LIST */
else if (!str_cmp( "list", arg) || !str_cmp( "gold", arg) || !str_cmp( "obj", arg)){
BOUNTY_DATA* bounty;
BBID_DATA* bbid;
char arg2[MIL];
argument = one_argument( argument, arg2);
if (paf)
strcpy(arg2, paf->string);
if (IS_NULLSTR( arg2 )){
send_to_char("List the bounty for who?\n\r", ch );
return;
}
else if ( (bounty = get_bounty( arg2)) == NULL){
send_to_char("There is no price on their head.\n\r", ch);
return;
}
/* VIEW */
if (!IS_NULLSTR( argument )){
if (atoi( argument ) < 1){
send_to_char("View which bounty? (number)\n\r", ch );
return;
}
else if ( (bbid = get_bbid( bounty, argument)) == NULL){
sendf(ch, "No such bounty foundf or %s.\n\r", bounty->name );
return;
}
else{
sendf(ch, "Victim: %-15s Bounty: %d\n\r", bounty->name, atoi(argument) );
show_bbid( ch, bbid );
}
return;
}
else
show_bounty( ch, bounty, !str_cmp(arg, "gold"), !str_cmp(arg, "obj") );
return;
}
else if ( (victim = get_char_room( ch, NULL, arg ) ) == NULL ){
send_to_char( "They aren't here.\n\r", ch );
return;
}
else if (!can_collect(victim->pcdata->pbounty, ch)){
sendf(ch, "You cannot collect bounty on %s\n\r.", PERS2(victim) );
return;
}
else if (IS_NPC(ch) || IS_NPC(victim)){
send_to_char("Not on mobiles.\n\r", ch );
return;
}
else if (!is_pk_abs(ch, victim)){
send_to_char("The gods will not allow you to harm them.\n\r", ch);
return;
}
else if ( !is_affected(victim, gsn_mortally_wounded) ){
sendf(ch, "%s is not standing still enough for you to collect a bounty.\n\r", PERS2(victim));
return;
}
sprintf(buf,"AAAAAAGGGGGHHHHH!!!!");
do_yell(victim, buf);
obj = create_object(get_obj_index(OBJ_VNUM_SEVERED_HEAD),ch->level);
sprintf(buf, obj->short_descr, victim->name);
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
sprintf(buf, obj->description, victim->name);
free_string( obj->description );
obj->description = str_dup( buf );
obj_to_char(obj, ch);
act("You slice off $N's head and place it in a bag.",ch,NULL,victim,TO_CHAR);
act("$n slices off $N's head and places it in a bag.",ch,NULL,victim,TO_NOTVICT);
act("$n slices off your head!",ch,NULL,victim,TO_VICT);
act("$n's headless body twitches violently.",victim,NULL,NULL,TO_ROOM);
act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
send_to_char( "You have been `1KILLED`` by a Bounty Hunter!\n\r",victim );
fulfill_bounty( ch, victim, IS_NULLSTR( argument ) ? "1" : argument );
_raw_kill( ch, victim, FALSE );
affect_strip(ch, skill_lookup("analyze"));
}
/* checks if a given bounty has allied priority when looked at by pCabal */
CABAL_DATA* is_bounty_priority( BOUNTY_DATA* bounty, CABAL_DATA* pCabal ){
CABAL_DATA* pCab = get_parent( pCabal );
BBID_DATA* bbid;
if (bounty == NULL || pCab == NULL)
return NULL;
else if (!IS_CABAL(pCab, CABAL_ROUGE) || !IS_CABAL(pCab, CABAL_ALLIANCE))
return NULL;
/* check bids in the bounty for alliances with this rouge cabal */
for (bbid = bounty->bids; bbid; bbid = bbid->next ){
if (bbid->pCabal && IS_CABAL(bbid->pCabal, CABAL_ALLIANCE) && get_parent(bbid->pCabal) != pCab
&& get_pact(bbid->pCabal, pCab, PACT_ALLIANCE, FALSE) != NULL)
return bbid->pCabal;
}
return NULL;
}
/* checks if given character can be covered by any rouge cabal memebers */
bool bounty_covered( CHAR_DATA* victim ){
if (IS_NPC(victim) || victim->pcdata->pbounty == NULL)
return TRUE;
else{
CHAR_DATA* vch;
for (vch = player_list; vch; vch = vch->next_player){
if (vch->pCabal && !IS_IMMORTAL(vch) && IS_CABAL(vch->pCabal, CABAL_ROUGE)
&& is_pk_abs(vch, victim))
return TRUE;
}
return FALSE;
}
}
/* command used to get a contract on a bounty rouge cabals cannot cover */
void do_contract( CHAR_DATA* ch, char* argument ){
CHAR_DATA* vch;
CHAR_DATA* mob;
int count = 0;
if (ch->pCabal && IS_CABAL(ch->pCabal, CABAL_ROUGE)){
send_to_char("Use \"who bounty\" to see bounties avaliable.\n\r", ch);
return;
}
for (mob = ch->in_room->people; mob; mob = mob->next_in_room ){
if (IS_NPC(mob) && IS_SET(mob->act, ACT_CONTRACTER))
break;
}
if (IS_NULLSTR(argument)){
bool fFound = FALSE;
send_to_char("Following bounties can be contracted out to you:\n\r", ch );
for (vch = player_list; vch; vch = vch->next_player){
if (vch->pcdata->pbounty && vch != ch && is_pk_abs(ch, vch)
&& can_see(ch, vch) && !bounty_covered( vch )){
sendf( ch, "%2d. %s\n\r", ++count, vch->name);
fFound = TRUE;
}
}
if (!fFound)
send_to_char("None.\n\r", ch);
return;
}
else if (is_affected(ch, gen_contract)){
send_to_char("You are still bound by previous contract.\n\r", ch);
return;
}
else if ( (vch = get_char_world( ch, argument)) == NULL){
send_to_char("They do not seem to be present.\n\r", ch );
return;
}
else if (ch == vch){
send_to_char("You cannot contract yourself.\n\r", ch);
return;
}
else if (bounty_covered( vch) || !is_pk_abs(ch, vch)){
send_to_char("Their bounty is not avaliable to be contracted out by you.\n\r", ch);
return;
}
else{
AFFECT_DATA af, *paf;
af.type = gen_contract;
af.level = ch->level;
af.duration = 72;
af.where = TO_AFFECTS;
af.bitvector= 0;
af.location = APPLY_NONE;
af.modifier = FALSE;
paf = affect_to_char( ch, &af );
string_to_affect( paf, vch->name );
if (mob ){
act("$N tells you 'You have 72 hours to do the deed, or until someone becomes avaliable.'", ch, NULL, mob, TO_CHAR);
act("$N nods ever so slightly and turns $S back on $n.", ch, NULL, mob, TO_ROOM);
}
else{
send_to_char("There is no one here to take your contract.\n\r", ch);
}
}
}
/* checks if the person can collect the bounty */
bool can_collect( BOUNTY_DATA* bounty, CHAR_DATA* ch ){
CHAR_DATA* och = ch;
AFFECT_DATA* paf;
if (IS_NPC(ch) && ch->master)
och = ch->master;
else if (IS_NPC(ch) && ch->leader)
och = ch->leader;
if (IS_NPC(och) || bounty == NULL)
return FALSE;
else if ( och->pCabal != NULL && IS_CABAL(och->pCabal, CABAL_ROUGE) )
return TRUE;
else if ( (paf = affect_find(och->affected, gen_contract)) != NULL
&& paf->has_string
&& !IS_NULLSTR(paf->string)
&& is_name(paf->string, bounty->name)){
return TRUE;
}
else
return FALSE;
}
bool check_rouge_bounty( CHAR_DATA* och, int pen ){
CHAR_DATA* ch = och;
CHAR_DATA* vch;
CABAL_DATA* pc;
char buf[MIL];
int sn = skill_lookup("analyze");
if (IS_NPC(och) && och->master)
ch = och->master;
if (ch->pCabal == NULL || !IS_CABAL(ch->pCabal, CABAL_ROUGE))
return FALSE;
else
pc = get_parent( ch->pCabal);
/* penalty for not collecting bounties */
for (vch = player_list; vch; vch = vch->next_player){
if (vch->pcdata->pbounty
&& !is_affected(vch, gsn_noquit )
&& can_see(ch, vch)
&& is_pk(ch, vch)
&& can_collect(vch->pcdata->pbounty, ch))
break;
}
return (vch != NULL);
/* Viri: no longer used */
if (vch != NULL){
AFFECT_DATA *paf;
int strike = 0;
// give them three strikes
if ( (paf = affect_find(ch->affected, sn)) == NULL){
AFFECT_DATA af;
af.type = sn;
af.level = 60;
af.duration = -1;
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 1;
affect_to_char(ch, &af);
strike = 1;
}
else{
paf->modifier++;
strike = paf->modifier;
}
if (strike > 3){
pen = (strike - 3) * pen;
strike++;
sprintf( buf, "%s has ignored a bounty!", ch->name);
cabal_echo( pc, buf );
distribute_cps(ch, ch->pCabal, pen * CPTS, TRUE );
// if person is out of cps we demote them
// we subtract the gain since reward takes effect on tick, not instantenously
if ((GET_CP( ch ) < 1) && ch->pcdata->rank > RANK_NEWBIE ){
char sub[MIL];
sprintf( buf, "Due to disregard for bounties, %s has been demoted.", PERS2(ch) );
cabal_echo( pc, buf );
strcat( buf, "\n\r");
sprintf( sub, "%s's demotion.", PERS2(ch));
do_hal( pc->name, sub, buf, NOTE_NEWS );
promote( ch, ch->pCabal, -1 );
if (ch->pcdata->member)
ch->pcdata->member->time_stamp = mud_data.current_time;
}
}
else{
sprintf( buf, "%s can ignore %d more %s.",
ch->name,
(3 - strike),
(3 - strike) == 1 ? "bounty" : "bounties");
cabal_echo( pc, buf );
}
return TRUE;
}
else
affect_strip(ch, sn );
return FALSE;
}