/*************************************************************************** * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills and Dug Michael. * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ #include "emud.h" /* Global functions. */ sh_int martial_arts_attack; sh_int fisticuffs_attack; sh_int brawling_attack; sh_int body_part_attack; bool OGRE_INTIMIDATE; bool remove_obj args( ( CHAR_DATA *ch, int iWear, bool fReplace, bool fDisplay ) ); /* Local functions. */ bool check_add_attack ( CHAR_DATA *, CHAR_DATA *); void clear_attack_list ( CHAR_DATA * ); void spam_attack_list ( CHAR_DATA * ); void add_to_victory_list ( CHAR_DATA *, CHAR_DATA *); void show_party_line ( CHAR_DATA * ); void raw_kill args( ( CHAR_DATA *victim ) ); void arena_death args( ( CHAR_DATA *victim ) ); void player_death args( ( CHAR_DATA *victim ) ); bool check_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_shield_block args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_tumble args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void check_killer args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void dam_message args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt)); char *get_dam_nounce args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt)); void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt)); bool has_mirror args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt)); bool has_icicle_armor args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt)); bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); int xp_compute args( ( CHAR_DATA *gch,CHAR_DATA *victim ) ); void group_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void trip args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void backstab args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void orc_brawl args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void fisticuffs args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) ); void martial_arts args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) ); struct attack_type { char * message; int dam_type; }; const struct attack_type attack_table[] = { { "hit", DAM_THRUST }, { "slice", DAM_SLICE }, { "stab", DAM_PIERCE }, { "slash", DAM_SLICE }, { "whip", DAM_REND }, { "claw", DAM_REND }, { "blast", DAM_THRUST }, { "pound", DAM_BASH }, { "crush", DAM_BASH }, { "grep", DAM_THRUST }, { "bite", DAM_PIERCE }, { "pierce", DAM_PIERCE }, { "chop", DAM_CHOP } }; const struct attack_type martial_arts_table[] = { { "combination punch", DAM_THRUST }, { "palm punch", DAM_THRUST }, { "thrust kick", DAM_BASH }, { "spinning back-hand", DAM_THRUST }, { "jump kick", DAM_THRUST }, { "round house", DAM_BASH }, { "flip kick", DAM_THRUST }, { "thrusting spear hand", DAM_PIERCE }, { "spinning reverse kick", DAM_THRUST }, { "spinning hook kick", DAM_THRUST }, { "flying scissors kick", DAM_REND }, { "triple round house kick", DAM_BASH } }; const struct attack_type fisticuffs_table[] = { { "combination punch", DAM_THRUST }, { "uppercut", DAM_THRUST }, { "kidney punch", DAM_THRUST }, { "fist blow", DAM_BASH }, { "haymaker", DAM_BASH }, { "sucker punch", DAM_BASH } }; const struct attack_type brawling_table[] = { { "knee", DAM_THRUST }, { "claw", DAM_REND }, { "bite", DAM_PIERCE }, { "head butt", DAM_BASH }, { "elbow slam", DAM_THRUST }, { "uppercut", DAM_THRUST } }; void check_asn_obj(CHAR_DATA *victim) { push_call("check_asn_obj(%p)",victim); if (IS_NPC(victim) || victim->fighting == NULL || IS_NPC(victim->fighting->who)) { pop_call(); return; } if (victim->fighting->who->pcdata->asn_obj) { OBJ_DATA *obj = victim->fighting->who->pcdata->asn_obj; victim->fighting->who->pcdata->asn_obj = NULL; if (obj->carried_by == victim) { obj_to_char(obj, victim->fighting->who); act("You quickly snatch $p from $N's failing grasp!", victim->fighting->who, obj, victim, TO_CHAR ); } } pop_call(); return; } /* Control the fights going on. Called periodically by update_handler. */ void violence_update( void ) { CHAR_DATA *ch; CHAR_DATA *victim; CHAR_DATA *rch; OBJ_DATA *obj; PLAYER_GAME *gpl; push_call("violence_update()"); for (ch = mud->f_char ; ch ; ch = mud->update_wch) { mud->update_wch = ch->next; if (ch->distracted > 0) { ch->distracted--; if (ch->distracted == 0 && IS_NPC(ch) && ch->position < ch->pIndexData->position) { do_stand(ch, ""); } } if (!IS_NPC(ch)) { if ((obj = get_eq_char(ch, WEAR_WIELD)) != NULL && get_obj_weight(obj) > str_app[get_curr_str(ch)].wield) { act( "$p slips out of your weakened grasp.", ch, obj, NULL, TO_CHAR ); act( "$p slips out of $n's weakened grasp.", ch, obj, NULL, TO_ROOM ); unequip_char(ch, obj); } if (is_affected(ch, gsn_nightmare)) { if (number_percent() < 5 && (obj = get_eq_char(ch, WEAR_LIGHT)) !=NULL) { act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM); switch (number_range(1,3)) { case 1: act( "The evil leer of a demon appears within the glaring light of $p!", ch, obj, NULL, TO_CHAR); break; case 2: act( "A soul rending shriek is torn from $p!", ch, obj, NULL, TO_CHAR); break; case 3: act( "Images of your painful demise emanate from $p!", ch, obj, NULL, TO_CHAR); break; } act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR); unequip_char(ch, obj); } else if (number_percent() < 5 && (obj = get_eq_char(ch, WEAR_HOLD)) !=NULL) { act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM); switch (number_range(1,3)) { case 1: act( "$p starts to slowly drain away your dwindling vitality!", ch, obj, NULL, TO_CHAR); break; case 2: act( "A whisper hisses from $p 'You shall do my bidding weakling!", ch, obj, NULL, TO_CHAR); break; case 3: act( "A stabbing pain lances through you from $p!", ch, obj, NULL, TO_CHAR); break; } act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR); unequip_char(ch, obj); } else if ( number_percent() < 5 && (obj = get_eq_char(ch, WEAR_WIELD )) !=NULL) { act( "$n screams and flings $p away!", ch, obj, NULL, TO_ROOM); switch (number_range(1,3)) { case 1: act( "The hilt of $p glows red starting to smolder with heat!", ch, obj, NULL, TO_CHAR); break; case 2: act( "Like a viper, $p turns on you and tries to strike!", ch, obj, NULL, TO_CHAR); break; case 3: act( "$p takes on a life of its own, struggling within your grasp!", ch, obj, NULL, TO_CHAR); break; } act( "You scream and fling $p away!", ch, obj, NULL, TO_CHAR); unequip_char(ch, obj); } } } if (IS_AFFECTED(ch, AFF2_BLEEDING)) { AFFECT_DATA *paf; int dam = 0; ch_printf(ch, "%sYour life is bleeding out of many nasty wounds!\n\r", get_color_string(ch, COLOR_YOU_ARE_HIT, VT102_BOLD)); act("$n's life is bleeding out of a many nasty wounds!", ch, NULL, NULL, TO_ROOM); for (paf = ch->first_affect ; paf ; paf = paf->next) { if (paf->bitvector == AFF2_BLEEDING) { dam += paf->modifier; } } if (dam < 1) { dam = 1; } if ((victim = get_char_pvnum(ch->critical_hit_by)) == NULL) { victim = ch; } damage(victim, ch, dam, TYPE_NOFIGHT); } if (IS_AFFECTED(ch, AFF2_TORRID_BALM) && number_bits(1)) { AFFECT_DATA *paf; int dam = 0; switch(number_bits(2)) { case 0: act("Your skin blisters from the torrid balm enveloping you.", ch, NULL, NULL, TO_CHAR); act("$n's skin blisters from the torrid balm enveloping $m.", ch, NULL, NULL, TO_ROOM); break; case 1: act("Torment lashes through you as the torrid balm brands your flesh.", ch, NULL, NULL, TO_CHAR); act("Torment lashes through $n as torrid balm brands $s flesh.", ch, NULL, NULL, TO_ROOM); break; case 2: act("You feel your flesh rendered by the torrid balm.", ch, NULL, NULL, TO_CHAR); act("You watch $n's flesh rendered by torrid balm.", ch, NULL, NULL, TO_ROOM); break; case 3: act("You scream out in agony as the torrid balm consumes you.", ch, NULL, NULL, TO_CHAR); act("$n screams out in agony as torrid balm consumes $m.", ch, NULL, NULL, TO_ROOM); break; } for (paf = ch->first_affect ; paf ; paf = paf->next) { if (paf->bitvector == AFF2_TORRID_BALM) { dam = number_range(1, 10 + paf->duration * 10) + paf->duration * paf->duration; if (number_bits(2) == 0) { paf->modifier += IS_NPC(ch) ? 5 : -1; } } } dam = URANGE(1, dam, UMAX(ch->hit, 1)); damage(ch, ch, dam, TYPE_NOFIGHT); } /* Add poison continuous damage here */ if (ch->poison) { POISON_DATA *pd; CHAR_DATA *attacker, *fch; int dmg; pd = ch->poison; attacker = get_char_pvnum(pd->poisoner); if (attacker == NULL) { attacker = ch; } if (pd->instant_damage_high > 0) { dmg = number_range(pd->instant_damage_low, pd->instant_damage_high); pd->instant_damage_high = 0; } else { dmg = number_range(pd->constant_damage_low, pd->constant_damage_high); } if (pd->for_npc != IS_NPC(ch)) { dmg /= 2; } for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (fch == ch && ch == attacker) { ch_printf(fch, "%sYou are shocked by poison for %dhp.\n\r", get_color_string(fch, COLOR_YOU_HIT, VT102_BOLD), dmg); } else if (fch == ch) { ch_printf(ch, "%sYou are shocked by poison.\n\r", get_color_string(ch, COLOR_YOU_ARE_HIT, VT102_BOLD)); } else if (fch == attacker) { ch_printf(fch, "%s%s is shocked by poison for %dhp.\n\r", get_color_string(fch,COLOR_YOU_HIT,VT102_BOLD), capitalize(get_name(ch)), dmg); } else { ch_printf(fch, "%s is shocked by poison.\n\r", capitalize(get_name(ch))); } } damage(attacker, ch, dmg, TYPE_NOFIGHT); if (pd->constant_duration <= 0) { ch->poison = ch->poison->next; FREEMEM(pd); } else { pd->constant_duration--; } } if (ch->fighting == NULL) { if (ch->position == POS_FIGHTING) { stop_fighting(ch, FALSE); } continue; } if ((victim = who_fighting(ch)) == NULL) { stop_fighting(ch, FALSE); continue; } if (ch->in_room != victim->in_room) { stop_fighting( ch, FALSE ); continue; } if (ch->position < POS_SLEEPING) { continue; } if (ch->attack != 0) { ch->attack = 0; } if (IS_NPC(ch)) { if (!IS_SET(ch->act, ACT_NO_DAMAGE)) { multi_hit( ch, victim, TYPE_UNDEFINED ); } else if (!IS_SET(ch->pIndexData->progtypes, FIGHT_PROG)) { log_build_printf(ch->pIndexData->vnum, "mob has ACT_NO_DAMAGE set but has no fight prog"); } } else { ch->pcdata->last_combat = mud->current_time; if (ch->pcdata->auto_flags != AUTO_QUICK) { check_improve(ch, gsn_first_strike); multi_hit( ch, victim, TYPE_UNDEFINED ); } } if (!valid_fight(ch, victim)) { continue; } set_fighting(victim, ch); mprog_hitprcnt_trigger(ch, victim); if (!valid_fight(ch, victim)) { continue; } mprog_fight_trigger(ch, victim); if (!valid_fight(ch, victim)) { continue; } /* assist rules - Scandum 27-02-2002 - charmed mobs are not assisted - players only assist when victim is a mob - grouped mobs assist, no questions asked - mobs do not attack their master - mobs do not attack their own kind (same vnum) - mobs do not attack someone more than 30 levels below - mobs of same vnum have 50.0% chance to assist - mobs of diff vnum have 12.5% chance to assist - mobs attack a random party member of the victim */ if (IS_AFFECTED(victim, AFF_CHARM) || IS_AFFECTED(ch, AFF_CHARM)) { continue; } for (rch = ch->in_room->first_person ; rch ; rch = mud->update_rch) { mud->update_rch = rch->next_in_room; if (!IS_AWAKE(rch) || rch->fighting || IS_AFFECTED(rch, AFF_ETHEREAL)) { continue; } if (!IS_NPC(rch) || rch->desc) { if (is_same_group(ch, rch) && IS_NPC(victim)) { multi_hit(rch, victim, TYPE_UNDEFINED); } continue; } if (IS_AFFECTED(rch, AFF_CHARM)) { if (rch->master == ch) { multi_hit(rch, victim, TYPE_UNDEFINED); } continue; } if (is_same_group(ch, rch)) { multi_hit(rch, victim, TYPE_UNDEFINED); continue; } if (!IS_NPC(ch) || rch->master == who_fighting(ch)) { continue; } if (rch->pIndexData == victim->pIndexData) { continue; } if (rch->pIndexData != ch->pIndexData && number_bits(2)) { continue; } if (rch->level / 2 <= ch->level && rch->level * 2 >= ch->level && number_bits(1)) { CHAR_DATA *vch; CHAR_DATA *target = NULL; int number; for (number = 0, vch = ch->in_room->first_person ; vch ; vch = vch->next_in_room, number++) { if (can_see(rch, vch) && is_same_group(vch, victim) && number_range(0, number) == 0) { target = vch; } } if (target != NULL) { multi_hit(rch, target, TYPE_UNDEFINED); } } } } /* Add Spam's party stat line here */ for (gpl = mud->f_player ; gpl ; gpl = gpl->next) { if (gpl->ch->fighting != NULL && IS_SET(gpl->ch->pcdata->spam, 1024)) { show_party_line( gpl->ch ); } if (gpl->ch->desc == NULL && gpl->ch->fighting && gpl->ch->wait == 0) { do_flee(gpl->ch, ""); } } pop_call(); return; } /* The SPAM stat line */ void show_party_line( CHAR_DATA *ch ) { CHAR_DATA *fch; char buf[MAX_STRING_LENGTH], buf2[200], buf3[200]; push_call("show_party_line(%p)",ch); buf[0]='\0'; for (fch = ch->in_room->first_person; fch != NULL; fch = fch->next_in_room) { if (fch != ch && is_same_group(ch, fch)) { strcpy(buf3, !IS_NPC(fch)?capitalize(fch->name): capitalize(fch->short_descr)); buf3[6]='\0'; sprintf(buf2, "%s:%d/%d ", buf3, fch->hit, fch->max_hit); strcat(buf, buf2); } } if (buf[0] != '\0') { ch_printf(ch, "%s%s\n\r", get_color_string(ch,COLOR_PROMPT,VT102_DIM), buf); } pop_call(); return; } /* Do one group of attacks. */ void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int chance, level, bonus; OBJ_DATA *wield; push_call("multi_hit(%p,%p,%p)",ch,victim,dt); OGRE_INTIMIDATE = FALSE; /* Disallow fighting in different rooms and shops */ if (victim->in_room != ch->in_room) { stop_fighting(ch, FALSE); pop_call(); return; } if (is_safe(ch, NULL)) { stop_fighting(ch, FALSE); pop_call(); return; } if (victim->fighting == NULL) { if (!IS_NPC(victim) || (IS_SET(victim->act, ACT_CLASS) && victim->class == CLASS_GLADIATOR)) { if (number_range(1, 200) < learned(victim, gsn_impale)) { wield = get_eq_char(victim, WEAR_WIELD); if (wield && wield->item_type == ITEM_WEAPON && wield->value[0] == WEAPON_TYPE_SPEAR) { act("You thrust $p into the ground.", victim, wield, NULL, TO_CHAR); act("$n thrusts $p into the ground.", victim, wield, NULL, TO_ROOM); one_hit(victim, ch, gsn_impale); } } } } if (ch->in_room != victim->in_room) { stop_fighting(ch, FALSE); pop_call(); return; } /* Added Ogre Intimidate here - Chaos 8/20/98 */ if (rspec_req(ch, RSPEC_INTIMIDATE) && !rspec_req(victim, RSPEC_INTIMIDATE)) { if (!IS_UNDEAD(victim) && number_range(1,6) == 1) { OGRE_INTIMIDATE = TRUE; send_to_char( "You intimidate your opponent.\n\r", ch); send_to_char( "You are intimidated by your opponent.\n\r", victim); } } one_hit(ch, victim, dt); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } if (ch->position != POS_FIGHTING && ch->position > POS_STUNNED) { set_fighting(ch, victim); } /* Added Orcish brawling - Chaos 8/20/98 */ if (rspec_req(ch, RSPEC_BRAWLING) && number_bits(3) == 0) { orc_brawl(ch, victim); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } } if (get_eq_char(ch, WEAR_DUAL_WIELD) || ch->race == RACE_KRAKEN || rspec_req(ch, RSPEC_MULTI_ARMS) || is_affected(ch,AFF2_STEELHAND)) { if (rspec_req(ch, RSPEC_MULTI_ARMS)) { chance = UMAX(50, learned(ch, gsn_dual_wield)); } else { chance = learned(ch, gsn_dual_wield); } bonus = chance / 10; if (number_percent() < chance) { one_hit(ch, victim, dt); check_improve(ch, gsn_dual_wield); } if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } } else { bonus = 0; } if (IS_AFFECTED(ch, AFF_HASTE)) { bonus += 10; } if (!IS_NPC(ch) && multi(ch, gsn_second_attack) == -1) { pop_call(); return; } level = multi_skill_level(ch, gsn_second_attack); chance = (learned(ch, gsn_second_attack)+bonus)*level/50; if (number_percent() < chance) { one_hit(ch, victim, dt); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } check_improve(ch, gsn_second_attack); } if (!IS_NPC(ch) && multi(ch, gsn_third_attack) == -1) { pop_call(); return; } level = multi_skill_level(ch, gsn_third_attack); chance = (learned(ch, gsn_third_attack)+bonus)*level/150; if (number_percent() < chance) { one_hit(ch, victim, dt); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } check_improve(ch, gsn_third_attack); } if (!IS_NPC(ch) && multi(ch, gsn_fourth_attack) == -1) { pop_call(); return; } level = multi_skill_level(ch, gsn_fourth_attack); chance = (learned(ch, gsn_fourth_attack)+bonus)*level/300; if (number_percent() < chance) { one_hit(ch, victim, dt); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } check_improve(ch, gsn_fourth_attack); } if (!IS_NPC(ch) && multi(ch, gsn_fifth_attack) == -1) { pop_call(); return; } level = multi_skill_level(ch, gsn_fifth_attack); chance = (learned(ch, gsn_fifth_attack)+bonus)*level/450; if (number_percent() < chance) { one_hit(ch,victim,dt); if (!valid_fight(ch, victim) || ch->fighting->who != victim) { pop_call(); return; } check_improve(ch, gsn_fifth_attack); } pop_call(); return; } bool check_hit( CHAR_DATA *ch, CHAR_DATA *victim, int hit_roll, int dam_type ) { int thac0, diceroll, level, scale; OBJ_DATA *wield; push_call("check_hit(%p,%p,%p,%p)",ch,victim,hit_roll,dam_type); /* Calculate to-hit-armor-class-0 versus armor - Chaos 10/5/93 */ level = multi_skill_level(ch, dam_type); if (dam_type == gsn_kick) scale = 15; else if (dam_type == gsn_shoot) scale = 14; else if (dam_type == gsn_backstab) scale = 14; else if (dam_type == gsn_head_butt) scale = 14; else if (dam_type == gsn_knife) scale = 13; else if (dam_type == gsn_trip) scale = 13; else if (dam_type == gsn_circle) scale = 13; else if (dam_type == gsn_throw) scale = 13; else if (dam_type == gsn_vampiric_touch) scale = 13; else if (dam_type == gsn_whirl) scale = 13; else if (dam_type == gsn_impale) scale = 13; else if (dam_type == gsn_bash) scale = 12; else if (dam_type == gsn_fisticuffs) scale = 12; else if (dam_type == gsn_gouge) scale = 12; else if (dam_type == gsn_martial_arts) scale = 11; else if (dam_type == gsn_acupunch) scale = 11; else if (dam_type == gsn_cripple) scale = 11; else { scale = 10; level = ch->level; } if (scale != 10 && number_percent() > learned(ch, dam_type)) { if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WIZTIME)) { ch_printf_color(ch, "{078}(check_hit(false) scale: %d, level: %d, learned: %d)\n\r", scale, level, learned(ch, dam_type)); } pop_call(); return FALSE; } if (IS_NPC(victim)) { thac0 = mob_armor(victim) + victim->level*4; } else { thac0 = 0 - (GET_AC(victim) - 100); } if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch)) { thac0 += 20; } if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) ) { thac0 += 20; } if (OGRE_INTIMIDATE) { thac0 -= ch->level*2; } if (victim->position == POS_SLEEPING) { thac0 = 0; } if (victim->position == POS_RESTING || victim->position == POS_SITTING) { thac0 -= ch->level; } if (!IS_NPC(ch) && ch->in_room->sector_type == SECT_ETHEREAL) { thac0 += (200 - ((get_curr_wis(ch) + get_curr_int(ch)) * 4)); } if (!IS_NPC(ch) && ch->in_room->sector_type == SECT_ASTRAL) { thac0 += (100 - (get_curr_int(ch) * 4)); } if (ch->distracted > 0) { thac0 += ch->level/3; ch->distracted--; } if (victim->distracted > 0) { thac0 -= ch->level/3; victim->distracted--; } if (IS_NPC(ch)) { diceroll = number_range(0, 34 + scale*level + hit_roll) + level*2; } else { if (learned(ch, gsn_precision)) { hit_roll += hit_roll * URANGE(25, multi_skill_level(ch, gsn_precision)/2, 50) * learned(ch, gsn_precision) / 10000; } diceroll = number_range(0, 39 + scale*level*12/10) + (hit_roll > 0 ? number_range(1, hit_roll * 2) : hit_roll) + level*2; } if (dam_type >= TYPE_HIT) { if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL) { if (!IS_SET(mud->flags, MUD_DUALFLIP)) { wield = get_eq_char( ch, WEAR_WIELD ); } } else { wield = get_eq_char(ch, WEAR_WIELD); } if (wield != NULL && wield->item_type == ITEM_WEAPON) { diceroll = (100 + weapon_skill(ch, wield->value[0])) * diceroll / 200; } } if (ch->move <= 0) { diceroll -= 10; } if (!can_see(ch, victim)) { diceroll -= 40; } if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WIZTIME)) { ch_printf_color(ch, "{078}(check_hit() diceroll: %d, thac: %d)\n\r", diceroll, thac0); } pop_call(); return(diceroll >= thac0); } /* Hit one guy once. */ void one_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dt) { OBJ_DATA *wield; AFFECT_DATA *paf; int dam; push_call("one_hit(%p,%p,%p)",ch,victim,dt); if (is_safe(ch, NULL)) { pop_call(); return; } if (ch->in_room != victim->in_room) { pop_call(); return; } if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL) { TOGGLE_BIT(mud->flags, MUD_DUALFLIP); if (!IS_SET(mud->flags, MUD_DUALFLIP)) { wield = get_eq_char(ch, WEAR_WIELD); } } else { wield = get_eq_char(ch, WEAR_WIELD); } /* Make them a bit tired */ if (!IS_NPC(ch) && ch->move > 0) { ch->move--; } /* Figure out the type of damage message. */ if (dt == TYPE_UNDEFINED) { if (IS_SET(ch->attack, ATTACK_MIRROR)) { pop_call(); return; } dt = TYPE_HIT; if (wield != NULL && wield->item_type == ITEM_WEAPON) { dt += wield->value[3]; } } /* Calc damage and check for specials */ dam = 0; if (IS_NPC(ch)) { dam = dice(get_damnodice(ch), get_damsizedice(ch)) + ch->npcdata->damplus; if (wield != NULL && wield->item_type == ITEM_WEAPON) { dam += weapon_skill(ch, wield->value[0]) * dice(wield->value[1], wield->value[2]) / 200; } else if (IS_SET(ch->act, ACT_CLASS)) { switch (ch->class) { case CLASS_SHAMAN: dt = gsn_fisticuffs; break; case CLASS_NINJA: dt = gsn_martial_arts; break; } } } else { if (wield != NULL && wield->item_type == ITEM_WEAPON) { dam = (100 + weapon_skill(ch, wield->value[0])) * dice(wield->value[1], wield->value[2]) / 200; } else { dam = dice(get_damnodice(ch), get_damsizedice(ch)); if(is_affected(ch,AFF2_STEELHAND)) /* only counts if no weapons are worn */ { for(paf=ch->first_affect;paf != NULL || paf->bitvector==AFF2_STEELHAND; paf=paf->next) { /* temporary check */ if(paf->bitvector != AFF2_STEELHAND) { log_printf("(%s [%d]): have to fix right affect grabbing.\n",__FILE__,__LINE__); } /* end of temp check */ } dam = dice(ch->level,paf->modifier); } else if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts)) { if (multi(ch, gsn_fisticuffs) != -1 && !wield && number_percent() < multi_skill_level(ch, gsn_fisticuffs)) { dt = gsn_fisticuffs; } else if (multi(ch, gsn_martial_arts) != -1 && !wield && number_percent() < multi_skill_level(ch, gsn_martial_arts)) { dt = gsn_martial_arts; } } } } /* Bonuses. */ dam += GET_DAMROLL(ch); if (victim->position == POS_SLEEPING) { dam = 4*dam/3; } if (victim->position == POS_RESTING) { dam = 6*dam/5; } if (victim->position == POS_SITTING) { dam = 7*dam/6; } if (!IS_NPC(ch) && ch->in_room->sector_type == SECT_ETHEREAL) { dam = 2 * dam / 3; } else if (!IS_NPC(ch) && ch->in_room->sector_type == SECT_ASTRAL) { dam = 2 * dam / 3; } if (dt == gsn_backstab) { if (!IS_NPC(ch)) { if (number_percent() > learned(ch, gsn_greater_backstab)) { dam = dam*(12 + multi_skill_level(ch, gsn_backstab))/10; } else { dam = dam*(12 + multi_skill_level(ch, gsn_backstab))/8; } } else { dam = dam*(12 + ch->level/2)/10; } } else if (dt == gsn_circle) { if (!IS_NPC(ch)) { dam = dam*(12 + multi_skill_level(ch, gsn_circle))/20; } else { dam = dam*(12 + ch->level/2)/20; } } else if (dt == gsn_knife) { if (!IS_NPC(ch)) { dam = dam * (12 + multi_skill_level(ch, gsn_knife))/24; } else { dam = dam * (12 + ch->level/2)/24; } } else if (dt == gsn_impale) { if (!IS_NPC(ch)) { dam = dam * (10 + multi_skill_level(ch, gsn_impale))/25; } else { dam = dam * (10 + ch->level/2)/25; } } else if (dt == gsn_martial_arts) { martial_arts(ch, victim, dam); pop_call(); return; } else if (dt == gsn_fisticuffs) { fisticuffs(ch, victim, dam); pop_call(); return; } else if (gsn_anatomy && !check_hit(ch, victim, GET_HITROLL(ch), dt)) { damage(ch, victim, 0, dt); check_improve(victim, gsn_armor_usage); pop_call(); return; } if (dam <= 0) { dam = 1; } damage(ch, victim, dam, dt); if (dt == gsn_backstab) { check_improve(ch, gsn_backstab); check_improve(ch, gsn_greater_backstab); } else if (dt == gsn_knife) { check_improve(ch, gsn_knife); } else if (dt == gsn_impale) { check_improve(ch, gsn_impale); } pop_call(); return; } void damage_hurt( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { bool auto_sac, auto_loot; bool confused=FALSE; char buf[MAX_INPUT_LENGTH]; /* Hurt the victim. Inform the victim of his new state. */ push_call("damage_hurt(%p,%p,%p,%p)",ch,victim,dam,dt); victim->hit -= dam; if (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL && victim->hit < 1) { victim->hit = 1; } update_pos(victim); if (victim->position != POS_DEAD && dam > 0) { show_char_to_char_1( victim, NULL); } if (dam > 0 && dt != TYPE_NOFIGHT && !is_spell(dt)) { if (IS_AFFECTED(victim, AFF2_FIRESHIELD) || victim->race == RACE_PHOENIX) { if (number_percent() <= 25) { damage(victim, ch, number_fuzzy(dam), gsn_fire_shield); } if (ch->in_room != victim->in_room) { pop_call(); return; } } if (IS_AFFECTED(victim, AFF2_ICICLE_ARMOR)) { if (number_percent() <= 10) { damage(victim, ch, number_fuzzy(ch->level), gsn_icicle_armor); } if (ch->in_room != victim->in_room) { pop_call(); return; } } } switch (victim->position) { case POS_MORTAL: act("$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM); send_to_char( "You are mortally wounded, and will die soon, if not aided.\n\r", victim); break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char("You are incapacitated and will slowly die, if not aided.\n\r",victim ); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.",victim, NULL, NULL, TO_ROOM ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case POS_DEAD: if (victim->fighting) { if (IS_NPC(ch) && ch->master) { victim->fighting->who = ch->master; } else { victim->fighting->who = ch; } } mprog_death_trigger(victim); mprog_kill_trigger(ch); act( "$n is DEAD!!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if (dam > victim->max_hit / 4 && (IS_NPC(victim) || victim->level < LEVEL_IMMORTAL)) { send_to_char( "*** That really did HURT!\n\r", victim); } if (victim->hit < victim->max_hit / 4 && (IS_NPC(victim) || victim->level < LEVEL_IMMORTAL)) { send_to_char( "*** You sure are BLEEDING!\n\r", victim); } break; } /* Sleep spells and extremely wounded folks. */ if (!IS_AWAKE(victim) || ch == victim) { if (dt != TYPE_NOFIGHT) { if (victim->fighting) { stop_hate_fear(victim->fighting->who); } } } /* Intercept object programs for damaging others */ if (!IS_NPC(ch) && dam > 0 && victim->position != POS_DEAD) { if (dt != TYPE_NOFIGHT && ch->desc != NULL) { OBJ_DATA *obj, *obj_next; OBJ_PROG *prg; for (obj = ch->first_carrying ; obj ; obj = obj_next) { obj_next = obj->next_content; if (obj->carried_by && IS_SET(obj->pIndexData->progtypes, TRIG_DAMAGE)) { for (prg = obj->pIndexData->first_prog ; prg ; prg = prg->next) { if (prg->trigger == TRIG_DAMAGE && number_percent() <= prg->percentage) { start_object_program(ch, obj, prg, ""); } } } } } } /* Intercept object programs for getting damaged */ if (!IS_NPC(victim) && dam > 0 && victim->position != POS_DEAD) { OBJ_DATA *obj, *obj_next; OBJ_PROG *prg; if (dt != TYPE_NOFIGHT && victim->desc != NULL) { for (obj = victim->first_carrying ; obj ; obj = obj_next) { obj_next = obj->next_content; if (obj->carried_by && IS_SET(obj->pIndexData->progtypes, TRIG_HIT)) { for (prg = obj->pIndexData->first_prog ; prg != NULL ; prg = prg->next) { if (prg->trigger == TRIG_HIT && number_percent() <= prg->percentage) { start_object_program( victim, obj, prg, ""); } } } } } } /* Payoff for killing things. */ if (victim->position == POS_DEAD) { OBJ_DATA *obj; if (victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA && !IS_NPC(victim)) { if (!IS_NPC(ch)) { if (ch != victim) { add_to_victory_list( ch, victim ); spam_attack_list(victim); } if ((which_god(ch) != GOD_NEUTRAL && which_god(victim) != GOD_NEUTRAL) && (which_god(ch) != which_god(victim))) { if (get_bounty(victim->name) != NULL) { collect_bounty(ch, victim); } victim->pcdata->history[HISTORY_KILL_BY_EN]++; ch->pcdata->history[HISTORY_KILL_EN]++; if (ch->pcdata->clan != NULL && victim->pcdata->clan != NULL) { switch (which_god(ch)) { case GOD_ULMO: ch->pcdata->clan->pkills[CLAN_ULMO_KILL]++; break; case GOD_DEMISE: ch->pcdata->clan->pkills[CLAN_DEMISE_KILL]++; break; case GOD_GAIA: ch->pcdata->clan->pkills[CLAN_GAIA_KILL]++; break; case GOD_HYPNOS: ch->pcdata->clan->pkills[CLAN_HYPNOS_KILL]++; break; case GOD_MANWE: ch->pcdata->clan->pkills[CLAN_MANWE_KILL]++; break; } switch (which_god(victim)) { case GOD_ULMO: victim->pcdata->clan->pdeaths[CLAN_ULMO_DEATH]++; break; case GOD_DEMISE: victim->pcdata->clan->pdeaths[CLAN_DEMISE_DEATH]++; break; case GOD_GAIA: victim->pcdata->clan->pdeaths[CLAN_GAIA_DEATH]++; break; case GOD_HYPNOS: victim->pcdata->clan->pdeaths[CLAN_HYPNOS_DEATH]++; break; case GOD_MANWE: victim->pcdata->clan->pdeaths[CLAN_MANWE_DEATH]++; break; } save_clan(ch->pcdata->clan); save_clan(victim->pcdata->clan); } ch->hit = ch->max_hit; ch->mana = ch->max_mana; ch->move = ch->max_move; act(god_table[ch->pcdata->god].pk_char_msg, ch, NULL, victim, TO_CHAR); act(god_table[ch->pcdata->god].pk_room_msg, ch, NULL, victim, TO_ROOM); sprintf(buf, "%s", get_name(ch)); do_battle("%s has slain %s!", buf, get_name(victim)); } else if (victim != ch) { log_printf("NEUTRAL PKILL"); victim->pcdata->history[HISTORY_KILL_BY_PC]++; ch->pcdata->history[HISTORY_KILL_PC]++; } } else { victim->pcdata->history[HISTORY_KILL_BY_NPC]++; if (victim->pcdata->clan != NULL) { victim->pcdata->clan->mdeaths++; save_clan( victim->pcdata->clan ); } } } if (IS_NPC(victim) && !IS_NPC(ch)) { if (ch->pcdata->clan != NULL) { ch->pcdata->clan->mkills++; } ch->pcdata->history[HISTORY_KILL_NPC]++; } if (!IS_NPC(victim)) { log_printf("%s killed by %s at %u", victim->name, get_name( ch ), victim->in_room->vnum ); save_char_obj(victim, BACKUP_SAVE); if (victim->race != RACE_PHOENIX && IS_NPC(ch)) { int exp_loss = victim->pcdata->exp - exp_level(victim->class, victim->level - 1); if (exp_loss > 0) { gain_exp(victim, 0 - exp_loss / 2); } } /* Knights Death - Chaos 9/14/95 */ if (victim->level > 91 && victim->level < 96 && victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA && victim->race != RACE_PHOENIX) { int add_hp, add_mana, add_move; victim->level--; victim->pcdata->mclass[victim->class]--; add_hp = 130; add_mana = 100; add_move = 85; add_hp *= (victim->pcdata->reincarnation + 2 ) / 2; add_mana *= (victim->pcdata->reincarnation + 3 ) / 3; add_move *= (victim->pcdata->reincarnation + 3 ) / 3; victim->max_hit -= add_hp; victim->max_move -= add_mana; victim->max_mana -= add_move; victim->pcdata->actual_max_hit -= add_hp; victim->pcdata->actual_max_move -= add_mana; victim->pcdata->actual_max_mana -= add_move; knight_adjust_hpmnmv( victim ); if (victim->pcdata->exp > exp_level(victim->class,(victim->level)-1 )+1) { gain_exp(victim, exp_level(victim->class, (victim->level)-1 )+1 - victim->pcdata->exp); } sub_player(victim); add_player(victim); } if (victim->in_room->area->low_r_vnum != ROOM_VNUM_ARENA) { if (IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF)) { if (victim->pcdata->exp > exp_level(victim->class, victim->level - 2)+1) { gain_exp( victim, exp_level(victim->class, (victim->level)-2 )+1- victim->pcdata->exp); } if (IS_SET(victim->act, PLR_KILLER)) { REMOVE_BIT(victim->act, PLR_KILLER); } if (IS_SET(victim->act, PLR_THIEF)) { REMOVE_BIT(victim->act, PLR_THIEF); } } } } else { group_gain( ch, victim ); } if ((ch == victim)) { if (ch->position == POS_DEAD) { if (IS_NPC(ch)) { log_printf("[%u] %s just killed itself using damage type %d.", ch->pIndexData->vnum, ch->short_descr, dt); } else { log_printf("%s just killed itself using damage type %d.", get_name(ch), dt); } raw_kill(ch); } pop_call(); return; } if (!confused) { set_fighting(victim, ch); } auto_loot = FALSE; auto_sac = FALSE; if (!IS_NPC(ch) && IS_NPC(victim)) { if (IS_SET(ch->act, PLR_AUTOSAC)) { auto_sac = TRUE; } if (IS_SET(ch->act, PLR_AUTOLOOT) || IS_SET(ch->act, PLR_AUTO_SPLIT)) { auto_loot = TRUE; } } if (!IS_NPC(ch) && !IS_NPC(victim) && ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { PLAYER_GAME *gpl; sprintf( buf, "%s has killed %s!\n\r", ch->name, victim->name ); for (gpl = mud->f_player ; gpl ; gpl = gpl->next ) { if (gpl->ch != ch && gpl->ch != victim && gpl->ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA ) { send_to_char( buf, gpl->ch ); } } } raw_kill( victim ); if ((obj = get_obj_list(ch, "npc_corpse", ch->in_room->first_content)) != NULL && can_see_obj(ch, obj)) { if ( auto_loot ) { FIGHT_DATA *fptr; fptr = ch->fighting; ch->fighting = NULL; do_get( ch, NULL ); ch->fighting = fptr; } if (auto_sac && rspec_req(ch, RSPEC_VAMPIRIC) && ch->pcdata->condition[COND_THIRST] < 48) { do_drink (ch, "npc_corpse"); } if ( auto_sac ) { do_sacrifice (ch, "npc_corpse"); } } if (ch->desc && CH(ch->desc)->pcdata->vt100 == 1) { vt100prompt( ch ); } pop_call(); return; } if (!IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->pcdata->wimpy && victim->wait == 0) { if (victim->desc != NULL && victim->desc->incomm[0] == '\0') { SET_BIT(victim->pcdata->interp, INTERP_AUTO); str_cpy_max(victim->desc->incomm, "flee", MAX_INPUT_LENGTH); } } if (ch->desc) { if (CH(ch->desc)->pcdata->vt100 == 1) { vt100prompt( ch ); } } if (victim->desc) { if (CH(victim->desc)->pcdata->vt100 == 1) { vt100prompt( victim ); } } pop_call(); return; } void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { OBJ_DATA *wield; bool confused; push_call("damage(%p,%p,%p,%p)",ch,victim,dam,dt); if (victim->position == POS_DEAD) { pop_call(); return; } if (dt != TYPE_NOFIGHT) { if (is_safe(ch, NULL)) { /* Disallow damage in shops and safe place. */ stop_fighting(ch, FALSE); pop_call(); return; } ch->furniture = NULL; if (ch->fighting == NULL && ch != victim) { set_fighting(ch,victim); } if (victim->fighting == NULL && ch != victim) { set_fighting(victim,ch); } if (ch->position == POS_STANDING) { ch->position = POS_FIGHTING; } if (victim != ch) { if (IS_AFFECTED(ch, AFF_HIDE)) { affect_strip(ch, gsn_hide); REMOVE_BIT(ch->affected_by, AFF_HIDE); act( "$n steps out from $s hiding spot.", ch, NULL, NULL, TO_ROOM ); act( "You step out from your hiding spot.", ch, NULL, NULL, TO_CHAR ); } if (IS_AFFECTED(ch, AFF_STEALTH)) { affect_strip(ch, gsn_stealth); affect_strip(ch, gsn_greater_stealth); REMOVE_BIT(ch->affected_by, AFF_STEALTH); act( "$n steps out into the room.", ch, NULL, NULL, TO_ROOM ); act( "You step out into the room.", ch, NULL, NULL, TO_CHAR ); } if (IS_AFFECTED(ch, AFF_INVISIBLE)) { affect_strip(ch, gsn_invis); REMOVE_BIT(ch->affected_by, AFF_INVISIBLE); if (!IS_AFFECTED(ch, AFF_IMP_INVISIBLE)) { act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM ); } } if (has_mirror(ch, victim, dt) || has_icicle_armor(ch, victim, dt)) { if (ch->position < POS_FIGHTING) { ch->position++; } pop_call(); return; } } } if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !CAN_FLY(ch) && which_god(ch) != GOD_ULMO) { if (number_percent() > 80 && number_percent() > get_curr_dex(ch)) { switch (number_bits(1)) { case 0: act("You slip on the ice, falling flat on your back.", ch, NULL, NULL, TO_CHAR); act("$n slips on the ice, falling flat on $s back.", ch, NULL, NULL, TO_ROOM); break; case 1: act("You lose your footing on the slippery ice and fall.", ch, NULL, NULL, TO_CHAR); act("$n loses $s footing on the slippery ice and falls.", ch, NULL, NULL, TO_ROOM); break; } wait_state(ch, PULSE_VIOLENCE / 4); ch->position = POS_SITTING; pop_call(); return; } } if (dt != TYPE_NOFIGHT) { switch (ch->position) { case POS_SLEEPING: if (!IS_AFFECTED(ch, AFF_SLEEP)) { ch->position = POS_RESTING; } pop_call(); return; case POS_RESTING: case POS_SITTING: do_stand(ch,""); pop_call(); return; } } /* Confusion spell - Chaos 7/26/96 */ confused = FALSE; if (IS_AFFECTED(ch, AFF2_CONFUSION) && number_range(0,4) == 0 && dt != TYPE_NOFIGHT) { CHAR_DATA *fch; int tch, pch; for (tch = 0, fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room) { if (!can_see(ch, fch)) { continue; } if (!can_attack(ch, fch) && ch != fch) { continue; } tch++; } if (tch > 1) { pch = number_range(1, tch); for (tch = 0, fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room ) { if (!can_see(ch, fch)) { continue; } if (!can_attack(ch, fch) && ch != fch) { continue; } tch++; if (tch == pch) { victim = fch; confused = TRUE; break; } } } } /* Set recently fought info. */ if (IS_NPC(victim) && !IS_NPC(ch) && !confused && dam > 0 && dt != TYPE_NOFIGHT) { if (ch->leader && !IS_NPC(ch->leader)) { victim->npcdata->pvnum_last_hit = ch->leader->pcdata->pvnum; } else { victim->npcdata->pvnum_last_hit = ch->pcdata->pvnum; } } if (dam && IS_NPC(victim) && ch != victim && dt != TYPE_NOFIGHT) { if (ch->level > 25 && victim->npcdata->hate_fear != ch->name) { RESTRING(victim->npcdata->hate_fear, ch->name); } } /* Damage enhancers */ if (!IS_NPC(ch) && !is_spell(dt) && dt != TYPE_NOFIGHT) { if (get_curr_str(ch) > 29) { dam = dam * get_curr_str(ch) / 29; } if (multi(ch, gsn_enhanced_damage) != -1) { dam += dam * URANGE(15, multi_skill_level(ch, gsn_enhanced_damage)/2, 35) * learned(ch, gsn_enhanced_damage) / 10000; check_improve(ch, gsn_enhanced_damage); } } /* Stop up any residual loopholes. Modified moving dam cap - Chaos 4/27/99 */ if (dt == gsn_backstab) { int dam_cap; int used_reincs; used_reincs = IS_NPC(ch) ? 0 : URANGE(0, ch->pcdata->reincarnation, 100); if (number_percent() < learned(ch, gsn_greater_backstab)) { dam_cap = 800+ch->level*10 + (250*used_reincs); } else { dam_cap = 800+ch->level*6 + (250*used_reincs); } dam_cap = number_fuzzy(dam_cap); if (dam > dam_cap) { dam = dam_cap; } } if (victim != ch) { /* Certain attacks are forbidden. Most other attacks are Returned. */ if (victim->position > POS_STUNNED && dt != TYPE_NOFIGHT) { if (victim->fighting == NULL && !confused ) { set_fighting(victim, ch); } } if (ch->position > POS_STUNNED && ch != victim && dt != TYPE_NOFIGHT) { if (ch->fighting == NULL && !confused) { set_fighting( ch, victim ); } /* If victim is charmed, ch might attack victim's master. */ if (IS_NPC(ch) && IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room == ch->in_room && number_bits(4) == 0 && dt != TYPE_NOFIGHT) { stop_fighting(ch, FALSE); multi_hit(ch, victim->master, TYPE_UNDEFINED); pop_call(); return; } } /* Add poison off of item */ if ((wield = get_eq_char(ch, WEAR_WIELD)) != NULL && wield->poison != NULL && dam > 0) { POISON_DATA *pd; if (IS_NPC(ch) || ch->pcdata->pvnum != wield->poison->owner) { while ((pd = wield->poison) != NULL) { wield->poison = wield->poison->next; FREEMEM(pd); } } else { if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { wield->poison->poisoner = -1; } else { wield->poison->poisoner = ch->pcdata->pvnum; } wield->poison->next = victim->poison; victim->poison = wield->poison; } wield->poison = NULL; } if (dt == gsn_knife && !IS_AFFECTED(victim, AFF2_BLEEDING) && dam > 0) { if (multi(ch, gsn_critical_hit) != -1 && number_percent() < learned(ch, gsn_critical_hit) / 4) { AFFECT_DATA af; af.type = gsn_critical_hit; af.duration = 0; af.modifier = 20 + number_range(1, multi_skill_level(ch, gsn_critical_hit)/2); af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_BLEEDING; if (!IS_NPC(ch)) { victim->critical_hit_by = ch->pcdata->pvnum; } else { victim->critical_hit_by = 0; } affect_join( victim, &af ); SET_BIT(victim->affected2_by, 0-AFF2_BLEEDING); ch_printf(ch, "%sYou feel particularly satisfied as...\n\r", get_color_string(ch,COLOR_YOU_HIT,VT102_BOLD)); check_improve(ch, gsn_critical_hit); } } /* Check for disarm, trip, parry, and dodge. */ if (dt >= TYPE_HIT) { if (IS_NPC(ch) && ch->desc == NULL) { if (number_percent() < ch->level / 30 + 1) { trip(ch, victim); } if (number_percent() < ch->level / 30 + 1) { disarm(ch, victim); } } if (victim->position > POS_RESTING) { if (check_parry(ch, victim)) { pop_call(); return; } if (check_dodge(ch, victim)) { pop_call(); return; } if (check_shield_block(ch, victim)) { pop_call(); return; } } } else if (victim->position > POS_RESTING && !is_spell(dt)) { if (check_tumble(ch, victim)) { pop_call(); return; } } } if (dt >= TYPE_HIT) { OBJ_DATA *obj; if (IS_SET(mud->flags, MUD_DUALFLIP) && get_eq_char(ch, WEAR_DUAL_WIELD) != NULL) { obj = get_eq_char(ch, WEAR_DUAL_WIELD); } else { obj = get_eq_char(ch, WEAR_WIELD); } if (obj && IS_SET(obj->extra_flags, ITEM_BURNING)) { dt = gsn_flame_blade; if (dam > 0) { dam += dice(1, 1 + obj->level / 10); } } } dam = damage_modify(ch, victim, dt, dam); if (dam > 0 && is_affected(victim, gsn_mana_shield)) { int ms_red, ms_dam; ms_red = URANGE(25, 100 * victim->mana / UMAX(1, victim->max_mana), 75); ms_dam = UMIN(dam*ms_red/100, victim->mana); dam -= ms_dam; victim->mana -= ms_dam; } if (dt != gsn_anatomy) { dam_message(ch, victim, dam, dt); } else { dam = victim->hit; } if (dam > 0 && is_affected(victim, gsn_mana_shield)) { if (100*victim->mana/victim->max_mana < 25) { act("$n flares brightly as $s mana shield shatters!", victim, NULL, NULL, TO_ROOM); send_to_char("You flare brightly as your mana shield shatters!\n\r", victim); affect_strip(victim, gsn_mana_shield); } } damage_hurt(ch, victim, dam, dt); pop_call(); return; } bool has_mirror(CHAR_DATA *ch, CHAR_DATA *victim, int dt) { AFFECT_DATA *paf; char message[MAX_INPUT_LENGTH]; const char *attack; bool all; push_call("has_mirror(%p,%p)",ch,victim); attack = NULL; all = FALSE; if (IS_AFFECTED(ch, AFF_TRUESIGHT)) { pop_call(); return FALSE; } if (!IS_AFFECTED(victim, AFF2_MIRROR_IMAGE)) { pop_call(); return FALSE; } if (dt == TYPE_NOFIGHT) { pop_call(); return FALSE; } SET_BIT(ch->attack, ATTACK_MIRROR); for (paf = victim->first_affect ; paf ; paf = paf->next) { if (paf->bitvector == AFF2_MIRROR_IMAGE) { if (number_range(0, paf->modifier)) { paf->modifier -= 1; if (paf->modifier <= 0) { all = TRUE; affect_strip(victim, paf->type); } } else { act( "You discover the real $T.", ch, NULL, short_to_name(get_name(victim), 1), TO_CHAR); act( "Your images disappear.", ch, NULL, victim, TO_VICT ); act( "$N's images disappear.", ch, NULL, victim, TO_NOTVICT ); affect_strip(victim, paf->type); pop_call(); return FALSE; } break; } } body_part_attack = get_body_part(ch, victim, dt, 0); attack = get_dam_nounce(ch, victim, dt); if (attack[0] != '\0') { sprintf(message, "Your %s destroys $N in one blow!", attack); act(message, ch, NULL, victim, TO_CHAR); sprintf(message, "$n's %s destroys $N in one blow!", attack); act(message, ch, NULL, victim, TO_ROOM); } else { act("You destroy $N in one blow!", ch, NULL, victim, TO_CHAR); act("$n destroys $N in one blow!", ch, NULL, victim, TO_ROOM); } if (all) { act( "You discover the real $T.", ch, NULL, short_to_name(get_name(victim), 1), TO_CHAR ); act( "Your images disappear.", ch, NULL, victim, TO_VICT ); act( "$N's images disappear.", ch, NULL, victim, TO_NOTVICT ); } pop_call(); return TRUE; } bool has_icicle_armor(CHAR_DATA *ch, CHAR_DATA *victim, int dt) { AFFECT_DATA *paf; char message[MAX_INPUT_LENGTH]; const char *attack = NULL; push_call("has_icicle_armor(%p,%p)",ch,victim); if (!IS_AFFECTED(victim, AFF2_ICICLE_ARMOR)) { pop_call(); return FALSE; } if (dt == TYPE_NOFIGHT || is_spell(dt)) { pop_call(); return FALSE; } for (paf = victim->first_affect ; paf ; paf = paf->next) { if (paf->bitvector == AFF2_ICICLE_ARMOR) { if (number_range(0, 200) < paf->modifier * -1) { body_part_attack = get_body_part(ch, victim, dt, 0); attack = get_dam_nounce(ch, victim, dt); if (attack[0] == '\0') { attack = "hit"; } affect_modify(victim, paf, FALSE); paf->modifier += 5; affect_modify(victim, paf, TRUE); if (paf->modifier < 0) { sprintf(message, "Your %s shatters a spike of $N's icicle armor into a hundred pieces!", attack); act(message, ch, NULL, victim, TO_CHAR); sprintf(message, "$n's %s shatters a spike of your icicle armor into a hundred pieces!", attack); act(message, ch, NULL, victim, TO_VICT); sprintf(message, "$n's %s shatters a spike of $N's icicle armor into a hundred pieces!", attack); act(message, ch, NULL, victim, TO_NOTVICT); } else { sprintf(message, "Your %s splinters $N's icicle armor into a thousand pieces!", attack); act(message, ch, NULL, victim, TO_CHAR); sprintf(message, "$n's %s splinters your icicle armor into a thousand pieces!", attack); act(message, ch, NULL, victim, TO_VICT); sprintf(message, "$n's %s splinters $N's icicle armor into a thousand pieces!", attack); act(message, ch, NULL, victim, TO_NOTVICT); affect_strip(victim, paf->type); } pop_call(); return TRUE; } break; } } pop_call(); return FALSE; } /* true if victim is a legal target for a mass attack - Scandum 27/05/2002 */ bool can_mass_attack( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("can_mass_attack(%p,%p)",ch,victim); if (victim == ch) { pop_call(); return FALSE; } if (victim->fighting && victim->fighting->who == ch) { pop_call(); return TRUE; } if (victim->fighting && !is_same_group(ch, victim->fighting->who)) { pop_call(); return FALSE; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL)) { pop_call(); return FALSE; } if (is_same_group(ch, victim)) { pop_call(); return FALSE; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { pop_call(); return TRUE; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM)) { pop_call(); return FALSE; } if (!IS_NPC(ch) && !IS_NPC(victim)) { pop_call(); return FALSE; } if (check_recently_fought(ch, victim)) { pop_call(); return FALSE; } pop_call(); return TRUE; } /* Rewrote this function to put all the no fighting crap in one neat function, charmed and possessed mobs attack like players. Scandum 18/02/02 */ bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim) { push_call("is_safe(%p,%p)",ch,victim); if (find_keeper(ch) != NULL) { ch_printf(ch, "%s%s tells you 'No fighting in here! You thug!'\n\r", get_color_string(ch,COLOR_SPEACH,VT102_BOLD), capitalize(find_keeper(ch)->short_descr)); pop_call(); return TRUE; } if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char( "You cannot do that here.\n\r", ch); pop_call(); return TRUE; } if (victim == NULL) { pop_call(); return FALSE; } if (who_fighting(ch) == victim) { pop_call(); return FALSE; } if (who_fighting(victim) == ch) { pop_call(); return FALSE; } if (ch == victim) { send_to_char( "You may not do that.\n\r", ch ); pop_call(); return TRUE; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master) { if (victim->master == ch) { raw_kill(victim); pop_call(); return TRUE; } send_to_char( "You cannot kill a slave.\n\r", ch ); pop_call(); return TRUE; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { pop_call(); return FALSE; } if (IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit / 2) { if (!IS_AFFECTED(ch, AFF_CHARM) && ch->desc == NULL) { pop_call(); return TRUE; } } if (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) || ch->desc != NULL) { if (!IS_NPC(victim)) { send_to_char( "You must MURDER a player.\n\r", ch); pop_call(); return TRUE; } } if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR); pop_call(); return TRUE; } if (check_recently_fought(ch, victim)) { ch_printf(ch, "%s was recently fought. Try later.\n\r", capitalize(victim->short_descr)); pop_call(); return TRUE; } if (IS_NPC(victim) && victim->fighting != NULL) { if (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) || ch->desc != NULL) { if (!is_same_group(ch, victim->fighting->who)) { ch_printf(ch, "%s seems to be in combat already!\n\r", capitalize(victim->short_descr)); pop_call(); return TRUE; } } } pop_call(); return FALSE; } bool check_recently_fought( CHAR_DATA *ch, CHAR_DATA *victim ) { CHAR_DATA *ch_ld; int pvnum_ld; push_call("check_recently_fought(%p,%p)",ch,victim); if (!IS_NPC(victim)) { pop_call(); return FALSE; } if (victim->npcdata->pvnum_last_hit == 0) { pop_call(); return FALSE; } if (MP_VALID_MOB(ch)) { pop_call(); return FALSE; } ch_ld = ch; if (IS_NPC(ch) && ch->master) { ch_ld = ch_ld->master; } if (ch_ld->leader != NULL) { ch_ld = ch_ld->leader; } if (!IS_NPC(ch_ld)) { pvnum_ld = ch_ld->pcdata->pvnum; } else { pvnum_ld = 0; } if (ch_ld == NULL || IS_NPC(ch_ld)) { pop_call(); return TRUE; } if (pvnum_ld != victim->npcdata->pvnum_last_hit) { pop_call(); return TRUE; } pop_call(); return FALSE; } /* See if an attack justifies a KILLER flag. */ void check_killer( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("check_killer(%p,%p)",ch,victim); if (IS_SET(victim->act, PLR_KILLER)) { pop_call(); return; } if (!IS_SET(ch->act, PLR_KILLER)) { send_to_char("*** You are now a KILLER!! ***\n\r", ch); } SET_BIT(ch->act, PLR_KILLER); ch->pcdata->killer_played = ch->pcdata->played; pop_call(); return; } bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance; bool cross_parry, reposte; push_call("check_parry(%p,%p)",ch,victim); if (IS_SET(victim->attack, ATTACK_PARRY)) { pop_call(); return FALSE; } if (get_eq_char(victim, WEAR_WIELD) == NULL) { pop_call(); return FALSE; } if (!IS_NPC(victim) && multi(victim, gsn_parry) == -1) { pop_call(); return( FALSE ); } reposte = (!IS_NPC(victim) && number_percent() < learned(victim, gsn_reposte)); cross_parry = (get_eq_char(victim, WEAR_DUAL_WIELD) != NULL); chance = learned(victim, gsn_parry) / (5 - cross_parry - reposte); reposte = reposte ? number_bits(1) : FALSE; cross_parry = cross_parry ? number_bits(1) : FALSE; if (OGRE_INTIMIDATE) { chance -= 15; reposte = FALSE; } if (number_percent() > chance) { pop_call(); return FALSE; } else { SET_BIT(victim->attack, ATTACK_PARRY); } if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3) { act( "You try to parry $n's attack, but $s aim is too precise.", ch, NULL, victim, TO_VICT); act( "$N tries to parry your attack, but your aim is too precise.", ch, NULL, victim, TO_CHAR); check_improve(ch, gsn_precision); pop_call(); return FALSE; } if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8)) { if (reposte) { act( "You parry and reposte $n's attack.", ch, NULL, victim, TO_VICT); } else if (cross_parry) { act( "You cross-parry $n's attack.", ch, NULL, victim, TO_VICT); } else { act( "You parry $n's attack.", ch, NULL, victim, TO_VICT); } } if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2)) { if (reposte) { act( "$N parries and repostes your attack.", ch, NULL, victim, TO_CHAR); } else if (cross_parry) { act( "$N cross-parries your attack.", ch, NULL, victim, TO_CHAR); } else { act( "$N parries your attack.", ch, NULL, victim, TO_CHAR); } } if (reposte) { one_hit(victim, ch, TYPE_UNDEFINED); check_improve(victim, gsn_reposte); } else { check_improve(victim, gsn_parry); } pop_call(); return TRUE; } bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance; push_call("check_dodge(%p,%p)",ch,victim); if (IS_SET(victim->attack, ATTACK_DODGE)) { pop_call(); return FALSE; } if (!learned(victim, gsn_dodge)) { pop_call(); return( FALSE ); } chance = UMIN(multi_skill_level(victim, gsn_dodge)/2+5, learned(victim, gsn_dodge) / 3); if (OGRE_INTIMIDATE) { chance -= 15; } if (number_percent() > chance) { pop_call(); return FALSE; } else { SET_BIT(victim->attack, ATTACK_DODGE); } if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3) { act( "You try to dodge $n's attack, but $s aim is too precise.", ch, NULL, victim, TO_VICT); act( "$N tries to dodge your attack, but your aim is too precise.", ch, NULL, victim, TO_CHAR); check_improve(ch, gsn_precision); pop_call(); return FALSE; } if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8)) { act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT); } if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2)) { act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR); } check_improve(victim, gsn_dodge); pop_call(); return TRUE; } bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance = 0; push_call("check_shield_block(%p,%p)",ch,victim); if (IS_SET(victim->attack, ATTACK_BLOCK)) { pop_call(); return FALSE; } if (get_eq_char(victim, WEAR_SHIELD) == NULL) { pop_call(); return FALSE; } if (!learned(victim, gsn_shield_block)) { pop_call(); return( FALSE ); } else { chance = UMIN(multi_skill_level(victim, gsn_shield_block)/2+5, learned(victim, gsn_shield_block) / 3); } if (OGRE_INTIMIDATE) { chance -= 15; } if (number_percent() > chance) { pop_call(); return FALSE; } else { SET_BIT(victim->attack, ATTACK_BLOCK); } if (!IS_NPC(ch) && number_percent() < learned(ch, gsn_precision)/3) { act( "You try to dodge $n's attack, but $s aim is too precise.", ch, NULL, victim, TO_VICT); act( "$N tries to dodge your attack, but your aim is too precise.", ch, NULL, victim, TO_CHAR); check_improve(ch, gsn_precision); pop_call(); return FALSE; } if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8)) { act( "You block $n's attack.", ch, NULL, victim, TO_VICT); } if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2)) { act( "$N blocks your attack.", ch, NULL, victim, TO_CHAR); } check_improve(victim, gsn_shield_block); pop_call(); return TRUE; } bool check_tumble( CHAR_DATA *ch, CHAR_DATA *victim) { int chance; push_call("check_tumble(%p,%p)",ch,victim); if (IS_SET(victim->attack, ATTACK_TUMBLE)) { pop_call(); return FALSE; } if (IS_NPC(victim) && (!IS_SET(victim->act, ACT_CLASS) || victim->class != CLASS_NINJA)) { pop_call(); return FALSE; } if (!learned(victim, gsn_tumble)) { pop_call(); return( FALSE ); } chance = UMIN(multi_skill_level(victim, gsn_tumble)/2+5, learned(victim, gsn_tumble) / 3); if (OGRE_INTIMIDATE) { chance -= 15; } if (number_percent() > chance) { pop_call(); return FALSE; } else { SET_BIT(victim->attack, ATTACK_TUMBLE); } if (ch == NULL) { act( "You flip back on your feet.", victim, NULL, NULL, TO_CHAR); act( "$n flips back on his feet.", victim, NULL, NULL, TO_ROOM); } else { if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8)) { act( "You tumble away from $n's attack.", ch, NULL, victim, TO_VICT); } if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2)) { act( "$N tumbles away from your attack.", ch, NULL, victim, TO_CHAR); } } check_improve(victim, gsn_tumble); pop_call(); return TRUE; } /* Set position of a victim. */ void update_pos( CHAR_DATA *victim ) { push_call("update_pos(%p)",victim); if (victim->fighting && in_camp(victim)) { CHAR_DATA *gch; for (gch = victim->in_room->first_person ; gch ; gch = gch->next_in_room) { if (is_same_group(victim, gch) && IS_AFFECTED(gch, AFF2_CAMPING)) { send_to_char( "Your camp is destroyed!\n\r", victim ); REMOVE_BIT(gch->affected2_by, 0-AFF2_CAMPING); break; } } } if (victim->hit > 0) { if (victim->position <= POS_STUNNED) { victim->position = POS_STANDING; } pop_call(); return; } if (IS_NPC(victim) || victim->hit <= -11) { victim->position = POS_DEAD; pop_call(); return; } if (victim->hit <= -6) { victim->position = POS_MORTAL; } else if (victim->hit <= -3) { victim->position = POS_INCAP; } else { victim->position = POS_STUNNED; } pop_call(); return; } void free_fight( CHAR_DATA *ch ) { push_call("free_fight(%p)",ch); if (ch->fighting != NULL) { if ((ch->fighting->prev == NULL && ch->fighting != mud->f_fight) || (ch->fighting->next == NULL && ch->fighting != mud->l_fight)) { log_printf("UNLINK ERROR free_fight: fight data not found on %s", ch->name); dump_stack(); pop_call(); return; } UNLINK(ch->fighting, mud->f_fight, mud->l_fight, next, prev); FREEMEM(ch->fighting); } ch->position = POS_STANDING; if (!IS_NPC(ch)) { ch->pcdata->asn_obj = NULL; } update_pos(ch); pop_call(); return; } /* Start fights. */ void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim ) { FIGHT_DATA *fight; push_call("set_fighting(%p,%p)",ch,victim); if (ch == victim) { pop_call(); return; } if (ch->fighting) { pop_call(); return; } if (ch->in_room != victim->in_room) { pop_call(); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { affect_strip(ch, gsn_sleep); } ALLOCMEM(fight, FIGHT_DATA, 1); fight->who = victim; fight->ch = ch; LINK(fight, mud->f_fight, mud->l_fight, next, prev); ch->fighting = fight; if (ch->position == POS_STANDING) { ch->position = POS_FIGHTING; } if (!IS_NPC(ch)) { ch->pcdata->last_combat = mud->current_time; } if (!IS_NPC(victim)) { victim->pcdata->last_combat = mud->current_time; } update_pos(ch); pop_call(); return; } /* Make a corpse out of a character. */ void make_corpse( CHAR_DATA *ch ) { char buf[MAX_INPUT_LENGTH]; OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *obj_next; push_call("make_corpse(%p)",ch); if (IS_NPC(ch) && IS_SET(ch->act, ACT_UNDEAD)) { for (obj = ch->first_carrying ; obj ; obj = obj_next) { obj_next = obj->next_content; if (IS_SET(obj->extra_flags, ITEM_INVENTORY)) { junk_obj( obj ); } else { obj_to_room( obj, ch->in_room->vnum ); } } pop_call(); return; } if (IS_NPC(ch)) { corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0); corpse->timer = number_range( 2, 4 ); corpse->level = ch->level; corpse->owned_by = 0; if (ch->fighting != NULL) { if (IS_NPC(ch->fighting->who) && IS_AFFECTED(ch->fighting->who, AFF_CHARM)) { if (!IS_NPC(ch->fighting->who->master)) { corpse->owned_by = ch->fighting->who->master->pcdata->pvnum; } } if (!IS_NPC(ch->fighting->who)) { corpse->owned_by = ch->fighting->who->pcdata->pvnum; } if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL && ch->master->pcdata!=NULL ) { corpse->owned_by = ch->master->pcdata->pvnum; } } if (ch->gold > 0) { obj_to_obj(create_money(ch->gold), corpse); ch->gold = 0; } if (IS_SET(ch->act, ACT_MOUNT)) { SET_BIT(corpse->extra_flags, ITEM_MOUNT); } } else { corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0); corpse->timer = 60; SET_BIT(corpse->extra_flags, ITEM_MODIFIED); if (ch->pcdata->corpse == NULL) { ch->pcdata->corpse = corpse; ch->pcdata->corpse_room = ch->in_room->vnum; } corpse->owned_by = ch->pcdata->pvnum; } sprintf(buf, "corpse %s %s", IS_NPC(ch) ? "npc_corpse" : "pc_corpse", short_to_name(get_name(ch), 1)); RESTRING(corpse->name, buf); sprintf(buf, "the corpse of %s", get_name(ch)); RESTRING(corpse->short_descr, buf); sprintf(buf, "The corpse of %s is lying here.", get_name(ch)); RESTRING(corpse->long_descr, buf); for (obj = ch->first_carrying ; obj ; obj = obj_next) { obj_next = obj->next_content; if (!IS_SET(obj->extra_flags, ITEM_INVENTORY) && !IS_SET(obj->extra_flags, ITEM_NODROP)) { obj_to_obj( obj, corpse ); } } obj_to_room(corpse, ch->in_room->vnum); if (!IS_NPC(ch)) { ch->pcdata->time_of_death = mud->current_time; ch->pcdata->just_died_ctr = 10; ch->pcdata->condition[COND_FULL] = 48; ch->pcdata->condition[COND_THIRST] = 48; ch->pcdata->condition[COND_DRUNK] = 0; if (ch->race != RACE_PHOENIX) { ch_printf(ch, "%s\n\r", god_table[ch->pcdata->god].death_msg); } else { send_to_char("You have arisen from your ashes.\n\r", ch); } } pop_call(); return; } /* Improved Death_cry contributed by Diavolo. */ void death_cry( CHAR_DATA *ch ) { EXIT_DATA *pexit; char *msg; int door, vnum, ran, temp_vnum; bool IS_BODY; push_call("death_cry(%p)",ch); ran = number_bits(4); vnum = 0; IS_BODY = (IS_NPC(ch) && (IS_SET(ch->act, ACT_BODY) || IS_SET(ch->act, ACT_RACE))); if (IS_BODY && number_bits(2) == 0 && !IS_SET(ch->act, ACT_UNDEAD)) { ran = get_body_part(ch, NULL, TYPE_HIT, 1); if (ran == -1) { msg = "$n splatters blood on your armor."; } else { vnum = OBJ_VNUM_SLICED_LEG; msg = body_table[ran].sliced; } } else { msg = "You hear $n's death cry."; } if (IS_SET( ch->act, ACT_UNDEAD)) { vnum = 0; ran = 7; } if (vnum == 0) { switch (ran) { default: break; case 0: msg = "$n hits the ground ... DEAD."; break; case 1: msg = "$n splatters blood on your armor."; break; case 2: if (IS_BODY) { break; } msg = "You smell $n's sphincter releasing in death."; vnum = OBJ_VNUM_FINAL_TURD; break; case 3: if (IS_BODY) { break; } msg = "$n's severed head plops on the ground."; vnum = OBJ_VNUM_SEVERED_HEAD; break; case 4: if (IS_BODY) { break; } msg = "$n's heart is torn from $s chest."; vnum = OBJ_VNUM_TORN_HEART; break; case 5: if (IS_BODY) { break; } msg = "$n's arm is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_ARM; break; case 6: if (IS_BODY) { break; } msg = "$n's leg is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_LEG; break; case 7: msg = "$n turns to dust."; break; } } if (!IS_SET(ch->act, ACT_ELEMENTAL)) { act( msg, ch, NULL, NULL, TO_ROOM ); } if (vnum != 0) { char buf[MAX_INPUT_LENGTH]; OBJ_DATA *obj; char *name; name = IS_NPC(ch) ? ch->short_descr : ch->name; obj = create_object( get_obj_index( vnum ), 0 ); obj->timer = number_range( 4, 7 ); SET_BIT(obj->extra_flags, ITEM_MODIFIED); if (IS_BODY) { sprintf(buf, body_table[ran].short_descr, name); } else { sprintf(buf, obj->short_descr, name); } RESTRING(obj->short_descr, buf); if (IS_BODY) { sprintf(buf, body_table[ran].long_descr, capitalize(name)); } else { sprintf(buf, obj->long_descr, name); } RESTRING(obj->long_descr, buf); if (IS_BODY) { sprintf(buf, body_table[ran].name, name); RESTRING(obj->name, buf); sprintf(buf, body_table[ran].description, capitalize(name)); RESTRING(obj->description, buf); } obj_to_room(obj, ch->in_room->vnum); } if (IS_NPC(ch)) { msg = "You hear something's death cry."; } else { msg = "You hear someone's death cry."; } temp_vnum = ch->in_room->vnum; for (door = 0 ; door <= 5 ; door++) { if ((pexit = get_exit(temp_vnum, door)) != NULL) { ch->in_room = room_index[pexit->to_room]; act( msg, ch, NULL, NULL, TO_ROOM ); } } ch->in_room = room_index[temp_vnum]; pop_call(); return; } void raw_kill( CHAR_DATA *victim ) { FIGHT_DATA *fight, *fight_next; PET_DATA *pet, *pet_next; push_call("raw_kill(%p)",victim); if (IS_NPC(victim)) { if (IS_SET(victim->act, ACT_WILL_DIE)) { pop_call(); return; } SET_BIT(victim->act, ACT_WILL_DIE); } for (fight = mud->f_fight ; fight ; fight = fight_next) { fight_next = fight->next; if (IS_NPC(fight->ch) && fight->ch != victim) { if (who_fighting(fight->ch) == victim && IS_SET(fight->ch->act, ACT_ONE_FIGHT) && !SET_BIT(victim->act, ACT_WILL_DIE)) { raw_kill(fight->ch); fight_next = mud->f_fight; } } } for (pet = mud->f_pet ; pet ; pet = pet_next) { pet_next = pet->next; if (IS_NPC(pet->ch) && pet->ch != victim) { if (pet->ch->master == victim && IS_AFFECTED(pet->ch, AFF_CHARM) && !IS_SET(pet->ch->act, ACT_WILL_DIE)) { raw_kill(pet->ch); pet_next = mud->f_pet; } } } if (victim->poison) { POISON_DATA *pd; while ((pd = victim->poison) != NULL) { victim->poison = victim->poison->next; FREEMEM( pd ); } } while (victim->first_affect) { affect_from_char(victim, victim->first_affect); } victim->affected_by = 0; victim->affected2_by = 0; if (!IS_NPC(victim)) { if (victim->pcdata->shadowing) { stop_shadow(victim); } if (victim->pcdata->shadowed_by) { stop_shadow(victim->pcdata->shadowed_by); } if (victim->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { arena_death(victim); } else { player_death(victim); } pop_call(); return; } make_corpse( victim ); stop_fighting(victim, TRUE); if (IS_AFFECTED(victim, AFF_CHARM) && victim->master && !IS_SET(victim->act, ACT_ELEMENTAL)) { send_to_char("Your pet dies a horrible death.\n\r", victim->master); } junk_mob(victim); if (victim->desc && victim->desc->original) { victim->desc->original->hit -= 50; send_to_char("You suffer from the death of your imp!\n\r", victim); do_return(victim, NULL); } pop_call(); return; } void arena_death( CHAR_DATA *victim ) { push_call("arena_death(%p)",victim); victim->position = POS_RESTING; victim->hit = UMAX( 1, victim->hit ); victim->mana = UMAX( 1, victim->mana ); victim->move = UMAX( 1, victim->move ); stop_fighting(victim, TRUE); char_from_room(victim); char_to_room(victim, ROOM_VNUM_TEMPLE); char_reset(victim); pop_call(); return; } void player_death( CHAR_DATA *victim ) { OBJ_DATA *obj, *obj_next; push_call("player_death(%p)",victim); if (victim->pcdata->death_room == ROOM_VNUM_SCHOOL) { if (victim->in_room->area->low_r_vnum != ROOM_VNUM_SCHOOL) { victim->pcdata->death_room = ROOM_VNUM_TEMPLE; } } check_asn_obj(victim); stop_fighting(victim, TRUE); make_corpse(victim); for (obj = victim->first_carrying ; obj ; obj = obj_next) { obj_next = obj->next_content; if (!IS_SET(obj->extra_flags, ITEM_INVENTORY)) { junk_obj( obj ); } } char_from_room(victim); if (victim->level < 2) { char_to_room(victim, ROOM_VNUM_SCHOOL); } else { char_to_room(victim, victim->pcdata->death_room); } victim->pcdata->recall = victim->in_room->vnum; victim->position = POS_RESTING; victim->hit = UMAX( 1, victim->hit ); victim->mana = UMAX( 1, victim->mana ); victim->move = UMAX( 1, victim->move ); char_reset(victim); save_char_obj(victim, NORMAL_SAVE); pop_call(); return; } void group_gain( CHAR_DATA *ch, CHAR_DATA *victim ) { CHAR_DATA *gch; int xp, cnt, group_level, group_count; push_call("group_gain(%p,%p)",ch,victim); if (IS_AFFECTED(victim, AFF_CHARM)) { pop_call(); return; } if (IS_NPC(victim) && victim->pIndexData->vnum == 9901) /* No Demons */ { pop_call(); return; } morph_update(ch, victim); group_level = group_count = 0; for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (is_same_group(gch, ch)) { if (group_level < reinc_eq_level(gch)) { group_level = reinc_eq_level(gch); } group_count += 1; gch->alignment -= victim->alignment / 50; if (gch->alignment < -1000) { gch->alignment = -1000; } if (gch->alignment > 1000) { gch->alignment = 1000; } } } for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (!is_same_group(gch, ch) || IS_NPC(gch)) { continue; } xp = xp_compute(gch, victim) * reinc_eq_level(gch) / UMAX(1, group_level); xp = xp * 100 / (80 + group_count * 20); if (gch->pcdata->reincarnation > 0) { for (cnt = 0 ; cnt < gch->pcdata->reincarnation ; cnt++) { xp = xp * 2 / 3; } } if (gch->level == 90) { xp /= 2; } if (gch->level > 90) { xp = xp * 2 / 3; } ch_printf(gch, god_table[which_god(gch)].exp_msg, xp); ch_printf(gch, "\n\r"); gain_exp(gch, xp); check_zap(gch, TRUE); } pop_call(); return; } /* Calculate roughly how much experience a character is worth */ int get_exp_worth( CHAR_DATA *ch ) { int exp = 0; push_call("get_exp_worth(%p)",ch); exp += ch->max_hit; exp += get_damnodice(ch) * get_damsizedice(ch) + GET_DAMROLL(ch); pop_call(); return exp; } /* Compute xp for a kill. Edit this function to change xp computations. */ int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim ) { int xp; int spread; push_call("xp_compute(%p,%p)",gch,victim); if (gch->in_room == NULL) { pop_call(); return(0); } if (IS_SET(gch->in_room->room_flags, ROOM_RIP)) { pop_call(); return(0); } if (IS_SET(gch->in_room->room_flags, ROOM_IS_CASTLE)) { pop_call(); return(0); } xp = exp_level(CLASS_MONSTER, victim->level) * (number_range(0, 50) / 100.0 + 0.75); if (!IS_NPC(victim)) { xp = 0; } if (xp < 75) { xp = 75; } if (which_god(gch) != GOD_NEUTRAL) { xp = xp * (100 + gch->pcdata->reincarnation) / 100; } if (gch->desc && gch->desc->mccp) { xp = xp * 11 / 10; } spread = 10 + reinc_eq_level(gch) / 10; if (reinc_eq_level(gch) > victim->level) { xp = xp * spread / (reinc_eq_level(gch) - victim->level + spread); } if (gch->in_room != NULL && gch->in_room->sector_type == SECT_ASTRAL) { xp += (xp * 35 / 100); } if (gch->in_room != NULL && gch->in_room->sector_type == SECT_ETHEREAL) { xp += (xp * 30 / 100); } xp = number_range(xp * 0.75, xp * 1.25); pop_call(); return xp; } void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { CHAR_DATA *fch; OBJ_DATA *wield; char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH], buf3[MAX_INPUT_LENGTH], ch_name[MAX_INPUT_LENGTH]; char youHit[41],hitYou[41]; const char *vs; const char *vp; const char *attack; char punct; int percent; push_call("dam_message(%p,%p,%d,%d)",ch,victim,dam,dt); if (dt == TYPE_NOFIGHT) { pop_call(); return; } percent = 100 * dam / UMAX(1, victim->max_hit); attack = NULL; if ( dam == 0 ) { vs = "miss"; vp = "misses"; } else if ( percent == 0 ) { vs = "tickle"; vp = "tickles"; } else if ( percent <= 2 ) { vs = "scratch"; vp = "scratches"; } else if ( percent <= 4 ) { vs = "graze"; vp = "grazes"; } else if ( percent <= 6 ) { vs = "hit"; vp = "hits"; } else if ( percent <= 9 ) { vs = "injure"; vp = "injures"; } else if ( percent <= 12 ) { vs = "wound"; vp = "wounds"; } else if ( percent <= 15 ) { vs = "maul"; vp = "mauls"; } else if ( percent <= 18 ) { vs = "decimate"; vp = "decimates"; } else if ( percent <= 21 ) { vs = "devastate"; vp = "devastates"; } else if ( percent <= 25 ) { vs = "maim"; vp = "maims"; } else if ( percent <= 29 ) { vs = "MUTILATE"; vp = "MUTILATES"; } else if ( percent <= 33 ) { vs = "DISEMBOWEL"; vp = "DISEMBOWELS"; } else if ( percent <= 37 ) { vs = "* EVISCERATE *"; vp = "* EVISCERATES *"; } else if ( percent <= 41 ) { vs = "** MASSACRE **"; vp = "** MASSACRES **"; } else if ( percent <= 50 ) { vs = "*** DEMOLISH ***"; vp = "*** DEMOLISHES ***"; } else if ( percent <= 60 ) { vs = "**** ANNIHILATE ****"; vp = "**** ANNIHILATES ****"; } else if ( percent <= 70 ) { vs = "!!!! SLAUGHTER !!!!"; vp = "!!!! SLAUGHTERS !!!!"; } else if (percent <= 80 ) { vs = "**** DISMEMBER ****"; vp = "**** DISMEMBERS ****"; } else if (percent <= 90) { vs = "**** *DEBONE* ****"; vp = "**** *DEBONES* ****"; } else { vs = "**** *OBLITERATE* ****"; vp = "**** *OBLITERATES* ****"; } punct = (percent <= 18) ? '.' : '!'; strcpy(hitYou, (dam <= 0) ? "" : get_color_code(victim, COLOR_YOU_ARE_HIT, VT102_BOLD)); strcpy(youHit, (dam <= 0) ? "" : get_color_code(ch, COLOR_YOU_HIT, VT102_BOLD)); str_cpy_max(ch_name, get_name(ch), 64); if (dt == TYPE_HIT) { attack = get_dam_nounce(ch, victim, dt); if (attack[0] != '\0') { sprintf(buf1, "%s's %s %s %s%c", capitalize(ch_name), attack, vp, get_name(victim), punct); if (ch->level > 50 && dam > 0) { sprintf(buf2, "%sYour %s %s %s for %dhp%c", youHit, attack, vp, get_name(victim), dam, punct); } else { sprintf(buf2, "%sYour %s %s %s%c", youHit, attack, vp, get_name(victim), punct); } if (victim->level > 50 && dam > 0) { sprintf(buf3, "%s%s's %s %s you for %dhp%c", hitYou, capitalize(get_name(ch)), attack, vp, dam, punct); } else { sprintf(buf3, "%s%s's %s %s you%c", hitYou, capitalize(get_name(ch)), attack, vp, punct); } } else { sprintf(buf1, "%s %s %s%c", capitalize(ch_name), vp, get_name(victim), punct); if (ch->level > 50 && dam > 0) { sprintf(buf2, "%sYou %s $N for %dhp%c", youHit, vs, dam, punct ); } else { sprintf(buf2, "%sYou %s $N%c", youHit, vs, punct); } if (victim->level > 50 && dam > 0) { sprintf(buf3, "%s%s %s you for %dhp%c", hitYou, capitalize(get_name(ch)), vp, dam, punct); } else { sprintf(buf3, "%s%s %s you%c", hitYou, capitalize(get_name(ch)), vp, punct); } } } else { attack = get_dam_nounce(ch, victim, dt); sprintf(buf1, "%s's %s %s %s%c", capitalize(ch_name), attack, vp, get_name(victim), punct); if (ch->level > 50 && dam > 0) { sprintf( buf2, "%sYour %s %s $N for %dhp%c", youHit,attack,vp,dam,punct ); } else { sprintf( buf2, "%sYour %s %s $N%c", youHit, attack, vp, punct ); } if (victim->level > 50 && dam > 0) { sprintf(buf3, "%s%s's %s %s you for %dhp%c", hitYou, capitalize(get_name(ch)), attack, vp, dam, punct); } else { sprintf(buf3,"%s%s's %s %s you%c", hitYou, capitalize(get_name(ch)), attack, vp, punct); } } /* Spam code for combat - Chaos 12/20/94 */ for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (fch->desc && fch != ch && fch != victim) { if (fch->position > POS_SLEEPING) { bool gch, gvic; gch = is_same_group( ch, fch ); gvic = is_same_group( victim, fch ); if (gch && !gvic) { if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 32)) { ch_printf(fch, "%s\n\r", buf1); } if (dam > 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 16)) { ch_printf(fch, "%s\n\r", buf1); } } else if (!gch && gvic) { if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 128)) { ch_printf(fch, "%s\n\r", buf1); } else if (dam > 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 64)) { ch_printf(fch, "%s%s\n\r", get_color_string(fch,COLOR_PARTY_HIT,VT102_BOLD), buf1); } } else if (!gch && !gvic) { if (dam <= 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 512)) { ch_printf(fch, "%s\n\r", buf1); } if (dam > 0 && !IS_SET(CH(fch->desc)->pcdata->spam, 256)) { ch_printf(fch, "%s\n\r", buf1); } } else { ch_printf(fch, "%s\n\r", buf1); } } } } if (dam == 0) { if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 2)) { if (ch->position > POS_SLEEPING) { act(buf2, ch, NULL, victim, TO_CHAR); } } if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 8)) { if (victim->position > POS_SLEEPING) { act(buf3, ch, NULL, victim, TO_VICT); } } } else { if (ch->desc && !IS_SET(CH(ch->desc)->pcdata->spam, 1)) { if (ch->position > POS_SLEEPING) { act(buf2, ch, NULL, victim, TO_CHAR); } } if (victim->desc && !IS_SET(CH(victim->desc)->pcdata->spam, 4)) { if (victim->position > POS_SLEEPING) { act(buf3, ch, NULL, victim, TO_VICT); } } } if (!IS_NPC(ch) && dt > TYPE_HIT) { if ((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL) { if (!IS_SET(mud->flags, MUD_DUALFLIP)) { wield = get_eq_char( ch, WEAR_WIELD ); } } else { wield = get_eq_char(ch, WEAR_WIELD); } if (wield == NULL || wield->item_type != ITEM_WEAPON) { pop_call(); return; } switch (wield->value[0]) { case WEAPON_TYPE_SWORD: check_improve(ch, gsn_weapon_sword); break; case WEAPON_TYPE_DAGGER: check_improve(ch, gsn_weapon_dagger); break; case WEAPON_TYPE_AXE: check_improve(ch, gsn_weapon_axe); break; case WEAPON_TYPE_MACE: check_improve(ch, gsn_weapon_mace); break; case WEAPON_TYPE_STAFF: check_improve(ch, gsn_weapon_staff); break; case WEAPON_TYPE_WHIP: check_improve(ch, gsn_weapon_whip); break; case WEAPON_TYPE_FLAIL: check_improve(ch, gsn_weapon_flail); break; case WEAPON_TYPE_SPEAR: check_improve(ch, gsn_weapon_spear); break; case WEAPON_TYPE_CLAW: check_improve(ch, gsn_weapon_claw); break; } } pop_call(); return; } int get_body_part( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int type ) { int part, pick, cnt, body; push_call("get_body_part(%p,%p,%p,%p)",ch,victim,dt,type); if (dt != TYPE_HIT) { pop_call(); return -1; } if (IS_NPC(ch) && IS_SET(ch->act, ACT_BODY) && ch->pIndexData->attack_parts && type == 0) { body = ch->pIndexData->attack_parts; } else if (IS_NPC(ch) && IS_SET(ch->act, ACT_BODY) && ch->pIndexData->body_parts && type == 1) { body = ch->pIndexData->body_parts; } else if (!IS_NPC(ch) || IS_SET(ch->act, ACT_RACE)) { body = race_table[ch->race].attack_parts; } else { pop_call(); return -1; } for (cnt = part = 0 ; part < MAX_BODY ; part++) { if (IS_SET(body, 1 << part)) { cnt++; } } pick = number_range(1, cnt); for (cnt = part = 0 ; part < MAX_BODY ; part++) { if (IS_SET(body, 1 << part) && ++cnt == pick) { pop_call(); return part; } } pop_call(); return -1; } /* Scandum 4-6-2003 */ int damage_modify( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam ) { int dam_type = DAM_THRUST; push_call("damage_modify(%p,%p,%p,%p)",ch,victim,dt,dam); if (dt == TYPE_HIT) { body_part_attack = get_body_part(ch, victim, dt, 0); } if (dam <= 0) { pop_call(); return 0; } if (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM)) { if (ch->in_room->sector_type == SECT_ETHEREAL || ch->in_room->sector_type == SECT_ASTRAL) { if (dt != TYPE_HIT && dt != TYPE_UNDEFINED) { dam = 2 * dam / 3; } } } if (!IS_NPC(victim) && dam > 1 && number_percent() < learned(victim, gsn_resilience)) { dam = UMAX(1, UMAX(dam - victim->level / 9, dam / 2)); if (number_bits(2) == 0) { check_improve(victim, gsn_resilience); } } if (IS_AFFECTED(victim, AFF_SANCTUARY)) { if (dam > 1) { dam = dam * 2/3; } } if (is_affected(victim, gsn_black_aura)) { dam = dam * 5/4; } /* Gith Damage +25% astral, +25% ethereall */ if (ch->in_room) { if (ch->in_room->sector_type == SECT_ASTRAL && rspec_req(ch, RSPEC_ASTRAL)) { dam = dam * 5/4; } if (ch->in_room->sector_type == SECT_ETHEREAL && rspec_req(ch, RSPEC_ETHEREAL)) { dam = dam * 5/4; } } if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch)) { dam = dam * 10/11; } if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch)) { dam = dam * 10/11; } if (dt == TYPE_NOFIGHT) { pop_call(); return dam; } if (dt == TYPE_HIT) { if (body_part_attack != -1) { dam_type = body_table[body_part_attack].dam_type; } } else { if (dt == gsn_martial_arts) { dam_type = martial_arts_table[martial_arts_attack].dam_type; } else if (dt == gsn_fisticuffs) { dam_type = fisticuffs_table[fisticuffs_attack].dam_type; } else if (dt == gsn_brawling) { dam_type = brawling_table[brawling_attack].dam_type; } else if (dt >= 0 && dt < MAX_SKILL) { dam_type = skill_table[dt].dam_type; } else if (dt >= TYPE_HIT) { if (dt < TYPE_HIT+sizeof(attack_table)/sizeof(attack_table[0])) { dam_type = attack_table[dt - TYPE_HIT].dam_type; } } else { if (dt != TYPE_UNDEFINED) { bug("damage_modify: bad dt %d.", dt); } } } if (dam <= 0) { dam = 1; } if (dam_type == DAM_NONE) { pop_call(); return dam; } if (dam_type == god_table[which_god(victim)].resistance) { dam = dam * 75 / 100; } if (IS_UNDEAD(victim)) { if (IS_SET(DAM_LIFE|DAM_POISON|DAM_EVIL, dam_type)) { dam = dam * 75 / 100; } } if (IS_SET(race_table[victim->race].res_low, dam_type)) { dam = dam * 90 / 100; } if (IS_SET(race_table[victim->race].res_high, dam_type)) { dam = dam * 80 / 100; } if (IS_SET(race_table[victim->race].vul_low, dam_type)) { dam = dam * 110 / 100; } if (IS_SET(race_table[victim->race].vul_high, dam_type)) { dam = dam * 120 / 100; } if (dam <= 0) { dam = 1; } pop_call(); return dam; } char *get_dam_nounce( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { static char *attack; push_call("get_dam_nounce(%p,%p,%p)",ch,victim,dt); attack = ""; if (dt == TYPE_HIT) { if (body_part_attack != -1) { attack = body_table[body_part_attack].attack; } } else { if (dt == gsn_martial_arts) { attack = martial_arts_table[martial_arts_attack].message; } else if (dt == gsn_fisticuffs) { attack = fisticuffs_table[fisticuffs_attack].message; } else if (dt == gsn_brawling) { attack = brawling_table[brawling_attack].message; } else if (dt == gsn_object_rape) { attack = &mpdamstring[0]; } else if (dt >= 0 && dt < MAX_SKILL) { attack = skill_table[dt].noun_damage; } else if (dt >= TYPE_HIT) { OBJ_DATA *obj; if (IS_SET(mud->flags, MUD_DUALFLIP) && get_eq_char(ch, WEAR_DUAL_WIELD) != NULL) { obj = get_eq_char(ch, WEAR_DUAL_WIELD); } else { obj = get_eq_char(ch, WEAR_WIELD); } if (obj->pIndexData->attack_string[0] != '\0') { attack = obj->pIndexData->attack_string; } else if (dt < TYPE_HIT+sizeof(attack_table)/sizeof(attack_table[0])) { attack = attack_table[dt - TYPE_HIT].message; } } else { if (dt != TYPE_UNDEFINED) { bug("get_dam_nounce: bad dt %d.", dt); } attack = attack_table[0].message; } } pop_call(); return attack; } int get_damnodice( CHAR_DATA *ch) { int dam = 0; push_call("get_damnodice(%p)",ch); if (IS_NPC(ch)) { dam = ch->npcdata->damnodice; } else { if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts)) { if (multi_skill_level(ch, gsn_fisticuffs) >= multi_skill_level(ch, gsn_martial_arts)) { dam = 3 + multi_skill_level(ch, gsn_fisticuffs) * learned(ch, gsn_fisticuffs) / 150; } else { dam = 3 + multi_skill_level(ch, gsn_martial_arts) * learned(ch, gsn_martial_arts) / 150; } if (is_affected(ch, gsn_stone_fist)) { dam += 3 + multi_skill_level(ch, gsn_stone_fist) / 20; } } else { dam = 1; } } pop_call(); return dam; } int get_damsizedice( CHAR_DATA *ch) { int dam = 0; push_call("get_damsizedice(%p)",ch); if (IS_NPC(ch)) { dam = ch->npcdata->damsizedice; } else { if (learned(ch, gsn_fisticuffs) || learned(ch, gsn_martial_arts)) { dam = 2; } else { dam = 4 + ch->level * 2 / 3; if (is_affected(ch, gsn_stone_fist)) { dam += 10 + multi_skill_level(ch, gsn_stone_fist) / 10; } } } pop_call(); return dam; } /* Disarm a creature. Caller must check for successful attack. */ void disarm( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj; push_call("disarm(%p,%p)",ch,victim); if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL) { pop_call(); return; } if (get_eq_char(victim, WEAR_DUAL_WIELD) != NULL && number_bits(1) == 0) { obj = get_eq_char(victim, WEAR_DUAL_WIELD); } if (IS_SET(obj->extra_flags,ITEM_INVENTORY)) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } if (!can_see_obj(ch, obj)) { if (number_percent() > 33) { send_to_char( "You failed.\n\r", ch); pop_call(); return; } } if (get_eq_char(ch, WEAR_WIELD) == NULL && number_bits(1) == 0) { send_to_char( "You failed.\n\r", ch); pop_call(); return; } if (IS_SET(ch->attack, ATTACK_DISARM)) { pop_call(); return; } else { SET_BIT(ch->attack, ATTACK_DISARM); } if (number_bits(1) == 0 && is_affected(victim, gsn_stone_fist)) { act( "$n tries to disarm you, but your stone fist's grasp is unbreakable.", ch, NULL, victim, TO_VICT); act( "You try to disarm $N, but $S stone fist's grasp is unbreakable.", ch, NULL, victim, TO_CHAR); pop_call(); return; } act( "$n disarms you!", ch, NULL, victim, TO_VICT ); act( "You disarm $N!", ch, NULL, victim, TO_CHAR ); act( "$n disarms $N!", ch, NULL, victim, TO_NOTVICT ); if (!IS_NPC(victim) && learned(victim, gsn_rearm) > number_percent()) { if (can_see_in_room(victim, victim->in_room) && !IS_AFFECTED(victim, AFF_BLIND)) { act( "You rearm yourself!!!", ch, NULL, victim, TO_VICT ); act( "$N rearms $Mself!!!", ch, NULL, victim, TO_CHAR ); act( "$N rearms $Mself!!!", ch, NULL, victim, TO_NOTVICT ); check_improve(victim, gsn_rearm); pop_call(); return; } } unequip_char(victim, obj); pop_call(); return; } void do_cripple( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; push_call("do_cripple(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_cripple) == -1) { send_to_char( "You better leave the street fighting to the marauders.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); pop_call(); return; } wait_state(ch, skill_table[gsn_trip].beats); if (!IS_AFFECTED(ch, AFF_TRUESIGHT) && IS_AFFECTED(victim, AFF2_MIRROR_IMAGE)) { damage(ch, victim, 0, gsn_cripple); } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_cripple)) { ch_printf(ch, "%s evades your vicious kick.\n\r", capitalize(get_name(victim))); pop_call(); return; } act( "$n cripples you with a well aimed kick!", ch, NULL, victim, TO_VICT ); act( "You cripple $N with a well aimed kick!", ch, NULL, victim, TO_CHAR ); act( "$n cripples $N with a well aimed kick!", ch, NULL, victim, TO_NOTVICT ); check_improve(ch, gsn_cripple); af.type = gsn_cripple; af.duration = number_range(1,2); af.bitvector = 0; if (IS_NPC(victim)) { af.modifier = number_range(5, ch->level/5); af.location = APPLY_AC; } else { af.modifier = -1 * number_range(1, ch->level/20); af.location = APPLY_DEX; } affect_join( victim, &af ); victim->speed = UMIN(victim->speed, get_max_speed(victim)); pop_call(); return; } /* Trip, player version */ void do_trip( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char text2[MAX_STRING_LENGTH]; push_call("do_trip(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_trip) == -1) { send_to_char( "You better leave the tripping to the street fighters.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); pop_call(); return; } wait_state(ch, skill_table[gsn_trip].beats); if (!IS_AFFECTED(ch, AFF_TRUESIGHT) && IS_AFFECTED(victim, AFF2_MIRROR_IMAGE)) { damage(ch, victim, 0, gsn_trip); } if (CAN_FLY(victim)) { sprintf(text2,"%s flies over your outstretched leg.\n\r", capitalize(get_name(victim))); send_to_char(text2, ch); pop_call(); return; } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_trip)) { sprintf(text2,"%s jumps over your outstretched leg.\n\r", capitalize(get_name(victim))); send_to_char(text2, ch); pop_call(); return; } act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT ); act( "You trip $N and $E goes down!", ch, NULL, victim, TO_CHAR ); act( "$n trips $N and $E goes down!", ch, NULL, victim, TO_NOTVICT ); check_improve(ch, gsn_trip); if (!check_tumble(NULL, victim)) { victim->position = POS_RESTING; wait_state(victim, skill_table[gsn_trip].beats / 2); } pop_call(); return; } /* Trip, mob version */ void trip( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("trip(%p,%p)",ch,victim); if (IS_SET(ch->attack, ATTACK_TRIP)) { pop_call(); return; } else { SET_BIT(ch->attack, ATTACK_TRIP); } if (victim->position <= POS_RESTING) { pop_call(); return; } if (CAN_FLY(victim)) { ch_printf(ch, "%s flies over your outstretched leg.\n\r", capitalize(get_name(victim))); pop_call(); return; } act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT ); act( "You trip $N and $E goes down!", ch, NULL, victim, TO_CHAR ); act( "$n trips $N and $E goes down!", ch, NULL, victim, TO_NOTVICT ); if (!check_tumble(NULL, victim)) { victim->position = POS_RESTING; } pop_call(); return; } void do_kill( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH]; CHAR_DATA *victim; bool found; push_call("do_kill(%p,%p)",ch,argument); if (!IS_NPC(ch)) { ch->pcdata->just_died_ctr = 0; } found = FALSE; victim = NULL; one_argument(argument, arg); if (argument[0] == '\0') { if (is_safe(ch, NULL)) { pop_call(); return; } for (victim = ch->in_room->first_person ; victim != NULL ; victim = victim->next_in_room) { if (IS_NPC(victim) && ch != victim && ch->level <= victim->level-(ch->level*2+10)) { if (can_see(ch,victim)) { sprintf(buf, "%s doesn't think you should fight in here.\n\r", capitalize(victim->short_descr)); send_to_char( buf, ch); pop_call(); return; } } } for (victim = ch->in_room->first_person ; found == FALSE && victim != NULL ; victim = victim->next_in_room) { if (can_see(ch, victim) && !IS_AFFECTED(victim, AFF_CHARM) && IS_NPC(victim) && ch != victim && !is_same_group(ch,victim)) { found = TRUE; break; } } if (!found) { send_to_char( "You cannot see anyone you can attack.\n\r", ch); pop_call(); return; } } if (!found) { if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } } if (victim == ch) { send_to_char( "You hit yourself. Ouch!\n\r", ch ); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } if ( ch->position == POS_FIGHTING ) { if (who_fighting(ch) == victim || IS_NPC(ch) || number_percent() > learned(ch, gsn_attack)) { send_to_char( "You do the best you can!\n\r", ch); pop_call(); return; } else { stop_fighting(ch, FALSE); check_improve(ch, gsn_attack); } } if (!IS_NPC(ch) && ch->pcdata->auto_flags == AUTO_QUICK && ch->hit > ch->pcdata->wimpy && ch->wait == 0) { int sn; bool ms = FALSE; if (!str_prefix("mass ", ch->pcdata->auto_command)) { ms = TRUE; sn = skill_lookup(&ch->pcdata->auto_command[5]); } else { sn = skill_lookup(ch->pcdata->auto_command); } if (sn != -1 && is_spell(sn) && ch->mana >= 3 * get_mana(ch, sn)) { sprintf(buf, "'%s'", skill_table[sn].name); set_fighting(ch,victim); set_fighting(victim,ch); if (ms) { do_mass(ch, buf); } else { do_cast(ch, buf); } pop_call(); return; } } wait_state(ch, PULSE_VIOLENCE/2); multi_hit(ch, victim, TYPE_UNDEFINED); pop_call(); return; } void do_murde( CHAR_DATA *ch, char *argument ) { push_call("do_murde(%p,%p)",ch,argument); send_to_char( "If you want to MURDER, spell it out.\n\r", ch ); pop_call(); return; } void add_to_victory_list( CHAR_DATA *ch, CHAR_DATA *victim) { int i; char buf[MAX_STRING_LENGTH]; push_call("add_to_victory_list(%p,%p)",ch,victim); for (i = 1 ; i < VICTORY_LIST_SIZE ; i++) { STRFREE(victory_list[i-1]); victory_list[i-1] = STRALLOC(victory_list[i]); } sprintf(buf, "Z%12s (%2dx Level %2d) %12s (%2dx Level %2d) %s", ch->name, ch->pcdata->reincarnation, ch->level, victim->name, victim->pcdata->reincarnation, victim->level, get_time_string(mud->current_time)); RESTRING(victory_list[i-1], buf); save_victors(); pop_call(); return; } void do_murder( CHAR_DATA *ch, char *argument ) { char buf[MAX_INPUT_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; push_call("do_murder(%p,%p)",ch,argument); one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Murder whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They aren't here.\n\r", ch); pop_call(); return; } if (victim == ch) { send_to_char( "You hit yourself. Ouch!\n\r", ch ); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if (IS_NPC(ch) || IS_NPC(victim)) { send_to_char( "You may not murder them.\n\r", ch ); pop_call(); return; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { send_to_char("Use kill instead.\n\r", ch); pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You do the best you can!\n\r", ch ); pop_call(); return; } if (!can_attack (ch, victim) ) { send_to_char( "You may not murder that person.\n\r", ch); pop_call(); return; } if (victim->pcdata->just_died_ctr > 0) { send_to_char("That person is currently protected by their god.\n\r", ch); pop_call(); return; } if (victim->fighting != NULL) { send_to_char( "You may not murder that person, at the moment.\n\r", ch); pop_call(); return; } if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF)) { if (victim->hit < victim->max_hit / 5) { send_to_char( "It would be dishonorable to murder someone so badly injured.\n\r", ch); pop_call(); return; } if (ch->pcdata->last_connect + 120 > mud->current_time) { ch_printf(ch, "You must wait %d seconds before you can murder anyone.\n\r", ch->pcdata->last_connect + 120 - mud->current_time); pop_call(); return; } } if (!IS_NPC(victim ) && victim->pcdata->corpse != NULL) { ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim)); pop_call(); return; } /* Code for total and max pvnum attacks - Chaos 5/6/99 */ if (!check_add_attack(ch, victim)) { ch_printf(ch, "%s has been attacked too many times.\n\r", get_name(victim)); pop_call(); return; } sprintf(buf, "%s", get_name(ch)); do_battle("%s battles 'Help! I am being attacked by %s!'", get_name(victim), buf); check_killer( ch, victim ); if (IS_AFFECTED(victim, AFF2_HAS_FLASH)) { if (number_percent() < learned(victim, gsn_flash_powder)/3) { AFFECT_DATA af; int attempt; ROOM_INDEX_DATA *was_in; REMOVE_BIT(victim->affected2_by, 0-AFF2_HAS_FLASH); act( "$n throws some powder onto the ground and there is a bright flash!", victim, NULL, NULL, TO_ROOM ); act( "You throw some powder onto the ground and there is a bright flash!", victim, NULL, ch, TO_CHAR ); if (!IS_AFFECTED(ch, AFF_TRUESIGHT)) { af.type = gsn_flash_powder; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_BLIND; af.location = APPLY_HITROLL; af.duration = 0; af.modifier = -6; affect_to_char(ch, &af); } else { act( "$N is unaffected by the bright flash!", ch, NULL, victim, TO_VICT ); act( "You ignore the effects of the flash.", ch, NULL, victim, TO_CHAR ); } was_in = victim->in_room; for (attempt = 0 ; attempt < 6 ; attempt++) { int door; door = number_door(); if (!is_valid_exit(victim, was_in, number_door())) { continue; } move_char(victim, door, TRUE); if (victim->in_room == was_in) { continue; } break; } if (victim->in_room != was_in) { pop_call(); return; } } else { send_to_char( "You fumble the flash powder and it spills everywhere!\n\r", victim); REMOVE_BIT(victim->affected2_by, 0-AFF2_HAS_FLASH); } } ch->pcdata->just_died_ctr = 0; clear_attack_list(ch); log_printf("ROOM [%u] MURDER %s attacking %s", ch->in_room->vnum, ch->name, victim->name); if (ch->pcdata->auto_flags == AUTO_QUICK && ch->hit > ch->pcdata->wimpy && ch->wait == 0) { int sn; bool ms = FALSE; if (!str_prefix("mass ", ch->pcdata->auto_command)) { ms = TRUE; sn = skill_lookup(&ch->pcdata->auto_command[5]); } else { sn = skill_lookup(ch->pcdata->auto_command); } if (sn != -1 && is_spell(sn) && ch->mana >= 3 * get_mana(ch, sn)) { sprintf(buf, "'%s'", skill_table[sn].name); set_fighting(ch,victim); set_fighting(victim,ch); if (ms) { do_mass(ch, buf); } else { do_cast(ch, buf); } pop_call(); return; } } /* bs chance based on multi_skill_level - Scandum 12/02/02 */ if (number_range(50, 99) < 100 * victim->hit / UMAX(1, victim->max_hit) && check_hit(ch, victim, GET_HITROLL(ch), gsn_backstab) && number_percent() < 100*multi_skill_level(ch, gsn_backstab)/ch->level) { OBJ_DATA * obj; if ((obj = get_eq_char(ch,WEAR_WIELD)) != NULL && (obj->value[3]==11 || obj->value[3]==2)) { one_hit(ch, victim, gsn_backstab); wait_state(ch, skill_table[gsn_backstab].beats); } pop_call(); return; } wait_state(ch, PULSE_VIOLENCE/2); multi_hit( ch, victim, TYPE_UNDEFINED ); pop_call(); return; } void backstab( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("backstab(%p,%p)",ch,victim); /* Anatomy skill - Martin 4/8/98 */ if (IS_NPC(victim) && !IS_NPC(ch) && victim->level < (ch->level-10) && number_percent() < learned(ch, gsn_anatomy)/12) { if (number_bits(1) == 0) { act( "$n thrusts $p into $N's heart.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_ROOM); act( "You thrust $p into $N's heart.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_CHAR); } else { act( "$n slits $N's throat with $p.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_ROOM); act( "You slit $N's throat with $p.", ch, get_eq_char( ch, WEAR_WIELD), victim, TO_CHAR); } check_improve(ch, gsn_anatomy); one_hit( ch, victim, gsn_anatomy ); pop_call(); return; } one_hit( ch, victim, gsn_backstab ); pop_call(); return; } void do_backstab( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; push_call("do_backstab(%p,%p)",ch,argument); one_argument( argument, arg ); if (!IS_NPC(ch) && multi(ch, gsn_backstab) == -1) { send_to_char("You are not that practiced a cut-throat.\n\r", ch ); pop_call(); return; } if (argument[0] == '\0') { for (victim = ch->in_room->first_person ; victim ; victim = victim->next_in_room) { if (IS_NPC(victim) && ch != victim && ch->level <= victim->level-(ch->level*2+10)) { if (can_see(ch, victim)) { ch_printf(ch, "%s doesn't think you should fight in here.\n\r", capitalize(victim->short_descr)); pop_call(); return; } } } for (victim = ch->in_room->first_person ; victim ; victim = victim->next_in_room) { if (can_see(ch, victim) && !IS_AFFECTED(victim, AFF_CHARM) && IS_NPC(victim) && ch != victim && !is_same_group(ch,victim)) { break; } } if (victim == NULL) { send_to_char( "You cannot see anyone you can backstab.\n\r", ch); pop_call(); return; } } else { if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } } if (victim == ch) { send_to_char( "How can you sneak up on yourself?\n\r", ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } if (!IS_NPC(ch) && !IS_NPC(victim)) { if (ch->in_room->area->low_r_vnum != ROOM_VNUM_ARENA) { send_to_char( "You may not backstab another player.\n\r", ch); pop_call(); return; } } if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL || (obj->value[3] != 11 && obj->value[3] != 2)) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); pop_call(); return; } if (victim->fighting != NULL) { send_to_char( "You can't backstab a fighting person.\n\r", ch ); pop_call(); return; } if (victim->hit < victim->max_hit/2) { act( "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } wait_state(ch, skill_table[gsn_backstab].beats); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_backstab) || number_range(50, 100) > 100 * victim->hit / UMAX(1, victim->max_hit)) { damage( ch, victim, 0, gsn_backstab); pop_call(); return; } backstab(ch,victim); pop_call(); return; } void do_flee( CHAR_DATA *ch, char *argument ) { ROOM_INDEX_DATA *was_in = NULL; ROOM_INDEX_DATA *now_in = NULL; CHAR_DATA *victim = NULL; CHAR_DATA *fch = NULL; EXIT_DATA *pexit = NULL; int dir, attempt, exp, hunt_door, hunt_chance; int door, door_count; bool valid_exits[6]={FALSE,FALSE,FALSE,FALSE,FALSE,FALSE}; char buf[MAX_INPUT_LENGTH]; push_call("do_flee(%p,%p)",ch,argument); /* Check berserk and position for link lost players - Scandum 21-08-2002 */ if (IS_AFFECTED(ch, AFF2_BERSERK)) { send_to_char( "You are berserk! Kill! Kill! Kill!\n\r", ch ); pop_call(); return; } if (ch->position < POS_FIGHTING) { send_to_char("Get up first!.\n\r", ch); pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char("You aren't fighting anyone.\n\r", ch); pop_call(); return; } was_in = ch->in_room; now_in = ch->in_room; dir = -1; if (argument[0] && number_percent() < learned(ch, gsn_withdraw)) { dir = direction_door(argument); } if (IS_SET(ch->in_room->room_flags, ROOM_SMOKE) && number_bits(2) && !IS_AFFECTED(ch, AFF_TRUESIGHT)) { send_to_char( "You blunder around and get lost in the smoke!\n\r", ch); if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE)) { wait_state(ch, PULSE_VIOLENCE / 4); } else { wait_state(ch, PULSE_VIOLENCE / 8); } pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_ICE) && !CAN_FLY(ch) && which_god(ch) != GOD_ULMO) { if (number_bits(2) == 0 && number_percent() > get_curr_dex(ch)) { switch (number_bits(1)) { case 0: act("You try to flee but your feet slip on the icy surface.", ch, NULL, NULL, TO_CHAR); act("$n tries to flee but $s feet slip on the icy surface.", ch, NULL, NULL, TO_ROOM); break; case 1: act("Your feet slip as you try to flee and you crash to the ice.", ch, NULL, NULL, TO_CHAR); act("$n's feet slip as $e tries to flee and $e crashes to the ice.", ch, NULL, NULL, TO_ROOM); break; } wait_state(ch, PULSE_VIOLENCE / 4); ch->position = POS_SITTING; pop_call(); return; } } if (is_affected(ch, gsn_cripple) && number_bits(1) == 0) { act("You try to limp away from combat, but $N does not let you get very far.", ch, NULL, victim, TO_CHAR); act("$n tries to limp away from combat, but you do not let $m get very far.", ch, NULL, victim, TO_VICT); act("$n tries to limp away from combat, but $N does not let $m get very far.", ch, NULL, victim, TO_NOTVICT); if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE)) { wait_state( ch, PULSE_VIOLENCE/2 ); } else { wait_state( ch, PULSE_VIOLENCE/4 ); } pop_call(); return; } for (door = 0, door_count = 0 ; door < 6 ; door++) { if (cspec_req(ch, CSPEC_QUICK_FLEE) || dir == door) { if (!can_move_char(ch, door)) { continue; } } else { if ((pexit = get_exit(was_in->vnum, door)) == NULL) { continue; } if (!can_use_exit(ch, pexit)) { continue; } if (IS_SET(pexit->exit_info, EX_CLOSED)) { continue; } if (IS_NPC(ch)) { if (IS_SET(room_index[pexit->to_room]->room_flags, ROOM_NO_MOB)) { continue; } if (room_index[pexit->to_room]->area != ch->in_room->area) { continue; } if (IS_SET(ch->act, ACT_STAY_SECTOR) && ch->reset && room_index[pexit->to_room]->sector_type != room_index[ch->reset->arg3]->sector_type) { continue; } } } valid_exits[door] = TRUE; door_count++; } if (door_count == 0) { send_to_char("Ah!!! You can't find an exit!\n\r",ch); if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE)) { wait_state( ch, PULSE_VIOLENCE/4 ); } else { wait_state( ch, PULSE_VIOLENCE/8 ); } pop_call(); return; } if (!can_see_in_room(ch, now_in) || IS_AFFECTED(ch, AFF_BLIND) || IS_NPC(ch) || (dir == -1 && !cspec_req(ch, CSPEC_QUICK_FLEE) && !rspec_req(ch,RSPEC_EASY_FLEE) && !IS_OUTSIDE(ch))) { for (attempt = 0 ; attempt < 6; attempt++) { door = number_door(); if (valid_exits[door] != TRUE) { continue; } move_char(ch, door, TRUE); now_in = ch->in_room; break; } } else if (was_in == now_in) { if (dir == -1) { door = number_door(); } else { door = dir; } while(valid_exits[door] != TRUE) { door++; if (door > 5) { door = 0; } } move_char(ch, door, TRUE); now_in = ch->in_room; } if (was_in != now_in) { char_from_room( ch ); char_to_room( ch, was_in->vnum ); act( "$n flees head over heels!", ch, NULL, NULL, TO_ROOM ); char_from_room( ch ); char_to_room( ch, now_in->vnum ); act( "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM); } if (was_in != now_in) { if (IS_NPC(ch) || ch->level >= 95) { send_to_char( "You flee head over heels from combat.\n\r", ch); } else { if (rspec_req(ch,CSPEC_QUICK_FLEE)) { exp = 25+ch->level*ch->level*1.5; } else { exp = 50+ch->level*ch->level*2.5; } sprintf( buf, "You flee head over heels from combat, losing %d experience.\n\r", exp); send_to_char( buf, ch); gain_exp( ch, 0-exp); } check_improve(ch, gsn_withdraw); } /* Hunt skill - Chaos 11/19/93 */ if (was_in != now_in) { for (fch = was_in->first_person ; fch ; fch = fch->next_in_room) { if (IS_NPC(fch)) { if (was_in->area != now_in->area) { continue; } if (IS_SET(ch->act, ACT_STAY_SECTOR) && ch->reset && now_in->sector_type != room_index[ch->reset->arg3]->sector_type) { continue; } } if (fch->fighting && fch->fighting->who == ch && IS_AFFECTED(fch, AFF_HUNT) && !IS_AFFECTED(fch, AFF_CHARM)) { hunt_chance = learned(fch, gsn_hunt) / 4; hunt_chance += learned(fch, gsn_greater_hunt) / 5; hunt_chance += 33 * multi_skill_level(fch, gsn_hunt) / fch->level; hunt_chance -= can_hear(fch, ch) ? 0 : 10; hunt_chance -= can_see(fch, ch) ? 0 : 10; hunt_chance -= rspec_req(ch, RSPEC_EASY_FLEE) ? 10 : 0; hunt_chance += fch->speed * 10; hunt_chance -= ch->speed * 10; hunt_chance -= learned(ch, gsn_withdraw) / 10; if (!IS_NPC(fch) && IS_SET(fch->act, PLR_WIZTIME)) { ch_printf_color(fch, "{078}(do_flee() hunt_chance: %d)\n\r", hunt_chance); } if (number_percent() < hunt_chance) { if (IS_AFFECTED(fch, AFF_BLIND)) /* added a harder hunt for blinded hunters, Manwe */ { hunt_door = number_door(); if (fch->in_room->exit[hunt_door] != 0) { pexit = fch->in_room->exit[hunt_door]; if (room_index[pexit->to_room] == NULL) { send_to_char("You try to hunt them down, but you blunder into a wall.\n\r",fch); act("$n starts hunting, but blunders into a wall!",fch, NULL, NULL, TO_ROOM); } else if (IS_SET(pexit->exit_info, EX_CLOSED) && !IS_AFFECTED(fch, AFF_PASS_DOOR) && !rspec_req(ch,RSPEC_PASS_DOOR)) { send_to_char("You try to hunt them down, but you smash into a closed door.\n\r",fch); act("$n starts hunting, but smashes into a closed door!",fch, NULL, NULL, TO_ROOM); } else if (IS_SET(pexit->exit_info, EX_CLOSED) && IS_SET(pexit->exit_info, EX_PASSPROOF)) { send_to_char("You try to hunt them down, but you smash into a closed door.\n\r",fch); act("$n starts hunting, but smashes into a closed door!",fch, NULL, NULL, TO_ROOM); } else { char_from_room(fch); char_to_room(fch, pexit->to_room); if (fch->in_room == ch->in_room) { send_to_char("You try to hunt them down, and now you SMELL them...\n\r",fch); send_to_char("You have been hunted down.\n\r",ch); stop_fighting(ch,TRUE); stop_fighting(fch,TRUE); set_fighting(ch,fch); set_fighting(fch,ch); pop_call(); return; } else { send_to_char("You tried to hunt them down, but now you're lost.\n\r",fch); act("$n looks as if they're hunting, but looks somehow lost.",fch, NULL, NULL, TO_ROOM); } } } else { send_to_char("You try to hunt them down, but you blunder into a wall.\n\r",fch); act("$n starts hunting, but blunders into a wall!",fch, NULL, NULL, TO_ROOM); } } else { send_to_char("You hunt them down!\n\r", fch); check_improve(fch, gsn_hunt); check_improve(fch, gsn_greater_hunt); char_from_room( fch ); char_to_room( fch, ch->in_room->vnum ); send_to_char("You have been hunted down.\n\r", ch); stop_fighting( ch, TRUE); stop_fighting( fch, TRUE); set_fighting( ch, fch); set_fighting( fch, ch); pop_call(); return; } } } } } if (was_in == now_in && !IS_SET(now_in->room_flags, ROOM_SAFE)) { if (IS_NPC(ch) || ch->level >= 95) { send_to_char("You failed!\n\r", ch); } else { exp = 20+ch->level*ch->level*1; sprintf( buf, "You failed! You lose %d exp.\n\r", exp); send_to_char( buf, ch); gain_exp( ch, -exp); } if (!IS_NPC(ch) && !rspec_req(ch, RSPEC_EASY_FLEE)) { wait_state( ch, PULSE_VIOLENCE/4 ); } else { wait_state( ch, PULSE_VIOLENCE/8 ); } pop_call(); return; } if (which_god(ch) != GOD_NEUTRAL && which_god(victim) != GOD_NEUTRAL) { if (which_god(ch) != which_god(victim) && ch->in_room->area->low_r_vnum != ROOM_VNUM_ARENA) { sprintf(buf, "%s", get_name(ch)); if (ch->desc == NULL) { do_battle("%s's arcane connection to the realm has been severed like a coward while in battle with %s!", buf, get_name(victim)); } else { do_battle("%s has fled like a coward from the wrath of %s!", buf, get_name(victim)); } } stop_fighting(ch, TRUE); pop_call(); return; } pop_call(); return; } void do_rescue( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *fch; push_call("do_rescue(%p,%p)",ch,argument); one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Rescue whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if (victim == ch) { send_to_char( "What about fleeing instead?\n\r", ch ); pop_call(); return; } if (!IS_NPC(ch) && IS_NPC(victim) && victim->master!=ch) { send_to_char( "They do not need your help.\n\r", ch ); pop_call(); return; } if ( !ch->fighting ) { send_to_char( "Too late.\n\r", ch ); pop_call(); return; } for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room) { if (fch->fighting && fch->fighting->who == victim) { break; } } if (fch == NULL) { send_to_char( "That person isn't under attack.\n\r", ch ); pop_call(); return; } if (multi(ch, gsn_rescue)==-1 && !IS_NPC(ch)) { send_to_char( "You cannot rescue.\n\r", ch ); pop_call(); return; } wait_state( ch, skill_table[gsn_rescue].beats ); if (number_percent() > learned(ch, gsn_rescue) || !is_same_group(ch, victim) || !IS_NPC(fch)) { send_to_char( "You failed to rescue.\n\r", ch ); ch_printf(victim, "%s tried to rescue you, but failed!\n\r", get_name(ch)); pop_call(); return; } act( "You rescue $N!", ch, NULL, victim, TO_CHAR ); act( "$n rescues you!", ch, NULL, victim, TO_VICT ); act( "$n rescues $N!", ch, NULL, victim, TO_NOTVICT ); check_improve(ch, gsn_rescue); for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room) { if (fch->fighting && fch->fighting->who == victim) { fch->fighting->who = ch; break; } } pop_call(); return; } void do_head_butt( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; push_call("do_headbutt(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_head_butt) == -1) { send_to_char( "You better leave the fisticuffs to the shamans.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch); pop_call(); return; } wait_state( ch, skill_table[gsn_head_butt].beats ); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_head_butt)) { damage( ch, victim, 0, gsn_head_butt ); pop_call(); return; } else { int dam = 5 + GET_DAMROLL(ch); if (IS_NPC(ch)) { dam += number_range(1, ch->level*2); } else { dam += number_range(multi_skill_level(ch, gsn_head_butt)/2, multi_skill_level(ch, gsn_head_butt)*2); } damage(ch, victim, dam, gsn_head_butt); check_improve(ch, gsn_head_butt); } pop_call(); return; } void do_kick( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; push_call("do_kick(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_kick) == -1) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch); pop_call(); return; } wait_state( ch, skill_table[gsn_kick].beats ); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_kick)) { damage( ch, victim, 0, gsn_kick ); pop_call(); return; } else { int dam = 5 + GET_DAMROLL(ch); if (IS_NPC(ch)) { dam += number_range(1, ch->level*2); } else { dam += number_range(multi_skill_level(ch, gsn_kick), multi_skill_level(ch, gsn_kick)*4/3); } damage(ch, victim, dam, gsn_kick); check_improve(ch, gsn_kick); } pop_call(); return; } void do_bash( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; push_call("do_bash(%p,%p)",ch,argument); if (get_eq_char(ch, WEAR_SHIELD) == NULL) { send_to_char("You cannot bash without a shield.\n\r", ch ); pop_call(); return; } if (learned(ch, gsn_bash) == 0) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); pop_call(); return; } wait_state(ch, skill_table[gsn_bash].beats); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_bash)) { damage( ch, victim, 0, gsn_bash ); pop_call(); return; } else { int dam = 10 + GET_DAMROLL(ch); if (IS_NPC(ch)) { dam += number_range(1, ch->level*3); } else { dam += number_range(multi_skill_level(ch, gsn_bash), multi_skill_level(ch, gsn_bash)*2); } if (IS_AFFECTED(ch, AFF_TRUESIGHT) || !IS_AFFECTED(victim, AFF2_MIRROR_IMAGE)) { if (number_bits(2) == 0) { act( "$n sends you sprawling with $s powerful bash!", ch, NULL, victim, TO_VICT ); act( "You send $N sprawling with your powerful bash!", ch, NULL, victim, TO_CHAR ); act( "$n sends $N sprawling with $s powerful bash!", ch, NULL, victim, TO_NOTVICT); wait_state(victim, skill_table[gsn_bash].beats/2); victim->position = POS_RESTING; } } damage(ch, victim, dam, gsn_bash); check_improve(ch, gsn_bash); } pop_call(); return; } void do_whirl( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim, *victim_next; push_call("do_whirl(%p,%p)",ch,argument); if (!IS_NPC(ch) && which_god(ch) != GOD_MANWE) { send_to_char( "You better leave the airial fighting to the Manwe followers.\n\r", ch); pop_call(); return; } if (!IS_NPC(ch) && multi(ch, gsn_whirl) == -1) { send_to_char( "You better leave the martial arts to the fighters.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } wait_state(ch, skill_table[gsn_whirl].beats); act("You spin around your pole in a whirlwind of movement!", ch, NULL, NULL, TO_CHAR); act("$n spins around $s pole in a whirlwind of movement!", ch, NULL, NULL, TO_ROOM); for (victim = ch->in_room->first_person ; victim ; victim = victim_next) { victim_next = victim->next_in_room; if (can_mass_attack(ch, victim)) { if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_whirl)) { damage( ch, victim, 0, gsn_whirl); pop_call(); return; } else { int dam = GET_DAMROLL(ch); if (IS_NPC(ch)) { dam += number_range(1, ch->level*2); } else { dam += number_range(1, multi_skill_level(ch, gsn_whirl)*7/3); } damage(ch, victim, dam, gsn_whirl); check_improve(ch, gsn_whirl); } } } pop_call(); return; } void do_acupunch(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; int level, stun, dmgL, dmgH; push_call("do_acupunch(%p,%p)",ch,argument); if (is_safe(ch, NULL)) { pop_call(); return; } if (!IS_NPC(ch) && multi(ch,gsn_acupunch) == -1) { send_to_char("Don't try this at home!!!\n\r",ch); pop_call(); return; } if (get_eq_char(ch, WEAR_WIELD) != NULL) { send_to_char("You cannot punch while wielding a weapon.\n\r", ch); pop_call(); return; } if (IS_NPC(ch)) { level = ch->level; } else { level = multi_skill_level(ch, gsn_acupunch); } if ((victim = who_fighting(ch)) == NULL) { send_to_char("You aren't fighting anyone.\n\r",ch); pop_call(); return; } wait_state(ch, skill_table[gsn_acupunch].beats); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_acupunch)) { damage(ch,victim,0,gsn_acupunch); pop_call(); return; } dmgL = level / 2; switch (number_range(1, 9)) { default: dmgH = level * 2; stun = 0; break; case 1: dmgH = level * 2; stun = 1; break; case 2: dmgH = level * 3; stun = 2; break; case 3: dmgH = level * 4; stun = 3; break; } damage(ch, victim, GET_DAMROLL(ch)+number_range(dmgL,dmgH), gsn_acupunch); if (ch->in_room != victim->in_room) { pop_call(); return; } if (stun) { act("$n stuns you and you go down!", ch, NULL, victim, TO_VICT); act("$n stuns $N and $E goes down!", ch, NULL, victim, TO_NOTVICT); act("You stun $N and $E goes down!", ch, NULL, victim, TO_CHAR); } switch (stun) { case 1: victim->position = POS_SITTING; break; case 2: victim->position = POS_RESTING; wait_state(victim, skill_table[gsn_acupunch].beats / 3); break; case 3: victim->position = POS_SLEEPING; wait_state(victim,(skill_table[gsn_acupunch].beats) / 2); break; } check_improve(ch, gsn_acupunch); pop_call(); return; } void fisticuffs( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) { int level; push_call("fisticuffs(%p,%p,%p)",ch,victim,dam); level = multi_skill_level(ch, gsn_fisticuffs); if (number_bits(1) == 0) { fisticuffs_attack = number_range(level/30, level/17); } else { fisticuffs_attack = number_range(0,5); } fisticuffs_attack = URANGE(0, fisticuffs_attack, 5); switch (fisticuffs_attack) { case 0: dam = (int) dam * 1.1; break; case 1: dam = (int) dam * 1.2; break; case 2: dam = (int) dam * 1.3; break; case 3: dam = (int) dam * 1.4; break; case 4: dam = (int) dam * 1.5; break; case 5: dam = (int) dam * 1.6; break; } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_fisticuffs)) { damage(ch, victim, 0, gsn_fisticuffs); } else { damage(ch, victim, dam, gsn_fisticuffs); check_improve(ch, gsn_fisticuffs); } pop_call(); return; } void martial_arts( CHAR_DATA *ch, CHAR_DATA *victim, int dam) { int level; push_call("martial_arts_attack(%p,%p,%p)",ch,victim,dam); level = multi_skill_level(ch, gsn_martial_arts); if (number_bits(1) == 0) { martial_arts_attack = number_range(level/16, level/8); } else { martial_arts_attack = number_range(0,11); } martial_arts_attack = URANGE(0, martial_arts_attack, 11); switch (martial_arts_attack) { case 0: dam = (int) dam * 1.00; break; case 1: dam = (int) dam * 1.05; break; case 2: dam = (int) dam * 1.10; break; case 3: dam = (int) dam * 1.15; break; case 4: dam = (int) dam * 1.20; break; case 5: dam = (int) dam * 1.25; break; case 6: dam = (int) dam * 1.30; break; case 7: dam = (int) dam * 1.35; break; case 8: dam = (int) dam * 1.40; break; case 9: dam = (int) dam * 1.45; break; case 10: dam = (int) dam * 1.50; break; case 11: dam = (int) dam * 1.55; break; } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_martial_arts)) { damage(ch, victim, 0, gsn_martial_arts); } else { damage(ch, victim, dam, gsn_martial_arts); check_improve(ch, gsn_martial_arts); } pop_call(); return; } void do_disarm( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; push_call("do_disarm(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_disarm) == -1) { send_to_char( "You don't know how to disarm opponents.\n\r", ch ); pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); pop_call(); return; } if (get_eq_char(victim, WEAR_WIELD) == NULL) { send_to_char( "Your opponent is not wielding a weapon.\n\r", ch ); pop_call(); return; } wait_state( ch, skill_table[gsn_disarm].beats ); if (IS_NPC(ch) || number_range(1, 100+get_curr_str(victim)) < learned(ch, gsn_disarm)) { disarm( ch, victim ); check_improve(ch, gsn_disarm); } else { send_to_char( "You failed.\n\r", ch ); } pop_call(); return; } void do_sla( CHAR_DATA *ch, char *argument ) { push_call("do_sla(%p,%p)",ch,argument); send_to_char( "If you want to SLAY, spell it out.\n\r", ch ); pop_call(); return; } void do_slay( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; push_call("do_slay(%p,%p)",ch,argument); one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Slay whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if (ch == victim) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); pop_call(); return; } if (!IS_NPC(victim) && victim->level == MAX_LEVEL) { act( "$N laughs at your pathetic attempt to slay $M.", ch, NULL, victim, TO_CHAR ); act( "You laugh at $n's pathetic attempt to slay you.", ch, NULL, victim, TO_VICT ); act( "$N laughs at $n's pathetic attempt to slay $M.", ch, NULL, victim, TO_NOTVICT); pop_call(); return; } act( "You slay $M in cold blood!", ch, NULL, victim, TO_CHAR ); act( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT ); act( "$n slays $N in cold blood!", ch, NULL, victim, TO_NOTVICT); /* to make progs trigger :) */ set_fighting(victim, ch); mprog_death_trigger(victim); raw_kill(victim); stop_hate_fear(ch); pop_call(); return; } void do_slaughter( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; push_call("do_slaughter(%p,%p)",ch,argument); one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Slaughter whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if ( ch == victim ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); pop_call(); return; } if (!IS_NPC(victim) && victim->level == MAX_LEVEL) { act( "$N laughs at your pathetic attempt to slaughter $M.", ch, NULL, victim, TO_CHAR ); act( "You laugh at $n's pathetic attempt to slaughter you.", ch, NULL, victim, TO_VICT ); act( "$N laughs at $n's pathetic attempt to slaughter $M.", ch, NULL, victim, TO_NOTVICT); pop_call(); return; } act( "You slaughter $M in cold blood!", ch, NULL, victim, TO_CHAR ); act( "$n slaughters you in cold blood!", ch, NULL, victim, TO_VICT ); act( "$n slaughters $N in cold blood!", ch, NULL, victim, TO_NOTVICT); if (!IS_NPC(victim)) { log_printf("%s slaughtered by %s at %u", victim->name, get_name(ch), victim->in_room->vnum); if (victim->pcdata->exp > exp_level(victim->class, (victim->level)-1)+1) { gain_exp( victim, exp_level(victim->class, (victim->level)-1)+1 - victim->pcdata->exp); } if (IS_SET(victim->act, PLR_KILLER) || IS_SET(victim->act, PLR_THIEF)) { if (victim->pcdata->exp > exp_level(victim->class, (victim->level)-2)+1) { gain_exp( victim, exp_level(victim->class, (victim->level)-2)+1 - victim->pcdata->exp); } if (IS_SET(victim->act, PLR_KILLER)) { REMOVE_BIT(victim->act, PLR_KILLER); } if (IS_SET(victim->act, PLR_THIEF)) { REMOVE_BIT(victim->act, PLR_THIEF); } } } set_fighting(victim,ch); /* to make progs trigger :) */ mprog_death_trigger(victim); raw_kill( victim ); pop_call(); return; } void do_suicide( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; bool killer, thief; killer=FALSE; thief=FALSE; push_call("do_suicide(%p,%p)",ch,argument); if (IS_NPC(ch)) { raw_kill(ch); pop_call(); return; } if (IS_SET(ch->act, PLR_KILLER)) { killer = TRUE; } if (IS_SET(ch->act, PLR_THIEF)) { thief = TRUE; } if (ch->fighting != NULL) { ch_printf(ch, "%s is trying to kill you, and suicide is not an option.\n\r", ch->fighting->who->name ); pop_call(); return; } one_argument_nolower( argument, arg ); if (arg[0] == '\0') { send_to_char( "!!! WARNING !!! This command is used to kill yourself.\n\rTo use you must enter in your password after the command.\n\r", ch ); pop_call(); return; } if (encrypt64(arg) == ch->pcdata->password) { send_to_char( "You commited suicide!\n\r", ch); raw_kill(ch); if (killer) { SET_BIT( ch->act, PLR_KILLER); } if (thief) { SET_BIT( ch->act, PLR_THIEF); } } else { send_to_char( "That was not your password. Are you sure you want to commit suicide?\n\r", ch); } pop_call(); return; } void do_shoot(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; OBJ_DATA *ammo, *cont, *weapon; int dir, dam; char *name; char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH]; push_call("do_shoot(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_shoot) == -1) { send_to_char("You better leave the shooting to ninjas.\n\r", ch); pop_call(); return; } if (ch->fighting != NULL) { send_to_char( "You are too distracted to shoot!\n\r", ch ); pop_call(); return; } if ((weapon = get_eq_char(ch,WEAR_WIELD)) == NULL) { send_to_char("You must wield a weapon to shoot!\n\r", ch); pop_call(); return; } if (weapon->item_type != ITEM_WEAPON) { send_to_char("You are not wielding a weapon.\n\r", ch); pop_call(); return; } switch(weapon->value[0]) { case WEAPON_TYPE_SHORTBOW: case WEAPON_TYPE_LONGBOW: case WEAPON_TYPE_CROSSBOW: case WEAPON_TYPE_BLOWPIPE: break; default: send_to_char("You are not wielding a weapon that can shoot.\n\r", ch); break; } for (ammo = ch->first_carrying ; ammo ; ammo = ammo->next_content) { if (ammo->item_type == ITEM_AMMO && ammo->value[0] == weapon->value[0] && ammo->level <= weapon->level) { break; } if (ammo->item_type == ITEM_CONTAINER && !IS_SET(ammo->value[1], CONT_CLOSED)) { cont = ammo; for (ammo = ammo->first_content ; ammo ; ammo = ammo->next_content) { if (ammo->item_type == ITEM_AMMO && ammo->value[0] == weapon->value[0] && ammo->level <= weapon->level) { break; } } if (ammo) { break; } else { ammo = cont; } } } if (ammo == NULL) { send_to_char("Ooops...forgot to stock up on ammunition, eh?\n\r", ch); pop_call(); return; } if (number_percent() > learned(ch, gsn_shoot)) { send_to_char("You fumble around and don't get any shots off!\n\r", ch); pop_call(); return; } argument = one_argument(argument, buf1); argument = one_argument(argument, buf2); if ((dir = direction_door(buf1)) == -1) { if ((dir = direction_door(buf2)) == -1) { send_to_char( "Shoot which direction?\n\r", ch ); pop_call(); return; } name = buf1; } else { name = buf2; } if (*name == '\0') { send_to_char( "Shoot at whom?\n\r", ch ); pop_call(); return; } if ((victim = find_char_dir(ch, dir, name)) == NULL) { send_to_char("Your victim must have slipped out of sight!\n\r", ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } if (find_keeper(victim) != NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE)) { send_to_char("You can't shoot into that room.\n\r", ch); pop_call(); return; } if (ch->in_room->area != victim->in_room->area) { send_to_char("They are too far to shoot at.\n\r", ch ); pop_call(); return; } if (IS_NPC(victim) && victim->hit < victim->max_hit / 2) { send_to_char("Your target is too wary to be shot at!\n\r", ch); pop_call(); return; } /* set wait time partial based on ammo speed.. */ wait_state(ch, skill_table[gsn_shoot].beats - ammo->value[2] * 2); if (ammo->in_obj) { act( "$n pulls $p from $P.", ch, ammo, ammo->in_obj, TO_ROOM ); act( "You pull $p from $P.", ch, ammo, ammo->in_obj, TO_CHAR ); } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_shoot)) { act( "$p whistles past your face.", ch, ammo, victim, TO_VICT ); act( "$p whistles past $N's face.", ch, ammo, victim, TO_CHAR ); if (number_percent() < 50) { junk_obj(ammo); } else { ammo->sac_timer = OBJ_SAC_TIME; obj_to_room(ammo, victim->in_room->vnum); } } else { dam = number_range(1, ammo->value[1] * ammo->value[3]); obj_to_char(ammo, victim); damage(ch, victim, dam, gsn_shoot); if (MP_VALID_MOB(victim) && dam > 0) { mprog_range_trigger(victim, ch, rev_dir[dir]); } } pop_call(); return; } void do_throw( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *weapon; int dir, dam, wielded; char buf1[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH], buf3[MAX_INPUT_LENGTH]; char *name, *item; push_call("do_throw(%p,%p)",ch,argument); if (IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit / 2) { pop_call(); return; } if (!IS_NPC(ch) && multi(ch, gsn_throw) == -1) { send_to_char("You decide not to throw...might hurt your back.\n\r", ch); pop_call(); return; } if (ch->fighting != NULL) { send_to_char( "You are too distracted to throw!\n\r", ch ); pop_call(); return; } argument = one_argument(argument, buf1); argument = one_argument(argument, buf2); argument = one_argument(argument, buf3); if ((dir = direction_door(buf1)) == -1) { if ((dir = direction_door(buf2)) == -1) { if ((dir = direction_door(buf3)) == -1) { send_to_char( "Throw which direction?\n\r", ch ); pop_call(); return; } else { name = buf2; item = buf1; } } else { name = buf3; item = buf1; } } else { name = buf3; item = buf2; } if (name[0] == '\0' || item[0] == '\0') { send_to_char( "Throw what at whom?\n\r", ch ); pop_call(); return; } if ((victim = find_char_dir(ch, dir, name)) == NULL) { send_to_char("Your victim must have slipped out of sight.\n\r", ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } if (find_keeper(victim) != NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE)) { send_to_char("You can't throw into that room.\n\r", ch); pop_call(); return; } if (ch->in_room->area != victim->in_room->area) { send_to_char("They are too far to throw things at.\n\r", ch); pop_call(); return; } if (IS_NPC(victim) && victim->hit < victim->max_hit/2) { send_to_char("You can't seem to get a good sight of your target.\n\r", ch); pop_call(); return; } wielded = FALSE; if ((weapon = get_eq_char(ch, WEAR_WIELD)) != NULL) { if (is_name(item, weapon->name) || is_name_short(item, weapon->name)) { wielded = TRUE; } } if (wielded == FALSE) { if (!remove_obj(ch, WEAR_WIELD, TRUE, FALSE)) { send_to_char("You can't throw with another weapon wielded!\n\r", ch); pop_call(); return; } weapon = get_obj_carry(ch, item); } if (weapon == NULL) { send_to_char("Hmmm...you don't seem to have that weapon.\n\r", ch); pop_call(); return; } if (IS_SET(weapon->extra_flags, ITEM_NODROP)) { send_to_char("You can't let go of it.\n\r", ch); pop_call(); return; } switch (weapon->value[0]) { case WEAPON_TYPE_DAGGER: case WEAPON_TYPE_AXE: case WEAPON_TYPE_SPEAR: break; default: send_to_char("You can't throw that type of weapon.\n\r", ch); pop_call(); return; } if (!wielded) { wait_state( ch, skill_table[gsn_throw].beats ); } else { wait_state( ch, skill_table[gsn_throw].beats / 2 ); } if (number_percent() > learned(ch, gsn_throw)) { send_to_char("You fumble around and don't throw a thing!\n\r", ch); pop_call(); return; } if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_throw)) { act("$p whistles past your face.", ch, weapon, victim, TO_VICT ); act("$p whistles past $N's face.", ch, weapon, victim, TO_CHAR ); if (number_percent() < 50) { junk_obj(weapon); } else { weapon->sac_timer = OBJ_SAC_TIME; obj_to_room(weapon, victim->in_room->vnum); } } else { dam = 3 * number_range(weapon->value[1], weapon->value[1]*weapon->value[2]); obj_to_char(weapon, victim); damage(ch, victim, dam, gsn_throw); if (MP_VALID_MOB(victim) && dam > 0) { mprog_range_trigger(victim, ch, rev_dir[dir]); } stop_fighting(ch, FALSE); pop_call(); return; } } void do_divert( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *fch; push_call("do_divert(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch,gsn_divert) == -1) { send_to_char( "What about fleeing instead?\n\r", ch ); pop_call(); return; } if (ch->fighting == NULL) { send_to_char( "You aren't fighting!\n\r", ch ); pop_call(); return; } for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (fch->fighting && fch->fighting->who == ch) { break; } } if (fch == NULL) { send_to_char( "You aren't under attack.\n\r", ch ); pop_call(); return; } one_argument( argument, arg ); if (arg[0] == '\0') { send_to_char( "Divert to whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if (victim == ch) { send_to_char( "What about fleeing instead?\n\r", ch ); pop_call(); return; } if (ch->fighting->who == victim) { act( "Trying to make $m fight $mself?", ch, NULL, victim, TO_CHAR); pop_call(); return; } if ((fch = who_fighting(victim)) == NULL) { send_to_char( "That person is not fighting right now.\n\r", ch ); pop_call(); return; } if (!is_same_group(ch,victim)) { act( "$N isn't a member of your group.", ch, NULL, victim, TO_CHAR); pop_call(); return; } wait_state( ch, skill_table[gsn_divert].beats ); if (!IS_NPC(ch->fighting->who)) { send_to_char( "You fail the divert.\n\r", ch ); pop_call(); return; } if (number_percent() > learned(ch, gsn_divert) || !IS_NPC(fch)) { send_to_char( "You fail the divert.\n\r", ch ); pop_call(); return; } act( "You divert the attack to $N!", ch, NULL, victim, TO_CHAR); act( "$n diverts the attack to you!", ch, NULL, victim, TO_VICT); act( "$n diverts the attack to $N!", ch, NULL, victim, TO_NOTVICT); check_improve(ch, gsn_divert); for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room) { if (fch->fighting && fch->fighting->who == ch) { fch->fighting->who = victim; break; } } pop_call(); return; } void do_knife( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; push_call("do_knife(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_knife) == -1) { send_to_char( "You'd better leave the nasty stuff to ninjas.\n\r", ch ); pop_call(); return; } if ((obj = get_eq_char(ch,WEAR_WIELD)) == NULL || (obj->value[3] != 11 && obj->value[3] != 2)) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); pop_call(); return; } one_argument( argument, arg ); if (arg[0] == '\0') { if ((victim = who_fighting(ch)) == NULL) { send_to_char("You are not fighting anyone.\n\r",ch); pop_call(); return; } } else if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("Knife whom?\n\r",ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } wait_state( ch, skill_table[gsn_knife].beats ); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_knife)) { damage( ch, victim, 0, gsn_knife); } else { one_hit( ch, victim, gsn_knife ); } pop_call(); return; } void do_distract( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; push_call("do_distract(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_distract) == -1) { send_to_char( "They'd just get mad at you if you tried.\n\r", ch ); pop_call(); return; } one_argument(argument,arg); if ((victim = get_char_room(ch,arg)) == NULL) { send_to_char("Distract whom?\n\r",ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } wait_state( ch, skill_table[gsn_distract].beats ); if (IS_NPC(ch) || number_range(1, 150) < learned(ch, gsn_distract)) { switch (number_bits(1)) { case 0: act( "$n informs you that your shoes are untied.", ch, NULL, victim, TO_VICT ); act( "You inform $N that $S shoes are untied.", ch, NULL, victim, TO_CHAR ); act( "$n inform $N that $S shoes are untied.", ch, NULL, victim, TO_NOTVICT ); break; case 1: act( "$n points at the sky above you and gasps. ", ch, NULL, victim, TO_VICT ); act( "You point at the sky above $M and gasp.", ch, NULL, victim, TO_CHAR ); act( "$n points at the sky above $N and gasps.", ch, NULL, victim, TO_NOTVICT ); break; } check_improve(ch, gsn_distract); victim->distracted += 10; wait_state( victim, skill_table[gsn_distract].beats ); } else { send_to_char( "They suddenly look very suspicious.\n\r", ch ); act( "$n is trying to distract you!", ch, NULL, victim, TO_VICT); victim->distracted = 0; if (IS_NPC(victim) && (number_bits(1) == 0)) { act( "$n suddenly looks VERY angry!",victim,NULL, NULL,TO_ROOM); multi_hit(victim,ch,TYPE_UNDEFINED); } } pop_call(); return; } bool valid_fight( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("valid_fight(%p,%p)",ch,victim); if (who_fighting(ch) == NULL) { pop_call(); return FALSE; } if (ch->in_room != victim->in_room) { pop_call(); return FALSE; } pop_call(); return TRUE; } CHAR_DATA *who_fighting( CHAR_DATA *ch ) { push_call("who_fighting(%p)",ch); if (ch->fighting == NULL) { pop_call(); return NULL; } if (ch->fighting->who == NULL) { pop_call(); return NULL; } if (ch->fighting->who->name == NULL) { log_printf("who_fighting: who->name == NULL for %s", ch->name); dump_stack(); pop_call(); return NULL; } if (ch->fighting->who->in_room != ch->in_room) { pop_call(); return NULL; } pop_call(); return ch->fighting->who; } void stop_fighting( CHAR_DATA *ch, bool fBoth ) { FIGHT_DATA *fight, *fight_next; push_call("stop_fighting(%p,%p)",ch,fBoth); free_fight( ch ); if (!fBoth) { pop_call(); return; } for (fight = mud->f_fight ; fight ; fight = fight_next) { fight_next = fight->next; if (fight->who == ch) { free_fight(fight->ch); } } pop_call(); return; } void do_auto( CHAR_DATA *ch, char *argument ) { char buf[MAX_INPUT_LENGTH]; int sn; bool ms; push_call("do_auto(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } if (argument[0] == '\0') { send_to_char( "Syntax: AUTO [AUTO|QUICK] [SKILL|SPELL]\n\r", ch); if (ch->pcdata->auto_command != NULL && ch->pcdata->auto_command[0] != '\0') { ch_printf( ch, "Current command: %s\n\r", ch->pcdata->auto_command); } else { ch_printf( ch, "Current command: Not defined\n\r" ); } switch (ch->pcdata->auto_flags) { case AUTO_OFF: send_to_char( "Current mode: Off\n\r", ch); break; case AUTO_AUTO: send_to_char( "Current mode: Auto\n\r", ch); break; case AUTO_QUICK: send_to_char( "Current mode: Quick\n\r", ch); break; } pop_call(); return; } if (!strcasecmp( argument, "auto")) { if (ch->pcdata->auto_command[0] != '\0') { send_to_char( "Turning AUTO mode on.\n\r", ch); ch->pcdata->auto_flags = AUTO_AUTO; pop_call(); return; } else { send_to_char( "You haven't defined a combat skill/spell.\n\r", ch); pop_call(); return; } } if (!strcasecmp(argument, "quick")) { if (ch->pcdata->auto_command[0] != '\0') { send_to_char( "Turning QUICK mode on.\n\r", ch); ch->pcdata->auto_flags=AUTO_QUICK; pop_call(); return; } else { send_to_char( "You haven't defined a combat skill/spell.\n\r", ch); pop_call(); return; } } if (!strcasecmp(argument, "off")) { send_to_char( "Turning auto modes off.\n\r", ch); ch->pcdata->auto_flags = AUTO_OFF; pop_call(); return; } /* Adding mass to auto command - Scandum 18-04-2002 */ if (!str_prefix("mass ", argument)) { if (learned(ch, gsn_mass) <= 0) { send_to_char( "You can't do that.\n\r", ch ); pop_call(); return; } sn = skill_lookup( &argument[5] ); ms = TRUE; if (!is_spell(sn)) { send_to_char( "That is not a spell.\n\r", ch ); pop_call(); return; } } else { sn = skill_lookup( argument ); ms = FALSE; } if (sn < 0 && ms == FALSE) { send_to_char( "That is not a skill or spell.\n\r", ch ); pop_call(); return; } /* Disallow ppl to do auto short range etc - Martin 7/8/98 */ if (skill_table[sn].minimum_position != POS_FIGHTING) { send_to_char( "You can only put combat skills/spells on auto.\n\r", ch ); pop_call(); return; } if (!IS_SET(skill_table[sn].race, 1 << ch->race)) { if (multi(ch, sn) == -1 || learned(ch, sn) <= 0) { send_to_char( "You can't do that.\n\r", ch ); pop_call(); return; } } if (ms == TRUE) { int sha_mlv = ch->pcdata->mclass[CLASS_SHAMAN]; int sor_mlv = ch->pcdata->mclass[CLASS_SORCERER]; if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE && sor_mlv < skill_table[gsn_mass].skill_level[CLASS_SORCERER]) || (skill_table[sn].target == TAR_CHAR_DEFENSIVE && sha_mlv < skill_table[gsn_mass].skill_level[CLASS_SHAMAN])) { send_to_char( "You don't have enough skill in the proper class.\n\r", ch ); pop_call(); return; } if (skill_table[sn].target != TAR_CHAR_OFFENSIVE && skill_table[sn].target != TAR_CHAR_DEFENSIVE) { send_to_char( "You cannot put mass spells on auto mass.\n\r", ch ); pop_call(); return; } sprintf(argument, "mass %s", skill_table[sn].name); } else { strcpy(argument, skill_table[sn].name); } STRFREE (ch->pcdata->auto_command); ch->pcdata->auto_command = STRALLOC( argument ); sprintf( buf, "Auto command set to: %s\n\r", argument ); send_to_char(buf, ch); pop_call(); return; } void do_spam( CHAR_DATA *ch, char *arg) { int val; push_call("do_spam(%p,%p)",ch,arg); if (arg == NULL || arg[0]=='\0') { send_to_char( "SPAM control settings:\n\r", ch); send_to_char( "Toggle Status Description\n\r", ch); if (!IS_SET(CH(ch->desc)->pcdata->spam, 1)) { send_to_char( " A On You hit\n\r" , ch); } else { send_to_char( " A Off You hit\n\r" , ch); } if (!IS_SET(CH(ch->desc)->pcdata->spam, 2)) { send_to_char( " B On You miss\n\r" , ch); } else { send_to_char( " B Off You miss\n\r" , ch); } if (!IS_SET(CH(ch->desc)->pcdata->spam, 4)) { send_to_char( " C On They hit you\n\r" , ch); } else { send_to_char( " C Off They hit you\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 8)) { send_to_char( " D On They miss you\n\r" , ch); } else { send_to_char( " D Off They miss you\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 16)) { send_to_char( " E On Party hits\n\r" , ch); } else { send_to_char( " E Off Party hits\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 32)) { send_to_char( " F On Party misses\n\r" , ch); } else { send_to_char( " F Off Party misses\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 64)) { send_to_char( " G On They hit party\n\r" , ch); } else { send_to_char( " G Off They hit party\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 128)) { send_to_char( " H On They miss party\n\r" , ch); } else { send_to_char( " H Off They miss party\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 256)) { send_to_char( " I On Other hit\n\r" , ch); } else { send_to_char( " I Off Other hit\n\r" , ch); } if( !IS_SET( CH(ch->desc)->pcdata->spam, 512)) { send_to_char( " J On Other miss\n\r" , ch); } else { send_to_char( " J Off Other miss\n\r" , ch); } if( IS_SET( CH(ch->desc)->pcdata->spam, 1024)) { send_to_char( " K On Show party status line\n\r" , ch); } else { send_to_char( " K Off Show party status line\n\r" , ch); } if (!IS_SET( CH(ch->desc)->pcdata->spam, 2048)) { send_to_char( " L ON You hear party members moving\n\r", ch); } else { send_to_char( " L off You don't hear party members moving\n\r", ch); } if (!IS_SET(CH(ch->desc)->pcdata->spam, 4096)) { send_to_char( " M ON You hear the uttering of spells\n\r",ch); } else { send_to_char( " M off You don't hear the uttering of spells\n\r",ch); } pop_call(); return; } val = -1; switch (tolower(arg[0])) { case 'a': val = 1; break; case 'b': val = 2; break; case 'c': val = 4; break; case 'd': val = 8; break; case 'e': val = 16; break; case 'f': val = 32; break; case 'g': val = 64; break; case 'h': val = 128; break; case 'i': val = 256; break; case 'j': val = 512; break; case 'k': val = 1024; break; case 'l': val = 2048; break; case 'm': val = 4096; break; } if (val == -1) { send_to_char( "That is not an option.\n\r", ch ); pop_call(); return; } TOGGLE_BIT(CH(ch->desc)->pcdata->spam, val); do_spam( ch, "" ); /* show stat change */ pop_call(); return; } void do_assassin( CHAR_DATA *ch, char *argument ) { push_call("do_assassin(%p,%p)",ch,argument); send_to_char( "If you want to ASSASSINATE, spell it out.\n\r", ch ); pop_call(); return; } void do_assassinate( CHAR_DATA *ch, char *argument ) { char buf[MAX_INPUT_LENGTH]; char arg[MAX_INPUT_LENGTH],arg2[MAX_INPUT_LENGTH]; CHAR_DATA *victim; push_call("do_assassinate(%p,%p)",ch,argument); if (IS_NPC(ch) || multi(ch, gsn_assassinate) == -1) { send_to_char( "Only ninjas can assassinate.\n\r", ch ); pop_call(); return; } argument = one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Assassinate whom?\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } if ( victim == ch ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if (IS_NPC(victim)) { send_to_char( "You may not assassinate them.\n\r", ch ); pop_call(); return; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { send_to_char("Use kill instead.\n\r", ch); pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You do the best you can!\n\r", ch ); pop_call(); return; } if (!can_attack (ch, victim) ) { send_to_char( "You may not assassinate that person.\n\r", ch); pop_call(); return; } if (victim->pcdata->just_died_ctr > 0) { send_to_char("That person is currently protected by their god.\n\r", ch); pop_call(); return; } if (victim->fighting != NULL) { send_to_char( "You may not assassinate that person, at the moment.\n\r", ch); pop_call(); return; } if (!IS_NPC(victim ) && victim->pcdata->corpse != NULL) { ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim)); pop_call(); return; } /* Code for total and max pvnum attacks - Chaos 5/6/99 */ if (!check_add_attack(ch, victim)) { ch_printf(ch, "%s has been attacked too many times.\n\rYou should leave them alone.\n\r", get_name(victim)); pop_call(); return; } /* ok...check and see if the victim has the specified item */ argument=one_argument( argument, arg2 ); if (arg2[0] != '\0' && number_percent() < learned(ch, gsn_assassinate)) { OBJ_DATA *obj; if ((obj = get_obj_list(victim, arg2, victim->first_carrying)) == NULL) { send_to_char( "They don't seem to have it!\n\r", ch ); pop_call(); return; } if (IS_SET(obj->extra_flags, ITEM_INVENTORY) || obj->level > ch->level) { send_to_char( "You wouldn't be able to pry it away.\n\r", ch ); pop_call(); return; } if (ch->carry_number >= can_carry_n(ch)) { send_to_char( "You have your hands full.\n\r", ch ); pop_call(); return; } if (ch->carry_weight >= can_carry_w(ch)) { send_to_char( "You can't carry that much weight.\n\r", ch ); pop_call(); return; } ch->pcdata->asn_obj = obj; } else { ch->pcdata->asn_obj = NULL; } check_killer( ch, victim ); if (number_percent() > learned(ch, gsn_muffle)/2) { sprintf(buf, "%s", get_name(victim)); do_battle("%s battles 'Help! I am being assassinated by %s!'", buf, get_name(ch)); } else { act( "You quickly silence $N before they can call for help!", ch, NULL, victim, TO_CHAR); act( "You are silenced by $n before you can call for help!", ch, NULL, victim, TO_VICT); check_improve(ch, gsn_muffle); } ch->pcdata->just_died_ctr = 0; clear_attack_list(ch); log_printf("ROOM [%u] ASSASSINATE %s attacking %s", ch->in_room->vnum, ch->name, victim->name); if (number_range(33, 100) < 100 * victim->hit / UMAX(1, victim->max_hit) && number_percent() < learned(ch, gsn_knife) && number_percent() < learned(ch, gsn_quick_draw) && number_percent() < 100*multi_skill_level(ch, gsn_quick_draw)/ch->level) { OBJ_DATA * obj; if ((obj = get_eq_char(ch,WEAR_WIELD)) != NULL && (obj->value[3]==11 || obj->value[3]==2)) { one_hit(ch, victim, gsn_knife); check_improve(ch, gsn_quick_draw); wait_state(ch, skill_table[gsn_knife].beats); pop_call(); return; } } wait_state(ch, PULSE_PER_SECOND); multi_hit( ch, victim, TYPE_UNDEFINED ); pop_call(); return; } void do_gouge( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; push_call("do_gouge(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_gouge) == -1) { ch_printf(ch, "You haven't been taught this dirty trick!\n\r"); pop_call(); return; } if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); pop_call(); return; } wait_state( ch, skill_table[gsn_gouge].beats ); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_gouge)) { damage(ch, victim, 0, gsn_gouge); pop_call(); return; } damage(ch, victim, number_range(5, ch->level), gsn_gouge); check_improve(ch, gsn_gouge); if (valid_fight(ch, victim)) { if (!IS_AFFECTED(victim, AFF_BLIND)) { if (!IS_AFFECTED(ch, AFF_TRUESIGHT)) { af.type = gsn_gouge; af.location = APPLY_HITROLL; af.modifier = -6; af.duration = multi_skill_level(ch,gsn_gouge) / 2 / get_curr_con(victim); af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); act( "You can't see a thing!", victim, NULL, NULL, TO_CHAR ); } else { act( "$N seems to be able to see despite your attack!", ch, NULL, victim, TO_CHAR ); act( "You are unaffected by $n's attack.", ch, NULL, victim, TO_VICT ); } } wait_state( ch, PULSE_VIOLENCE ); } else { act( "Your fingers plunge into your victim's brain, causing immediate death!", ch, NULL, NULL, TO_CHAR ); } pop_call(); return; } void do_circle( CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; OBJ_DATA *obj; push_call("do_circle(%p,%p)",ch,argument); if ((victim = who_fighting(ch)) == NULL) { send_to_char( "You can't circle when you aren't fighting.\n\r", ch); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL || (obj->value[3] != 11 && obj->value[3] != 2)) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); pop_call(); return; } if (!ch->fighting) { send_to_char( "You can't circle when you aren't fighting.\n\r", ch); pop_call(); return; } if (!victim->fighting) { send_to_char( "You can't circle around a person who is not fighting.\n\r", ch ); pop_call(); return; } if (who_fighting(victim) == ch) { act( "You can't circle around them without a distraction.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } wait_state( ch, skill_table[gsn_circle].beats ); if (!check_hit(ch, victim, GET_HITROLL(ch), gsn_circle)) { damage( ch, victim, 0, gsn_circle ); pop_call(); return; } one_hit( ch, victim, gsn_circle ); pop_call(); return; } void do_berserk( CHAR_DATA *ch, char *argument ) { push_call("do_berserk(%p,%p)",ch,argument); if (!IS_NPC(ch) && ch->pcdata->mclass[multi(ch, gsn_berserk)] != ch->level) { send_to_char("You spit foam and roar but nobody seems to notice.\n\r", ch); pop_call(); return; } if (IS_NPC(ch) || number_percent() < learned(ch, gsn_berserk)) { AFFECT_DATA af; af.type = gsn_berserk; af.duration = 5; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_BERSERK; af.modifier = 0 - ch->level / 3; af.location = APPLY_SAVING_SPELL; affect_to_char( ch, &af ); af.modifier = ch->level / 4; af.location = APPLY_HITROLL; affect_to_char( ch, &af ); af.modifier = ch->level / 2; af.location = APPLY_DAMROLL; affect_to_char( ch, &af ); send_to_char( "Now you REALLY wanna KILL!\n\r",ch); check_improve(ch, gsn_berserk); } else { wait_state( ch, skill_table[gsn_berserk].beats ); send_to_char("You failed to go berserk!\n\r",ch); } pop_call(); return; } void do_bloodfrenzy(CHAR_DATA *ch, char *arg) { push_call("do_bloodfrenzy(%p,%p)",ch,arg); if (which_god(ch) != GOD_DEMISE) { send_to_char("You try to look crazy, but can't keep it up for very long.\n\r", ch); pop_call(); return; } if (number_percent() < learned(ch, gsn_bloodfrenzy)) { AFFECT_DATA af; if (is_affected(ch, gsn_bloodfrenzy)) { send_to_char( "Blood already maddened you!\n\r", ch ); pop_call(); return; } af.type = gsn_bloodfrenzy; af.duration = 12; af.bitvector = 0; af.modifier = (1 + ch->level / 18 + ch->pcdata->reincarnation); af.location = APPLY_DAMROLL; affect_to_char( ch, &af ); af.modifier = (1 + ch->level / 18); af.location = APPLY_STR; affect_to_char( ch, &af ); send_to_char("You feel rage spreading through your body.\n\r",ch); act( "$n gets a crazy look in $s eyes.", ch, NULL, NULL, TO_ROOM ); check_improve(ch, gsn_bloodfrenzy); } else { wait_state(ch, skill_table[gsn_bloodfrenzy].beats); send_to_char("You failed to get mad at the sight of blood.\n\r",ch); } pop_call(); return; } void do_drain( CHAR_DATA *ch, char *arg ) { CHAR_DATA *victim; char arg1[MAX_INPUT_LENGTH]; push_call("do_drain(%p,%p)",ch,arg); if (learned(ch, gsn_drain) == 0) { send_to_char("The undead curse is not upon you.\n\r",ch); pop_call(); return; } one_argument( arg, arg1 ); if (arg1[0] == '\0') { if ((victim = who_fighting(ch)) == NULL) { send_to_char("You are not fighting anyone.\n\r",ch); pop_call(); return; } } else if ((victim = get_char_room(ch, arg1)) == NULL) { send_to_char("Drain whom?\n\r",ch); pop_call(); return; } if (is_safe(ch, victim)) { pop_call(); return; } wait_state(ch, skill_table[gsn_drain].beats); if (!check_hit(ch, victim, GET_HITROLL(ch), TYPE_HIT)) { damage(ch, victim, 0, gsn_drain); } else { int dam = GET_DAMROLL(ch); dam += number_range(ch->level*1, ch->level*2); ch->hit = UMIN(ch->max_hit, ch->hit+dam/10); gain_condition(ch, COND_FULL, 1); gain_condition(ch, COND_THIRST, 1); damage(ch, victim, dam, gsn_drain); } pop_call(); return; } void do_strangle( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; push_call("do_strangle(%p,%p)",ch,argument); if (learned(ch, gsn_strangle) == 0) { send_to_char( "They would just get mad at you.\n\r", ch ); pop_call(); return; } if ((victim = get_char_room(ch, argument)) == NULL) { send_to_char("Strangle whom?\n\r",ch); pop_call(); return; } if (IS_NPC(victim) && is_safe(ch, victim)) { pop_call(); return; } if (!IS_NPC(victim)) { if (victim == ch) { send_to_char( "You strangle yourself. Uch!\n\r", ch ); pop_call(); return; } if (is_safe(ch, NULL)) { pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You do the best you can!\n\r", ch ); pop_call(); return; } if (!can_attack (ch, victim) ) { send_to_char( "You may not strangle that person.\n\r", ch); pop_call(); return; } if (victim->pcdata->just_died_ctr > 0) { send_to_char("That person is currently protected by their god.\n\r", ch); pop_call(); return; } if (victim->fighting != NULL) { send_to_char( "You may not strangle that person, at the moment.\n\r", ch); pop_call(); return; } if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF)) { if (ch->pcdata->last_connect + 120 > mud->current_time) { ch_printf(ch, "You must wait %d seconds before you can strangle anyone.\n\r", ch->pcdata->last_connect + 120 - mud->current_time); pop_call(); return; } } if (victim->pcdata->corpse != NULL) { ch_printf(ch, "%s has been killed quite recently.\n\r", get_name(victim)); pop_call(); return; } } wait_state( ch, skill_table[gsn_strangle].beats ); if (IS_AFFECTED(victim, AFF_SLEEP)) { send_to_char( "They are already unconscious.\n\r", ch ); pop_call(); return; } if (number_range(1, victim->level * 3 / 2) > multi_skill_level(ch, gsn_strangle) || number_percent() > learned(ch, gsn_strangle)) { act("$n is trying to strangle you!", ch, NULL, victim, TO_VICT); act("You failed to strangle $N!", ch, NULL, victim, TO_CHAR); if (IS_NPC(victim)) { act( "$n suddenly looks VERY angry!", victim, NULL, NULL, TO_ROOM); multi_hit(victim, ch, TYPE_UNDEFINED); } pop_call(); return; } af.type = gsn_sleep; af.duration = 1; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_SLEEP; affect_to_char( victim, &af ); wait_state(victim, skill_table[gsn_strangle].beats * 3 / 2); if ( IS_AWAKE(victim) ) { send_to_char( "The world blurs as your consciousness fades.\n\r", victim ); act( "$n collapses onto the ground.", victim, NULL, NULL, TO_ROOM ); victim->position = POS_SLEEPING; } pop_call(); return; } void knight_adjust_hpmnmv( CHAR_DATA *ch ) { int val_hp, val_mana, val_move, tmp; push_call("knight_adjust_hpmnmv(%p)",ch); val_hp = ch->pcdata->actual_max_hit; val_mana = ch->pcdata->actual_max_mana; val_move = ch->pcdata->actual_max_move; if (val_mana < 100 && val_move < 100) { tmp = 200 - val_move - val_mana; val_hp -= tmp; val_mana = 100; val_move = 100; } else if (val_mana < 100) { tmp = 100 - val_mana; if( val_move - tmp/2 < 100 ) { tmp -= ( val_move - 100 ); val_move = 100; val_mana = 100; val_hp -= tmp; } else { val_mana = 100; val_move -= (tmp/2); val_hp -= (tmp/2); } } else if (val_move < 100) { tmp = 100 - val_move; if (val_mana - tmp/2 < 100) { tmp -= ( val_mana - 100 ); val_move = 100; val_mana = 100; val_hp -= tmp; } else { val_move = 100; val_mana -= (tmp/2); val_hp -= (tmp/2); } } tmp = ch->pcdata->actual_max_hit - ch->max_hit; ch->pcdata->actual_max_hit = val_hp; ch->max_hit = val_hp - tmp; tmp = ch->pcdata->actual_max_mana - ch->max_mana; ch->pcdata->actual_max_mana = val_mana; ch->max_mana = val_mana - tmp; tmp = ch->pcdata->actual_max_move - ch->max_move; ch->pcdata->actual_max_move = val_move; ch->max_move = val_move - tmp; if (ch->hit > ch->max_hit) { ch->hit = ch->max_hit; } if (ch->mana > ch->max_mana) { ch->mana = ch->max_mana; } if (ch->move > ch->max_move) { ch->move = ch->max_move; } pop_call(); return; } bool can_reincarnate_attack( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("can_reincarnate_attack(%p,%p)",ch,victim); if (IS_NPC(ch) || IS_NPC(victim)) { pop_call(); return TRUE; } if (ch->pcdata->reincarnation*2/3 > victim->pcdata->reincarnation) { pop_call(); return FALSE; } if (ch->pcdata->reincarnation*3/2 < victim->pcdata->reincarnation) { pop_call(); return FALSE; } pop_call(); return TRUE; } /* 0 1 2 3 4 5 6 7 8 9 A reincarnate attack chart: 0 * 1 * 2 * * 3 * * * 4 * * * * 5 * * * * 6 * * * * * * 7 * * * * * * 8 * * * * * 9 * * * * * A * * * * */ bool can_attack( CHAR_DATA *ch, CHAR_DATA *victim) { push_call("can_attack(%p,%p)",ch,victim); if (IS_NPC(ch) || IS_NPC(victim)) { pop_call(); return TRUE; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA && victim->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { pop_call(); return TRUE; } if (victim->level >= LEVEL_IMMORTAL || ch->level >= LEVEL_IMMORTAL) { pop_call(); return FALSE; } if (ch->pcdata->reincarnation < victim->pcdata->reincarnation) { if (ch->pcdata->reincarnation*3/2 < victim->pcdata->reincarnation) { pop_call(); return FALSE; } if (victim->pcdata->reincarnation*2/3 > ch->pcdata->reincarnation) { pop_call(); return FALSE; } } if (ch->pcdata->reincarnation > victim->pcdata->reincarnation) { if (ch->pcdata->reincarnation*2/3 > victim->pcdata->reincarnation) { pop_call(); return FALSE; } if (victim->pcdata->reincarnation*3/2 < ch->pcdata->reincarnation) { pop_call(); return FALSE; } } if (which_god(ch) == GOD_NEUTRAL || which_god(victim) == GOD_NEUTRAL) { pop_call(); return FALSE; } if (ch->pcdata->clan && ch->pcdata->clan == victim->pcdata->clan) { pop_call(); return FALSE; } if (which_god(victim) == which_god(ch)) { pop_call(); return FALSE; } if (ch->level <= 25 || victim->level <= 25) { pop_call(); return FALSE; } if (victim->level < ch->level-10 || victim->level > ch->level+10) { pop_call(); return FALSE; } pop_call(); return TRUE; } /* Orish Brawling - Chaos 8/20/98 */ void orc_brawl( CHAR_DATA *ch, CHAR_DATA *victim) { int level; int dmg, dmgL, dmgH; int tshares, pshare; push_call("orc_brawl(%p,%p)",ch,victim); level = ch->level; /* Find total shares */ if (level < 15) { tshares = 8; } else if (level < 30) { tshares = 15; } else if (level < 45) { tshares = 21; } else if (level < 60) { tshares = 26; } else if (level < 75) { tshares = 30; } else { tshares = 33; } pshare = number_range(1, tshares); if (pshare <= 8) { brawling_attack = 0; dmgL = (int) level * 0.25; dmgH = (int) level * 0.50; } else if( pshare <= 15 ) { brawling_attack = 1; dmgL = (int) level * 0.50; dmgH = (int) level * 0.75; } else if( pshare <= 21 ) { brawling_attack = 2; dmgL = (int) level * 0.75; dmgH = (int) level * 1.00; } else if( pshare <= 26 ) { brawling_attack = 3; dmgL = (int) level * 1.00; dmgH = (int) level * 1.25; } else if( pshare <= 30 ) { brawling_attack = 4; dmgL = (int) level * 1.25; dmgH = (int) level * 1.50; } else { brawling_attack = 5; dmgL = (int) level * 1.50; dmgH = (int) level * 1.75; } dmg = number_range(dmgL, dmgH); if (check_hit(ch, victim, GET_HITROLL(ch), TYPE_HIT)) { damage(ch, victim, GET_DAMROLL(ch) + dmg, gsn_brawling); } else { damage(ch, victim, 0, gsn_brawling); } pop_call(); return; } void stop_hate_fear( CHAR_DATA *ch ) { push_call("stop_hate_fear(%p)",ch); if (IS_NPC(ch) && *ch->npcdata->hate_fear) { STRFREE(ch->npcdata->hate_fear); ch->npcdata->hate_fear = STRDUPE(str_empty); } pop_call(); return; } /* Could use some messages */ void found_hating( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_INPUT_LENGTH]; push_call("found_hating(%p,%p)",ch,victim); if (!can_see(ch, victim)) { if (number_bits(2) != 0) { pop_call(); return; } if (IS_SET(ch->act, ACT_SMART)) { switch (number_bits(2)) { case 0: sprintf(buf, "I can smell your blood %s!", short_to_name(get_name(victim), 1)); break; case 1: sprintf(buf, "Where are you %s? Come here and die!", short_to_name(get_name(victim), 1)); break; case 2: sprintf(buf, "Just wait until I find you %s - then you'll pay!", short_to_name(get_name(victim), 1)); break; case 3: sprintf(buf, "You're dead %s! Just as soon as I get my hands on you!", short_to_name(get_name(victim), 1)); break; } do_say(ch, buf); } switch (number_bits(2)) { case 0: act("$n staggers around blindly, attacking the air!", ch, NULL, NULL, TO_ROOM); break; case 1: act("$n lurches around the area trying to find something to attack!", ch, NULL, NULL, TO_ROOM); break; case 2: act("$n growls in frustration as $e tries to attack unseen enemies!", ch, NULL, NULL, TO_ROOM); break; case 3: act("$n snarls quietly as $e attacks thin air!", ch, NULL, NULL, TO_ROOM); break; } pop_call(); return; } if (is_safe(ch, NULL)) { if (number_bits(2) != 0) { pop_call(); return; } if (IS_SET(ch->act, ACT_SMART)) { switch (number_bits(2)) { case 0: sprintf(buf, "You're a coward %s! Fight me!", short_to_name(get_name(victim), 1)); break; case 1: sprintf(buf, "That's right %s, hide from me you coward!", short_to_name(get_name(victim), 1)); break; case 2: sprintf(buf, "C'mon %s, fight you craven dog!", short_to_name(get_name(victim), 1)); break; case 3: sprintf(buf, "Only a coward would hide here %s!", short_to_name(get_name(victim), 1)); break; } do_say(ch, buf); } pop_call(); return; } if (IS_SET(ch->act, ACT_SMART)) { switch (number_bits(2)) { case 0: sprintf(buf, "I'll get you now %s! Die!", short_to_name(get_name(victim), 1)); break; case 1: sprintf(buf, "We were not done yet %s!", short_to_name(get_name(victim), 1)); break; case 2: sprintf(buf, "Defend yourself %s!", short_to_name(get_name(victim), 1)); break; case 3: sprintf(buf, "Prepare for your death %s!", short_to_name(get_name(victim), 1)); break; } do_say(ch, buf); } else { switch (number_bits(2)) { case 0: act("$n contorts $s face and surges to the attack!", ch, NULL, NULL, TO_ROOM); break; case 1: act("$n snarls and leaps to the attack!", ch, NULL, NULL, TO_ROOM); break; case 2: act("$n growls and lunges forwards!", ch, NULL, NULL, TO_ROOM); break; case 3: act("$n grinds $s teeth and leaps forwards!", ch, NULL, NULL, TO_ROOM); break; } } multi_hit(ch, victim, TYPE_UNDEFINED); pop_call(); return; } void do_attack( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim = NULL; char buf[MAX_STRING_LENGTH]; push_call("do_attack(%p,%p)",ch,argument); one_argument(argument, buf); if (buf[0] == '\0') { victim = ch; } else if ((victim = get_player_world(ch, buf)) == NULL) { send_to_char("Syntax: attack <player>\n\r", ch); pop_call(); return; } get_attack_string( victim, ch, buf ); send_to_char( ansi_translate_text( ch, buf), ch ); pop_call(); return; } void get_attack_string( CHAR_DATA *ch, CHAR_DATA *viewer, char *buf ) { int cnt, leng; int attacks; char buf2[MAX_INPUT_LENGTH]; push_call("get_attack_string(%p,%p,%p)",ch,viewer,buf); if (ch == NULL) { pop_call(); return; } leng = str_cpy_max( buf, "{138} Total Player Killer Attacks:\n\r", MAX_STRING_LENGTH); attacks=0; for (cnt = 0; cnt < MAX_PK_ATTACKS ; cnt++) { if (ch->pcdata->last_pk_attack_time[cnt] > 0) { attacks++; if( ch->pcdata->last_pk_attack_time[cnt] > mud->current_time ) { sprintf( buf2, "{178}%12s till {128}%s\n\r", ch->pcdata->last_pk_attack_name[cnt], get_time_string(ch->pcdata->last_pk_attack_time[cnt])); } else { sprintf( buf2, "{078}%12s till {028}%s\n\r", ch->pcdata->last_pk_attack_name[cnt], get_time_string(ch->pcdata->last_pk_attack_time[cnt])); } leng = str_apd_max( buf, buf2, leng, MAX_STRING_LENGTH ); } } if (attacks == 0 ) { if ( viewer == ch ) { sprintf( buf, "{138} You have never been attacked.\n\r" ); } else { sprintf( buf, "{138} %s has never been attacked.\n\r", ch->name ); } } pop_call(); return; } /* Code for total and max pvnum attacks - Chaos 4/20/99 */ bool check_add_attack( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("check_add_attack(%p,%p)",ch,victim); /* Killers and Thieves can always be attacked - Scandum 07/02/02 */ if (!IS_NPC(ch) && !IS_NPC(victim)) { int oldest_attack, total_pvnum_attacks, attacks_today, cnt; attacks_today = 0; oldest_attack = 0; total_pvnum_attacks = 0; for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++) { if (victim->pcdata->last_pk_attack_time[cnt] == 0) { oldest_attack = cnt; } else if (victim->pcdata->last_pk_attack_time[oldest_attack] > victim->pcdata->last_pk_attack_time[cnt]) { oldest_attack = cnt; } if (victim->pcdata->last_pk_attack_time[cnt] > mud->current_time) { attacks_today++; } if (ch->pcdata->pvnum == victim->pcdata->last_pk_attack_pvnum[cnt] && victim->pcdata->last_pk_attack_time[cnt] > mud->current_time) { total_pvnum_attacks++; } } if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF)) { if (attacks_today >= MAX_PK_ATTACKS) { pop_call(); return( FALSE ); } if (total_pvnum_attacks >= 5) { pop_call(); return( FALSE ); } victim->pcdata->last_pk_attack_time[oldest_attack] = mud->current_time + 60 * 60 * 6; victim->pcdata->last_pk_attack_pvnum[oldest_attack] = ch->pcdata->pvnum; STRFREE(victim->pcdata->last_pk_attack_name[oldest_attack]); victim->pcdata->last_pk_attack_name[oldest_attack] = STRALLOC(ch->name); } } pop_call(); return( TRUE ); } /* Scandum 14-01-2003 */ void clear_attack_list( CHAR_DATA *ch ) { int cnt; push_call("clear_attack_list(%p)",ch); for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++) { ch->pcdata->last_pk_attack_time[cnt] = 0; STRFREE(ch->pcdata->last_pk_attack_name[cnt]); ch->pcdata->last_pk_attack_name[cnt] = STRDUPE(str_empty); } pop_call(); return; } void spam_attack_list( CHAR_DATA *ch ) { int cnt; push_call("spam_attack_list(%p)",ch); for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++) { ch->pcdata->last_pk_attack_time[cnt] = mud->current_time + 60 * 60 * 24; ch->pcdata->last_pk_attack_pvnum[cnt] = 0; STRFREE(ch->pcdata->last_pk_attack_name[cnt]); ch->pcdata->last_pk_attack_name[cnt] = STRDUPE(str_empty); } pop_call(); return; }