/
area/city/
area/crypts/
area/guilds/
area/psuedowild/
area/religion/
data/documents/MPDocs/
data/html/
data/mobprogs/
data/quest/
data/world/
data/world/_utilities/
data/world/images/
design/html/
notes/
player/
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zlib.h>
#include "merc.h"
#include "world.h"
#include "recycle.h"
#include "gdl.h"
#include "bounty.h"
#include "interp.h"

/* GDL thingy */
BEGIN_ELE_LIST(BOUNTY)
STR(name)
STR(shortd)
STR(who)
INT(id)
INT(timeleft)
INT(amount)
INT(bountypnts)
INT(mob)
INT(questp)
END_ELE_LIST

BOUNTY *bounty_list;
int global_bounty;

void load_bounty()
{
    LOAD_LIST(bounty_list,BOUNTY,BOUNTY_FILE);
    load_global_bounty();
    return;
}

/*
 * do_bounty()
 *
 * Display and placement of bounties on players.
 */
void do_bounty(CHAR_DATA * ch, char *argument)
{
    BOUNTY *p;
    char buf[MSL];
    char buf2[MSL];
    char buf3[MSL];
    char arg[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int value = 0;
    CHAR_DATA * mob;
    OBJ_DATA * paper;
    int cnt = 0;;

    argument = one_argument (argument, arg);
    argument = one_argument (argument, arg2);
    
    for (mob = ch->in_room->people; mob; mob = mob->next_in_room)
    {
        if (IS_NPC (mob) && IS_SET (mob->act, ACT_BOUNTY))
            break;
    }
    
    if (mob == NULL)
    {
        send_to_char ("You can't do that here.\n\r", ch);
        return;
    }
    
    if (arg[0] == '\0')
    {
        
        if (bounty_list == NULL)
        {
            do_say(mob, "There are no bounties availible, please check agaian at a later time.");
            return;
        }
        
        do_say(mob, "The following bounties are availible to collect...");
        for (p = bounty_list; p ; p = p->next)
        {
            cnt++;
            
            if (p->timeleft == -1)
                sprintf(buf3, "this bounty will last {Wforever{x");
            else if (p->timeleft == 0)
                sprintf(buf3, "this bounty will expire {RWithin the hour");
            else
                sprintf(buf3, "there are {R%d{x hours left", p->timeleft);
            
            if (p->name == ch->name)
                sprintf(buf2, "you");
            else
                sprintf(buf2, "%s", p->shortd);
            
            if (ch->level >= 125)
            {
                sprintf(buf, "{C[{w%-3d{C]{x a bounty of {Y%d gold{x pieces, {B%d{x questpoints has been placed on {b%s{x by {m%s{x, %s{x.",
                    p->id,
                    p->amount,
                    p->questp, 
                    buf2,
                    p->who,
                    buf3);
                do_say(mob, buf);
            }
            else
            {
                sprintf(buf, "{x a bounty of {Y%d gold{x pieces, {B%d{x questpoints has been placed on {b%s{x by {m%s{x, %s{x.",
                    p->amount,
                    p->questp, 
                    buf2,
                    p->who,
                    buf3);
                do_say(mob, buf);
            }
        }
        sprintf(buf, "Total %d bounties, %d of which are mob generated\n", 
            cnt,
            count_mob_bounties());
        stc(buf, ch);
            
        do_say(mob, "Thats all we have for now. Good hunting.'");
        return;
    }
    
    if (!str_prefix(arg, "clear"))
    {
        for (p = bounty_list; p ; p = p->next)
            free_bounty(p);
        stc("Done\n\r", ch);
        return;
    }
    
    /* Handle claiming */
    if (!str_prefix (arg, "claim"))
    {
        paper = get_eq_char (ch, WEAR_HOLD);
        
        if (paper == NULL)
        {
            do_say(mob, "Hmm, but you hold no proof in your hands!");
            return;
        }
        if (paper->item_type != ITEM_BOUNTY)
        {
            do_say(mob, "I'm sorry, but you must hold your proof in your hands.");
            return;
        }
        sprintf(buf, "Ahh, You return the big toe of %s I see, very well.. let me see how much it is worth...", paper->material);
        do_say(mob, buf);
        sprintf(buf, "The bounty on {w%s{G is worth {Y%d{y gold{G, {W%d{w questpoints{G, {R%d{r bounty points{G. Congradulations %s. Well done!",
            paper->material,
            paper->value[0],
            paper->value[1],
            paper->value[2],
            ch->name);
        do_say(mob, buf);
        ch->gold            += paper->value[0];
        ch->quest_curr      += paper->value[1];
        ch->quest_accum     += paper->value[1];
        ch->bountypnts      += paper->value[2];
        ch->bountypnts_accum+= paper->value[2];

        
        for (p = bounty_list; p ; p = p->next)
            if (p->who == paper->material)
                free_bounty(p);

        extract_obj(paper);
        return;
    }
    
    if ((victim = get_char_world (ch, arg)) == NULL)
    {
        do_say(mob, "I'm sorry, but that person isn't here.");
        return;
    }
    
    if (IS_NPC (victim) && (ch->level < 125))
    {
        do_say(mob, "Hmm? I'm sorry, but why not just go kill it yourself?");
        do_say(mob, "I mean, yeesh, it sits there and dies.. how hard can it be?");
        return;
    }
    
    value = atoi (arg2);
    
    if (value <= 0 && (ch->level < 125))
    {
        do_say(mob, "Erm, you must give a REAL value in gold pieces.");
        return;
    }
    
    /* Find previous bounty and add to it */
    for (p = bounty_list; p ; p = p->next)
    {
        if (p->name == victim->name)
        {
            if (ch->gold < value)
            {
                sprintf(buf, "I'm sorry %s, but you do not have that much gold.", ch->name);
                do_say(mob, buf);
                return;
            }
            p->amount += value;
            if (ch->level < 125)
                ch->gold -= value;
            
            sprintf(buf, "The bounty on %s has been increased to %d {ygold{x pieces.", p->name, p->amount);
            do_say(mob, buf);
            SAVE_LIST(bounty_list, BOUNTY, BOUNTY_FILE);
            save_global_bounty();
            return;
        }
    }
    
    
    p = malloc(sizeof(BOUNTY));
    p->name         = victim->name;
    global_bounty++;
    p->id           = global_bounty;
    p->timeleft     = -1;
    p->amount       = value;
    p->questp          = 0;
    p->bountypnts   = 5;
    p->who          = ch->name;
    p->mob          = FALSE;
    if (IS_NPC(victim))
        p->shortd = victim->short_descr;
    else
        p->shortd = victim->name;
    p->next     = bounty_list;
    bounty_list = p;
    SAVE_LIST(bounty_list, BOUNTY, BOUNTY_FILE);
    save_global_bounty();
    
    sprintf(buf, "Your bounty of {y%d{G gold pieces has been placed on %s.", value, p->name);
    do_say(mob, buf);
    return;
    
}

/*
 * check_bounty()
 *
 * checks to see if theres a bounty, if so, give the papers, and remove bounty.
 */
void check_bounty(CHAR_DATA * ch, CHAR_DATA * victim)
{
    BOUNTY *p;
    
    /*log_string("Check bounty"); */
    
    if (bounty_list == NULL)
        return;
    
    for (p = bounty_list; p ; p = p->next)
    {
        if (p->name == victim->name)
        {
            create_bounty_paper(ch, p->shortd, p->amount, p->questp, p->bountypnts, p);
            free_bounty(p);
        }
    }
    return; 
}

/*
 * create_bounty_paper()
 *
 * Creates the bounty paper with the victim's name
 * to be collected at a later date.
 * obj->material used for their name
 *
 * Ears/Scaples too common
 *
 * I like big toes.
 */
void create_bounty_paper(CHAR_DATA * ch, char *who, int gold, int qps, int bounties, BOUNTY * p)
{
    char name_set[MSL];
    char shor_set[MSL];
    char long_set[MSL];
    OBJ_DATA * obj = create_object (get_obj_index (35), 0);
    
    sprintf(name_set, "%s big toe", who);
    sprintf(shor_set, "the {bsevered{x big toe of {W%s{x.", who);
    sprintf(long_set, "the {Bsevered{x big toe of {W%s{x has been carelessly left here.", who);
    
    free_string(obj->name);
    free_string(obj->short_descr);
    free_string(obj->description);
    free_string(obj->material);
    obj->name               = str_dup (name_set);
    obj->short_descr        = str_dup (shor_set);
    obj->description        = str_dup (long_set);
    obj->material           = str_dup (who);
    obj->value[0]           = gold;
    obj->value[1]           = qps;
    obj->value[2]           = bounties;
    
    obj->level              = 1;
    
    act ("{M$n claim $p!", ch, obj, NULL, TO_ROOM);
    act ("{MYou claim $p!", ch, obj, NULL, TO_CHAR);
    
    obj_to_char(obj, ch);
    
    free_bounty(p);
    
    return;
}


/*
 * free_bounty()
 *
 * Removes a bounty from the list
 */
void free_bounty(BOUNTY * p)
{
    BOUNTY * x;
    
    if (p == bounty_list)
        bounty_list = p->next;
    else
    {
        for (x = bounty_list; x && x->next != x; x = x->next)
        {
            if (x == NULL)
            {
                log_string("FREE_BOUNTY: bounty not found");
                return;
            }
            x->next = x->next;
        }
    }

    SAVE_LIST(bounty_list, BOUNTY, BOUNTY_FILE);
    return;
}
        
    

/*
 * save()
 *
 * saves the count file. Useless stats are fun ya know.
 */
void save_global_bounty()
{
    FILE *fp;
    
    if (!(fp = fopen (BOUNTY_CNT_FILE,"w+")))
    {
        log_string ("creation of new bounty_cnt_file failed");
    }
    else
    {
        fprintf (fp, "%d", global_bounty);
        fclose(fp);
    }
    return;
}

/*
 * load()
 *
 * loads the bounty count file.
 */
void load_global_bounty()
{
    bool fail = FALSE;
    /* Try and load time from file first */
    FILE *fp;
    if ((fp = fopen (BOUNTY_CNT_FILE, "r")))
    {
        fscanf(fp, "%d", &(global_bounty));
        fclose (fp);
    }
    else
    {
        log_string ("failed open of bounty_cnt_file");
        fail = TRUE;
    }
    if (fail)
    {
        global_bounty = 2;
    }
    return;
}

/*
 * count_mob_bounties()
 *
 * utility, counts total mob bounties availible
 */
int count_mob_bounties()
{
    BOUNTY * p;
    int cnt = 0;
    
    for (p = bounty_list; p ; p = p->next)
    {
        if (p->mob)
            cnt++;
    }
    return cnt;
}

/*
 * generate_random_bounty()
 *
 * From time to time, random bounties will be given out, no more than 20 at a time..
 * mob search routine taken from quest thingy =)
 */
void generate_random_bounty()
{
    MOB_INDEX_DATA *vsearch;
    int counter;
    int mob_vnum;
    int value;
    int quest;
    BOUNTY * p;
    CHAR_DATA * victim;
    int test = count_mob_bounties();

    for (counter = 0; counter < 99999; counter ++)
    {
        mob_vnum = number_range(50, 32600);

        if ( (vsearch = get_mob_index(mob_vnum) ) != NULL )
        {
            if (   vsearch->pShop == NULL
                && !IS_SET(vsearch->act, ACT_TRAIN)
                && !IS_SET(vsearch->act, ACT_PRACTICE)
                    && !IS_SET(vsearch->act, ACT_IS_HEALER)
                && !IS_SET(vsearch->act, ACT_PET)
                && !IS_SET(vsearch->affected_by, AFF_CHARM)
                && number_percent() < 40) break;
                else vsearch = NULL;
        }
    }

    if ( vsearch == NULL || ( victim = get_char_world2( vsearch->player_name ) ) == NULL )
        return;
    
    /*
     * cant make any more random ones
     */
    if (test >= MAX_RANDOM_BOUNTIES)
        return;
    
    /* Determine value, I have it set for random +/-5 levevels * 1000
      plus a random 1-1000 for a good mix
     */
    value = victim->level;
    if (value <= 0)
        value = 1;
    
    value *= 1000;
    value += number_range(-333, 333);

    quest = 0;
    quest += number_range(1, (victim->level / 2)) + 1;
    
    /* ok have the mob, make bounty */
    p = malloc(sizeof(BOUNTY));
    p->name         = victim->name;
    global_bounty++;
    p->id           = global_bounty;
    p->who          = rand_bounty_giver();
    p->timeleft     = number_range(30, 60);
    p->amount       = value;
    p->questp          = quest;
    p->bountypnts   = 2;
    p->next         = bounty_list;
    p->mob          = 1;

    if (IS_NPC(victim))
        p->shortd = victim->short_descr;
    else
        p->shortd = victim->name;
    
    bounty_list = p;
    SAVE_LIST(bounty_list, BOUNTY, BOUNTY_FILE);
    save_global_bounty();
    return;
}

/*
 * get_char_world2()
 *
 * identical to stock, just removed ch parts of it
 * to make it a nice non-specific utility
 */
CHAR_DATA *get_char_world2 (char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *wch;
    int number;
    int count;

    number = number_argument (argument, arg);
    count = 0;
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
        if (wch->in_room == NULL
            || !is_name (arg, wch->name))
            continue;
        if (++count == number)
            return wch;
    }

    return NULL;
}


/*
 * bountiers[]
 *
 * List of possible random bounty givers
 */
char *const bountiers[10] =
{
    "The City of Vandagard",
    "The Necromancer's Guild",
    "The colsolidated Bank of Vandagard",
    "Misha",
    "The Faith of Gwenidon",
    "The Fighter's Guild",
    "The Blades",
    "Thri, lord of the realm",
    "Matilda's General Store",
    "Thieve's local 104 union"
};

/*
 * rand_bounty_giver()
 *
 * Randomly chooses a bounty giver
 */
char *rand_bounty_giver()
{
    int rand = number_range(0, 9);
    
    return (bountiers[rand]);
}


/*
 * Updates bounty list, timer, etc
 */
void update_bounty()
{
    BOUNTY * p;
    
    for (p = bounty_list; p ; p = p->next)
    {
        if (p->timeleft != -1) /* -1 == Player bounties, always active */
        {
            if (p->timeleft == 0)
            {   /* No more time, remove it */
                free_bounty(p);
            }
            else
                p->timeleft--;
        }
                
    }
}

/*
 * utility, finds a bounty based on name
 */
BOUNTY * find_bounty(char *name)
{
    BOUNTY * p;
    
    for (p = bounty_list; p ; p = p->next)
    {
        if (p->who == name)
            return p;
        else
            return NULL;
    }
    return NULL;
}