dba/doc/
dba/doc/old/MPDocs/
dba/src/old_files/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "recycle.h"


void do_fuse (CHAR_DATA *ch, char *argument) {
    DESCRIPTOR_DATA *d, *desc1, *desc2;
    CHAR_DATA *ch2, *fuse;
    char arg[MAX_INPUT_LENGTH];
    char *msg = "***********************************************\n\r"
                "*$n has fused with $N, with $n\n\r"
                "*taking control.  $N will remain\n\r"
                "*conscious of everything happening,\n\r"
                "*but can take no action while the\n\r"
                "*fuse lasts.\n\r"
                "***********************************************\n\r";
    char slave_name[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int i, j;

    if (IS_NPC(ch)) {
        send_to_char ("Players only.\n\r", ch);
        return;
    }

    one_argument (argument, arg);

    if (argument[0] == '\0') {
        send_to_char ("fuse <target> to fuse with someone.\n\r"
                      "fuse accept to accept a request to fusion.\n\r"
                      "fuse decline to decline the request.\n\r"
                      "fuse cancel to cancel an outgoing request.\n\r", ch);
        return;
    }
    else if (!str_cmp(argument, "accept")) {
        if (ch->pcdata->fusion_request) {
            send_to_char ("You must first cancel your request to fuse with someone.\n\r", ch);
            return;
        }

        ch2 = ch;
        ch = NULL;

        // Find character who issued request
        for (d = descriptor_list; d; d = d->next) {
            if (d->character && d->character->pcdata && d->character->pcdata->fusion_request == ch2) {
                ch = d->character;
                break;
            }
        }
        if (ch == NULL) {
            send_to_char ("No one wants to fuse with you!\n\r", ch2);
            return;
        }

        act ("{r$n fuses with $N!{x", ch, NULL, ch2, TO_NOTVICT);

        desc1 = ch->desc;
        desc2 = ch2->desc;

        fuse = new_char ();
        fuse->pcdata = new_pcdata ();

        fuse->name = str_dup (ch->name);

        // Locate a vowel in the name, around the 5th letter
        for (i = UMIN(strlen(ch->name)-1, 5); i > 1; --i)
            if (LOWER(ch->name[i]) == 'a' || LOWER(ch->name[i]) == 'e' ||
                LOWER(ch->name[i]) == 'i' || LOWER(ch->name[i]) == 'o' ||
                LOWER(ch->name[i]) == 'u' || LOWER(ch->name[i]) == 'y')
                break;

        // Now add the first 3 of the second name after the vowel
        ++i;
        for (j = 0; ch2->name[j] != '\0' && j < 3; ++j)
            fuse->name[i+j] = LOWER(ch2->name[j]);
        fuse->name[i+j+1] = '\0';

        fuse->id = get_pc_id ();

        // Add the two chars together
        // (All ripped from load_char_obj)

        fuse->race = ch->race;
        fuse->act = ch->act;
        fuse->comm = ch->comm;
        if (ch->prompt)
            fuse->prompt = str_dup (ch->prompt);
        fuse->pcdata->confirm_delete = FALSE;
        fuse->pcdata->board = &boards[DEFAULT_BOARD];
        fuse->pcdata->pwd = str_dup ("");
        if (ch->pcdata->bamfin)
            fuse->pcdata->bamfin = str_dup (ch->pcdata->bamfin);
        if (ch->pcdata->bamfout)
            fuse->pcdata->bamfout = str_dup (ch->pcdata->bamfout);
        fuse->pcdata->title = str_dup (" the {YFused{x.");
        for (i = 0; i < MAX_STATS; i++)
            fuse->perm_stat[i] = ch->perm_stat[i] + ch2->perm_stat[i];
        fuse->pcdata->condition[COND_THIRST] = ch->pcdata->condition[COND_THIRST] + ch2->pcdata->condition[COND_THIRST];
        fuse->pcdata->condition[COND_FULL] = ch->pcdata->condition[COND_FULL] + ch2->pcdata->condition[COND_FULL];
        fuse->pcdata->condition[COND_HUNGER] = ch->pcdata->condition[COND_HUNGER] + ch2->pcdata->condition[COND_HUNGER];
        fuse->pcdata->security = ch->pcdata->security;

        fuse->size = ch->size;
        fuse->affected_by = ch->affected_by;
        fuse->alignment = URANGE(-1000,ch->alignment + ch2->alignment,1000);
        for	(i = 0; i < 4; i++)
            fuse->armor[i] = ch->armor[i] + ch2->armor[i];
        for (i = 0; i < MAX_ALIAS; ++i) {
            if (fuse->pcdata->alias[i] == NULL)
                break;
            fuse->pcdata->alias[i] = str_dup (fuse->pcdata->alias[i]);
            fuse->pcdata->alias_sub[i] = str_dup (fuse->pcdata->alias_sub[i]);
        }
        for (i = 0; i < MAX_STATS; i++) {
            fuse->mod_stat[i] = ch->mod_stat[i] + ch2->mod_stat[i];
            fuse->perm_stat[i] = ch->perm_stat[i] + ch2->perm_stat[i];
        }
        for (i = 0; i < MAX_BOARD; i++)
            fuse->pcdata->last_note[i] = ch->pcdata->last_note[i];
        fuse->clan = ch->clan;
        fuse->comm = ch->comm;
        fuse->damroll = ch->damroll + ch2->damroll;
        fuse->hitroll = ch->hitroll + ch2->hitroll;
        fuse->max_hit = ch->max_hit + ch2->max_hit;
        fuse->hit = fuse->max_hit;
        fuse->max_ki = ch->max_ki + ch2->max_ki;
        fuse->ki = fuse->max_ki;
        fuse->pcdata->perm_hit = ch->pcdata->perm_hit + ch2->pcdata->perm_hit;
        fuse->pcdata->perm_ki = ch->pcdata->perm_ki + ch2->pcdata->perm_ki;
        fuse->invis_level = ch->invis_level;
        fuse->incog_level = ch->incog_level;
        fuse->level = ch->level;
        fuse->played = ch->played + ch2->played;
        fuse->pl = UMIN(get_perm_pl(ch) + get_perm_pl(ch2), MAX_PL);
        fuse->cur_pl = fuse->pl / 4;
        fuse->perm_trans = ch->perm_trans;
        fuse->race = ch->race;
        fuse->saving_throw = ch->saving_throw + ch2->saving_throw;
        fuse->lines = ch->lines;
        fuse->sex = ch->sex;
        for (i=0; i<MAX_SKILL; ++i)
            fuse->pcdata->learned[i] = UMIN(ch->pcdata->learned[i] + ch2->pcdata->learned[i], 10);
        fuse->pcdata->true_sex = ch->pcdata->true_sex;
        fuse->train = ch->train + ch2->train;
        fuse->trans = ch->trans;
        fuse->trans_count = ch->trans_count;
        fuse->wimpy = ch->wimpy;
        fuse->wiznet = ch->wiznet;
        fuse->zenni = ch->zenni + ch2->zenni;

        default_colour(fuse);

        fuse->fuse_control = str_dup (ch->name);
        fuse->fuse_slave = str_dup (ch2->name);
        fuse->fuse_count = 5;
        fuse->fused = TRUE;

        char_to_room(fuse, ch->in_room);

        strcpy (slave_name, ch2->name);
        strcat (slave_name, "Slave");

        fuse->next = char_list;
        char_list = fuse;
        reset_char (fuse);

        act (msg, ch, NULL, ch2, TO_CHAR);

        // Remove the characters
        save_char_obj (ch);
        save_char_obj (ch2);

        if (ch->pcdata->in_progress)
            free_note (ch->pcdata->in_progress);
        if (ch2->pcdata->in_progress)
            free_note (ch2->pcdata->in_progress);

        extract_char (ch, TRUE);
        extract_char (ch2, TRUE);

        // Set the descriptors, create some place-holder character for the slave
        fuse->desc = desc1;
        fuse->desc->fuse = desc2;

        fuse->desc->character = fuse;
        fuse->desc->fuse->character = new_char ();
        fuse->desc->fuse->character->pcdata = new_pcdata ();
        fuse->desc->fuse->connected = CON_FUSE_SLAVE;
        fuse->desc->fuse->character->name = str_dup (slave_name);

        return;
    }
    else if (!str_cmp(argument, "decline")) {
        ch2 = NULL;

        // Find character who issued request
        for (d = descriptor_list; d; d = d->next) {
            if (d->character->pcdata->fusion_request == ch) {
                ch2 = d->character;
                break;
            }
        }
        if (ch2 == NULL) {
            send_to_char ("No one wants to fuse with you!\n\r", ch);
            return;
        }

        send_to_char ("Your request to fuse has been declined.\n\r", ch2);
        send_to_char ("You decline the request to fuse.\n\r", ch);
        ch2->pcdata->fusion_request = NULL;
        return;
    }
    else if (!str_cmp(argument, "cancel")) {
        if (ch->pcdata->fusion_request == NULL) {
            send_to_char ("You haven't asked anyone to fuse.\n\r", ch);
            return;
        }

        send_to_char ("The request to fuse has been canceled.\n\r", ch->pcdata->fusion_request);
        send_to_char ("You have canceled the request to fuse.\n\r", ch);
        ch->pcdata->fusion_request = NULL;
        return;
    }
    else if ((ch2 = get_char_room(ch, NULL, arg)) == NULL || IS_NPC(ch2)) {
        send_to_char ("Character not found.\n\r", ch);
        return;
    }

    if (3*(ch->pl/4) > ch2->pl || 3*(ch2->pl/4) > ch->pl) {
        send_to_char ("You cannot fuse because you and your target are of radically different powerlevel.\n\r", ch);
        return;
    }

    if (ch->pcdata->fusion_request)
        send_to_char ("The request to fuse has been canceled.\n\r", ch->pcdata->fusion_request);

    ch->pcdata->fusion_request = ch2;

    send_to_char ("You have sent out a request to fuse.\n\r", ch);
    sprintf (buf, "You have been asked by %s to fuse.\n\r", ch->name);
    send_to_char (buf, ch2);

    return;
}


void do_unfuse (CHAR_DATA *ch, char *argument) {
    if (IS_NPC(ch)) {
        send_to_char ("Players only.\n\r", ch);
        return;
    }

    if (!IS_FUSED(ch)) {
        send_to_char ("Your not fused!\n\r", ch);
        return;
    }

    unfuse (ch);

    return;
}

void unfuse (CHAR_DATA *ch) {
    DESCRIPTOR_DATA *desc1, *desc2;
    CHAR_DATA *ch1, *ch2;
    ROOM_INDEX_DATA *in_room;
    char fuse_control[40], fuse_slave[40];

    /*
     * Try to change each character's stats
     * to reflect anything gained during a
     * fusion.  Doesn't work.  If the
     * player's skills are both 10, fused
     * has only only 10 as well. So, it
     * appears the stats have gone from
     * 10+10 down only 10 - thus, after fuse
     * both players lose 5 in each skill
    long long int c_pl;
    int c_zenni, c_train;
    int c_hit, c_ki;
    int c_skill[MAX_SKILL];
    int c_align;
    int i;
    */

    if (IS_NPC(ch) || !IS_FUSED(ch))
        return;

    send_to_char ("{rThe fuse is broken!{x\n\r", ch);

    desc1 = ch->desc;
    desc2 = ch->desc->fuse;

    desc1->fuse = NULL;
    desc2->connected = CON_PLAYING;

    strcpy (fuse_control, ch->fuse_control);
    strcpy (fuse_slave, ch->fuse_slave);
    in_room = ch->in_room;

    /*
    c_pl    = get_perm_pl(ch);
    c_zenni = ch->zenni;
    c_train = ch->train;
    c_hit   = ch->max_hit;
    c_ki    = ch->max_ki;
    c_align = ch->alignment;
    for (i=0; i<MAX_SKILL; ++i)
        c_skill[i] = ch->pcdata->learned[i];
    */

    if (ch->pcdata->in_progress)
        free_note (ch->pcdata->in_progress);
    extract_char (ch, TRUE);

    load_char_obj (desc1, fuse_control);
    load_char_obj (desc2, fuse_slave);

    ch1 = desc1->character;
    ch2 = desc2->character;

    char_to_room(ch1, in_room);
    char_to_room(ch2, in_room);

    ch1->next = ch2;
    ch2->next = char_list;
    char_list = ch1;

    /*
    c_pl    -= get_perm_pl(ch1) + get_perm_pl(ch2);
    c_zenni -= ch1->zenni + ch2->zenni;
    c_train -= ch1->train + ch2->train;
    c_hit   -= ch1->max_hit + ch2->max_hit;
    c_ki    -= ch1->max_ki + ch2->max_ki;
    c_align -= ch1->alignment + ch2->alignment;
    for (i=0; i<MAX_SKILL; ++i)
        c_skill[i] -= ch1->pcdata->learned[i] + ch2->pcdata->learned[i];

    ch1->pl       += c_pl / 2;
    ch1->cur_pl    = UMIN(ch1->cur_pl, ch1->pl);
    ch1->zenni    += c_zenni / 2;
    ch1->train    += c_train / 2;
    ch1->max_hit  += c_hit / 2;
    ch1->max_ki   += c_ki / 2;
    ch1->alignment = URANGE(-1000, ch1->alignment + c_align / 2, 1000);

    ch2->pl       += c_pl / 2;
    ch2->cur_pl    = UMIN(ch2->cur_pl, ch2->pl);
    ch2->zenni    += c_zenni / 2;
    ch2->train    += c_train / 2;
    ch2->max_hit  += c_hit / 2;
    ch2->max_ki   += c_ki / 2;
    ch2->alignment = URANGE(-1000, ch2->alignment + c_align / 2, 1000);

    for (i=0; i<MAX_SKILL; ++i) {
        ch1->pcdata->learned[i] += c_skill[i] / 2;
        ch2->pcdata->learned[i] += c_skill[i] / 2;
    }
    */

    reset_char (ch1);
    reset_char (ch2);

    act ("{r$n seperates from the fusion with $N!{x", ch1, NULL, ch2, TO_NOTVICT);
    act ("{rYou break from the fusion with $N.{x", ch1, NULL, ch2, TO_CHAR);
    act ("{rYou break from the fusion with $N.{x", ch2, NULL, ch1, TO_CHAR);
}