#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;
OBJ_DATA *obj, *obj_next;
char arg[MAX_INPUT_LENGTH];
char *msg = "***********************************************\n\r"
"*%s has fused with %s, with %s\n\r"
"*taking control. %s 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)) {
sendch ("Players only.\n\r", ch);
return;
}
if (get_skill(ch, gsn_fusion) < 1) {
sendch ("You do not know how to fuse.\n\r", ch);
return;
}
one_argument (argument, arg);
if (argument[0] == '\0') {
sendch ("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) {
sendch ("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) {
sendch ("No one wants to fuse with you!\n\r", ch2);
return;
}
if (IS_FUSED(ch2)) {
sendch ("You're already fused!\n\r", ch2);
return;
}
if (IS_FUSED(ch)) {
act ("$e is already fused!", ch2, NULL, ch, TO_CHAR);
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] = '\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(ch->pl + ch2->pl, MAX_PL);
fuse->cur_pl = 25;
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;
// Take all the equipment from the controller
for (obj = ch->carrying; obj; obj = obj_next) {
obj_next = obj->next_content;
obj_from_char (obj);
obj_to_char (obj, fuse);
}
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);
// 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->character = fuse;
fuse->slave = new_char ();
fuse->slave->desc = desc2;
fuse->slave->desc->connected = CON_FUSE_SLAVE;
fuse->slave->desc->character = fuse->slave;
fuse->slave->pcdata = new_pcdata ();
fuse->slave->name = str_dup (slave_name);
sprintf (buf, msg, fuse->fuse_control, fuse->fuse_slave, fuse->fuse_control, fuse->fuse_slave);
sendch (buf, fuse);
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 && d->character->pcdata &&
d->character->pcdata->fusion_request == ch) {
ch2 = d->character;
break;
}
}
if (ch2 == NULL) {
sendch ("No one wants to fuse with you!\n\r", ch);
return;
}
sendch ("Your request to fuse has been declined.\n\r", ch2);
sendch ("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) {
sendch ("You haven't asked anyone to fuse.\n\r", ch);
return;
}
sendch ("The request to fuse has been cancelled.\n\r", ch->pcdata->fusion_request);
sendch ("You have cancelled 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)) {
sendch ("Character not found.\n\r", ch);
return;
}
if (IS_FUSED(ch2)) {
sendch ("You're already fused!\n\r", ch2);
return;
}
if (IS_FUSED(ch)) {
act ("$e is already fused!", ch2, NULL, ch, TO_CHAR);
return;
}
if (ch->pl/2 > ch2->pl || ch2->pl/2 > ch->pl) {
sendch ("You cannot fuse because you and your target are of radically different powerlevel.\n\r", ch);
return;
}
if (get_skill(ch2, gsn_kaioken) < 1) {
sendch ("You cannot fuse because your target does not know how to.\n\r", ch);
return;
}
if (ch->pcdata->fusion_request)
sendch ("The request to fuse has been cancelled.\n\r", ch->pcdata->fusion_request);
ch->pcdata->fusion_request = ch2;
sendch ("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);
sendch (buf, ch2);
return;
}
void do_unfuse (CHAR_DATA *ch, char *argument) {
if (IS_NPC(ch)) {
sendch ("Players only.\n\r", ch);
return;
}
if (!IS_FUSED(ch)) {
sendch ("You're not fused!\n\r", ch);
return;
}
unfuse (ch);
return;
}
void unfuse (CHAR_DATA *ch) {
DESCRIPTOR_DATA *desc1, *desc2 = NULL, d; // d is a temporary descriptor
CHAR_DATA *ch1, *ch2;
OBJ_DATA *obj, *obj_next;
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;
sendch ("{rThe fuse is broken!{x\n\r", ch);
desc1 = ch->desc;
if (ch->slave)
desc2 = ch->slave->desc;
if (desc2)
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 (desc1) {
load_char_obj (desc1, fuse_control);
ch1 = desc1->character;
}
else {
load_char_obj (&d, fuse_control);
ch1 = d.character;
ch1->desc = NULL;
}
if (desc2) {
load_char_obj (desc2, fuse_slave);
ch2 = desc2->character;
}
else {
load_char_obj (&d, fuse_slave);
ch2 = d.character;
ch2->desc = NULL;
}
char_to_room(ch1, in_room);
char_to_room(ch2, in_room);
ch1->next = ch2;
ch2->next = char_list;
char_list = ch1;
// Take all the equipment from the previous controlling character
for (obj = ch1->carrying; obj; obj = obj_next) {
obj_next = obj->next_content;
obj_from_char (obj);
extract_obj (obj);
}
// Give all equipment to the new character
for (obj = ch->carrying; obj; obj = obj_next) {
obj_next = obj->next_content;
obj_from_char (obj);
obj_to_char (obj, ch1);
}
if (ch->pcdata->in_progress)
free_note (ch->pcdata->in_progress);
extract_char (ch, TRUE);
// extracting the fused character will set the descriptors to NULL -- set them back
ch1->desc = desc1;
if (desc1)
desc1->character = 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);
}