From: gbarnett@polarnet.com Subject: Fireweapons I'd like to take this opportunity to contribute something to the list. Any constructive criticism is welcome. This code implements ranged combat using the FIREWEAPON and MISSILE item types. Included is the do_fire procedure, the message data structure, the do_load_weapon procedure, and an update to look_in_obj. Not included: How to add the skill SHOOT and the interpreter stuff for the load/reload and shoot/fire commands. I would appreciate an email if you use the code.. I'm intersted in knowing if anyone found it useful.. and more to the point..written well enough to use..even as a starting point .. :) A couple notes: This is built on the assumption of 1-100 stats.. You'll want to modify the 'if we hit' section to suit your mud's specific stat/skill setup. No flames on the method of calculating a hit, please.. it'll be changed on my mud too.. once I finalize all the balance issues... Fireweapon Item setup Value 0: Missile Type 1: missile vnum (unused) 2: Max ammo 3: Current Ammo Missile Item setup Value 0: Missile Type 1: Quality (unused) 2: Missile Action (unused) 3: Current Ammo gbarnett@polarnet.com - http://www.polarnet.com/Users/gbarnett/ - telnet:mud.polarnet.com (4000) ---- To start, in act.info.c, this section of code should be added to look_in_obj: } else if ((GET_OBJ_TYPE(obj) != ITEM_DRINKCON) && (GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN) && (GET_OBJ_TYPE(obj) != ITEM_CONTAINER)) + { + if ( (GET_OBJ_TYPE(obj) == ITEM_FIREWEAPON) || + (GET_OBJ_TYPE(obj) == ITEM_MISSILE) ) { + sprintf(buf, "It contains %d units of ammunition.\r\n", GET_OBJ_VAL(obj,3)) ; + send_to_char(buf,ch); + } else { + send_to_char("There's nothing inside that!\r\n", ch); + } } else { if (GET_OBJ_TYPE(obj) == ITEM_CONTAINER) { if (IS_SET(GET_OBJ_VAL(obj, 1), CONT_CLOSED)) ---- In constant.c: const char *shot_types[] = { "a missile", "a bullet", "an arrow", "a bolt", "a shell", "a rocket", "\n" }; const int shot_damage[] = { 25, 35, 25, 35, 50, 75, 0 }; ---- Then in act.other.c or fight.c, put these two functions: ACMD(do_load_weapon) { /* arg1 = fire weapon arg2 = missiles */ char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; struct obj_data *missile; struct obj_data *weapon = GET_EQ(ch, WEAR_HOLD); int num_needed = 0; int num_left = 0; int num_ammo = 0; two_arguments(argument, arg1, arg2); if (!*arg1 || !*arg2) { send_to_char("Usage LOAD|RELOAD ",ch); return; } if (!weapon) { send_to_char("You must hold the weapon to load it.",ch); return; } if (GET_OBJ_TYPE(weapon) != ITEM_FIREWEAPON) { send_to_char("That item doesn't use ammunition!",ch); return; } missile = get_obj_in_list_vis(ch, arg2, ch->carrying); if (!missile) { send_to_char("What are you trying to use as ammunition?",ch); return; } if (GET_OBJ_TYPE(missile) != ITEM_MISSILE) { send_to_char("That isn't ammunition!",ch); return; } if (GET_OBJ_VAL(missile,0) != GET_OBJ_VAL(weapon,0)) { send_to_char("The ammunition won't fit in the weapon!",ch); return; } num_needed = GET_OBJ_VAL(weapon,2) - GET_OBJ_VAL(weapon,3); if (!num_needed) { send_to_char("It's already fully loaded.",ch); return; } num_ammo = GET_OBJ_VAL(missile,3); if (!num_ammo) { /* shouldn't really get here.. this one's for Murphy :) */ send_to_char("It's empty!",ch); extract_obj(missile); return; } if (num_ammo <= num_needed) { GET_OBJ_VAL(weapon,3) += num_ammo; extract_obj(missile); } else { GET_OBJ_VAL(weapon,3) += num_needed; GET_OBJ_VAL(missile,3) -= num_needed; } act("You load $p", FALSE, ch, weapon, 0, TO_CHAR); act("$n loads $p", FALSE, ch, weapon, 0, TO_ROOM); } ACMD(do_fire) { /* fire [direction] */ char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; char argt[MAX_INPUT_LENGTH]; struct obj_data *weapon; struct char_data *vict; int target_room = -1; int source_room = -1; int far_room = 0; int num1 = 0; int num2 = 0; int roll = 0; int dmg = 0; half_chop(argument, arg1, argt); half_chop(argt, arg2, arg3); /* arg1 = weapon arg2= victim arg3= direction */ if (!*arg1 || !*arg2) { send_to_char("Usage: FIRE [direction]",ch); return; } if (ROOM_FLAGGED(ch->in_room, ROOM_PEACEFUL)) { send_to_char("This room just has such a peaceful, easy feeling...\r\n", ch ); return; } if (!GET_SKILL(ch, SKILL_SHOOT)) { send_to_char("You aren't trained in the use of this weapon.",ch); return; } weapon = GET_EQ(ch, WEAR_HOLD); if (!weapon) { sprintf(buf2, "You aren't holding %s!\r\n",arg1); send_to_char(buf2, ch); return; } if ( (GET_OBJ_TYPE(weapon) != ITEM_FIREWEAPON) ) { send_to_char("You can't fire that!",ch); return; } if ( !GET_OBJ_VAL(weapon, 3) ) { send_to_char("It isn't loaded.",ch); return; } if (*arg3) { /* attempt to fire direction x */ far_room = -1; switch (arg3[0]) { case 'n': case 'N': far_room = 0; break; case 'e': case 'E': far_room = 1; break; case 's': case 'S': far_room = 2; break; case 'w': case 'W': far_room = 3; break; case 'u': case 'U': far_room = 4; break; case 'd': case 'D': far_room = 5; break; } if (far_room == -1 ) { send_to_char("Invalid direction given. Valid values are N, E, S, W, U, D.",ch ); return; } if (CAN_GO(ch, far_room)) { target_room = world[ch->in_room].dir_option[far_room]->to_room; } if (target_room == -1) { send_to_char("You can't find anything worth firing at in that direction.",ch) ; return; } source_room = ch->in_room; ch->in_room = target_room; vict = get_char_room_vis(ch, arg2); ch->in_room = source_room; if (!vict) { sprintf(buf, "There doesn't seem to be a %s that way.",arg2); send_to_char(buf, ch); return; } } else { vict = get_char_room_vis(ch, arg2); if ((!*arg2) || (!vict)) { act("Who are you trying to fire $p at?", FALSE, ch, weapon, 0, TO_CHAR); return; } } /* ok.. got a loaded weapon, the victim is identified */ GET_OBJ_VAL(weapon, 3) -= 1; num1 = GET_DEX(ch) - GET_DEX(vict); if (num1 > 25) num1 = 25; if (num1 < -25) num1 = -25; num2 = GET_SKILL(ch, SKILL_SHOOT); num2 = (int)(num2 * .75); if (num2 < 1) num2 = 1; roll = number(1, 101); /* strcpy(argt, shot_types[GET_OBJ_VAL(weapon, 0)]); */ sprintbit((long) GET_OBJ_VAL(weapon, 0), shot_types, argt); if ( (num1+num2) >= roll ) { /* we hit 1) print message in room. 2) print rush message for mob in mob's room. 3) trans mob 4) set mob to fighting ch */ sprintf(buf, "You hit $N with %s fired from $p!", argt); act(buf, FALSE, ch, weapon, vict, TO_CHAR); sprintf(buf, "$n hit you with %s fired from $p!", argt); act(buf, FALSE, ch, weapon, vict, TO_VICT); sprintf(buf, "$n hit $N with %s fired from $p!", argt); act(buf, FALSE, ch, weapon, vict, TO_NOTVICT); act("$n rushes at $N and attacks!",FALSE, vict, 0, ch, TO_NOTVICT); act("$n rushes at you and attacks!",FALSE, vict, 0, ch, TO_VICT); act("You rush at $N and attack!",FALSE, vict, 0, ch, TO_CHAR); char_from_room(vict); char_to_room(vict, ch->in_room); act("$n rushes at $N and attacks!",FALSE, vict, 0, ch, TO_NOTVICT); dmg = shot_damage[GET_OBJ_VAL(weapon, 0)]; damage(ch, vict, dmg, TYPE_UNDEFINED); } else { /* we missed 1) print miss message */ sprintf(buf, "You fire %s at $N and miss!", argt); act(buf, FALSE, ch, weapon, vict, TO_CHAR); sprintf(buf, "$n fires %s at you and misses!", argt); act(buf, FALSE, ch, weapon, vict, TO_VICT); sprintf(buf, "$n fires %s at $N and misses!", argt); act(buf, FALSE, ch, weapon, vict, TO_NOTVICT); } }