Exemplo n.º 1
0
/*
 * Check if an object is melee weapon and allows wielding with two-hands
 */
bool object_allow_two_hands_wielding(object_type *o_ptr)
{
	if (object_is_melee_weapon(o_ptr) && ((o_ptr->weight > 99) || (o_ptr->tval == TV_POLEARM))) return TRUE;

	/* Hack: Shield Mastery technique */
	if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH && object_is_shield(o_ptr)) return TRUE;
	return FALSE;
}
Exemplo n.º 2
0
void
combat_attack(Character *who, Character *whom)
{

    int dir;
    int tohit, damage, damage1, damage2, damage_reduced;
    int hits, hits2, luck1, luck2;
    int i;
    int item, weapon_skill;
    char *attack_type;
    int bonus;

    who->ap -= COMBAT_ATTACK_COST;

    if (abs(who->x - whom->x) > abs(who->y - whom->y)) {
        if (who->x > whom->x)
            dir = CHARACTER_LEFT;
        else
            dir = CHARACTER_RIGHT;
    } else {
        if (who->y > whom->y)
            dir = CHARACTER_UP;
        else
            dir = CHARACTER_DOWN;
    }


    character_attack(who, dir);



    tohit = 0;

    if (game_in_party(who))
        damage = 4;             /* bare hand */
    else
        damage = 6;             /* something better */

    attack_type = "swings";

    /* when unarmed, brawl is in effect */
    weapon_skill = 0x40;

    bonus = 0;

    for (i = 0; i < who->items_num; ++i)
        if (who->item_used[i]) {
            item = who->items[i];
            if (object_is_weapon(item)) {
                weapon_skill = object_weapon_skill(item);
                damage = object_weapon_damage(item);
                tohit += object_weapon_to_hit(item);
                if (object_weapon_class(item) == 8)     /* bow */
                    attack_type = "fires";

                /* Sting, Glamdring, Anduril, Durin's Axe, Magic Bow */
                if (item == 0x60 || item == 0x63 || item == 0x62
                    || item == 0x67 || item == 0x65)
                    bonus = 1;

                /* Spider Sword */
                if (item == 0x64 && strcmp(whom->name, "Spider"))
                    bonus = 1;

                /* Troll Slayer */
                if (item == 0x66 &&
                    (strcmp(whom->name, "Troll") ||
                     strcmp(whom->name, "Olog-hai")))
                    bonus = 1;

            }

            /* armours have impairing effect */
            if (object_is_armour(item))
                tohit -= object_weapon_to_hit(item);
        }

    /* better chance to hit if we are skilled with our weapon */
    for (i = 0; i < who->skills_num; ++i)
        if (weapon_skill == who->skills[i]) {
            tohit += 2;
            break;
        }

    damage_reduced = 0;

    for (i = 0; i < whom->items_num; ++i)
        if (whom->item_used[i]) {
            item = who->items[i];

            /* armours have impairing effect */
            if (object_is_armour(item)) {
                damage_reduced = object_armour_reduced(item);
                tohit += object_weapon_to_hit(item);
            }

            if (object_is_shield(item))
                tohit -= object_shield_to_hit(item);
        }


    /* better chance to defend if we have dodge */
    for (i = 0; i < whom->skills_num; ++i)
        if (whom->skills[i] == 0x46) {
            tohit -= 2;
            break;
        }


    hits = combat_if_hits(who->dex, whom->dex, tohit);
    hits2 = combat_if_hits(who->dex, whom->dex, tohit);

    luck1 = lotr_rnd(30 + who->luck);
    luck2 = lotr_rnd(30 + who->luck);

    if (luck1 > 2 * luck2)
        hits = max(hits, hits2);

    if (2 * luck1 < luck2)
        hits = min(hits, hits2);


    /* Balrog must be a deadly foe */
    if (!strcmp(who->name, "Balrog")) {
        hits = 1;
        bonus = 1;
    }

    if (hits) {
        damage1 = lotr_rnd(who->str) / 10 + lotr_rnd(damage)
            + bonus * lotr_rnd(damage) - damage_reduced;
        damage2 = lotr_rnd(who->str) / 10 + lotr_rnd(damage)
            + bonus * lotr_rnd(damage) - damage_reduced;


        luck1 = lotr_rnd(30 + who->luck);
        luck2 = lotr_rnd(30 + who->luck);

        damage = damage1;

        if (luck1 > 2 * luck2)
            damage = max(damage1, damage2);

        if (2 * luck1 < luck2)
            damage = min(damage1, damage2);

        if (damage < 0)
            damage = 0;

        whom->life -= damage;
        if (whom->life < 0)
            whom->life = 0;

    }


    combat_who_attacked = whom;

    if (hits) {
        if (damage > 0) {
            if (whom->life == 0) {
                snprintf(combat_result_text, sizeof(combat_result_text), "%s kills %s.", who->name,
                         whom->name);
                combat_character_remove(whom);

            } else {
                if (whom->life >= 6 || !game_in_party(whom)) {
                    snprintf(combat_result_text, sizeof(combat_result_text),
                             "%s hits %s for %d points of damage.", who->name,
                             whom->name, damage);
                } else {
                    snprintf(combat_result_text, sizeof(combat_result_text),
                             "%s hits %s for %d points of damage, knocking %s out of cold.",
                             who->name, whom->name, damage, whom->name);
                }
            }
        } else {
            snprintf(combat_result_text, sizeof(combat_result_text), "%s hits %s but does no damage.",
                     who->name, whom->name);
        }
    } else {
        snprintf(combat_result_text, sizeof(combat_result_text), "%s %s at and misses %s.", who->name,
                 attack_type, whom->name);
    }

    if (hits)
        sound_play(10);
    else
        sound_play(11);

    combat_attack_animation = 1;

}
Exemplo n.º 3
0
void display_weapon_info(doc_ptr doc, int hand)
{
    object_type *o_ptr = equip_obj(p_ptr->weapon_info[hand].slot);
    char o_name[MAX_NLEN];
    u32b flgs[TR_FLAG_SIZE];
    int dd;
    int ds;
    int to_d = 0;
    int to_h = 0;
    int mult;
    critical_t crit = {0};
    int crit_pct = 0;
    int num_blow = NUM_BLOWS(hand);
    bool force = FALSE;
    doc_ptr cols[2] = {0};

    if (p_ptr->weapon_info[hand].wield_how == WIELD_NONE) return;
    if (!o_ptr) return;

    dd = o_ptr->dd + p_ptr->weapon_info[hand].to_dd;
    ds = o_ptr->ds + p_ptr->weapon_info[hand].to_ds;
    if (object_is_known(o_ptr))
    {
        to_d = o_ptr->to_d;
        to_h = o_ptr->to_h;
    }

    switch (display_weapon_mode)
    {
    case MAULER_STUNNING_BLOW:
    case MAULER_CRITICAL_BLOW:
    case MAULER_CRUSHING_BLOW:
    case MAULER_KNOCKBACK:
        num_blow = 100;
        break;
    case MAULER_KNOCKOUT_BLOW:
        num_blow = 100;
        to_h -= 50;
        break;
    case PY_POWER_ATTACK:
        to_h += 10;
        to_d += p_ptr->lev / 2;
        break;
    }

    weapon_flags_known(hand, flgs);
    if ( (have_flag(flgs, TR_FORCE_WEAPON) || p_ptr->tim_force) 
      && (p_ptr->csp > o_ptr->dd*o_ptr->ds/5) )
    {
        force = TRUE;
    }

    if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH && object_is_shield(o_ptr))
    {
        dd = 3 + p_ptr->weapon_info[hand].to_dd;
        ds = o_ptr->ac + p_ptr->weapon_info[hand].to_ds;
        if (object_is_known(o_ptr))
        {
            to_h = o_ptr->to_a;
            to_d = o_ptr->to_a;
            to_h += 2*o_ptr->to_h;
            to_d += 2*o_ptr->to_d;
        }
    }

    mult = 100;
    if (have_flag(flgs, TR_VORPAL2))
        mult = mult * 5 / 3;
    else if (have_flag(flgs, TR_VORPAL))
        mult = mult * 11 / 9;

    mult += mult * p_ptr->weapon_info[hand].to_mult / 100;

    if (display_weapon_mode == MAULER_CRUSHING_BLOW)
    {
        int d = p_ptr->lev/5;
        int n = 10*(1 + d)/2; /* scale by 10 */

        mult = mult * (50 + n)/30;
    }

    if (!have_flag(flgs, TR_ORDER))
    {
        const int attempts = 10 * 1000;
        int i;
        int crits = 0;
        /* Compute Average Effects of Criticals by sampling */
        for (i = 0; i < attempts; i++)
        {
            critical_t tmp = critical_norm(o_ptr->weight, to_h, p_ptr->weapon_info[hand].to_h, display_weapon_mode, hand);
            if (tmp.desc)
            {
                crit.mul += tmp.mul;
                crit.to_d += tmp.to_d;
                crits++;
            }
            else
                crit.mul += 100;
        }
        crit.mul = crit.mul / attempts;
        crit.to_d = crit.to_d * 100 / attempts;
        crit_pct = crits * 1000 / attempts;
    }
    else
        crit.mul = 100;


    /* Display in 2 columns, side by side */
    cols[0] = doc_alloc(60);
    cols[1] = doc_alloc(10);

    /* Column #1 */
    object_desc(o_name, o_ptr, OD_COLOR_CODED | OD_NAME_AND_ENCHANT);
    if (prace_is_(RACE_MON_SWORD))
        doc_printf(cols[0], "<color:y> You    :</color> <indent><style:indent>%s</style></indent>\n", o_name);
    else
        doc_printf(cols[0], "<color:y> Hand #%d:</color> <indent><style:indent>%s</style></indent>\n", hand+1, o_name);

    doc_printf(cols[0], " %-7.7s: %d.%d lbs\n", "Weight", o_ptr->weight/10, o_ptr->weight%10);

    if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH)
    {
        assert(o_ptr->tval == TV_SHIELD);
        doc_printf(cols[0], " %-7.7s: %dd%d (%+d,%+d)\n", "Bash", dd, ds, to_h, to_d);
        doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n",
                    "Profic",
                    skills_shield_describe_current(o_ptr->sval),
                    skills_shield_calc_bonus(o_ptr->sval));
    }
    else
    {
        doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n",
                    "Profic",
                    skills_weapon_describe_current(o_ptr->tval, o_ptr->sval),
                    skills_weapon_calc_bonus(o_ptr->tval, o_ptr->sval));
    }
    doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Hit", to_h, p_ptr->weapon_info[hand].to_h, to_h + p_ptr->weapon_info[hand].to_h);
    doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Dam", to_d, p_ptr->weapon_info[hand].to_d, to_d + p_ptr->weapon_info[hand].to_d);
    doc_printf(cols[0], " %-7.7s: %d.%2.2d\n", "Blows", num_blow/100, num_blow%100);

    if (p_ptr->weapon_info[hand].dual_wield_pct < 1000)
    {
        doc_printf(cols[0], " %-7.7s: %d.%d%%\n", "Skill",
            p_ptr->weapon_info[hand].dual_wield_pct/ 10,
            p_ptr->weapon_info[hand].dual_wield_pct % 10);
    }

    mult = mult * crit.mul / 100;
    to_d = to_d + crit.to_d/100 + p_ptr->weapon_info[hand].to_d;

    doc_printf(cols[0], "<color:G> %-7.7s</color>\n", "Damage");

    if (!have_flag(flgs, TR_ORDER))
    {
        if (crit.to_d)
        {
            doc_printf(cols[0], " %-7.7s: %d.%02dx + %d.%02d\n", "Crits",
                            crit.mul/100, crit.mul%100, crit.to_d/100, crit.to_d%100);
        }
        else
        {
            doc_printf(cols[0], " %-7.7s: %d.%02dx (%d.%d%%)\n", "Crits",
                            crit.mul/100, crit.mul%100, crit_pct / 10, crit_pct % 10);
        }
    }
    if (p_ptr->weapon_info[hand].to_mult)
    {
        int m = 100 + p_ptr->weapon_info[hand].to_mult;
        doc_printf(cols[0], " %-7.7s: %d.%02dx\n", "Mauler", m / 100, m % 100);
    }


    _display_weapon_slay(mult, 100, FALSE, num_blow, dd, ds, to_d, "Normal", TERM_WHITE, cols[0]);
    if (force)
        _display_weapon_slay(mult, 100, force, num_blow, dd, ds, to_d, "Force", TERM_L_BLUE, cols[0]);

    if (p_ptr->tim_slay_sentient)
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Sent.", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_ANIMAL)) 
        _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_ANIMAL))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_EVIL))   
        _display_weapon_slay(mult, 350, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_EVIL))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_SLAY_GOOD))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Good", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_SLAY_LIVING))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Living", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_HUMAN))
        _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_HUMAN))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_UNDEAD))
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_UNDEAD))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_DEMON))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_DEMON))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_ORC))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_ORC))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_TROLL))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_TROLL))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_GIANT))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_GIANT))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_DRAGON))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_DRAGON))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_BRAND_ACID))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Acid", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_ELEC))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Elec", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_FIRE))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Fire", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_COLD))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Cold", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_POIS))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Poison", TERM_RED, cols[0]);

    if (p_ptr->weapon_info[hand].wield_how == WIELD_TWO_HANDS)
    {
        if (p_ptr->weapon_info[hand].omoi)
            doc_insert(cols[0], " Your weapon requires two hands to wield properly.\n");
    }

    if (p_ptr->weapon_info[hand].info)
    {
        byte a = p_ptr->weapon_info[hand].info_attr;
        if (!a) a = TERM_WHITE; /* uninitialized is TERM_DARK???! */
        doc_printf(cols[0], " <color:%c>%s</color>\n", attr_to_attr_char(a), p_ptr->weapon_info[hand].info);
    }

    /* Column #1 */
    doc_insert(cols[1], "<color:G>Accuracy</color>\n");
    doc_insert(cols[1], " AC Hit\n");

    doc_printf(cols[1], "%3d %2d%%\n", 25, hit_chance(hand, to_h, 25));
    doc_printf(cols[1], "%3d %2d%%\n", 50, hit_chance(hand, to_h, 50));
    doc_printf(cols[1], "%3d %2d%%\n", 75, hit_chance(hand, to_h, 75));
    doc_printf(cols[1], "%3d %2d%%\n", 100, hit_chance(hand, to_h, 100));
    doc_printf(cols[1], "%3d %2d%%\n", 125, hit_chance(hand, to_h, 125));
    doc_printf(cols[1], "%3d %2d%%\n", 150, hit_chance(hand, to_h, 150));
    doc_printf(cols[1], "%3d %2d%%\n", 175, hit_chance(hand, to_h, 175));
    doc_printf(cols[1], "%3d %2d%%\n", 200, hit_chance(hand, to_h, 200));

    /* Assemble the result */
    doc_insert_cols(doc, cols, 2, 1);
    doc_free(cols[0]);
    doc_free(cols[1]);
}
Exemplo n.º 4
0
void
combat_start(void)
{

    int i, j;
    int leader_x, leader_y;

    combat_mode = 1;
    music_combat_started();
    quit_menu();
    combat_attack_animation = 0;

    map_get_center(&combat_x, &combat_y);

    combat_x /= 8;
    combat_y /= 8;

    combat_x -= COMBAT_C_X;
    combat_y -= COMBAT_C_Y;


    combat_party_size = game_get_party_characters(combat_party);

    combat_leader_x = game_get_leader()->x;
    leader_x = combat_leader_x / 4 - combat_x;
    combat_leader_y = game_get_leader()->y;
    leader_y = combat_leader_y / 4 - combat_y;

    if (leader_x < 0)
        leader_x = 0;
    if (leader_y < 0)
        leader_y = 0;
    if (leader_x >= COMBAT_WIDTH)
        leader_x = COMBAT_WIDTH - 1;
    if (leader_y >= COMBAT_HEIGHT)
        leader_x = COMBAT_HEIGHT - 1;


    combat_area_init();

    combat_area[leader_x][leader_y] = 1;
    combat_stack[0][0] = leader_x;
    combat_stack[0][1] = leader_y;
    combat_stack_size = 1;
    combat_stack_start = 0;
    combat_stack_proceed();


    for (i = 0; i < combat_party_size; ++i)
        combat_move_to_area(combat_party[i]);

    ring_not_working = 0;

    for (i = 0; i < combat_enemies_num; ++i) {
        /* somewhat stupid */
        if (!strcmp(combat_enemies[i]->name, "Nazgul") ||
            !strcmp(combat_enemies[i]->name, "Witch-King") ||
            !strcmp(combat_enemies[i]->name, "Ghostking") ||
            !strcmp(combat_enemies[i]->name, "Ghost") ||
            !strcmp(combat_enemies[i]->name, "Balrog") ||
            !strcmp(combat_enemies[i]->name, "Barrow Wight") ||
            !strcmp(combat_enemies[i]->name, "Werewolf"))
            ring_not_working = 1;

        if (strcmp(combat_enemies[i]->name, "Tentacles"))
            combat_move_to_area(combat_enemies[i]);

        for (j = 0; j < combat_enemies[i]->items_num; ++j)
            combat_enemies[i]->item_used[j] = 0;

        for (j = 0; j < combat_enemies[i]->items_num; ++j)
            if (object_is_weapon(combat_enemies[i]->items[j])) {
                combat_enemies[i]->item_used[j] = 1;
                break;
            }

        for (j = 0; j < combat_enemies[i]->items_num; ++j)
            if (object_is_armour(combat_enemies[i]->items[j])) {
                combat_enemies[i]->item_used[j] = 1;
                break;
            }

        for (j = 0; j < combat_enemies[i]->items_num; ++j)
            if (object_is_shield(combat_enemies[i]->items[j])) {
                combat_enemies[i]->item_used[j] = 1;
                break;
            }

    }

    active_character = NULL;
    combat_next_turn();

}