/** * \file fight.c * Central Combat Processor * * This module deals with combat, wounds, rescue and death. * * Copyright 2005, Mary C. Huston, All rights reserved. * Copyright (C) 2004, Shadows of Isildur: Traithe * * The program(s) may be used and/or copied only with written * permission or in accordance with the terms and conditions * stipulated in the license from DIKU GAMMA (0.0) and SOI. * * \author Mary Huston * \author Email: auroness@gmail.com * ****************************************************************************** */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <ctype.h> #include <time.h> #include <unistd.h> #include "structs.h" #include "protos.h" #include "utils.h" #include "decl.h" CHAR_DATA *combat_list = NULL; CHAR_DATA *combat_next_dude = NULL; /* Next dude global trick */ void compete (CHAR_DATA *src, CHAR_DATA *tar, int iterations); /* Weapon attack texts */ void load_messages(void) { FILE *f1; int i,type; struct message_type *messages; char chk[100]; if (!(f1 = fopen(MESS_FILE, "r"))){ perror("read messages"); abort(); } for (i = 0; i < MAX_MESSAGES; i++) { fight_messages[i].a_type = 0; fight_messages[i].number_of_attacks=0; fight_messages[i].msg = 0; } fscanf(f1, " %s \n", chk); while(*chk == 'M') { fscanf(f1," %d\n", &type); for (i = 0; (i < MAX_MESSAGES) && (fight_messages[i].a_type!=type) && (fight_messages[i].a_type); i++); if(i>=MAX_MESSAGES){ system_log ("Too many combat messages.", TRUE); abort(); } CREATE(messages,struct message_type,1); fight_messages[i].number_of_attacks++; fight_messages[i].a_type=type; messages->next=fight_messages[i].msg; fight_messages[i].msg=messages; messages->die_msg.attacker_msg = fread_string(f1); messages->die_msg.victim_msg = fread_string(f1); messages->die_msg.room_msg = fread_string(f1); messages->miss_msg.attacker_msg = fread_string(f1); messages->miss_msg.victim_msg = fread_string(f1); messages->miss_msg.room_msg = fread_string(f1); messages->hit_msg.attacker_msg = fread_string(f1); messages->hit_msg.victim_msg = fread_string(f1); messages->hit_msg.room_msg = fread_string(f1); messages->god_msg.attacker_msg = fread_string(f1); messages->god_msg.victim_msg = fread_string(f1); messages->god_msg.room_msg = fread_string(f1); fscanf(f1, " %s \n", chk); } fclose(f1); } void add_criminal_time (CHAR_DATA *ch, int zone, int penalty_time) { AFFECTED_TYPE *af; magic_add_affect (ch, MAGIC_CRIM_BASE + zone, penalty_time, 0, 0, 0, 0); af = get_affect (ch, MAGIC_CRIM_BASE + zone); if ( af->a.spell.duration > 36 ) af->a.spell.duration = 36; } void criminalize (CHAR_DATA *ch, CHAR_DATA *vict, int zone, int crime) { int criminalize_him = 0; int penalty_time = 0; AFFECTED_TYPE *af; ROOM_DATA *room; CHAR_DATA *tch; char *date = NULL; char msg [MAX_STRING_LENGTH] = {'\0'}; if ( crime == CRIME_KILL ) penalty_time = 24; else if ( crime == CRIME_STEAL ) penalty_time = 8; else if ( crime == CRIME_PICKLOCK ) penalty_time = 4; else penalty_time = 4; /* This allows someone to avoid criminalization by assisting a guard and then turning on the guard, or other similar things. This is bad. */ if ( !ch || !vict ) return; if ( ch->fighting ) return; room = ch->room; if ( is_area_enforcer (ch) ) return; if ( !IS_SET (room->room_flags, LAWFUL) ) return; if ( vict ) { if ( IS_SET (vict->act, ACT_CRIMINAL) ) return; if ( IS_SET (vict->act, ACT_WILDLIFE) ) return; if ( IS_SET (vict->act, ACT_AGGRESSIVE) ) return; if ( IS_SET (vict->act, ACT_PARIAH) ) return; if ( (get_affect (vict, MAGIC_CRIM_BASE + zone) || get_affect (vict, MAGIC_CRIM_HOODED + zone)) && !get_affect (ch, MAGIC_CRIM_BASE + zone) ) return; } if ( is_hooded (ch) ) { if ( (!OUTSIDE (ch) && !IS_LIGHT (room)) || (OUTSIDE (ch) && IS_NIGHT) ) { if ( !(af = get_affect (ch, MAGIC_CRIM_HOODED + zone)) ) magic_add_affect (ch, MAGIC_CRIM_HOODED + zone, 1, penalty_time, 0, 0, 0); else af->a.spell.modifier += penalty_time; for ( tch = ch->room->people; tch; tch = tch->next_in_room ) enforcer (tch, ch, 1, 1); if ( !ch->deleted && !af ) { af = get_affect (ch, MAGIC_CRIM_HOODED + zone); affect_remove (ch, af); } return; } else if ( !number (0, 4) ) criminalize_him = 1; else magic_add_affect (ch, MAGIC_CRIM_HOODED + zone, 40, penalty_time, 0, 0, 0); } else criminalize_him = 1; if ( criminalize_him ) { send_to_char ("An onlooker gasps at your actions and runs off to find " "help!\n", ch); /* Add hooded crim affect with penalty of 0 as a marker */ magic_add_affect (ch, MAGIC_CRIM_HOODED + zone, 40, 0, 0, 0, 0); add_criminal_time (ch, zone, penalty_time); /* Interconnected city zones */ if ( zone == 1 ) { magic_add_affect (ch, MAGIC_CRIM_HOODED + 3, 40, 0, 0, 0, 0); add_criminal_time (ch, 3, penalty_time); } else if ( zone == 3 ) { magic_add_affect (ch, MAGIC_CRIM_HOODED + 1, 40, 0, 0, 0, 0); add_criminal_time (ch, 1, penalty_time); } if ( IS_MORTAL (ch) ) { date = timestr(date); if ( crime == CRIME_KILL ) snprintf (msg, MAX_STRING_LENGTH, "Flagged wanted for Assault in %s for %d hours. [%d]\n", zone_table[ch->room->zone].name, penalty_time, ch->in_room); else if ( crime == CRIME_STEAL ) snprintf (msg, MAX_STRING_LENGTH, "Flagged wanted for Attempted Theft in %s for %d hours. [%d]\n", zone_table[ch->room->zone].name, penalty_time, ch->in_room); else if ( crime == CRIME_PICKLOCK ) snprintf (msg, MAX_STRING_LENGTH, "Flagged wanted for Breaking and Entering in %s for %d hours. [%d]\n", zone_table[ch->room->zone].name, penalty_time, ch->in_room); else snprintf (msg, MAX_STRING_LENGTH, "Flagged wanted in %s for %d hours. [%d]\n", zone_table[ch->room->zone].name, penalty_time, ch->in_room); if ( !IS_NPC (ch) ) { add_message (ch->tname, 3, "Server", date, "Wanted.", "", msg, 0); add_message ("Crimes", 2, "Server", date, ch->tname, "", msg, 0); } } } /* Immediate guard response */ for ( tch = ch->room->people; tch; tch = tch->next_in_room ) enforcer (tch, ch, 1, 1); } void stop_fighting_sounds (CHAR_DATA *ch, ROOM_DATA *room) { int dir, from_dir; ROOM_DIRECTION_DATA *exit_room; ROOM_DATA *next_room; char buf [MAX_STRING_LENGTH] = {'\0'}; char *e_dirs [] = { "to the north", "to the east", "to the south", "to the west", "above", "below" }; AFFECTED_TYPE *af; if ( !ch->room ) return; if ( !room ) return; for ( dir = 0; dir <= 5; dir++ ) { if ( !(exit_room = PASSAGE (ch, dir)) ) continue; if ( !(next_room = vtor (exit_room->to_room)) ) continue; if ( dir == 0 ) from_dir = 2; else if ( dir == 1 ) from_dir = 3; else if ( dir == 2 ) from_dir = 0; else if ( dir == 3 ) from_dir = 1; else if ( dir == 4 ) from_dir = 5; else from_dir = 4; if ( next_room->affects && next_room->affects->type == MAGIC_ROOM_FIGHT_NOISE && next_room->affects->a.room.duration == from_dir ) { next_room->affects = next_room->affects->next; } else for ( af = next_room->affects; af; af = af->next ) { if ( !af->next ) break; if ( af->next->type != MAGIC_ROOM_FIGHT_NOISE ) continue; if ( af->next->a.room.duration != from_dir ) continue; af->next = af->next->next; } snprintf (buf, MAX_STRING_LENGTH, "The sounds of an armed conflict %s have died away.", e_dirs[from_dir]); send_to_room (buf, next_room->virtual); } } void fighting_sounds (CHAR_DATA *ch) { int dir, from_dir; ROOM_DIRECTION_DATA *exit_room; ROOM_DATA *next_room; AFFECTED_TYPE *af; char buf [MAX_STRING_LENGTH] = {'\0'}; char *e_dirs [] = { "the north", "the east", "the south", "the west", "above", "below" }; bool found = FALSE; for ( dir = 0; dir <= 5; dir++ ) { if ( !(exit_room = PASSAGE (ch, dir)) ) continue; if ( !(next_room = vtor (exit_room->to_room)) ) continue; if ( dir == 0 ) from_dir = 2; else if ( dir == 1 ) from_dir = 3; else if ( dir == 2 ) from_dir = 0; else if ( dir == 3 ) from_dir = 1; else if ( dir == 4 ) from_dir = 5; else from_dir = 4; for ( af = next_room->affects; af; af = af->next ) { if ( af->type != MAGIC_ROOM_FIGHT_NOISE ) continue; if ( af->a.room.duration != from_dir ) continue; found = TRUE; } if ( !found ) { if ( !next_room->affects ) { next_room->affects = (AFFECTED_TYPE *)alloc (sizeof (AFFECTED_TYPE), 13); next_room->affects->type = MAGIC_ROOM_FIGHT_NOISE; next_room->affects->a.room.duration = from_dir; next_room->affects->next = NULL; } else for ( af = next_room->affects; af; af = af->next ) { if ( !af->next ) { af->next = (AFFECTED_TYPE *)alloc (sizeof (AFFECTED_TYPE), 13); af->next->type = MAGIC_ROOM_FIGHT_NOISE; af->next->a.room.duration = from_dir; af->next->next = NULL; break; } } snprintf (buf, MAX_STRING_LENGTH, "You hear the sounds of armed battle erupt from %s!", e_dirs[from_dir]); send_to_room (buf, next_room->virtual); } } } void set_fighting (CHAR_DATA *ch, CHAR_DATA *vict) { AFFECTED_TYPE *af; clear_pmote(ch); if ( IS_SET (ch->flags, FLAG_COMPETE) || IS_SET (vict->flags, FLAG_COMPETE) ) return; if ( ch->fighting ) { return; } if ( ch == vict ) /* No way, not in this game :( */ return; ch->next_fighting = combat_list; combat_list = ch; if ( (af = get_affect (ch, MAGIC_AFFECT_SLEEP)) ) affect_remove (ch, af); if ( GET_FLAG (ch, FLAG_AUTOFLEE) && AWAKE(ch) ) { send_to_char ("You try to escape!\n\r", ch); act ("$n tries to escape!", FALSE, ch, 0, 0, TO_ROOM); SET_BIT (ch->flags, FLAG_FLEE); } if ( (IS_SET (vict->act, ACT_PURSUE) || (!morale_broken(vict) && !IS_SET (vict->act, ACT_SENTINEL) && (IS_SET (vict->act, ACT_AGGRESSIVE) || IS_SET (vict->act, ACT_ENFORCER)))) && !vict->following ) { /* vict->following = ch; */ vict->speed = ch->speed; } if ( (IS_SET (ch->act, ACT_PURSUE) || (!morale_broken(ch) && !IS_SET (ch->act, ACT_SENTINEL) && (IS_SET (ch->act, ACT_AGGRESSIVE) || IS_SET (ch->act, ACT_ENFORCER)))) && !ch->following ) { /* vict->following = ch; */ ch->speed = vict->speed; } if ( (af = is_crafting(ch)) ) { act ("$n stops doing $s craft.", FALSE, ch, 0, 0, TO_ROOM); send_to_char ("You stop doing your craft.\n", ch); af->a.craft->timer = 0; } if ( (af = is_crafting(vict)) ) { act ("$n stops doing $s craft.", FALSE, vict, 0, 0, TO_ROOM); send_to_char ("You stop doing your craft.\n", vict); af->a.craft->timer = 0; } ch->fighting = vict; /* fighting_sounds(ch); */ add_threat (vict, ch, 2); add_threat (ch, vict, 2); clear_moves (ch); clear_moves (vict); if ( IS_NPC(ch) && !ch->desc && (is_area_enforcer(ch) || ch->race == RACE_WOLF) && IS_SET (ch->flags, FLAG_KILL) ) do_alert (ch, "", 0); if ( IS_NPC(vict) && !vict->desc && (is_area_enforcer(vict) || vict->race == RACE_WOLF) && IS_SET (vict->flags, FLAG_KILL) ) do_alert (vict, "", 0); } void stop_fighting (CHAR_DATA *ch) { CHAR_DATA *tch; bool fighting = FALSE; for ( tch = ch->room->people; tch; tch = tch->next_in_room ) { if ( tch == ch ) continue; if ( tch->fighting ) fighting = TRUE; } if (ch == combat_next_dude) combat_next_dude = ch->next_fighting; if ( combat_list == ch ) combat_list = ch->next_fighting; else { for (tch = combat_list; tch && (tch->next_fighting != ch); tch = tch->next_fighting); if (!tch) { system_log ("Char fighting not found Error (fight.c, stop_fighting)", TRUE); sigsegv(SIGSEGV); } tch->next_fighting = ch->next_fighting; } ch->next_fighting = 0; ch->fighting = 0; if ( GET_POS (ch) == FIGHT ) GET_POS (ch) = STAND; REMOVE_BIT (ch->flags, FLAG_KILL); if ( ch->mount && !IS_SET (ch->act, ACT_MOUNT) && ch->mount->fighting ) stop_fighting (ch->mount); if ( IS_NPC(ch) ) { ch->speed = 0; ch->threats = NULL; ch->attackers = NULL; } } void make_statue (CHAR_DATA *ch) { OBJ_DATA *statue; OBJ_DATA *o; WOUND_DATA *wound; WOUND_DATA *cwound; LODGED_OBJECT_INFO *lodged; LODGED_OBJECT_INFO *clodged; char buf [MAX_STRING_LENGTH] = {'\0'}; char buf2 [MAX_STRING_LENGTH] = {'\0'}; int i; OBJ_DATA *temp_arg = NULL; statue = load_object (VNUM_STATUE); if ( !IS_NPC (ch) ) snprintf (buf, MAX_STRING_LENGTH, "statue pc_%s", GET_NAME (ch)); else { (void)one_argument (GET_NAME (ch), buf2); snprintf (buf, MAX_STRING_LENGTH, "statue npc_%s", buf2); } statue->name = str_dup (buf); snprintf (buf, MAX_STRING_LENGTH, "An eerily lifelike statue of %s looms here.", ch->short_descr); statue->description = str_dup(buf); snprintf (buf, MAX_STRING_LENGTH, "an eerily lifelike statue of %s", ch->short_descr); statue->short_description = str_dup(buf); for ( wound = ch->wounds; wound; wound = wound->next ) { if ( !statue->wounds ) { CREATE (statue->wounds, WOUND_DATA, 1); statue->wounds->location = add_hash(wound->location); statue->wounds->type = add_hash(wound->type); statue->wounds->name = add_hash(wound->name); statue->wounds->severity = add_hash(wound->severity); statue->wounds->bleeding = 0; statue->wounds->poison = wound->poison; statue->wounds->infection = wound->infection; statue->wounds->healerskill = wound->healerskill; statue->wounds->lasthealed = wound->lasthealed; statue->wounds->lastbled = wound->lastbled; statue->wounds->next = NULL; } else for ( cwound = statue->wounds; cwound; cwound = cwound->next ) { if ( cwound->next ) continue; CREATE (cwound->next, WOUND_DATA, 1); cwound->next->location = add_hash(wound->location); cwound->next->type = add_hash(wound->type); cwound->next->name = add_hash(wound->name); cwound->next->severity = add_hash(wound->severity); cwound->next->bleeding = 0; cwound->next->poison = wound->poison; cwound->next->infection = wound->infection; cwound->next->healerskill = wound->healerskill; cwound->next->lasthealed = wound->lasthealed; cwound->next->lastbled = wound->lastbled; cwound->next->next = NULL; break; } } for ( lodged = ch->lodged; lodged; lodged = lodged->next ) { if ( !statue->lodged ) { CREATE (statue->lodged, LODGED_OBJECT_INFO, 1); statue->lodged->vnum = lodged->vnum; statue->lodged->location = add_hash(lodged->location); statue->lodged->next = NULL; } else for ( clodged = statue->lodged; clodged; clodged = clodged->next ) { if ( !clodged->next ) { CREATE (clodged->next, LODGED_OBJECT_INFO, 1); clodged->next->vnum = lodged->vnum; clodged->next->location = add_hash(lodged->location); clodged->next->next = NULL; break; } } } if ( ch->right_hand ) { o = ch->right_hand; ch->right_hand = NULL; o->equiped_by = NULL; o->carried_by = NULL; o->next_content = NULL; obj_to_obj (o, statue); } if ( ch->left_hand ) { o = ch->left_hand; ch->left_hand = NULL; o->equiped_by = NULL; o->carried_by = NULL; o->next_content = NULL; obj_to_obj (o, statue); } statue->obj_flags.weight = get_weight (ch) * 5; for ( i = 0; i < MAX_WEAR; i++ ) if ( get_equip (ch, i) ){ temp_arg = unequip_char(ch, i); obj_to_obj (temp_arg, statue); } IS_CARRYING_N (ch) = 0; obj_to_room (statue, ch->in_room); } #define MAX_NPC_CORPSE_TIME 12 /* 3 RL hours -- corpses are saved. */ #define MAX_PC_CORPSE_TIME 96 /* 1 RL day -- corpses are saved. */ void make_corpse (CHAR_DATA *ch) { OBJ_DATA *corpse; OBJ_DATA *o; WOUND_DATA *wound; WOUND_DATA *cwound; LODGED_OBJECT_INFO *lodged; LODGED_OBJECT_INFO *clodged; char buf [MAX_STRING_LENGTH] = {'\0'}; char buf2 [MAX_STRING_LENGTH] = {'\0'}; int i; OBJ_DATA *temp_arg = NULL; corpse = load_object (VNUM_CORPSE); if ( !IS_NPC (ch) ) snprintf (buf, MAX_STRING_LENGTH, "corpse pc_%s", GET_NAME (ch)); else { (void)one_argument (GET_NAME (ch), buf2); snprintf (buf, MAX_STRING_LENGTH, "corpse npc_%s", buf2); } corpse->name = str_dup (buf); snprintf (buf, MAX_STRING_LENGTH, "The corpse of %s is lying here.", ch->short_descr); corpse->description = str_dup(buf); snprintf (buf, MAX_STRING_LENGTH, "the corpse of %s", ch->short_descr); corpse->short_description = str_dup(buf); for ( wound = ch->wounds; wound; wound = wound->next ) { if ( !corpse->wounds ) { CREATE (corpse->wounds, WOUND_DATA, 1); corpse->wounds->location = add_hash(wound->location); corpse->wounds->type = add_hash(wound->type); corpse->wounds->name = add_hash(wound->name); corpse->wounds->severity = add_hash(wound->severity); corpse->wounds->bleeding = 0; corpse->wounds->poison = wound->poison; corpse->wounds->infection = wound->infection; corpse->wounds->healerskill = wound->healerskill; corpse->wounds->lasthealed = wound->lasthealed; corpse->wounds->lastbled = wound->lastbled; corpse->wounds->next = NULL; } else for ( cwound = corpse->wounds; cwound; cwound = cwound->next ) { if ( cwound->next ) continue; CREATE (cwound->next, WOUND_DATA, 1); cwound->next->location = add_hash(wound->location); cwound->next->type = add_hash(wound->type); cwound->next->name = add_hash(wound->name); cwound->next->severity = add_hash(wound->severity); cwound->next->bleeding = 0; cwound->next->poison = wound->poison; cwound->next->infection = wound->infection; cwound->next->healerskill = wound->healerskill; cwound->next->lasthealed = wound->lasthealed; cwound->next->lastbled = wound->lastbled; cwound->next->next = NULL; break; } } for ( lodged = ch->lodged; lodged; lodged = lodged->next ) { if ( !corpse->lodged ) { CREATE (corpse->lodged, LODGED_OBJECT_INFO, 1); corpse->lodged->vnum = lodged->vnum; corpse->lodged->location = add_hash(lodged->location); corpse->lodged->next = NULL; } else for ( clodged = corpse->lodged; clodged; clodged = clodged->next ) { if ( !clodged->next ) { CREATE (clodged->next, LODGED_OBJECT_INFO, 1); clodged->next->vnum = lodged->vnum; clodged->next->location = add_hash(lodged->location); clodged->next->next = NULL; break; } } } if ( ch->right_hand ) { o = ch->right_hand; ch->right_hand = NULL; o->equiped_by = NULL; o->carried_by = NULL; o->next_content = NULL; obj_to_obj (o, corpse); } if ( ch->left_hand ) { o = ch->left_hand; ch->left_hand = NULL; o->equiped_by = NULL; o->carried_by = NULL; o->next_content = NULL; obj_to_obj (o, corpse); } if ( ch->mob ) { if ( GET_FLAG (ch, FLAG_WILLSKIN) ) { corpse->o.od.value [2] = -ch->mob->skinned_vnum; corpse->o.od.value [3] = -ch->mob->carcass_vnum; } else { corpse->o.od.value [2] = ch->mob->skinned_vnum; corpse->o.od.value [3] = ch->mob->carcass_vnum; } } else { corpse->o.od.value [2] = 0; corpse->o.od.value [3] = 0; } corpse->obj_flags.weight = get_weight (ch); if ( IS_NPC (ch) ) corpse->obj_timer = MAX_NPC_CORPSE_TIME; else corpse->obj_timer = MAX_PC_CORPSE_TIME; SET_BIT (corpse->obj_flags.extra_flags, ITEM_TIMER); for ( i = 0; i < MAX_WEAR; i++ ) { if ( get_equip (ch, i) ) { if ( GET_ITEM_TYPE (get_equip(ch, i)) == ITEM_CONTAINER && IS_SET (ch->plr_flags, NEW_PLAYER_TAG) ) continue; temp_arg = unequip_char(ch, i); obj_to_obj (temp_arg, corpse); } } IS_CARRYING_N (ch) = 0; obj_to_room (corpse, ch->in_room); } void remove_guest_skills (CHAR_DATA *ch) { int i; if ( !IS_SET (ch->flags, FLAG_GUEST) ) return; for ( i = 0; i <= MAX_SKILLS; i++ ) { ch->skills[i] = 0; ch->pc->skills[i] = 0; } ch->speaks = db_race_table[ch->race].race_speaks; ch->skills [ch->speaks] = calc_lookup(ch, REG_CAP, db_race_table[ch->race].race_speaks); ch->pc->skills [ch->speaks] = ch->skills [ch->speaks]; } void death_email (CHAR_DATA *ch) { char buf [MAX_STRING_LENGTH] = {'\0'}; MYSQL_RES *result; MYSQL_ROW row; ACCOUNT_DATA *account; FILE *fp; bool found = FALSE; if ( !ch || !ch->pc || !ch->pc->account ) return; if ( !(account = load_account (ch->pc->account)) ) return; if ( !(fp = fopen(ch->tname, "w+")) ) return; fprintf (fp, "From: %s <%s>\n" "To: %s\n" "X-Sender: %s" "Mime-Version: 1.0\n" "Content-type: text/plain;charset=\"us-ascii\"\n" "Organization: %s\n" "Subject: %s's Recent Demise\n" "\n", MUD_NAME, MUD_EMAIL, account->email, MUD_EMAIL, MUD_NAME, ch->tname); result = NULL; fprintf (fp, "Hello,\n\n" " Our records indicate that your PC, %s, has recently passed on. For\n" "your convenience and future reference, we have taken the liberty of\n" "compiling all of %s journal entries, in-game board posts and in-\n" "character writings; they are attached below.\n\n" " Thanks for playing, and we hope to see you back again soon.\n" "\n" "\n" " Best Regards,\n" " The Admin Team\n\n", ch->tname, HSHR(ch)); mysql_safe_query ("SELECT * FROM player_journals WHERE name = '%s' ORDER BY post_number ASC", ch->tname); result = mysql_store_result(database); if ( mysql_num_rows (result) ) { fprintf (fp, "Journal Entries:\n\n"); while ( (row = mysql_fetch_row(result)) ) { found = TRUE; fprintf (fp, "--\nDate: %s\nSubject: %s\n\n%s\n", row[4], row[2], row[5]); } fprintf (fp, "\n"); mysql_free_result (result); result = NULL; } mysql_safe_query ("SELECT * FROM boards WHERE author = '%s' ORDER BY board_name,post_number ASC", ch->tname); result = mysql_store_result(database); if ( mysql_num_rows (result) ) { fprintf (fp, "In-Game Board Posts:\n\n"); while ( (row = mysql_fetch_row(result)) ) { found = TRUE; fprintf (fp, "--\nDate: %s [%s]\nSubject: %s\n\n%s\n", row[5], row[4],row[2], row[6]); } fprintf (fp, "\n"); mysql_free_result (result); result = NULL; } mysql_safe_query ("SELECT * FROM player_writing WHERE author = '%s' ORDER BY db_key,page ASC", ch->tname); result = mysql_store_result(database); if ( mysql_num_rows(result) ) { fprintf (fp, "In-Character Writings:\n\n"); while ( (row = mysql_fetch_row(result)) ) { found = TRUE; fprintf (fp, "--\nDate: %s\n\n%s\n", row[3], row[8]); } fprintf (fp, "\n"); mysql_free_result (result); result = NULL; } if ( !found ) fprintf (fp, "--\nNo writing was found in our database.\n"); fclose (fp); snprintf (buf, MAX_STRING_LENGTH, "/usr/sbin/sendmail %s < %s", account->email, ch->tname); system (buf); unlink (ch->tname); free_account (account); account = NULL; } void raw_kill (CHAR_DATA *ch) { CHAR_DATA *tch; DESCRIPTOR_DATA *d; if ( ch->fighting ) { if (ch == combat_next_dude) combat_next_dude = ch->next_fighting; if ( combat_list == ch ) combat_list = ch->next_fighting; else { for (tch = combat_list; tch && (tch->next_fighting != ch); tch = tch->next_fighting); if (!tch) { system_log ("Char fighting not found Error (fight.c, stop_fighting)", TRUE); sigsegv (SIGSEGV); } tch->next_fighting = ch->next_fighting; } ch->next_fighting = 0; ch->fighting = 0; } for ( tch = character_list; tch; tch = tch->next ) { if ( tch->deleted ) continue; if ( tch->aiming_at == ch && ch->room != tch->room ) act ("$n collapses, slain. You lower your weapon.", FALSE, ch, 0, tch, TO_VICT | TO_ACT_FORMAT); } if ( !IS_SET (ch->plr_flags, FLAG_PETRIFIED) ) make_corpse (ch); else make_statue (ch); if ( IS_SET (ch->plr_flags, FLAG_PETRIFIED) ) { act ("$n suddenly seems to grow stiff, turning to stone before your very eyes!", TRUE, ch, 0, 0, TO_ROOM | TO_ACT_FORMAT); act ("As the hated rays of the sun strike your skin, you suddenly grow stiff, and your mind is awash in helpless rage before -- nothing...", TRUE, ch, 0, 0, TO_CHAR | TO_ACT_FORMAT); } else if ( !ch->mount ) { send_to_room ("\n", ch->in_room); if ( GET_POS (ch) >= 7 ) act ("$n collapses to the ground, dead.", TRUE, ch, 0, 0, TO_ROOM | TO_ACT_FORMAT); else act ("$n expires with a ragged exhalation.", TRUE, ch, 0, 0, TO_ROOM | TO_ACT_FORMAT); ch->mount = NULL; } else if ( ch->mount && IS_SET (ch->act, ACT_MOUNT) ) { send_to_room ("\n", ch->in_room); act ("$n collapses, dead, dumping $N to the ground in the process.", TRUE, ch, 0, ch->mount, TO_NOTVICT | TO_ACT_FORMAT); act ("$n collapses, dead, dumping you to the ground in the process.", TRUE, ch, 0, ch->mount, TO_VICT | TO_ACT_FORMAT); ch->mount->mount = NULL; ch->mount = NULL; } else if ( ch->mount && !IS_SET (ch->act, ACT_MOUNT) ) { send_to_room ("\n", ch->in_room); act ("$n falls to the ground from atop $N, dead.", TRUE, ch, 0, ch->mount, TO_NOTVICT | TO_ACT_FORMAT); act ("$n falls to the ground from atop you, dead.", TRUE, ch, 0, ch->mount, TO_VICT | TO_ACT_FORMAT); ch->mount->mount = NULL; ch->mount = NULL; } if ( (!IS_NPC(ch) && !IS_SET (ch->flags, FLAG_GUEST)) || (IS_SET (ch->flags, FLAG_GUEST) && ch->desc) ) { GET_POS(ch) = POSITION_STANDING; while ( ch->wounds ) wound_from_char (ch, ch->wounds); while ( ch->lodged ) lodge_from_char (ch, ch->lodged); ch->damage = 0; if ( IS_SET (ch->flags, FLAG_GUEST) ) { nanny_create_guest (ch->desc, "recreate"); } else { d = ch->desc; extract_char (ch); SEND_TO_Q ("#0Your character has, regrettably, passed away. Our condolences. . .#0\n\n" "#0Thank you for playing - we hope to see you back again soon!#0\n", d); d->connected = CON_ACCOUNT_MENU; nanny (d, ""); if ( IS_MORTAL (ch) && !ch->pc->mortal_mode ) { death_email (ch); mysql_safe_query ("UPDATE newsletter_stats SET pc_deaths=pc_deaths+1"); } } } else { extract_char(ch); } } void die (CHAR_DATA *ch) { int duration = 0; STORED_PC_DATA *pc; char *date = NULL; char buf [MAX_STRING_LENGTH] = {'\0'}; char msg [MAX_STRING_LENGTH] = {'\0'}; char buf2 [MAX_STRING_LENGTH] = {'\0'}; if ( ch->combat_log ) { system_log (ch->combat_log, FALSE); } if ( !IS_NPC (ch) ) { if ( !IS_SET (ch->flags, FLAG_GUEST) ) { date = timestr(date); if ( IS_SET (ch->plr_flags, FLAG_PETRIFIED) ) snprintf (msg, MAX_STRING_LENGTH, "Location: %s [%d]\n\nDied of petrification.\n", ch->room->name, ch->in_room); else if ( ch->delay_info1 && ch->delay_ch && !IS_SET (ch->flags, FLAG_BINDING) ) { snprintf (buf2, MAX_STRING_LENGTH, " [%s]", ch->delay_ch->tname); snprintf (msg, MAX_STRING_LENGTH, "Location: %s [%d]\n\nAssailant: #5%s#0%s\n\nWeapon: #2%s#0\n", ch->room->name, ch->in_room, ch->delay_ch->short_descr, !IS_NPC(ch->delay_ch) ? buf2 : "", vtoo(ch->delay_info1)->short_description); } else if ( ch->delay_ch && !ch->delay_info1 && !IS_SET (ch->flags, FLAG_BINDING) ) { snprintf (buf2, MAX_STRING_LENGTH, " [%s]", ch->delay_ch->tname); snprintf (msg, MAX_STRING_LENGTH, "Location: %s [%d]\n\nAssailant: #5%s#0%s\n", ch->room->name, ch->in_room, ch->delay_ch->short_descr, !IS_NPC(ch->delay_ch) ? buf2 : ""); } else snprintf (msg, MAX_STRING_LENGTH, "Location: %s [%d]\n\nDied of unspecified causes, e.g. bloodloss or falling.\n", ch->room->name, ch->in_room); add_message (ch->tname, 3, "Server", date, "Died.", "", msg, 0); add_message ("Deaths", 2, "Server", date, ch->tname, "", msg, 0); if ( ch->desc && ch->desc->account ) { for ( pc = ch->desc->account->pc; pc; pc = pc->next ) { if ( !str_cmp (pc->name, ch->tname) ) { pc->state = STATE_DIED; break; } } } mem_free (date); } if ( !IS_SET (ch->flags, FLAG_GUEST) ) { if ( !IS_SET (ch->plr_flags, FLAG_PETRIFIED) ) snprintf (buf, MAX_STRING_LENGTH, "%s has been slain!\n", ch->tname); else snprintf (buf, MAX_STRING_LENGTH, "%s has been petrified!\n", ch->tname); send_to_gods (buf); } ch->delay_ch = 0; ch->delay_info1 = 0; /* NOTE: af doesn't point to anything after affects are removed */ if ( duration > 100 ) /* Fix a bug where some players have a LARGE */ duration = 1; /* number of hours */ while ( ch->hour_affects ) affect_remove (ch, ch->hour_affects); ch->pc->create_state = STATE_DIED; ch->pc->last_died = time (0); save_char (ch, TRUE); } raw_kill (ch); if ( IS_SET (ch->plr_flags, FLAG_PETRIFIED) ) REMOVE_BIT (ch->plr_flags, FLAG_PETRIFIED); } char *replace_string(char *str, char *weapon, char *local) { static char buf [MAX_STRING_LENGTH] = {'\0'}; /* Leave as static */ char *cp; cp = buf; for (; *str; str++) { if (*str == '#') { switch(*(++str)) { case 'W' : for (; *weapon; *(cp++) = *(weapon++)); break; case 'L' : for (;*local;*(cp++)=*(local++)); break; default : *(cp++) = '#'; break; } } else { *(cp++) = *str; } *cp = 0; } /* For */ return(buf); } int damage (CHAR_DATA *ch, CHAR_DATA *victim, int dam, int attacktype) { int i,j,nr; struct message_type *messages; char buf [MAX_STRING_LENGTH] = {'\0'}; OBJ_DATA *temp_arg = NULL; if ( GET_POS(victim) <= POSITION_DEAD ) { snprintf (buf, MAX_STRING_LENGTH, "kill -SEGV %d", getpid()); system (buf); } if ((GET_TRUST(victim)>3) && !IS_NPC(victim)) dam=0; if (victim != ch) { if ( GET_POS (ch) > POSITION_STUNNED && !ch->fighting ) set_fighting (ch, victim); if (GET_POS(victim) > POSITION_STUNNED) { if (!(victim->fighting)) set_fighting(victim, ch); GET_POS(victim) = POSITION_FIGHTING; } } if ( dam > 0 ) GET_HIT (victim) -= dam; /* God knows how the victim was hit */ else { for(i = 0; i < MAX_MESSAGES; i++) { if (fight_messages[i].a_type == attacktype) { nr = dice (1, fight_messages[i].number_of_attacks); for(j=1,messages=fight_messages[i].msg;(j<nr)&&(messages);j++) messages=messages->next; if ( !IS_NPC (victim) && !IS_MORTAL (victim) ) { temp_arg = get_equip (ch, WEAR_PRIM); act (messages->god_msg.attacker_msg, FALSE, ch, temp_arg, victim, TO_CHAR); act (messages->god_msg.victim_msg, FALSE, ch, temp_arg, victim, TO_VICT); act (messages->god_msg.room_msg, FALSE, ch, temp_arg, victim, TO_NOTVICT); } else if (dam != 0) { if (GET_POS(victim) == POSITION_DEAD) { temp_arg = get_equip (ch, WEAR_PRIM); act (messages->die_msg.attacker_msg, FALSE, ch, temp_arg, victim, TO_CHAR); act (messages->die_msg.victim_msg, FALSE, ch, temp_arg, victim, TO_VICT); act (messages->die_msg.room_msg, FALSE, ch, temp_arg, victim, TO_NOTVICT); } else { temp_arg = get_equip (ch, WEAR_PRIM); act (messages->hit_msg.attacker_msg, FALSE, ch, temp_arg, victim, TO_CHAR); act (messages->hit_msg.victim_msg, FALSE, ch, temp_arg, victim, TO_VICT); act (messages->hit_msg.room_msg, FALSE, ch, temp_arg, victim, TO_NOTVICT); } } else { /* Dam == 0 */ temp_arg = get_equip (ch, WEAR_PRIM); act (messages->miss_msg.attacker_msg, FALSE, ch, temp_arg, victim, TO_CHAR); act (messages->miss_msg.victim_msg, FALSE, ch, temp_arg, victim, TO_VICT); act (messages->miss_msg.room_msg, FALSE, ch, temp_arg, victim, TO_NOTVICT); } } } } if (GET_POS(victim) < POSITION_DEAD) if (ch->fighting == victim) stop_fighting(ch); if (!AWAKE(victim)) if (victim->fighting) stop_fighting(victim); if (GET_POS(victim) == POSITION_DEAD) { if (IS_NPC(victim) || victim->desc) if (!IS_NPC(victim)) { snprintf (buf, MAX_STRING_LENGTH, "%s killed by %s at %s", GET_NAME(victim), (IS_NPC(ch) ? ch->short_descr : GET_NAME(ch)), vtor (victim->in_room)->name); if (IS_NPC(ch) && IS_SET(ch->act,ACT_MEMORY)) forget (ch, victim); } die(victim); return 1; } return 0; } #define SINGLE 1 #define PRIMARY 2 #define SECONDARY 3 void hit_char (CHAR_DATA *ch, CHAR_DATA *victim, int smite_parm) { int killed = 0; OBJ_DATA *weapon; AFFECTED_TYPE *temp_aff = NULL; if ( !ch || !victim ) return; if ( IS_SET (victim->act, ACT_FLYING) && !IS_SET (ch->act, ACT_FLYING) && AWAKE(victim) ) { send_to_char ("They are flying out of reach!\n", ch); return; } if ( IS_NPC(ch) && !ch->desc ) { ready_melee_weapons (ch); } if ( IS_NPC (victim) && !victim->desc ) { ready_melee_weapons (victim); } if ( victim->delay && victim->delay_type != DEL_LOAD_WEAPON ) break_delay (victim); if ( ch->delay && ch->delay_type != DEL_LOAD_WEAPON ) break_delay (ch); if ( GET_POS (ch) != POSITION_DEAD && GET_POS (victim) != POSITION_DEAD ) criminalize (ch, victim, victim->room->zone, CRIME_KILL); if ( !ch->fighting && !smite_parm ) set_fighting (ch, victim); if ( IS_SUBDUEE (victim) ) { act ("$n takes a swing at $N.", FALSE, ch, 0, victim, TO_NOTVICT); act ("$N takes a swing at you.", FALSE, victim, 0, ch, TO_CHAR); } if ( IS_SUBDUEE (ch) ) { if ( ch->fighting ) stop_fighting (ch); return; } if ( GET_FLAG (ch, FLAG_FLEE) ) { if ( !ch->primary_delay && !flee_attempt (ch) ) ch->primary_delay = 16; return; } guard_check (victim); if ( IS_SUBDUER (ch) ) return; if ( get_affect (victim, AFFECT_GUARD_DIR) ) { act ("The attack prevents you from continuing to guard the exit.", FALSE, victim, 0, 0, TO_CHAR); act ("The attack prevents $n from continuing to guard the exit.", FALSE, victim, 0, 0, TO_ROOM | TO_ACT_FORMAT); temp_aff = get_affect (victim, AFFECT_GUARD_DIR); affect_remove (victim, temp_aff); } /* Empty handed attack / Primary / Dual */ if ( !ch->primary_delay && (get_equip (ch, WEAR_PRIM) || get_equip (ch, WEAR_BOTH) || (!get_equip (ch, WEAR_PRIM) && !get_equip (ch, WEAR_BOTH) && !get_equip (ch, WEAR_SEC))) ) { if ( GET_FLAG (ch, FLAG_SUBDUING) ) { if ( !(weapon = get_equip (ch, WEAR_PRIM)) ) return; if ( weapon->o.weapon.use_skill != SKILL_LIGHT_EDGE ) return; } if ( get_affect (ch, MAGIC_AFFECT_DIZZINESS) && !number (0, 3) ) { send_to_char ("You battle your dizziness as you ready your attack.", ch); act ("$N staggers, appearing dizzy.", TRUE, ch, 0, 0, TO_ROOM); ch->primary_delay += 5 * 4; } else smite (ch, victim, 1); } if ( ch->deleted || victim->deleted || !victim->room || !ch->room ) killed = 1; if ( !killed && !can_move (victim) && !GET_FLAG (ch, FLAG_KILL) && ch->fighting ) { act ("$N can't move.", FALSE, ch, 0, victim, TO_CHAR); /* Aggressives don't stop trying to kill */ if ( !ch->mob || !IS_SET (ch->act, ACT_AGGRESSIVE) ) stop_fighting (ch); return; } /* Secondary weapon attack */ if ( !killed && !ch->secondary_delay && get_equip (ch, WEAR_SEC) ) { if ( GET_FLAG (ch, FLAG_SUBDUING) && !((weapon = get_equip (ch, WEAR_SEC)) && weapon->o.weapon.use_skill != SKILL_LIGHT_EDGE ) ) return; smite (ch, victim, 2); } if ( !ch->deleted && !victim->deleted && ch->fighting && ch->room && victim->room && IS_SUBDUEE (victim) ) stop_fighting (ch); if ( !ch->deleted && !victim->deleted && ch->fighting && !killed && !can_move (victim) && !GET_FLAG (ch, FLAG_KILL) ) { act ("$N can't move.", FALSE, ch, 0, victim, TO_CHAR); /* Aggressives don't stop trying to kill */ if ( !ch->mob || !IS_SET (ch->act, ACT_AGGRESSIVE) ) stop_fighting (ch); } if ( !ch->deleted && !ch->fighting && GET_POS (ch) == FIGHT ) GET_POS (ch) = STAND; } char *get_dam_word (int damage) { if ( damage <= 6 ) return " "; if ( damage <= 10 ) return " hard "; if ( damage <= 15 ) return " very hard "; if ( damage <= 20 ) return " extremely hard "; return " incredibly hard "; } int combat_roll (int ability) { int r; int roll_result; r = number (1, 100); if ( ability > 98 ) ability = 98; if ( ability < 5 ) ability = 5; if ( r > ability ) roll_result = SUC_MF - ((r % 5) ? 0 : 1); else roll_result = SUC_MS + ((r % 5) ? 0 : 1); return roll_result; } #define AD (fd + strlen (fd)) void advance (CHAR_DATA *src, CHAR_DATA *tar) { if ( src->distance_to_target >= 2 ) { act("You begin advancing on $N, preparing for battle.", FALSE, src, 0, tar, TO_CHAR); act("$n begins advancing on $N, preparing for battle.", FALSE, src, 0, tar, TO_NOTVICT); act("$n begins advancing on you, preparing for battle.", FALSE, src, 0, tar, TO_VICT); } else if ( src->distance_to_target == 1 ) { act("You close to polearm range on $N!", FALSE, src, 0, tar, TO_CHAR); act("$n closes to polearm range on $N!", FALSE, src, 0, tar, TO_NOTVICT); act("$n closes to polearm range on you!", FALSE, src, 0, tar, TO_VICT); } else if ( src->distance_to_target == 0 ) { act("You close to melee range on $N!", FALSE, src, 0, tar, TO_CHAR); act("$n closes to melee range on $N!", FALSE, src, 0, tar, TO_NOTVICT); act("$n closes to melee range on you!", FALSE, src, 0, tar, TO_VICT); } src->primary_delay = 20; src->distance_to_target -= 1; tar->distance_to_target -= 1; } int smite (CHAR_DATA *src, CHAR_DATA *tar, int attack_num) { float defense = 0; float attack = 0; int off_success = 0; int def_success = 0; int off_result = 0; int def_result = 0; int defense_hand = 0; int location = 0; int damage = 0; int hit_type = 0; int i = 0; int j = 0; int wear_loc1 = 0; int wear_loc2 = 0; char loc[MAX_STRING_LENGTH] = {'\0'}; OBJ_DATA *tar_prim = get_equip (tar, WEAR_PRIM); OBJ_DATA *tar_sec = get_equip (tar, WEAR_SEC); OBJ_DATA *tar_both = get_equip (tar, WEAR_BOTH); OBJ_DATA *src_prim = get_equip (src, WEAR_PRIM); OBJ_DATA *src_sec = get_equip (src, WEAR_SEC); OBJ_DATA *src_dual = get_equip (src, WEAR_BOTH); OBJ_DATA *attack_weapon = NULL; OBJ_DATA *defense_weapon = NULL; OBJ_DATA *shield = NULL; OBJ_DATA *attack_shield = NULL; OBJ_DATA *eq1 = NULL; OBJ_DATA *eq2 = NULL; OBJ_DATA *broken_eq = NULL; CHAR_DATA *mount; AFFECTED_TYPE *af = NULL; int bonus = 0; float attack_modifier = 0; float defense_modifier = 0; float r1 = 0; char fd [MAX_STRING_LENGTH] = {'\0'}; CHAR_DATA *dch= NULL; char *temp_arg = NULL; *fd = 0; if ( IS_SET (src->act, ACT_VEHICLE) ) return 0; snprintf (AD, MAX_STRING_LENGTH, "%s [%d hp %d mvs] strike %d %s [%d hp %d mvs] ", GET_NAME (src), GET_HIT (src), GET_MOVE (src), attack_num, GET_NAME (tar), GET_HIT (tar), GET_MOVE (tar)); attack_modifier = 100.0; defense_modifier = 100.0; if ( src->in_room != tar->in_room ) return 0; if ( attack_num == 1 ) attack_weapon = src_prim ? src_prim : src_dual; else attack_weapon = src_sec; if ( attack_weapon && (attack_weapon->o.weapon.use_skill == SKILL_SHORTBOW || attack_weapon->o.weapon.use_skill == SKILL_LONGBOW || attack_weapon->o.weapon.use_skill == SKILL_CROSSBOW || attack_weapon->o.weapon.use_skill == SKILL_SLING || attack_weapon->o.weapon.use_skill == SKILL_THROWN) ) return 0; if ( attack_weapon && GET_ITEM_TYPE (attack_weapon) != ITEM_WEAPON && GET_ITEM_TYPE (attack_weapon) != ITEM_SHIELD ) attack_weapon = NULL; if ( IS_SET (src->flags, FLAG_PACIFIST) ) return 0; if ( attack_weapon ) snprintf (AD, MAX_STRING_LENGTH, "%s\n\r", attack_weapon->short_description); else { attack = src->skills [SKILL_BRAWLING]; /* default attack */ snprintf (AD, MAX_STRING_LENGTH, "BRAWLING\n\r"); } if ( attack_weapon ) attack = src->skills [attack_weapon->o.weapon.use_skill]; if ( attack < src->offense ) { attack = src->offense; snprintf (AD, MAX_STRING_LENGTH, "Using Offense %d ", (int) attack); } snprintf (AD, MAX_STRING_LENGTH, "ABase %d ", (int) attack); /* Weapon bonus/penalty */ bonus = 100; if ( attack_weapon ) { for ( af = attack_weapon->xaffected; af; af = af->next ) switch ( af->a.spell.location ) { case APPLY_OFFENSE: case APPLY_CLUB: case APPLY_SPEAR: case APPLY_SWORD: case APPLY_DAGGER: case APPLY_AXE: case APPLY_WHIP: case APPLY_POLEARM: snprintf (AD, MAX_STRING_LENGTH, "+%d WEAP-AFF ", af->a.spell.modifier); bonus += af->a.spell.modifier; break; default: break; } } if ( (attack_shield = get_equip (src, WEAR_SHIELD)) ) { for ( af = attack_shield->xaffected; af; af = af->next ) { if ( af->a.spell.location == APPLY_OFFENSE ) { snprintf (AD, MAX_STRING_LENGTH, "%d OFF/SHIELD PEN ", af->a.spell.modifier); bonus += af->a.spell.modifier; } } } if ( bonus < 0 ) attack_modifier = 0.0; else attack_modifier = attack_modifier * bonus / 100.0; snprintf (AD, MAX_STRING_LENGTH, "weapmod %d ", bonus); /* Fatigue penalty */ if ( GET_MAX_MOVE (src) > 0 ) j = GET_MOVE (src) * 100 / GET_MAX_MOVE (src); else j = 0; if ( j > 100 ) j = 100; for ( i = 0; j > fatigue [i].percent; i++ ) ; snprintf (AD, MAX_STRING_LENGTH, "fatigue %3.2f ", fatigue [i].penalty); attack_modifier = attack_modifier * fatigue [i].penalty; /* Dual wield penalty */ if ( attack_num == 2 ) { r1 = .60 + .40 * src->skills [SKILL_DUAL] / 100.0; snprintf (AD, MAX_STRING_LENGTH, "Dual Pen %3.2f ", r1); attack_modifier = attack_modifier * r1; } /* Encumberance penalty */ for ( i = 0; i < CUMBERANCE_ENTRIES; i++ ) { if ( GET_STR (src) * enc_tab [i].str_mult_wt >= IS_CARRYING_W (src) ) break; } attack_modifier = attack_modifier * enc_tab [i].penalty; snprintf (AD, MAX_STRING_LENGTH, "Enc %3.2f ", enc_tab [i].penalty); /* Fightmode modifier */ attack_modifier = attack_modifier * fight_tab [src->fight_mode].offense_modifier; if ( get_affect (src, MAGIC_AFFECT_FURY) ) { attack_modifier = attack_modifier * 1.25; snprintf (AD, MAX_STRING_LENGTH, "* 1.25 [FURY] "); } if ( get_affect (src, MAGIC_AFFECT_DIZZINESS) ) { attack_modifier = attack_modifier * 0.75; snprintf (AD, MAX_STRING_LENGTH, "* 0.75 [DIZZINESS] "); } snprintf (AD, MAX_STRING_LENGTH, "FM %3.2f ", fight_tab [src->fight_mode].offense_modifier); snprintf (AD, MAX_STRING_LENGTH, " = OFFENSE %3.0f\n", attack * attack_modifier / 100); /* DEFENSE */ /* We need to know which weapon to defend with */ shield = get_equip (tar, WEAR_SHIELD); if ( shield && shield->obj_flags.type_flag != ITEM_SHIELD ) { printf ("Non-shield object %d, on %d(%s), at %d\n", shield->virtual, IS_NPC (tar) ? tar->mob->virtual : 0, tar->name, tar->room->virtual); fflush (stdout); } defense_weapon = NULL; if ( tar_both ) { defense_weapon = tar_both; defense_hand = 1; } else if ( tar_prim && !tar_sec && !shield ) { defense_weapon = tar_prim; defense_hand = 1; } else if ( tar_sec && !tar_prim && !shield ) { defense_weapon = tar_sec; defense_hand = 2; } else if ( shield && !tar_prim && !tar_sec ) { defense_weapon = shield; defense_hand = 1; } else if ( shield && tar_prim ) { if ( tar->primary_delay > tar->secondary_delay ) { defense_weapon = shield; defense_hand = 2; } else { defense_weapon = tar_prim; defense_hand = 1; } } else if ( shield && tar_sec ) { if ( tar->primary_delay > tar->secondary_delay ) { defense_weapon = tar_sec; defense_hand = 2; } else { defense_weapon = shield; defense_hand = 1; } } else if ( tar_prim && tar_sec ) { if ( tar->primary_delay > tar->secondary_delay ) { defense_weapon = tar_sec; defense_hand = 2; } else { defense_weapon = tar_prim; defense_hand = 1; } } else { defense_weapon = NULL; defense_hand = 1; } if ( shield != defense_weapon ) shield = NULL; if ( defense_weapon && GET_ITEM_TYPE (defense_weapon) != ITEM_WEAPON && GET_ITEM_TYPE (defense_weapon) != ITEM_SHIELD ) defense_weapon = NULL; if ( !defense_weapon ) defense = tar->skills [SKILL_DODGE]; else if ( defense_weapon->obj_flags.type_flag == ITEM_SHIELD ) defense = tar->skills [SKILL_BLOCK]; else if ( defense_weapon->obj_flags.type_flag == ITEM_WEAPON ) { if ( defense_weapon->o.weapon.use_skill == SKILL_LONGBOW || defense_weapon->o.weapon.use_skill == SKILL_SHORTBOW || defense_weapon->o.weapon.use_skill == SKILL_CROSSBOW || defense_weapon->o.weapon.use_skill == SKILL_SLING || defense_weapon->o.weapon.use_skill == SKILL_THROWN ) { defense = tar->skills [SKILL_DODGE]; defense_weapon = NULL; } else defense = tar->skills [SKILL_PARRY]; } else { defense = 0; } if ( real_skill (tar, SKILL_DANGER_SENSE) ) if ( skill_use (tar, SKILL_DANGER_SENSE, 0) ) defense += tar->skills [SKILL_DANGER_SENSE] / 5; /* * On a successful use of the Danger Sense skill, if * the skill being checked is a defensive combat skill, * it grants them a bonus; they are able to sense the * impending blow before it lands. (Nexus) */ if ( IS_SET (tar->flags, FLAG_PACIFIST) ) defense += 10; if ( defense > 95 ) defense = 95; /* Unless you're Legolas, using bows in melee isn't so bright... */ if ( tar->aiming_at ) defense -= 20; snprintf (AD, MAX_STRING_LENGTH, "DBase %d ", (int) defense); /* Fatigue penalty */ if ( GET_MAX_MOVE (tar) > 0 ) j = GET_MOVE (tar) * 100 / GET_MAX_MOVE (tar); else { j = 0; } if ( j > 100 ) j = 100; for ( i = 0; j > fatigue [i].percent; i++ ) ; snprintf (AD, MAX_STRING_LENGTH, "Fatigue %3.2f ", fatigue [i].penalty); defense_modifier = defense_modifier * fatigue [i].penalty; /* Encumberance penalty */ for ( i = 0; i < CUMBERANCE_ENTRIES; i++ ) { if ( GET_STR (tar) * enc_tab [i].str_mult_wt >= IS_CARRYING_W (tar) ) break; } snprintf (AD, MAX_STRING_LENGTH, "Enc %3.2f ", enc_tab [i].penalty); defense_modifier = defense_modifier * enc_tab [i].penalty; /* Fightmode modifier */ defense_modifier = defense_modifier * fight_tab [tar->fight_mode].defense_modifier; snprintf (AD, MAX_STRING_LENGTH, "FM %3.2f ", fight_tab [tar->fight_mode].defense_modifier); /* Hand delay modifier */ if ( defense_hand == 1 ) r1 = (100 - 5 * tar->primary_delay) / 100.0; else r1 = (100 - 5 * tar->secondary_delay) / 100.0; if ( r1 < .25 ) /* Maximum 75% penalty for being delayed. */ r1 = .25; defense_modifier = defense_modifier * r1; snprintf (AD, MAX_STRING_LENGTH, "DelayPen %3.2f ", r1); /* Weapon/shield defense */ if ( defense_weapon ) { bonus = 100; for ( af = defense_weapon->xaffected; af; af = af->next ) { if ( defense_weapon->obj_flags.type_flag == ITEM_SHIELD ) { if ( af->a.spell.location == APPLY_BLOCK ) bonus += af->a.spell.modifier; } else if ( af->a.spell.location == APPLY_PARRY ) bonus += af->a.spell.modifier; } if ( bonus < 0 ) defense_modifier = 0.0; else defense_modifier = defense_modifier * bonus / 100.0; snprintf (AD, MAX_STRING_LENGTH, "Weapbon %d ", bonus); } defense = defense * defense_modifier / 100; attack = attack * attack_modifier / 100; if ( attack_weapon && (attack_weapon->o.od.value[3] == SKILL_MEDIUM_EDGE || attack_weapon->o.od.value[3] == SKILL_MEDIUM_BLUNT || attack_weapon->o.od.value[3] == SKILL_MEDIUM_PIERCE) ) { if ( attack_weapon->location == WEAR_SEC ) attack -= 10; } if ( attack_weapon && (attack_weapon->o.od.value[3] == SKILL_HEAVY_EDGE || attack_weapon->o.od.value[3] == SKILL_HEAVY_BLUNT || attack_weapon->o.od.value[3] == SKILL_HEAVY_PIERCE) ) { if ( attack_weapon->location == WEAR_PRIM ) attack -= 10; if ( attack_weapon->location == WEAR_SEC ) attack -= 20; } if ( defense_weapon && (defense_weapon->o.od.value[3] == SKILL_HEAVY_EDGE || defense_weapon->o.od.value[3] == SKILL_HEAVY_BLUNT || defense_weapon->o.od.value[3] == SKILL_HEAVY_PIERCE) ) { if ( defense_weapon->location == WEAR_PRIM ) defense -= 10; if ( defense_weapon->location == WEAR_SEC ) defense -= 20; } snprintf (AD, MAX_STRING_LENGTH, " = DEFENSE %d\n", (int) defense); attack = figure_wound_skillcheck_penalties (src, attack); defense = figure_wound_skillcheck_penalties (tar, defense); defense = MAX (5, defense); attack = MAX (5, attack); snprintf (AD, MAX_STRING_LENGTH, "End Result: %f Attack\n", attack); off_success = combat_roll (attack); def_success = combat_roll (defense); if ( attack_weapon ) hit_type = attack_weapon->o.weapon.hit_type; else { if ( src->nat_attack_type == 0 ) hit_type = 9; else if ( src->nat_attack_type == 1 || src->nat_attack_type == 3 ) hit_type = 7; else if ( src->nat_attack_type == 2 ) hit_type = 8; } /* Must be standing or fighting AND not in frantic mode */ if ( (GET_POS (tar) != STAND && GET_POS (tar) != FIGHT) || tar->fight_mode == 0 ) { def_result = RESULT_NONE; off_result = ignore_offense [off_success]; snprintf (AD, MAX_STRING_LENGTH, "IGNORE: %s = %s\n", cs_name [off_success], rs_name [off_result]); } else if ( defense_hand == 1 && !defense_weapon ) { off_result = dodge_offense [off_success] [def_success]; def_result = dodge_defense [off_success] [def_success]; snprintf (AD, MAX_STRING_LENGTH, "DODGE: %s(%d) = %s(%d); %s(%d) = %s(%d)\n", cs_name [off_success], off_success, rs_name [off_result], off_result, cs_name [def_success], def_success, rs_name [def_result], def_result); } else if ( defense_weapon ) { off_result = shield_parry_offense [off_success] [def_success]; def_result = shield_parry_defense [off_success] [def_success]; if ( off_result == RESULT_BLOCK && defense_weapon != shield ) { off_result = RESULT_PARRY; def_result = RESULT_PARRY; } snprintf (AD, MAX_STRING_LENGTH, "BLOCK/PARRY: %s = %s; %s = %s\n", cs_name [off_success], rs_name [off_result], cs_name [def_success], rs_name [def_result]); } figure_damage (src, tar, attack_weapon, off_result, &damage, &location); temp_arg = figure_location(tar, location); snprintf (loc, MAX_STRING_LENGTH, "%s",temp_arg ); wear_loc1 = body_tab [0] [location].wear_loc1; wear_loc2 = body_tab [0] [location].wear_loc2; eq1 = get_equip (tar, wear_loc1); eq2 = get_equip (tar, wear_loc2); if ( eq2 && IS_SET (eq2->obj_flags.wear_flags, ITEM_WEAR_ABOUT) && (name_is ("cloak", eq2->name) || name_is("cape", eq2->name)) && number(0,2) ) eq2 = NULL; if ( off_result == RESULT_FUMBLE ) { if ( GET_DEX (src) <= number (1, 21) ) { if ( attack_weapon && number (0, 1) ) off_result = RESULT_NEAR_FUMBLE; else off_result = RESULT_NEAR_STUMBLE; } else if ( !attack_weapon || number (0, 1) ) off_result = RESULT_STUMBLE; if ( off_result != RESULT_FUMBLE ) snprintf (AD, MAX_STRING_LENGTH, "offensive result -> %s\n", rs_name [off_result]); } if ( def_result == RESULT_FUMBLE ) { if ( GET_DEX (tar) <= number (1, 21) ) { if ( defense_weapon && number (0, 1) ) def_result = RESULT_NEAR_FUMBLE; else def_result = RESULT_NEAR_STUMBLE; } else if ( !defense_weapon || number (0, 1) ) def_result = RESULT_STUMBLE; if ( def_result != RESULT_FUMBLE ) snprintf (AD, MAX_STRING_LENGTH, "defensive result -> %s\n", rs_name [def_result]); } /* DA can occur only if defending a primary attacker */ if ( def_result == RESULT_ADV && tar->fighting != src ) def_result = RESULT_NONE; if ( attack_weapon && (off_result == RESULT_BLOCK || off_result == RESULT_PARRY) ) { if ( attack_weapon && ((defense_weapon && attack_weapon->quality <= defense_weapon->quality) || (shield && attack_weapon->quality <= shield->quality)) && number (1,100) > attack_weapon->quality ) { if ( shield ) damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); else damage_to_obj (attack_weapon, number(1,MAX(damage,5)), defense_weapon->o.weapon.hit_type); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) off_result = RESULT_WEAPON_BREAK; } else if ( attack_weapon && defense_weapon && number (1,100) > defense_weapon->quality ) { damage_to_obj (defense_weapon, number(1,MAX(damage,5)), hit_type); if ( (number(1,100) > defense_weapon->quality && number(1,100) > defense_weapon->item_wear) || defense_weapon->item_wear <= 0 ) def_result = RESULT_WEAPON_BREAK; } else if ( attack_weapon && shield && number(1,100) > shield->quality ) { damage_to_obj (shield, number(1,MAX(damage,5)), hit_type); if ( (number(1,100) > shield->quality && number(1,100) > shield->item_wear) || shield->item_wear <= 0 ) def_result = RESULT_SHIELD_BREAK; } else if ( attack_weapon && ((defense_weapon && attack_weapon->quality > defense_weapon->quality) || (shield && attack_weapon->quality > shield->quality)) && attack_weapon->quality > defense_weapon->quality && number(1,100) > attack_weapon->quality ) { if ( shield ) damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); else damage_to_obj (attack_weapon, number(1,MAX(damage,5)), defense_weapon->o.weapon.hit_type); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) off_result = RESULT_WEAPON_BREAK; } } if ( (off_result == RESULT_HIT1 || off_result == RESULT_HIT2 || off_result == RESULT_HIT3 || off_result == RESULT_HIT4) && attack_weapon && (eq1 || eq2) ) { if ( attack_weapon && eq1 && eq1->o.od.value[0] > 2 && attack_weapon->quality <= eq1->quality && number (1,100) > attack_weapon->quality ) { damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) { off_result = RESULT_WEAPON_BREAK; def_result = RESULT_ANY; } } else if ( attack_weapon && eq2 && eq2->o.od.value[0] > 2 && attack_weapon->quality <= eq2->quality && number (1,100) > attack_weapon->quality ) { damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) { off_result = RESULT_WEAPON_BREAK; def_result = RESULT_ANY; } } else if ( attack_weapon && eq1 && number (1,100) > eq1->quality ) { if ( GET_ITEM_TYPE (eq1) == ITEM_ARMOR ) damage_to_obj (eq1, number(1,MAX(damage,5)), hit_type); else damage_to_obj (eq1, number(1,MAX(damage,5)), hit_type); if ( (number(1,100) > eq1->quality && number(1,100) > eq1->item_wear) || eq1->item_wear <= 0 ) broken_eq = eq1; } else if ( attack_weapon && eq2 && number (1,100) > eq2->quality ) { if ( GET_ITEM_TYPE (eq2) == ITEM_ARMOR ) damage_to_obj (eq2, number(1,MAX(damage,5)), hit_type); else damage_to_obj (eq2, number(1,MAX(damage,5)), hit_type); if ( number(1,100) > eq2->quality && number(1,100) > eq2->item_wear ) broken_eq = eq2; } else if ( attack_weapon && eq1 && eq1->o.od.value[0] > 2 && attack_weapon->quality > eq1->quality && number (1,100) > attack_weapon->quality ) { damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) { off_result = RESULT_WEAPON_BREAK; def_result = RESULT_ANY; } } else if ( attack_weapon && eq2 && eq2->o.od.value[0] > 2 && attack_weapon->quality > eq2->quality && number (1,100) > attack_weapon->quality ) { damage_to_obj (attack_weapon, number(1,MAX(damage,5)), 3); if ( (number(1,100) > attack_weapon->quality && number(1,100) > attack_weapon->item_wear) || attack_weapon->item_wear <= 0 ) { off_result = RESULT_WEAPON_BREAK; def_result = RESULT_ANY; } } } if ( IS_SET (tar->flags, FLAG_COMPETE) ) { if ( attack_weapon ) return wound_to_char (tar, loc, damage, attack_weapon->o.weapon.hit_type, 0, 0, 0); else return wound_to_char (tar, loc, damage, src->nat_attack_type, 0, 0, 0); } combat_results (src, tar, attack_weapon, defense_weapon, broken_eq, damage, loc, off_result, def_result, attack_num, fd, off_success, def_success); snprintf (AD, MAX_STRING_LENGTH, "---------------------------------------\n"); for ( dch = src->room->people; dch; dch = dch->next_in_room ) if ( IS_SET (dch->debug_mode, DEBUG_FIGHT) ) send_to_char (fd, dch); if ( tar->deleted ) return 1; else { if ( IS_RIDER (tar) ) { mount = tar->mount; /* if ( mount && (mount->skills [SKILL_RIDE] < 33 || (mount->skills [SKILL_RIDE] < 66 && !skill_use (mount, SKILL_RIDE, 0))) ) { dump_rider (tar, FALSE); flee_attempt (mount); } */ } return 0; } } void combat_msg_substitute (char *msg, char *template, CHAR_DATA *src, CHAR_DATA *tar, OBJ_DATA *attack_weapon, OBJ_DATA *defense_weapon, char *location, int damage) { int aw_type = 6; char loc[MAX_STRING_LENGTH] = {'\0'}; char *temp_arg = NULL; if ( attack_weapon ) aw_type = attack_weapon->o.weapon.hit_type; *msg = '\0'; while ( *template ) { if ( *template != '#' ) { *msg = *template; template++; msg++; *msg = '\0'; } else { switch ( template [1] ) { case 'S': if ( aw_type == 6 ) strcat (msg, attack_names_plural [src->nat_attack_type]); else strcat (msg, wtype2 [aw_type * 2 + number (0, 1)]); break; case 's': if ( aw_type == 6 ) strcat (msg, attack_names [src->nat_attack_type]); else strcat (msg, wtype [aw_type * 2 + number (0, 1)]); break; case 'O': if ( !attack_weapon ) strcat (msg, attack_part [src->nat_attack_type]); else{ temp_arg = see_object_in(tar, attack_weapon); strcat (msg, temp_arg); } break; case 'o': if ( !defense_weapon ) strcat (msg, "fist"); else{ temp_arg = see_object_in(src,defense_weapon); strcat (msg, temp_arg); } break; case 'L': temp_arg = expand_wound_loc(location); snprintf (loc, MAX_STRING_LENGTH, "%s", temp_arg); strcat (msg, loc); break; case 'C': strcat (msg, crithits [aw_type * 2 + number (0, 1)]); break; case 'c': strcat (msg, crithit [aw_type * 2 + number (0, 1)]); break; case 'B': strcat (msg, break_def [aw_type * 2 + 1]); break; case 'b': strcat (msg, break_def [aw_type * 2]); break; case 'D': temp_arg = get_dam_word (damage); strcat (msg, temp_arg); break; case 'R': strcat (msg, "\n\r"); break; default: *msg = *template; /* Not a variable */ msg [1] = '\0'; template--; /* Work around for advance 2 chars */ break; } msg = &msg [strlen (msg)]; template = &template [2]; /* Advance two characters */ } } } void combat_results (CHAR_DATA *src, CHAR_DATA *tar, OBJ_DATA *attack_weapon, OBJ_DATA *defense_weapon, OBJ_DATA *broken_eq, int damage, char *location, int off_result, int def_result, int attack_num, char *fd, int off_success, int def_success) { int attack_delay = 0; int i = 0; int j = 0; int skill = 0; int delay_modifier = 0; int hit_type = 0; int table = 0; int current_sum = 0; int best_sum = 0; AFFECTED_TYPE *invulnerability = NULL; COMBAT_MSG_DATA *best_cm = NULL; COMBAT_MSG_DATA *tcm = NULL; CHAR_DATA *tch = NULL; OBJ_DATA *tobj = NULL; OBJ_DATA *temp_obj = NULL; char msg1 [MAX_STRING_LENGTH] = {'\0'}; char msg2 [MAX_STRING_LENGTH] = {'\0'}; char msg3 [MAX_STRING_LENGTH] = {'\0'}; char buf [MAX_STRING_LENGTH] = {'\0'}; char log_message [MAX_STRING_LENGTH] = {'\0'}; char *temp_arg = NULL; *log_message = '\0'; if ( tar ) { snprintf (log_message, MAX_STRING_LENGTH, "by %s", src->short_descr); if ( IS_NPC (src) ) snprintf (log_message + strlen (log_message), MAX_STRING_LENGTH, " (%d)", src->mob->virtual); else snprintf (log_message + strlen (log_message), MAX_STRING_LENGTH, " (PC %s)", src->tname); } if ( attack_weapon ) snprintf (log_message + strlen (log_message), MAX_STRING_LENGTH, " w/ %s (%d)", attack_weapon->short_description, attack_weapon->virtual); if ( (off_result < RESULT_HIT || off_result > RESULT_HIT4) && !number (0, 1) ) { skill = SKILL_BRAWLING; if ( attack_weapon ) skill = attack_weapon->o.weapon.use_skill; if ( attack_num == 1 ) skill_use (src, skill, 0); else if ( number (0, 1) ) { if ( number (0, 1) ) skill_use (src, SKILL_DUAL, 0); else skill_use (src, skill, 0); } fix_offense (src); } if ( off_result >= RESULT_HIT && off_result <= RESULT_HIT4 && !number (0, 1) ) { if ( GET_POS (tar) == STAND || GET_POS (tar) == FIGHT ) { if ( !defense_weapon ) skill = SKILL_DODGE; else if ( defense_weapon->obj_flags.type_flag == ITEM_WEAPON ) skill = SKILL_PARRY; else if ( defense_weapon->obj_flags.type_flag == ITEM_SHIELD ) skill = SKILL_BLOCK; else { skill = SKILL_PARRY; } skill_use (tar, skill, 0); fix_offense (tar); } } if ( tar->fight_mode == 0 && /* frantic mode */ (GET_POS (tar) == STAND || GET_POS (tar) == FIGHT) ) table = 'F'; else if ( GET_POS (tar) != STAND && GET_POS (tar) != FIGHT && tar->fight_mode != 0 ) table = 'I'; /* Ignore */ else if ( !defense_weapon ) table = 'D'; /* Dodge */ else if ( defense_weapon->obj_flags.type_flag == ITEM_SHIELD ) table = 'B'; /* Block */ else table = 'P'; /* Parry */ for ( tcm = cm_list; tcm; tcm = tcm->next ) { if ( off_result != tcm->off_result ) continue; if ( tcm->table != '*' && tcm->table != table ) continue; if ( tcm->def_result != RESULT_ANY && tcm->def_result != def_result ) continue; if ( !best_cm ) { best_cm = tcm; continue; } /* Hierarchy */ /* x any * msg */ /* x any t msg */ /* x y * msg */ /* x y t msg */ current_sum = 0; if ( best_cm->def_result != RESULT_ANY ) current_sum += 2; if ( best_cm->table != '*' ) current_sum += 1; if ( current_sum == 3 ) break; best_sum = 0; if ( tcm->def_result != RESULT_ANY ) best_sum += 2; if ( tcm->table != '*' ) best_sum += 1; if ( current_sum < best_sum ) best_cm = tcm; } combat_msg_substitute (msg1, best_cm->def_msg, src, tar, attack_weapon, defense_weapon, location, damage); combat_msg_substitute (msg2, best_cm->off_msg, src, tar, attack_weapon, defense_weapon, location, damage); combat_msg_substitute (msg3, best_cm->other_msg, src, tar, attack_weapon, defense_weapon, location, damage); /* Oh wait, vehicles get a generic message */ if ( IS_SET (tar->act, ACT_VEHICLE) ) { if ( attack_weapon ) { act ("You attack $N with your $o.", FALSE, src, attack_weapon, tar, TO_CHAR); act ("$n attacks you with his $o.", FALSE, src, attack_weapon, tar, TO_VICT); act ("$n attacks $N with $s $o.", FALSE, src, attack_weapon, tar, TO_NOTVICT); } else { act ("You kick at $N, trying to destroy it.", FALSE, src, 0, tar, TO_CHAR); act ("$n kicks at you, trying to break you.", FALSE, src, 0, tar, TO_VICT); act ("$n kicks at $N, trying to break it.", FALSE, src, 0, tar, TO_NOTVICT); } } else { act (msg1, FALSE, tar, attack_weapon, src, TO_CHAR | TO_ACT_FORMAT | TO_ACT_COMBAT); act (msg2, FALSE, tar, attack_weapon, src, TO_VICT | TO_ACT_FORMAT | TO_ACT_COMBAT); act (msg3, FALSE, tar, attack_weapon, src, TO_NOTVICT | TO_ACT_FORMAT | TO_ACT_COMBAT); } /* Make sure invulnerability is set last in the IF clause below. */ if ( damage && attack_weapon && !IS_SET (attack_weapon->obj_flags.extra_flags, ITEM_MAGIC) && (invulnerability = get_affect (tar, MAGIC_AFFECT_INVULNERABILITY)) ) { act ("$n appears undamaged!", FALSE, tar, 0, 0, TO_ROOM); act ("$n's $o didn't wound you.", FALSE, src, attack_weapon, tar, TO_VICT); } if ( damage ) { if ( attack_weapon ) hit_type = attack_weapon->o.weapon.hit_type; else hit_type = 6; /* natural attack */ if ( off_result != RESULT_HIT && off_result != RESULT_HIT1 && off_result != RESULT_HIT2 && off_result != RESULT_HIT3 && off_result != RESULT_HIT4 ) system_log ("Damage result without a HIT.", TRUE); } else if ( off_result == RESULT_STUMBLE ) { GET_POS (src) = SIT; add_second_affect (SPA_STAND, 8, src, NULL, NULL, 0); if ( IS_SET (tar->flags, FLAG_FLEE) ) flee_attempt (tar); } else if ( off_result == RESULT_FUMBLE ) { if ( (tobj = get_equip (src, WEAR_PRIM)) == attack_weapon && !IS_SET(src->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (src, WEAR_PRIM); obj_to_room (temp_obj, src->in_room); } else if ( (tobj = get_equip (src, WEAR_SEC)) == attack_weapon && !IS_SET(src->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (src, WEAR_SEC); obj_to_room (temp_obj, src->in_room); } else if ( (tobj = get_equip (src, WEAR_BOTH)) == attack_weapon && !IS_SET(src->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (src, WEAR_BOTH); obj_to_room (temp_obj, src->in_room); } else if ( !IS_SET (src->flags, FLAG_COMPETE) ){ system_log("Disarm, but couldn't find weapons's hand. (attacker)", TRUE); } if ( !IS_SET (src->flags, FLAG_COMPETE) ) { if ( attack_weapon == src->right_hand ) src->right_hand = NULL; else if ( attack_weapon == src->left_hand ) src->left_hand = NULL; add_second_affect (SPA_GET_OBJ, 6, src, attack_weapon, "", 0); add_second_affect (SPA_WEAR_OBJ, 10, src, attack_weapon, "", 0); SET_BIT (attack_weapon->tmp_flags, SPA_DROPPED); } } else if ( off_result == RESULT_WEAPON_BREAK ) { if ( get_equip (src, WEAR_PRIM) == attack_weapon ){ temp_obj = unequip_char (src, WEAR_PRIM); extract_obj (temp_obj); } else if ( get_equip (src, WEAR_SEC) == attack_weapon ){ temp_obj = unequip_char (src, WEAR_SEC); extract_obj (temp_obj); } else if ( get_equip (src, WEAR_BOTH) == attack_weapon ){ temp_obj = unequip_char (src, WEAR_BOTH); extract_obj (temp_obj); } else{ system_log("Weapon Break, but couldn't find weapons's hand. (attacker)", TRUE); } if ( attack_weapon == src->right_hand ) src->right_hand = NULL; else if ( attack_weapon == src->left_hand ) src->left_hand = NULL; } else if ( off_result == RESULT_ADV ) system_log("How could offence get RESULT_ADV?", TRUE); if ( def_result == RESULT_FUMBLE ) { if ( get_equip (tar, WEAR_PRIM) == defense_weapon && !IS_SET (tar->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (tar, WEAR_PRIM); obj_to_room (temp_obj, tar->in_room); } else if ( get_equip (tar, WEAR_SEC) == defense_weapon && !IS_SET (tar->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (tar, WEAR_SEC); obj_to_room (temp_obj, tar->in_room); } else if ( get_equip (tar, WEAR_BOTH) == defense_weapon && !IS_SET (tar->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (tar, WEAR_BOTH); obj_to_room (temp_obj, tar->in_room); } else if ( get_equip (tar, WEAR_SHIELD) == defense_weapon && !IS_SET (tar->flags, FLAG_COMPETE) ){ temp_obj = unequip_char (tar, WEAR_SHIELD); obj_to_room (temp_obj, tar->in_room); } else if ( !IS_SET (tar->flags, FLAG_COMPETE) ){ system_log("Disarm, but couldn't find weapons's hand. (defender)", TRUE); } if ( !IS_SET (tar->flags, FLAG_COMPETE) ) { if ( defense_weapon == tar->right_hand ) tar->right_hand = NULL; else if ( defense_weapon == tar->left_hand ) tar->left_hand = NULL; add_second_affect (SPA_GET_OBJ, 6, tar, defense_weapon, "", 0); add_second_affect (SPA_WEAR_OBJ, 10, tar, defense_weapon, "", 0); SET_BIT (defense_weapon->tmp_flags, SPA_DROPPED); } } else if ( def_result == RESULT_WEAPON_BREAK || def_result == RESULT_SHIELD_BREAK ) { if ( get_equip (tar, WEAR_PRIM) == defense_weapon ){ temp_obj = unequip_char (tar, WEAR_PRIM); extract_obj (temp_obj); } else if ( get_equip (tar, WEAR_SEC) == defense_weapon ){ temp_obj = unequip_char (tar, WEAR_SEC); extract_obj (temp_obj); } else if ( get_equip (tar, WEAR_BOTH) == defense_weapon ){ temp_obj = unequip_char (tar, WEAR_BOTH); extract_obj (temp_obj); } else if ( get_equip (tar, WEAR_SHIELD) == defense_weapon ){ temp_obj = unequip_char (tar, WEAR_SHIELD); extract_obj (temp_obj); } else{ system_log("BREAK, but couldn't find weapons's hand. (defender)", TRUE); } if ( defense_weapon == tar->right_hand ) tar->right_hand = NULL; else if ( defense_weapon == tar->left_hand ) tar->left_hand = NULL; } else if ( def_result == RESULT_STUMBLE ) { if ( GET_POS (tar) == FIGHT || GET_POS (tar) == STAND ) { GET_POS (tar) = SIT; add_second_affect (SPA_STAND, 8, tar, NULL, NULL, 0); } else def_result = RESULT_NONE; } if ( attack_weapon ) hit_type = attack_weapon->o.weapon.hit_type; else { if ( src->nat_attack_type == 0 ) hit_type = 9; else if ( src->nat_attack_type == 1 || src->nat_attack_type == 3 ) hit_type = 7; else if ( src->nat_attack_type == 2 ) hit_type = 8; } if ( broken_eq ) { temp_arg = obj_short_desc(broken_eq); snprintf (buf, MAX_STRING_LENGTH, "#2%s#0 is destroyed by the blow.", temp_arg); buf[2] = toupper(buf[2]); act (buf, FALSE, tar, 0, 0, TO_CHAR | TO_ACT_FORMAT | TO_ACT_COMBAT); act (buf, FALSE, tar, 0, 0, TO_ROOM | TO_ACT_FORMAT | TO_ACT_COMBAT); extract_obj (broken_eq); } tar->delay_ch = src; if ( attack_weapon ) tar->delay_info1 = attack_weapon->virtual; if ( !invulnerability && damage && wound_to_char (tar, location, damage, hit_type, 0, 0, 0) ) { def_result = RESULT_DEAD; } else { if ( tar->fighting && IS_SET (tar->act, ACT_VEHICLE) ) stop_fighting (tar); if ( !tar->fighting && !IS_SET (tar->act, ACT_VEHICLE) ) { set_fighting (tar, src); if ( !AWAKE (tar) && GET_POS(tar) != POSITION_UNCONSCIOUS ) do_wake (tar, "", 0); add_second_affect (SPA_STAND, 8, tar, NULL, NULL, 0); } if ( !src->fighting ) set_fighting (src, tar); if ( (GET_POS(tar) == POSITION_STUNNED || GET_POS(tar) == POSITION_UNCONSCIOUS) && !IS_SET (src->flags, FLAG_KILL) ) { if ( src->fighting ) stop_fighting (src); for ( tch = src->room->people; tch; tch = tch->next_in_room ) if ( tch->fighting == src && tch != src && GET_HIT (tch) > 0 ) { set_fighting (src, tch); break; } } } tar->delay_ch = NULL; tar->delay_info1 = 0; if ( def_result == RESULT_PARRY || def_result == RESULT_BLOCK ) { if ( get_equip (tar, WEAR_PRIM) == defense_weapon || get_equip (tar, WEAR_BOTH) == defense_weapon ) tar->primary_delay++; else if ( get_equip (tar, WEAR_SEC) == defense_weapon ) tar->secondary_delay++; } else if ( def_result == RESULT_ADV ) { tar->primary_delay = 0; tar->secondary_delay = 0; } attack_delay = 0; /* Weapon delay / natural delay / calculated delay */ if ( attack_weapon ) { attack_delay += use_table [attack_weapon->o.weapon.use_skill].delay + attack_weapon->o.weapon.delay; attack_delay += attack_weapon->o.od.value[5]; if ( (attack_weapon->o.od.value[3] == SKILL_MEDIUM_EDGE || attack_weapon->o.od.value[3] == SKILL_MEDIUM_BLUNT || attack_weapon->o.od.value[3] == SKILL_MEDIUM_PIERCE) && attack_weapon->location == WEAR_BOTH ) attack_delay += 8; } else if ( IS_NPC (src) ) attack_delay += src->natural_delay; else attack_delay += 20 - GET_DEX (src) + use_table [SKILL_BRAWLING].delay; snprintf (AD, MAX_STRING_LENGTH, "AttDel %d ", attack_delay); /* str+dex delay adjustment */ delay_modifier = 100; delay_modifier = delay_modifier - (GET_STR (src) + GET_DEX (src) - 15); snprintf (AD, MAX_STRING_LENGTH, "STRDEXadj %d%% ", delay_modifier); attack_delay = attack_delay * delay_modifier / 100; /* Fatigue adjustment */ if ( GET_MAX_MOVE (src) > 0 ) j = GET_MOVE (src) * 100 / GET_MAX_MOVE (src); else j = 0; if ( j > 100 ) j = 100; for ( i = 0; j > fatigue [i].percent; i++ ) ; if ( i == 0 ) attack_delay += 8; /* Completely Exhausted */ else if ( i == 1 ) attack_delay += 4; /* Exhausted */ snprintf (AD, MAX_STRING_LENGTH, "Fatigue %d ", attack_delay); /* Fightmode delay adjustment */ attack_delay += fight_tab [src->fight_mode].delay; snprintf (AD, MAX_STRING_LENGTH, "FM %d = %d [%d] (2)=%d\n", attack_delay, attack_delay, attack_num, src->secondary_delay); if ( attack_num == 1 ) src->primary_delay = attack_delay; else src->secondary_delay = attack_delay; } void figure_damage (CHAR_DATA *src, CHAR_DATA *tar, OBJ_DATA *attack_weapon, int off_result, int *damage, int *location) { OBJ_DATA *eq; char buf [MAX_STRING_LENGTH] = {'\0'}; int body_type; int wear_loc1; int wear_loc2; int i; float dam = 0; AFFECTED_TYPE *shock = NULL; AFFECTED_TYPE *af; *damage = 0; /* Determine hit location */ body_type = 0; i = number (1, 100); *location = -1; while ( i > 0 ) i = i - body_tab [body_type] [++(*location)].percent; wear_loc1 = body_tab [body_type] [*location].wear_loc1; wear_loc2 = body_tab [body_type] [*location].wear_loc2; /* Assess automatic damage by NPCs */ if ( IS_NPC (src) ) dam += src->mob->damroll; /* For weapons, add weapon damage roll and affects */ if ( attack_weapon ) { if ( attack_weapon->o.weapon.dice && attack_weapon->o.weapon.sides ) { if ( (attack_weapon->o.od.value[3] == SKILL_MEDIUM_EDGE || attack_weapon->o.od.value[3] == SKILL_MEDIUM_BLUNT || attack_weapon->o.od.value[3] == SKILL_MEDIUM_PIERCE) && attack_weapon->location == WEAR_BOTH ) dam += dice (attack_weapon->o.weapon.dice, attack_weapon->o.weapon.sides+2); else dam += dice (attack_weapon->o.weapon.dice, attack_weapon->o.weapon.sides); } else { snprintf (buf, MAX_STRING_LENGTH, "Ineffective weapon, vnum %d on mob %d room %d\n", attack_weapon->virtual, src->mob ? src->mob->virtual : -1, src->in_room); system_log (buf, TRUE); } for ( af = attack_weapon->xaffected; af; af = af->next ) { if ( af->a.spell.location == APPLY_DAMROLL ) dam += af->a.spell.modifier; } } /* For NPCs with no weapons, add natural attack */ else if ( IS_NPC (src) ) { if ( src->mob->damnodice * src->mob->damsizedice < 8 && shock ) dam += dice (2, 4); else dam += dice (src->mob->damnodice, src->mob->damsizedice); } /* For bare handed PCs */ else if ( shock ) dam += dice (2, 4); else dam += number (0, 2); /* Subtract the armor protection at the hit location */ eq = get_equip (tar, wear_loc1); if ( eq && eq->obj_flags.type_flag == ITEM_ARMOR ) if ( attack_weapon || !shock ) dam -= eq->o.armor.armor_value; /* Mobs will have marmor, which is natural armor */ if ( attack_weapon || !shock ) dam -= (tar->armor); /* Weapon vs armor */ eq = get_equip (tar, wear_loc2); if ( attack_weapon && eq ) dam += weapon_armor_table [attack_weapon->o.weapon.hit_type] [eq->o.armor.armor_type]; else if ( !attack_weapon && eq ) dam += weapon_nat_attack_table [src->nat_attack_type] [eq->o.armor.armor_type]; /* Multiply by hit location multiplier */ dam *= (body_tab [body_type] [*location].damage_mult*1.0) / (body_tab [body_type] [*location].damage_div*1.0); /* Multiply in critical strike bonus */ if ( off_result == RESULT_HIT || (off_result == RESULT_HIT && (!attack_weapon && src->nat_attack_type == 0)) ) dam *= 1; else if ( off_result == RESULT_HIT1 ) dam *= 1.3; else if ( off_result == RESULT_HIT2 ) dam *= 1.5; else if ( off_result == RESULT_HIT3 || (off_result == RESULT_HIT && !attack_weapon) ) { dam += 2; dam *= 1.7; } else if ( off_result == RESULT_HIT4 ) { dam += 3; dam *= 2; } else { *damage = 0; return; } /* Subtract/add spell offsets */ if ( (af = get_affect (tar, MAGIC_AFFECT_ARMOR)) ) if ( attack_weapon || !shock ) dam -= af->a.spell.modifier; /* Reduce damage by SANCTUARY or BLESS. Note: Not cumulative */ if ( get_affect (tar, MAGIC_AFFECT_CURSE) && !get_affect (tar, MAGIC_AFFECT_BLESS) ) dam += dam / 4 + 1; else if ( get_affect (tar, MAGIC_AFFECT_BLESS) && !get_affect (tar, MAGIC_AFFECT_CURSE) ) dam = dam * 3 / 4; if ( attack_weapon || src->nat_attack_type > 0 ) (float) (dam *= COMBAT_BRUTALITY); dam = (int)dam; if ( dam <= 0 ) dam = number (0, 1); *damage = dam; } int weaken (CHAR_DATA *victim, int hits, int moves, char *log_msg) { char buf [MAX_STRING_LENGTH] = {'\0'}; if ( hits == 0 && moves == 0 ) return 0; if ( log_msg ) { snprintf (buf, MAX_STRING_LENGTH, "%s (%dh/%dm)", log_msg, hits, moves); add_combat_log(victim, buf); } if ( !IS_MORTAL (victim) && !IS_NPC (victim) ) return 0; /* If moves is negative, then we subtract excess moves from hits */ moves = -moves; if ( GET_MOVE (victim) > moves ) GET_MOVE (victim) -= moves; else GET_MOVE (victim) = 0; if ( GET_POS (victim) == POSITION_DEAD ) { if ( moves ) { act ("$n dies of exhaustion!", FALSE, victim, 0, 0, TO_ROOM); add_combat_log(victim, "Death by exhaustion"); } die (victim); return 1; } return 0; } void subdue_resync (CHAR_DATA *ch) { CHAR_DATA *tch; /* ch needs someone else to subdue */ if ( ch->fighting ) stop_fighting (ch); for ( tch = ch->room->people; tch; tch = tch->next_in_room ) { if ( tch->fighting == ch ) { set_fighting (ch, tch); act ("You turn to confront $N.", FALSE, ch, 0, tch, TO_CHAR); act ("$n turns to confront $N.", FALSE, ch, 0, tch, TO_ROOM); act ("$N turns to confront you.", FALSE, tch, 0, ch, TO_CHAR); if ( !IS_SET (tch->flags, FLAG_SUBDUING) ) REMOVE_BIT (ch->flags, FLAG_SUBDUING); break; } } if ( !ch->fighting ) send_to_char ("You stop fighting.\n\r", ch); } void remove_subduer (CHAR_DATA *ch) { CHAR_DATA *tch; int was_in_room; for ( tch = ch->room->people; tch == ch; ) tch = tch->next_in_room; was_in_room = ch->in_room; char_from_room (ch); for ( ; tch; tch = tch->next_in_room ) if ( tch->fighting == ch ) subdue_resync (tch); char_to_room (ch, was_in_room); } void subdue_char (CHAR_DATA *ch, CHAR_DATA *victim) { int victim_was_room = 0; OBJ_DATA *obj = NULL; OBJ_DATA *temp_obj = NULL; AFFECTED_TYPE *af = NULL; if ( ch->fighting ) stop_fighting (ch); if ( victim->fighting ) stop_fighting (victim); REMOVE_BIT (ch->flags, FLAG_SUBDUING); REMOVE_BIT (ch->flags, FLAG_SUBDUEE); REMOVE_BIT (victim->flags, FLAG_SUBDUING); REMOVE_BIT (victim->flags, FLAG_SUBDUER); SET_BIT (ch->flags, FLAG_SUBDUER); SET_BIT (victim->flags, FLAG_SUBDUEE); clear_moves (victim); clear_current_move (victim); ch->subdue = victim; victim->subdue = ch; if ( GET_POS(victim) < POSITION_STANDING ) { act ("You fall upon your foe and get $M into a firm headlock.", FALSE, ch, 0, victim, TO_CHAR); act ("$N falls upon you and gets you into a firm headlock.", FALSE, victim, 0, ch, TO_CHAR); act ("$n falls upon $N.", FALSE, ch, 0, victim, TO_NOTVICT); act ("You haul $N to $S feet.", FALSE, ch, 0, victim, TO_CHAR); act ("$N hauls you to your feet.", FALSE, victim, 0, ch, TO_CHAR); act ("$e hauls $M to $S feet in a firm headlock.", FALSE, ch, 0, victim, TO_NOTVICT); GET_POS(victim) = POSITION_STANDING; } else { act ("You grapple $N and lock $M firmly in your grasp.", FALSE, ch, 0, victim, TO_CHAR); act ("$N grapples you and locks you firmly in $S grasp!", FALSE, victim, 0, ch, TO_CHAR); act ("$n grapples $N and locks $M firmly in $s grasp.", FALSE, ch, 0, victim, TO_NOTVICT); } /* Nobody is trying to subdue ch. Lets stop or redirect subdue attempts against victim */ victim_was_room = victim->in_room; char_from_room (victim); remove_subduer (ch); char_to_room (victim, victim_was_room); remove_subduer (victim); if ( ch->mob && IS_SET (ch->act, ACT_ENFORCER) && is_hooded (victim) ) { obj = get_equip (victim, WEAR_ABOUT); if ( obj ) { temp_obj = unequip_char (victim, WEAR_ABOUT); obj_to_char (temp_obj, victim); act ("$n removes your $p.", FALSE, ch, obj, victim, TO_VICT); act ("$n removes $N's $p.", FALSE, ch, obj, victim, TO_NOTVICT); act ("You remove $N's $p.", FALSE, ch, obj, victim, TO_CHAR); } obj = get_equip (victim, WEAR_HEAD); if ( obj ) { temp_obj = unequip_char (victim, WEAR_HEAD); obj_to_char (temp_obj, victim); act ("$n removes your $p.", FALSE, ch, obj, victim, TO_VICT); act ("$n removes $N's $p.", FALSE, ch, obj, victim, TO_NOTVICT); act ("You remove $N's $p.", FALSE, ch, obj, victim, TO_CHAR); } if ( (af = get_affect (victim, MAGIC_CRIM_HOODED + ch->room->zone)) ) add_criminal_time (victim, ch->room->zone, af->a.spell.modifier); } } void perform_violence (void) { CHAR_DATA *ch; CHAR_DATA *new_combat_list = NULL; for ( ch = combat_list; ch; ch = combat_next_dude ) { if ( ch->next_fighting && (!ch->next_fighting->fighting || !ch->next_fighting->room) ) ch->next_fighting = ch->next_fighting->next_fighting; combat_next_dude = ch->next_fighting; if ( !ch->fighting || !ch->fighting->room ) continue; if ( get_affect (ch, MAGIC_HIDDEN) ) { remove_affect_type (ch, MAGIC_HIDDEN); act ("$n reveals $mself.", TRUE, ch, 0, 0, TO_ROOM); } if ( IS_NPC (ch) && !IS_SET (ch->flags, FLAG_FLEE) && (IS_SET (ch->flags, FLAG_AUTOFLEE) || morale_broken (ch))) { ch->speed = 4; do_flee (ch, "", 0); add_threat (ch, ch->fighting, 5); continue; } if ( !ch->fighting ) { sigsegv(SIGSEGV); } /* Remove delays from both hands */ ch->primary_delay -= pulse_violence; ch->secondary_delay -= pulse_violence; if ( ch->primary_delay < 0 ) ch->primary_delay = 0; if ( ch->secondary_delay < 0 ) ch->secondary_delay = 0; /* Stop fighting if player is physically incapable */ if ( !AWAKE (ch) || ch->in_room != ch->fighting->in_room || get_affect (ch, MAGIC_AFFECT_PARALYSIS) ) { stop_fighting (ch); continue; } /* No combat if there are delays */ if ( ch->primary_delay && ch->secondary_delay ) continue; if ( GET_POS (ch) == STAND ) GET_POS (ch) = FIGHT; if ( GET_POS (ch) != FIGHT ) continue; if ( ch->mount && !ch->mount->fighting ) set_fighting (ch->mount, ch->fighting); hit_char (ch, ch->fighting, 0); if ( combat_next_dude && combat_next_dude->deleted ) system_log("Loss of combat_next_dude in fight.c: perform_violence.", TRUE); } /* Reverse the combat list */ new_combat_list = combat_list; if ( combat_list ) { combat_list = combat_list->next_fighting; new_combat_list->next_fighting = NULL; } while ( combat_list ) { ch = combat_list; combat_list = combat_list->next_fighting; ch->next_fighting = new_combat_list; new_combat_list = ch; } combat_list = new_combat_list; } void do_stop (CHAR_DATA *ch, char *argument, int cmd) { CHAR_DATA *tch; AFFECTED_TYPE *af; if ( is_mounted (ch) && ch->mount->moves ) ch = ch->mount; if ( ch->moves ) { clear_moves (ch); clear_current_move (ch); send_to_char ("Movement commands cancelled.\n", ch); if ( is_mounted (ch) ) send_to_char ("Movement commands cancelled.\n", ch->mount); return; } if ( (af = is_crafting(ch)) ) { act ("$n stops doing $s craft.", FALSE, ch, 0, 0, TO_ROOM); send_to_char ("You stop doing your craft.\n", ch); af->a.craft->timer = 0; return; } if ( (af = get_affect (ch, MAGIC_TOLL)) ) { if ( af->a.toll.room_num == ch->in_room ) { stop_tolls (ch); return; } /* Toll affect should have been there...continue with stop */ stop_tolls (ch); } if ( clear_current_move (ch) ) return; if ( ch->delay || ch->aim ) { break_delay (ch); return; } if ( GET_TRUST (ch) ) { for ( tch = ch->room->people; tch; tch = tch->next_in_room ) { if ( tch->fighting ) { if ( tch != ch ) { act ("You immediately obey $N's command to stop fighting!", TRUE, tch, 0, ch, TO_CHAR); act ("$N obeys.", FALSE, ch, 0, tch, TO_CHAR); } forget (tch, tch->fighting); stop_fighting (tch); } if ( IS_NPC (tch) ) { tch->attackers = NULL; tch->threats = NULL; } } send_to_char ("All combat in the room has been stopped.\n", ch); return; } if ( !ch->fighting ) { send_to_char ("You're not fighting anyone.\n\r", ch); return; } if ( ch->fighting->fighting != ch || GET_FLAG (ch->fighting, FLAG_FLEE) ) { send_to_char ("You stop fighting.\n\r", ch); stop_fighting (ch); return; } SET_BIT (ch->act, PLR_STOP); /* Same as ACT_STOP */ if ( IS_SET (ch->fighting->act, PLR_STOP) ) { send_to_char ("Your opponent agrees.\n\r", ch); act ("Both you and $N stop fighting.\n\r", FALSE, ch->fighting, 0, ch, TO_CHAR); if ( IS_NPC (ch->fighting) ) { remove_threat (ch->fighting, ch); remove_attacker (ch->fighting, ch); } if ( IS_NPC (ch) ) { remove_threat (ch, ch->fighting); remove_attacker (ch, ch->fighting); } REMOVE_BIT (ch->act, PLR_STOP); REMOVE_BIT (ch->fighting->act, PLR_STOP); if ( ch->fighting->fighting ) stop_fighting (ch->fighting); if ( ch->fighting ) stop_fighting (ch); return; } send_to_char ("You motion for a truce to your opponent.\n\r", ch); act ("$N motions for a truce.", FALSE, ch->fighting, 0, ch, TO_CHAR); act ("$N motions for a truce with $n.", FALSE, ch->fighting, 0, ch, TO_ROOM); } void do_release (CHAR_DATA *ch, char *argument, int cmd) { char buf [MAX_STRING_LENGTH] = {'\0'}; CHAR_DATA *target; if ( !IS_SUBDUER (ch) ) { if ( !IS_SET (ch->flags, FLAG_SUBDUER) ) { send_to_char ("You have no prisoner in tow.", ch); return; } REMOVE_BIT (ch->flags, FLAG_SUBDUER); if ( ch->subdue && is_he_somewhere (ch->subdue) && ch->subdue->subdue == ch ) { REMOVE_BIT (ch->subdue->flags, FLAG_SUBDUER); REMOVE_BIT (ch->subdue->flags, FLAG_SUBDUEE); send_to_char ("You are no longer a prisoner.\n\r", ch->subdue); send_to_char ("Ok.\n\r", ch); ch->subdue->subdue = NULL; return; } ch->subdue = NULL; send_to_char ("Alright.\n\r", ch); return; } argument = one_argument (argument, buf); if ( *buf && name_is (buf, GET_NAMES (ch->subdue)) ) argument = one_argument (argument, buf); if ( !*buf ) { release_prisoner (ch, NULL); return; } if ( !str_cmp (buf, "to") ) { argument = one_argument (argument, buf); if ( !*buf ) { send_to_char ("Who do you want to release your prisoner to?\n\r", ch); return; } } if ( !(target = get_char_room_vis (ch, buf)) ) { send_to_char ("There is no such person here to receive your prisoner.\n\r", ch); return; } release_prisoner (ch, target); } int release_prisoner (CHAR_DATA *ch, CHAR_DATA *target) { int quiet = 0; if ( !target ) { if ( !IS_SUBDUER (ch) ) { REMOVE_BIT (ch->flags, FLAG_SUBDUER); act ("You have no prisoner.", FALSE, ch, 0, 0, TO_CHAR); return 0; } act ("$N releases you.", FALSE, ch->subdue, 0, ch, TO_CHAR); act ("You release $N.", FALSE, ch, 0, ch->subdue, TO_CHAR); act ("$n releases $N.", FALSE, ch, 0, ch->subdue, TO_NOTVICT); REMOVE_BIT (ch->flags, FLAG_SUBDUER); REMOVE_BIT (ch->subdue->flags, FLAG_SUBDUEE); ch->subdue->subdue = NULL; ch->subdue = NULL; return 1; } if ( IS_SUBDUER (target) ) { act ("$N has $S arms full with another prisoner.", FALSE, ch, 0, target, TO_CHAR); return 0; } if ( IS_SUBDUEE (target) ) { act ("$N is a prisoner himself!", FALSE, ch, 0, target, TO_CHAR); return 0; } if ( GET_POS (target) != STAND ) { act ("$N cannot accept your prisoner at the moment.", FALSE, ch, 0, target, TO_CHAR); return 0; } if ( !real_skill (target, SKILL_SUBDUE) ) { act ("$N isn't able to take care of your prisoner.", FALSE, ch, 0, target, TO_CHAR); return 0; } target->subdue = ch->subdue; target->subdue->subdue = target; ch->subdue = NULL; SET_BIT (target->flags, FLAG_SUBDUER); REMOVE_BIT (ch->flags, FLAG_SUBDUER); act ("You release your prisoner to $N.", FALSE, ch, 0, target, TO_CHAR); act ("$N releases his prisoner to you.", FALSE, target, 0, ch, TO_CHAR); if ( IS_SET (target->subdue->act, PLR_QUIET) ) quiet = 1; else SET_BIT (target->subdue->act, PLR_QUIET); act ("$n releases his prisoner to $N.", FALSE, ch, 0, target, TO_NOTVICT); if ( !quiet ) REMOVE_BIT (target->subdue->act, PLR_QUIET); act ("You are tossed into the arms of $N.", FALSE, target->subdue, 0, target, TO_CHAR); trigger (ch, "", TRIG_PRISONER); return 1; } /*int retaliate (CHAR_DATA *ch, CHAR_DATA *subject) { if (!IS_NPC(ch)) return; if (IS_SET(ch->act, ACT_WIMPY)) { s return 0; ; }*/ int flee_room (CHAR_DATA *ch) { ROOM_DATA *room_exit; ROOM_DATA *room; int room_exit_virt; int exit_tab [6]; int zone; int num_exits = 0; int to_exit; int i; char log_msg [MAX_STRING_LENGTH] = {'\0'}; room = vtor (ch->in_room); zone = room->zone; if ( GET_POS (ch) == POSITION_FIGHTING ) { do_flee (ch,"",0); return 0; } if ( GET_POS (ch) < POSITION_RESTING ) return 0; if ( GET_POS (ch) < POSITION_STANDING ) do_stand (ch,"",0); if ( ch->desc && ch->desc->original ) return 0; for ( i = 0; i < 6; i++ ) { if ( !CAN_GO (ch, i) ) continue; room_exit = vtor (PASSAGE (ch, i)->to_room); if ( !room_exit ) { snprintf (log_msg, MAX_STRING_LENGTH, "ERROR: Room %d, dir %d doesn't go to %d", ch->in_room, i, PASSAGE (ch, i)->to_room); system_log(log_msg, TRUE); continue; } exit_tab [num_exits++] = i; } if ( num_exits == 0 ) return 0; to_exit = number (1, num_exits) - 1; if ( vtor (PASSAGE (ch, exit_tab [to_exit])->to_room)->virtual == ch->last_room ) to_exit = (to_exit + 1) % num_exits; room_exit_virt = vtor (PASSAGE (ch, exit_tab [to_exit])->to_room)->virtual; ch->last_room = room_exit_virt; do_move (ch, "", exit_tab [to_exit]); return 1; } void do_subdue (CHAR_DATA *ch, char *argument, int cmd) { char buf [MAX_STRING_LENGTH] = {'\0'}; CHAR_DATA *target = NULL; char *temp_arg = NULL; if ( IS_SET (ch->room->room_flags, OOC) && IS_MORTAL(ch) ) { send_to_char ("You can't do that in an OOC area.\n", ch); return; } if ( !db_race_table [ch->race].can_subdue ) { snprintf (buf, MAX_STRING_LENGTH, "A %s cannot subdue.\n", db_race_table [ch->race].name); send_to_char (buf, ch); return; } argument = one_argument (argument, buf); if (!*buf && !ch->fighting) { send_to_char ("Subdue whom?\n\r",ch); return; } if ( ch->subdue && !is_he_here (ch, ch->subdue, 0) ) ch->subdue = NULL; if ( ch->fighting && !is_he_here (ch, ch->fighting, 0) ) stop_fighting (ch); if ( ch->fighting && (!*buf || !name_is (buf, GET_NAMES(ch->fighting)))) target = ch->fighting; else if ( !(target = get_char_room_vis (ch, buf)) ) { send_to_char ("You don't see them here.\n\r", ch); return; } else if (ch == target) { send_to_char("Be serious.\n\r",ch); return; } /* else if ( !db_race_table [target->race].can_subdue ) { act ("$N cannot be subdued.", FALSE, ch, 0, target, TO_CHAR); return; } */ else if (ch->subdue && name_is (buf, GET_NAMES(ch->subdue))) { send_to_char("You already have them subdued!\n\r",ch); return; } else if ( IS_SUBDUEE (target) ) { temp_arg = char_short (target->subdue); snprintf (buf, MAX_STRING_LENGTH, "$N has already been subdued by %s.\n", temp_arg); act (buf, FALSE, ch, 0, target, TO_CHAR); return; } else if ( ch->subdue ) { send_to_char ("Release your current prisoner, first.\n", ch); return; } if ( GET_POS (target) != UNCON && GET_POS (target) != SLEEP ) { send_to_char ("They must be unconscious or asleep, first.\n", ch); return; } if ( IS_NPC(ch) && !ch->desc ) { do_sheathe (ch,"",0); do_wear (ch, "shield", 0); do_sheathe (ch,"",0); if ( ch->right_hand ) { (void)one_argument (ch->right_hand->name, buf); do_wear (ch, buf, 0); } if ( ch->left_hand ) { (void)one_argument (ch->left_hand->name, buf); do_wear (ch, buf, 0); } } if ( ch->right_hand || ch->left_hand ) { send_to_char ("You'll need both hands free to subdue.\n", ch); return; } if ( GET_POS (target) == SLEEP ) { GET_POS (target) = STAND; if ( number(1,100) <= target->skills [SKILL_LISTEN] ) { do_wake (target, "", 0); act ("You are startled awake as $N unsuccessfully attempts to grab you!", FALSE, target, 0, ch, TO_CHAR | TO_ACT_FORMAT); act ("$n is startled awake as you unsuccessfully attempt to grab $m!", TRUE, target, 0, ch, TO_VICT | TO_ACT_FORMAT); return; } else { act ("You are awakened abruptly!", FALSE, target, 0, ch, TO_CHAR | TO_ACT_FORMAT); } } else if ( ch->fighting ) { send_to_char("You abandon your opponent.\n\r",ch); act("$N turns away from you suddenly.",FALSE,ch->fighting,0,ch,TO_CHAR); act("$n turns away from $N.",FALSE,ch,0,target,TO_NOTVICT); } if ( IS_SUBDUER (target) ) release_prisoner (target, NULL); subdue_char (ch, target); } void do_escape (CHAR_DATA *ch, char *argument, int cmd) { int chance; int pressure; char log_message [MAX_STRING_LENGTH] = {'\0'}; if ( !IS_SUBDUEE (ch) ) { if ( ch->fighting ) do_flee (ch, "", 0); else send_to_char ("You are not currently subdued.\n", ch); return; } if ( get_second_affect (ch, SPA_ESCAPE, NULL) ) { act ("$N is still holding you very tightly.", FALSE, ch, 0, ch->subdue, TO_CHAR); return; } chance = 20 + 2 * (GET_STR (ch) + GET_AGI (ch) - GET_STR (ch->subdue) - GET_DEX (ch->subdue)); if ( chance > number (0, 100) ) { act ("You manage to wriggle free of $N's grasp!", FALSE, ch, 0, ch->subdue, TO_CHAR); act ("$N wriggles free of your grasp!", FALSE, ch->subdue, 0, ch, TO_CHAR); act ("$n escapes from $N's grasp.", TRUE, ch, 0, ch->subdue, TO_NOTVICT); REMOVE_BIT (ch->subdue->flags, FLAG_SUBDUER); REMOVE_BIT (ch->flags, FLAG_SUBDUEE); ch->subdue->subdue = NULL; ch->subdue = NULL; return; } act ("$N chokes you when you attempt to escape.", FALSE, ch, 0, ch->subdue, TO_CHAR); act ("You choke $N to prevent $M from escaping.", FALSE, ch->subdue, 0, ch, TO_CHAR); act ("$n tries and fails to escape $N.", TRUE, ch, 0, ch->subdue, TO_NOTVICT); pressure = GET_STR (ch->subdue) - 10; if ( pressure > 0 ) { snprintf (log_message, MAX_STRING_LENGTH, "Choked by %s while escaping", ch->tname); if ( wound_to_char (ch, "neck", number(1,pressure),9, 0, 0, 0) ) { act ("$n crumples to the ground dead!", FALSE, ch->subdue, 0, ch, TO_CHAR); act ("$n chokes $N to death!", FALSE, ch, 0, ch->subdue, TO_NOTVICT); return; } } add_second_affect (SPA_ESCAPE, 10, ch, NULL, NULL, 0); } void do_choke (CHAR_DATA *ch, char *argument, int cmd) { int pressure; send_to_char ("This command is disabled.\n", ch); return; if ( !IS_SUBDUER (ch) ) { send_to_char ("You can only choke someone you have subdued.\n", ch); return; } pressure = GET_STR (ch) - 10; if ( pressure <= 0 ) { act ("You are not strong enough to choke $N.", FALSE, ch, 0, ch->subdue, TO_CHAR); act ("$N applies pressure to your neck, but doesn't hurt you.", FALSE, ch->subdue, 0, ch, TO_CHAR); return; } act ("You choke $N.", FALSE, ch, 0, ch->subdue, TO_CHAR); act ("$N chokes you!", TRUE, ch->subdue, 0, ch, TO_CHAR); act ("$n chokes $N.", FALSE, ch, 0, ch->subdue, TO_NOTVICT); if ( wound_to_char (ch, "neck", 2 * pressure, 9, 0, 0, 0) ) { act ("$n crumples to the ground dead!", FALSE, ch->subdue, 0, ch, TO_CHAR); act ("$n chokes $N to death!", FALSE, ch, 0, ch->subdue, TO_NOTVICT); } } void fix_offense (CHAR_DATA *ch) { int i; int best_skill = SKILL_BRAWLING; for ( i = SKILL_BRAWLING; i <= SKILL_CROSSBOW; i++ ) if ( ch->skills [i] > ch->skills [best_skill] ) best_skill = i; ch->offense = ch->skills [best_skill] / 2; } void do_compete (CHAR_DATA *ch, char *argument, int cmd) { char buf [MAX_STRING_LENGTH] = {'\0'}; CHAR_DATA *src; CHAR_DATA *tar; int iterations = 100; char *temp_arg = NULL; argument = one_argument (argument, buf); if ( str_cmp (ch->tname, IMPLEMENTOR_ACCOUNT) ) { send_to_char ("This command is for the implementor only.\n", ch); return; } if ( !(src = get_char_room_vis (ch, buf)) ) { send_to_char ("First combatant isn't here.\n\r", ch); free(argument); return; } if(temp_arg) free(temp_arg); temp_arg = argument; argument = one_argument (temp_arg, buf); if ( !(tar = get_char_room_vis (ch, buf)) ) { send_to_char ("Second combatant isn't here.\n\r", ch); return; } disable_timer_abort = TRUE; argument = one_argument (argument, buf); if ( strtol(buf, NULL, 10)) iterations = strtol(buf, NULL, 10); compete (src, tar, iterations); disable_timer_abort = FALSE; return; } struct stats_data { int kills; int hits_given; int hits_given_2; int swipes; int swipes_2; int smites; int smites_2; int breaks; } src_stats, tar_stats; int compete_smite (CHAR_DATA *src, CHAR_DATA *tar, struct stats_data *stats) { int old_hits; int killed = 0; old_hits = GET_DAM (tar); if ( !src->primary_delay && (get_equip (src, WEAR_PRIM) || get_equip (src, WEAR_BOTH) || (!get_equip (src, WEAR_PRIM) && !get_equip (src, WEAR_BOTH) && !get_equip (src, WEAR_SEC))) ) { stats->swipes++; killed = smite (src, tar, 1); } if ( old_hits != GET_DAM (tar) ) { stats->smites++; stats->hits_given += GET_DAM (tar) - old_hits; } if ( killed ) { stats->kills++; heal_all_wounds (src); heal_all_wounds (tar); return 1; } old_hits = GET_DAM (tar); if ( !src->secondary_delay && get_equip (src, WEAR_SEC) ) { stats->swipes_2++; killed = smite (src, tar, 2); } if ( old_hits != GET_DAM (tar) ) { stats->smites_2++; stats->hits_given_2 += GET_DAM (tar) - old_hits; } if ( killed ) { stats->kills++; heal_all_wounds (src); heal_all_wounds (tar); return 1; } return 0; } /** Debug function to test weapons and defense values in close to real-game conditions ***/ void compete (CHAR_DATA *src, CHAR_DATA *tar, int iterations) { int tick = 0; int i; OBJ_DATA *src_prim = NULL; OBJ_DATA *tar_prim = NULL; OBJ_DATA *src_sec = NULL; OBJ_DATA *tar_sec = NULL; OBJ_DATA *src_both = NULL; OBJ_DATA *tar_both = NULL; OBJ_DATA *src_shield = NULL; OBJ_DATA *tar_shield = NULL; OBJ_DATA *obj, *next_obj; char buf [MAX_STRING_LENGTH] = {'\0'}; char name [MAX_STRING_LENGTH] = {'\0'}; if ( get_equip (src, WEAR_PRIM) ) src_prim = vtoo (get_equip (src, WEAR_PRIM)->virtual); if ( get_equip (tar, WEAR_PRIM) ) tar_prim = vtoo (get_equip (tar, WEAR_PRIM)->virtual); if ( get_equip (src, WEAR_SEC) ) src_sec = vtoo (get_equip (src, WEAR_SEC)->virtual); if ( get_equip (tar, WEAR_SEC) ) tar_sec = vtoo (get_equip (tar, WEAR_SEC)->virtual); if ( get_equip (src, WEAR_BOTH) ) src_both = vtoo (get_equip (src, WEAR_BOTH)->virtual); if ( get_equip (tar, WEAR_BOTH) ) tar_both = vtoo (get_equip (tar, WEAR_BOTH)->virtual); if ( get_equip (src, WEAR_SHIELD) ) src_shield = vtoo (get_equip (src, WEAR_SHIELD)->virtual); if ( get_equip (tar, WEAR_SHIELD) ) tar_shield = vtoo (get_equip (tar, WEAR_SHIELD)->virtual); SET_BIT (src->flags, FLAG_COMPETE); SET_BIT (tar->flags, FLAG_COMPETE); src->primary_delay = 0; src->secondary_delay = 0; src_stats.kills = 0; src_stats.hits_given = 0; src_stats.hits_given_2 = 0; src_stats.swipes = 0; src_stats.swipes_2 = 0; src_stats.smites = 0; src_stats.smites_2 = 0; src_stats.breaks = 0; tar->primary_delay = 0; tar->secondary_delay = 0; tar_stats.kills = 0; tar_stats.hits_given = 0; tar_stats.hits_given_2 = 0; tar_stats.swipes = 0; tar_stats.swipes_2 = 0; tar_stats.smites = 0; tar_stats.smites_2 = 0; tar_stats.breaks = 0; GET_MOVE (src) = GET_MAX_MOVE (src); GET_MOVE (tar) = GET_MAX_MOVE (tar); GET_HIT (src) = GET_MAX_HIT (src); GET_HIT (tar) = GET_MAX_HIT (tar); REMOVE_BIT (src->flags, FLAG_KILL); REMOVE_BIT (tar->flags, FLAG_KILL); for ( i = 0; i < iterations; i++ ) { while ( 1 ) { if ( !(tick % 4) ) second_affect_update (); if ( tick & 1 ) { if ( compete_smite (src, tar, &src_stats) ) break; if ( compete_smite (tar, src, &tar_stats) ) break; } else { if ( compete_smite (tar, src, &tar_stats) ) break; if ( compete_smite (src, tar, &src_stats) ) break; } if ( src->primary_delay ) src->primary_delay--; if ( src->secondary_delay ) src->secondary_delay--; if ( tar->primary_delay ) tar->primary_delay--; if ( tar->secondary_delay ) tar->secondary_delay--; tick++; } GET_MOVE (src) = GET_MAX_MOVE (src); GET_MOVE (tar) = GET_MAX_MOVE (tar); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); second_affect_update (); if ( src_prim && !get_equip (src, WEAR_PRIM) ) { src_stats.breaks++; obj = load_object (src_prim->virtual); obj_to_char (obj, src); equip_char (src, obj, WEAR_PRIM); } if ( tar_prim && !get_equip (tar, WEAR_PRIM) ) { tar_stats.breaks++; obj = load_object (tar_prim->virtual); obj_to_char (obj, tar); equip_char (tar, obj, WEAR_PRIM); } if ( src_sec && !get_equip (src, WEAR_SEC) ) { src_stats.breaks++; obj = load_object (src_sec->virtual); obj_to_char (obj, src); equip_char (src, obj, WEAR_SEC); } if ( tar_sec && !get_equip (tar, WEAR_SEC) ) { tar_stats.breaks++; obj = load_object (tar_sec->virtual); obj_to_char (obj, tar); equip_char (tar, obj, WEAR_SEC); } if ( src_both && !get_equip (src, WEAR_BOTH) ) { src_stats.breaks++; obj = load_object (src_both->virtual); obj_to_char (obj, src); equip_char (src, obj, WEAR_BOTH); } if ( tar_both && !get_equip (tar, WEAR_BOTH) ) { tar_stats.breaks++; obj = load_object (tar_both->virtual); obj_to_char (obj, tar); equip_char (tar, obj, WEAR_BOTH); } if ( src_shield && !get_equip (src, WEAR_SHIELD) ) { src_stats.breaks++; obj = load_object (src_shield->virtual); obj_to_char (obj, src); } if ( tar_shield && !get_equip (tar, WEAR_SHIELD) ) { tar_stats.breaks++; obj = load_object (tar_shield->virtual); obj_to_char (obj, src); } tics++; } snprintf (buf, MAX_STRING_LENGTH, "Name Kills DamP DamS StrkP StrkS MissP MissS Breaks\n\r"); send_to_room_unf (buf, src->in_room); snprintf (buf, MAX_STRING_LENGTH, "=============== ====== ===== ===== ====== ====== ====== ====== ======\n\r"); send_to_room_unf (buf, src->in_room); strncpy (name, src->name, 15); name [15] = '\0'; while ( strlen (name) < 15 ) strcat (name, " "); snprintf (buf, MAX_STRING_LENGTH, "%15s %-6d %-5d %-5d %-6d %-6d %-6d %-6d %-6d\n\r", name, src_stats.kills, tar_stats.hits_given, tar_stats.hits_given_2, src_stats.smites, src_stats.smites_2, src_stats.swipes, src_stats.swipes_2, src_stats.breaks); send_to_room_unf (buf, src->in_room); strncpy (name, tar->name, 15); name [15] = '\0'; while ( strlen (name) < 15 ) strcat (name, " "); snprintf (buf, MAX_STRING_LENGTH, "%15s %-6d %-5d %-5d %-6d %-6d %-6d %-6d %-6d\n\r", name, tar_stats.kills, src_stats.hits_given, src_stats.hits_given_2, tar_stats.smites, tar_stats.smites_2, tar_stats.swipes, tar_stats.swipes_2, tar_stats.breaks); send_to_room_unf (buf, src->in_room); REMOVE_BIT (src->flags, FLAG_COMPETE); REMOVE_BIT (tar->flags, FLAG_COMPETE); for ( obj = src->room->contents; obj; obj = next_obj ) { next_obj = obj->next_content; extract_obj (obj); } } void sa_rescue (SECOND_AFFECT *sa) { int result; CHAR_DATA *tch,*rescuee; if ( !is_he_somewhere (sa->ch) ) return; rescuee = (CHAR_DATA *) sa->obj; result = rescue_attempt (sa->ch, rescuee); if ( result == 2 ) /* can't rescue...stop trying */ return; else if ( result == 0 ) { /* Failed, try again */ act ("$n makes another failed attempt at rescuing $N.", FALSE, sa->ch, 0, rescuee, TO_NOTVICT); act ("$N tries again, but fails to rescue you.", FALSE, rescuee, 0, sa->ch, TO_CHAR); act ("You try again, but fail to rescue $n.", FALSE, rescuee, 0, sa->ch, TO_VICT); add_second_affect (SPA_RESCUE, 3, sa->ch, sa->obj, NULL, 0); return; } else if ( result == 1 ) /* Couldn't try...try asap */ add_second_affect (SPA_RESCUE, 1, sa->ch, sa->obj, NULL, 0); else if ( result == 3 ) { for ( tch = sa->ch->room->people; tch; tch = tch->next_in_room ) if ( tch->fighting == rescuee ) break; if ( !tch ) return; if ( !sa->ch->fighting ) set_fighting (sa->ch, tch); else sa->ch->fighting = tch; if ( tch->fighting ) { stop_fighting (tch); if (rescuee->fighting) stop_fighting (rescuee); } set_fighting (tch, sa->ch); act ("You draw $N's attention.", FALSE, sa->ch, 0, tch, TO_CHAR); act ("$N draws your attention.", FALSE, tch, 0, sa->ch, TO_CHAR); act ("$N draws $n's attention.", FALSE, tch, 0, sa->ch, TO_NOTVICT); act ("You stop fighting $N.", FALSE, rescuee, 0, tch, TO_CHAR); } } /* Rescue results: 0 = failed to rescue (3 sec pause) Normal failure...try again 1 = no rescue attempt, not possible yet (1 sec pause) Not in FIGHT or STAND mode Being subdued 2 = can't rescue (delete sa) Fighting friend, or friend fighting us Friend not here Friend begin fought 3 = success */ int rescue_attempt (CHAR_DATA *ch, CHAR_DATA *friend) { CHAR_DATA *tch; int agi_diff; if ( GET_POS (ch) < FIGHT ) return 1; if ( IS_SET (ch->flags, FLAG_SUBDUING) ) return 1; if ( !is_he_here (ch, friend, TRUE) ) return 2; if ( IS_SET (friend->flags, FLAG_SUBDUING) ) return 1; if ( ch->fighting == friend || friend->fighting == ch ) return 2; for ( tch = ch->room->people; tch; tch = tch->next_in_room ) if ( tch->fighting == friend ) break; if ( !tch ) return 2; agi_diff = (GET_AGI (ch) - GET_AGI (tch)) + /* * easier to rescue if you are fighting your friend's enemy * harder to rescue if you are fighting someone else * otherwise rescue as normal */ (ch->fighting == tch)?8:(ch->fighting)?2:5; if ( agi_diff >= number (1, 10) ) return 3; else if ( number (0, 19) == 0 ) return 3; else return 0; } void do_rescue (CHAR_DATA *ch, char *argument, int cmd) { int result; CHAR_DATA *friend; CHAR_DATA *tch; SECOND_AFFECT *sa; char buf [MAX_STRING_LENGTH] = {'\0'}; argument = one_argument (argument, buf); sa = get_second_affect (ch, SPA_RESCUE, NULL); if ( !*buf ) { if ( sa ) { send_to_char ("You stop trying to rescue.\n", ch); remove_second_affect (sa); return; } send_to_char ("Rescue whom?\n", ch); return; } if ( !(friend = get_char_room_vis (ch, buf)) ) { send_to_char ("You don't see them here.\n", ch); return; } if ( friend == ch ) { send_to_char ("Rescue yourself?\n", ch); return; } if ( friend == ch->fighting ) { send_to_char ("You can't rescue your opponent?\n", ch); return; } for ( tch = ch->room->people; tch; tch = tch->next_in_room ) if ( tch->fighting == friend ) break; if ( !tch ) { act ("$N doesn't need rescuing.", FALSE, ch, 0, friend, TO_CHAR); return; } if ( sa ) { if ( (CHAR_DATA *) sa->obj == friend ) { act ("You're still trying your best to rescue $N.", FALSE, ch, 0, friend, TO_CHAR); return; } sa->obj = (OBJ_DATA *) friend; act ("You will try to rescue $N now.", FALSE, ch, 0, friend, TO_CHAR); return; } result = rescue_attempt (ch, friend); if ( result == 0 ) { act ("You try to draw $N's attention.", FALSE, ch, 0, tch, TO_CHAR); act ("$N tries to draw your attention.", FALSE, tch, 0, ch, TO_CHAR); act ("$n tries to draw $N's attention.", FALSE, ch, 0, tch, TO_NOTVICT); add_second_affect (SPA_RESCUE, 3, ch, (OBJ_DATA *) friend, NULL, 0); } else if ( result == 3 ) { act ("You draw $N's attention.", FALSE, ch, 0, tch, TO_CHAR); act ("$N draws your attention.", FALSE, tch, 0, ch, TO_CHAR); act ("$N draws $n's attention.", FALSE, tch, 0, ch, TO_NOTVICT); if ( GET_POS (ch) != POSITION_DEAD && GET_POS (tch) != POSITION_DEAD ) criminalize (ch, tch, ch->room->zone, CRIME_KILL); if ( !tch->fighting ) set_fighting (tch, ch); else tch->fighting = ch; } else if ( result == 1 ) { act ("You will try to rescue $N when you can.", FALSE, ch, 0, friend, TO_CHAR); add_second_affect (SPA_RESCUE, 1, ch, (OBJ_DATA *) friend, NULL, 0); } else { /* better be result == 2, shouldn't be possible */ printf ("Rescue attempt, result = 2\n"); } return; } void do_surrender (CHAR_DATA *ch, char *argument, int cmd) { CHAR_DATA *tch; char buf [MAX_STRING_LENGTH] = {'\0'}; argument = one_argument (argument, buf); if ( IS_SWIMMING (ch) ) { send_to_char ("You can't do that while swimming!\n", ch); return; } if ( IS_SET (ch->flags, FLAG_SUBDUER) ) { send_to_char ("Release your prisoner, first.\n", ch); return; } if ( IS_SET (ch->room->room_flags, OOC) ) { send_to_char ("Sorry, but this command is disabled in OOC areas.\n", ch); return; } if ( !*buf && ch->fighting ) tch = ch->fighting; else if ( !(tch = get_char_room_vis (ch, buf)) ) { send_to_char ("Surrender to whom?\n", ch); return; } if ( ch == tch ) { send_to_char ("Surrender to yourself? Hmm...\n", ch); return; } if ( tch->fighting && tch->fighting != ch ) { send_to_char ("They're a little too busy to take prisoners, right now...\n", ch); return; } if ( tch->subdue ) { send_to_char ("They are unable to take another prisoner.\n", ch); return; } if ( IS_SET (tch->flags, FLAG_KILL) ) { send_to_char ("They don't look particularly interested in taking prisoners...\n", ch); return; } act ("You surrender yourself into $N's custody.", FALSE, ch, 0, tch, TO_CHAR | TO_ACT_FORMAT); act ("$n surrenders $mself into your custody.", TRUE, ch, 0, tch, TO_VICT | TO_ACT_FORMAT); act ("$n surrenders $mself into $N's custody.", TRUE, ch, 0, tch, TO_NOTVICT | TO_ACT_FORMAT); subdue_char (tch, ch); return; } void do_study (CHAR_DATA *ch, char *argument, int cmd) { CHAR_DATA *crim; char buf [MAX_STRING_LENGTH] = {'\0'}; argument = one_argument (argument, buf); if ( IS_SET (ch->room->room_flags, OOC) ) { send_to_char ("That command is disabled in OOC areas.\n", ch); return; } if ( !*buf ) { send_to_char ("Study is used to identify those who are masked.\n", ch); return; } if ( !(crim = get_char_room_vis (ch, buf)) ) { send_to_char ("Study whom?\n", ch); return; } if ( crim == ch ) { send_to_char ("You like the way you look.\n", ch); return; } do_look (ch, buf, 0); act ("You stare at $N.", FALSE, ch, 0, crim, TO_CHAR); act ("$n is staring at $N.", FALSE, ch, 0, crim, TO_NOTVICT); act ("$n stares at you.", FALSE, ch, 0, crim, TO_VICT); if ( !is_hooded (crim) ) return; ch->delay_ch = crim; ch->delay_type = DEL_STARE; ch->delay = 5; return; } void delayed_study (CHAR_DATA *ch) { AFFECTED_TYPE *af = NULL; char buf [MAX_STRING_LENGTH] = {'\0'}; if ( !is_he_here (ch, ch->delay_ch, TRUE) ) return; if ( !is_hooded (ch->delay_ch) ) return; if ( !skill_use (ch, SKILL_SCAN, 0) ) { act ("The identity of $N remains a mystery.", FALSE, ch, 0, ch->delay_ch, TO_CHAR); return; } snprintf (buf, MAX_STRING_LENGTH, "You discover that $N is %s.", ch->delay_ch->short_descr); act (buf, FALSE, ch, 0, ch->delay_ch, TO_CHAR); if ( ch->mob && IS_SET (ch->act, ACT_ENFORCER) ) { magic_add_affect (ch->delay_ch, MAGIC_STARED, 90, 0, 0, 0, 0); if ( (is_area_enforcer(ch) && (ch->race == 0) ) && (ch->in_room / 1000 == 1 || ch->in_room / 1000 == 2 || ch->in_room / 1000 == 3) ) { if ( ch->delay_ch->race >= 1 && CAN_SEE (ch, ch->delay_ch) ) { /* Beasts in Gondor? Uh oh... */ criminalize (ch->delay_ch, ch, ch->room->zone, 6); } } } if ( !get_affect (ch->delay_ch, MAGIC_CRIM_BASE + ch->room->zone) ) return; if ( is_area_enforcer (ch) ) act ("$E is a criminal!", FALSE, ch, 0, ch->delay_ch, TO_CHAR); /* Make criminal hot */ if ( !(af = get_affect (ch->delay_ch, MAGIC_CRIM_HOODED)) ) magic_add_affect (ch->delay_ch, MAGIC_CRIM_HOODED + ch->room->zone, 400, 0, 0, 0, 0); else af->a.spell.duration = 400; /* Probably should check to see if this is an enforcer of the zone */ if ( ch->mob && is_area_enforcer(ch) ) enforcer (ch, ch->delay_ch, 1, 1); }