Dual Wield
For Circle 3.0 BPL 17
By LordKaT
(Circle@si.rr.com)
Well I figure after my OH-SO-POPULAR limit PK for
BPL16 I might as well release YADWCS (Yet Another Duel Wield Code Snippet)
First off, I would like to thank Fire for the original code to duel wield.
Next, Im not responcible if your computer blows up, mud goes boom, or a
horrid dismemberment as a result of this code.
Special Note:
I use a heavily modified Cirlce 3.0 BPL 17 with races, *real* two handed
weapons, an exploding Puff the Dragon, A Newbie-zone guard, skill/spell
proficency increase-on-use and other such fun stuff. Yes, you all have
credit where credit is due the only problem is that the mud aint up yet
Anyway here we go.
Stuff you will need:
spells.h
structs.h
act.item.c
class.c
constants.c
fight.c
spell_parser.c
A large bladder
Several cups of pig's blood (for added effect)
---spells.h---
Under the Player Skills defenitions add:
#define SKILL_DUAL_WIELD xxx
where 'xxx' is the next number in the list
---structs.h---
Under the character equipment positions add:
#define WEAR_DWIELD xxx
where 'xxx' is the next number in the list
dont forget to change NUM_WEARS to one more than its currenlt number
(in stock, it should now, after adding WEAR_DWIELD, read 19)
---act.item.c---
In the function find_eq_pos find the line that reads:
if (CAN_WEAR(obj, ITEM_WEAR_SHIELD))
And change to:
if (CAN_WEAR(obj, ITEM_WEAR_SHIELD) && (!GET_EQ(ch, WEAR_DWIELD)))
Note: On my source the 'where =...' line is on the next line of each if
statement I belive in stock they are on the same line.
In the fucntion wear_message, in the const char *wear_messages add:
{
"$n wields $p.",
"You wield $p."
}
right after the 'holds' messages. Also, do not forget to add the extra
comma after the closing bracket of the holds messages.
In the function perform_wear, in the const char *already_wearing
messages, add:
"You're already dual wielding a weapon.\r\n"
to the end of the list, remebering to add an extra comma at the end of
the 'already holding something' message or else you will get an error :)
Now in the same perform_wear function replace the original
if (GET_EQ(ch, wheere))
with this beefed up one:
if (GET_EQ(ch, where)) {
if (where == WEAR_WIELD)
if (!GET_EQ(ch, WEAR_DWIELD) && GET_SKILL(ch, SKILL_DUAL_WIELD))
where = WEAR_DWIELD;
else {
send_to_char(already_wearing[where], ch);
return;
}
}
In the ACMD(do_wield) function find the statement:
if (!*arg)
send_to_char("Wield what?\r\n", ch);
And directly underneath it place:
else if (GET_EQ(ch, WEAR_DWIELD))
send_to_char ("You are getting confused. Remove the secondary weapon first.\n\r", ch);
In the ACMD(do_grab) fucntion find the statement:
if (!*arg)
send_to_char("Hold what?\r\n", ch);
And directly underneath it place:
else if (GET_EQ(ch, WEAR_DWIELD))
send_to_char ("You cannot dual wield AND hold something.\n\r", ch);
In the ACMD(do_Remove) function find the statement:
if (!get_object_in_equip_vis(ch, arg, ch->equipment, &i)) {
sprintf(buf, "You don't seem to be using %s %s.\r\n", AN(arg), arg);
send_to_char(buf, ch);
} else
perform_remove(ch, i);
And directly underneath it place:
if (!GET_EQ(ch, WEAR_WIELD) && (GET_EQ(ch, WEAR_DWIELD)))
{
send_to_char("Since you are not wielding a weapon, you can't dual wield too!\r\n", ch);
perform_remove(ch, WEAR_DWIELD);
}
Note: this should remain in the else statement that is right above the
first if.
Here is the actual ACMD(do_dwield) function:
ACMD(do_dwield)
{
struct obj_data *obj;
one_argument(argument, arg);
if (IS_NPC(ch) || !GET_SKILL(ch, SKILL_DUAL_WIELD))
send_to_char("You have no idea how to do that.\r\n", ch);
else if (!*arg)
send_to_char("Dual wield what?\r\n", ch);
else if (!GET_EQ(ch, WEAR_WIELD))
send_to_char ("You must choose a primary weapon.\n\r", ch);
else if (FIGHTING(ch))
send_to_char("You are too busy fighting to attempt that!\r\n", ch);
else if (GET_EQ(ch, WEAR_SHIELD))
send_to_char ("You cannot dual wield while using a shield.\n\r", ch);
else if (GET_EQ(ch, WEAR_HOLD))
send_to_char ("You can't dual wield while holding an item.\n\r", ch);
else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) {
sprintf(buf, "You don't seem to have %s %s.\r\n", AN(arg), arg);
send_to_char(buf, ch);
}
// this next else statement is just an example of how to
// prevent 2 two hamded weapons from being dual wielded
// edit this if you need to, or simple delete it.
else if (IS_OBJ_STAT(obj, ITEM_TWO_HANDED) && GET_EQ(ch, WEAR_WIELD))
send_to_char("You cant hold 2 two-handed weapions.\r\n", ch);
else {
if (!CAN_WEAR(obj, ITEM_WEAR_WIELD))
send_to_char("You can't wield that.\r\n", ch);
else if (GET_LEVEL(ch) == LVL_IMPL)
perform_wear(ch, obj, WEAR_DWIELD);
else if (GET_OBJ_WEIGHT(obj) > str_app[STRENGTH_APPLY_INDEX(ch)].wield_w && GET_LEVEL(ch) < LVL_IMPL)
send_to_char("It's too heavy for you to use.\r\n", ch);
else
perform_wear(ch, obj, WEAR_DWIELD);
}
}
---class.c---
In the Spell/Skill table where you define what Spell/Skill the classes
have add:
spell_level(SKILL_DUAL_WIELD, CLASS_WARRIOR, 10);
Feel free to change the class/level or whatever
---constants.c---
In the const char *where[] add:
" "
as your last statement in there, right befor the };
In the const char *equipment_types[] add:
"Dual wielded",
As your second to last entry, "\n" should be last.
In the const char *wear_bits[] add:
"DWIELD",
As your second to last entry, "\n" should be last.
---fight.c---
Add this function right after the hit function. This is just a carbon copy
of hit, with just a different name, however for this to work, the hit
function will have to be edited.
void double_hit(struct char_data * ch, struct char_data * victim, int type)
{
struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
int w_type, victim_ac, calc_thaco, dam, diceroll;
/* Do some sanity checking, in case someone flees, etc. */
if (ch->in_room != victim->in_room) {
if (FIGHTING(ch) && FIGHTING(ch) == victim)
stop_fighting(ch);
return;
}
/* Find the weapon type (for display purposes only) */
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON)
w_type = GET_OBJ_VAL(wielded, 3) + TYPE_HIT;
else {
if (IS_NPC(ch) && (ch->mob_specials.attack_type != 0))
w_type = ch->mob_specials.attack_type + TYPE_HIT;
else
w_type = TYPE_HIT;
}
/* Calculate the THAC0 of the attacker */
if (!IS_NPC(ch))
calc_thaco = thaco((int) GET_CLASS(ch), (int) GET_LEVEL(ch));
else /* THAC0 for monsters is set in the HitRoll */
calc_thaco = 20;
calc_thaco -= str_app[STRENGTH_APPLY_INDEX(ch)].tohit;
calc_thaco -= GET_HITROLL(ch);
calc_thaco -= (int) ((GET_INT(ch) - 13) / 1.5); /* Intelligence helps! */
calc_thaco -= (int) ((GET_WIS(ch) - 13) / 1.5); /* So does wisdom */
/* Calculate the raw armor including magic armor. Lower AC is better. */
victim_ac = compute_armor_class(victim) / 10;
/* roll the die and take your chances... */
diceroll = number(1, 20);
/* decide whether this is a hit or a miss */
if ((((diceroll < 20) && AWAKE(victim)) && ((diceroll == 1) || ((calc_thaco - diceroll) > victim_ac)))) {
/* the attacker missed the victim */
if (type == SKILL_BACKSTAB)
damage(ch, victim, 0, SKILL_BACKSTAB);
else
damage(ch, victim, 0, w_type);
} else {
/* okay, we know the guy has been hit. now calculate damage. */
/* Start with the damage bonuses: the damroll and strength apply */
dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
dam += GET_DAMROLL(ch);
/* Maybe holding arrow? */
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
/* Add weapon-based damage if a weapon is being wielded */
dam += dice(GET_OBJ_VAL(wielded, 1), GET_OBJ_VAL(wielded, 2));
} else {
/* If no weapon, add bare hand damage instead */
if (IS_NPC(ch)) {
dam += dice(ch->mob_specials.damnodice, ch->mob_specials.damsizedice);
} else {
dam += number(0, 2); /* Max 2 bare hand damage for players */
}
}
if (GET_POS(victim) < POS_FIGHTING)
dam *= 1 + (POS_FIGHTING - GET_POS(victim)) / 3;
/* at least 1 hp damage min per hit */
dam = MAX(1, dam - (dam / 2));
if (type == SKILL_BACKSTAB) {
dam *= backstab_mult(GET_LEVEL(ch));
damage(ch, victim, dam, SKILL_BACKSTAB);
}
else
damage(ch, victim, dam, w_type);
}
}
In the actual hit fucntion itself, change the FINAL else statement to look like:
else {
damage(ch, victim, dam, w_type);
if (GET_EQ(ch, WEAR_DWIELD) && GET_HIT(victim) > 0)
double_hit(ch, FIGHTING(ch), TYPE_UNDEFINED);
}
You can do away with double_hit and replace it with damage however this
results in a loss of 2 attempts and one attack will just mimick the other.
---spell_parser.c---
In mag_assign_spells, as the last entry befor the final closing } add:
skillo(SKILL_DUAL_WIELD, "dual wield");
*sigh*
Finally done with this text file.
If I screwed up, let me know by e-mailing Circle@si.rr.com with your
question/complaint
But, This should work, even if your Circle has been heavily modified
Remeber, this is for 3.0 BPL 17 :)
--LordKaT