// $Id: skills.cc,v 1.11.2.19 2000/06/28 01:34:29 greear Exp $
// $Revision: 1.11.2.19 $ $Author: greear $ $Date: 2000/06/28 01:34:29 $
//
//ScryMUD Server Code
//Copyright (C) 1998 Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred)
// greearb@agcs.com
//
//*********************** skills.cc ********************//
#include "misc.h"
#include "misc2.h"
#include "classes.h"
#include "spells.h"
#include "battle.h"
#include "skills.h"
#include "commands.h"
#include "batl_prc.h"
#include "socials.h"
#include "social2.h"
#include <PtrArray.h>
#include "load_wld.h"
#include "SkillSpell.h"
int track(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
// log("In track\n");
int p_lrnd = get_percent_lrnd(TRACK_SKILL_NUM, pc);
if (p_lrnd == 0) {
pc.show(CS_TRACK_DUH);
return -1;
}
/* check for miss on skill */
if ((d(1, p_lrnd) * 4) < d(1,100)) {
Sprintf(buf, "You sense a trail to the %S.\n",
door_list[d(1,8)].names.peekFront());
show(buf, pc);
return 0;
}//if
if (!victim) {
mudlog.log(ERROR, "ERROR: NULL(s) sent to track().\n");
}//if
else if (pc.isMob()) {
mudlog.log(ERROR, "ERROR: mob trying to track..\n");
}//if
else if (pc.POS != POS_STAND) {
show("You must be standing in order to track.\n",
pc);
}//if
else if (!pc.IS_FIGHTING.isEmpty()) {
show("You can't track while you're fighting!!\n", pc);
}//if
else if (!victim->Strlen()) {
show("Track who??\n", pc);
}//if
else { //ok, should be good to go
int znum = pc.getCurZoneNum();
int in_room;
// this fn sets in_room btw.
crit_ptr = room::haveCritNamedInZone(ZoneCollection::instance().elementAt(znum),
i_th, victim, pc.SEE_BIT, in_room);
if (!crit_ptr) {
show("That person is not found in these parts.\n", pc);
}//if
else {
if (pc.getCurRoomNum() == in_room) {
show("You're already here!\n", pc);
}//if
else {
List<int> path;
path_from_a_to_b(pc.getCurRoomNum(), in_room, path);
/*log("TRACK: HERE IS PATH.\n");
Cell<int> tcll(path);
int tint;
while (tint = Next(tcll)) {
Sprintf(buf, "TRACK: %i ", tint);
log(buf);
}//while
*/
if (path.isEmpty()) {
show("You can't get there from here!\n", pc);
}//if
else {
Cell<door*> cll(ROOM.DOORS);
door* ptr;
path.popFront(); //get rid of first one
while ((ptr = cll.next())) {
if (abs(ptr->destination) == path.peekFront()) {
Sprintf(buf, "You sense a trail leading %S.\n",
direction_of_door(*ptr));
show(buf, pc);
return 0;
}//if
}//while
Sprintf(buf, "TRACK: no exit to this room: %i\n",
path.peekFront());
//log(buf);
show(buf, pc);
}//else got some kinda path
}//else not already in same room
}//else found a crit ptr
}//else, good to go
return -1;
}//track
int trip(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
if (!victim->Strlen()) {
if (!(crit_ptr = pc.IS_FIGHTING.peekFront())) {
show("Trip who?\n", pc);
return -1;
}//if
}//if
else {
crit_ptr = ROOM.haveCritNamed(i_th, victim, pc.SEE_BIT);
}//if
if (crit_ptr) {
if (crit_ptr == &pc) {
show("You trip over your own two feet!\n", pc);
return 0;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, pc.getCurRoomNum(),
TRUE, i_th, victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(crit_ptr, "SVPFA", -1, pc)) {
return -1;
}//if
if (!(crit_ptr = check_for_diversions(*crit_ptr, "GM", pc)))
return -1;
return do_trip(*crit_ptr, pc);
}//if
else {
show("Trip who??\n", pc);
}//else
return -1;
}//trip
int do_trip(critter& vict, critter& pc) {
String buf(100);
short do_fatality = FALSE;
if ((vict.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: MOB sent to do_trip.\n");
return -1;
}//if
if (!pc.IS_FIGHTING.haveData(&vict)) {
join_in_battle(pc, vict);
}//if
if (skill_did_hit(pc, TRIP_SKILL_NUM, vict)) {
pc.PAUSE += 2; //increment pause_count
exact_raw_damage(d(4, 5), NORMAL, vict, pc);
vict.PAUSE += d(1,3);
vict.setPosn(POS_SIT);
Sprintf(buf, "trips %S.", name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
Sprintf(buf, "%S trips you!\n", name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You trip %S!\n", name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
if (vict.HP < 0) {
Sprintf(buf, "breaks %s neck as %s hits the ground!! ***CRACK***\n",
get_his_her(vict), get_he_she(vict));
emote(buf, vict, ROOM, TRUE);
do_fatality = TRUE;
}//if fatality
}//if
else { //missed
Sprintf(buf, "You nimbly dodge %S's attempt to trip you!\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf, "dodges %S's attempt to trip %s.",
name_of_crit(pc, ~0), get_him_her(vict));
emote(buf, vict, ROOM, TRUE, &pc);
Sprintf(buf, "%S dodges your attempt to trip %s.\n",
name_of_crit(vict, pc.SEE_BIT), get_him_her(vict));
show(buf, pc);
pc.PAUSE += 2; //increment pause_count
}//else
if (do_fatality) {
agg_kills_vict(&pc, vict);
}//if
return 0;
}//do_trip()
int steal(int i_th, const String* obj, int j_th, const String* victim,
critter& pc) {
critter* crit_ptr = NULL;
object* objptr = NULL;
int gold = FALSE;
String buf(100);
crit_ptr = ROOM.haveCritNamed(j_th, victim, pc.SEE_BIT);
if (crit_ptr) {
if (crit_ptr == &pc) {
show("There's a bright idea!\n", pc);
return 0;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, pc.getCurRoomNum(), TRUE,
i_th, victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(crit_ptr, "mSVPF", -1, pc)) {
return -1;
}//if
if (!obj->Strlen() || (strcasecmp(*obj, "gold") == 0)) {
gold = TRUE;
}//if
else {
objptr = have_obj_named(crit_ptr->inv, i_th, obj, pc.SEE_BIT,
ROOM);
}//else
return do_steal(objptr, *crit_ptr, pc, gold);
}//if
else {
show("Steal from who??\n", pc);
}//else
return -1;
}//steal
int do_steal(object* obj, critter& vict, critter& pc,
short steal_gold = FALSE) {
String buf(100);
int amt;
if (!vict.isImmort() && skill_did_hit(pc, STEAL_SKILL_NUM, vict)) {
if (obj && !obj_get_by(*obj, pc, TRUE, TRUE)) {
return -1;
}
/* it worked */
pc.PAUSE += 1; //increment pause_count
if (obj) {
vict.loseInv(obj);
pc.gainInv(obj);
/* no explicit penalties if you don't get caught! */
Sprintf(buf, "You successfully lift %S from %S!\n",
long_name_of_obj(*obj, pc.SEE_BIT),
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
}//if an object
else if (steal_gold) {
pc.GOLD += (amt = (d(1,vict.GOLD) / 4));
vict.GOLD -= amt;
/* no explicit penalties if you don't get caught! */
Sprintf(buf, "You successfully lift %i coins from %S!\n",
amt, name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
}//if
else { //!gold AND !obj, bad guess!!
show(
"You snoop around undetected, but don't find what you're looking for!\n",
pc);
return 0;
}//else
return 0;
}//if
else { //got caught!!!
Sprintf(buf, "%S catches you with your hands on %s things!!\n",
name_of_crit(vict, pc.SEE_BIT), get_his_her(vict));
show(buf, pc);
Sprintf(buf, "is caught trying to steal from %S.\n",
name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
Sprintf(buf, "You catch %S with %s hands in your pockets!.\n",
name_of_crit(pc, vict.SEE_BIT), get_his_her(pc));
show(buf, vict);
if (!vict.pc) {
if (!vict.mob->proc_data || (vict.mob->getBenevolence() < 5)) {
/* gonna be a whuppin! */
do_hit(pc, vict); //start battle
}//
else {
sob(1, &NULL_STRING, vict, room_list[vict.getCurRoomNum()]);
}//else
}//if
else {
if (pc.pc) { //P_STEAL
pc.PC_FLAGS.turn_on(20);
}//if
}//else
return -1;
}//else
return -1;
}//do_steal
int kick(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
if (!victim->Strlen()) {
if (!(crit_ptr = pc.IS_FIGHTING.peekFront())) {
show("Kick who?\n", pc);
return -1;
}//if
}//if
else {
crit_ptr = ROOM.haveCritNamed(i_th, victim, pc.SEE_BIT);
}//if
if (crit_ptr) {
if (crit_ptr == &pc) {
show("You kick yourself for your stupidity!\n", pc);
Sprintf(buf, "kicks %s.", get_himself_herself(pc));
emote(buf, pc, ROOM, TRUE);
return 0;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, pc.getCurRoomNum(), TRUE,
i_th, victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(crit_ptr, "SVPF", -1, pc)) {
return -1;
}//if
if (!(crit_ptr = check_for_diversions(*crit_ptr, "GM", pc)))
return -1;
return do_kick(*crit_ptr, pc);
}//if
else {
show("Kick who??\n", pc);
}//else
return -1;
}//kick
int do_kick(critter& vict, critter& pc) {
String buf(100);
short do_fatality = FALSE;
if ((vict.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: MOB sent to do_kick.\n");
return -1;
}//if
if (!pc.IS_FIGHTING.haveData(&vict)) {
join_in_battle(pc, vict);
}//if
if (skill_did_hit(pc, KICK_SKILL_NUM, vict)) {
pc.PAUSE += d(1,2); //increment pause_count
float d1 = (((float)(pc.STR)) * (float)(pc.getLevel()) + 5.0) / 60.0;
exact_raw_damage(d((int)d1, 5), NORMAL, vict, pc);
vict.PAUSE += d(1,3);
if (vict.HP < 0) {
Sprintf(buf, "kicks in %S's temple with %s foot!!\n",
name_of_crit(vict, ~0), get_his_her(pc));
emote(buf, pc, ROOM, TRUE, &vict);
Sprintf(buf,
"You see %S's foot racing straight for your temple...\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf,
"You crush %S's temple with your round-house kick!!\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
do_fatality = TRUE;
}//if fatality
else {
Sprintf(buf, "%S kicks you in the chest!\n",
name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You kick %S.\n", name_of_crit(vict, vict.SEE_BIT));
show(buf, pc);
Sprintf(buf, "kicks %S!\n", name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
}//else
}//if
else { //missed
Sprintf(buf, "kicks mightily at %S, missing by a foot!\n",
vict.getName());
emote(buf, pc, ROOM, FALSE, &vict);
Sprintf(buf, "%S narrowly misses your head with %s foot!\n",
name_of_crit(pc, vict.SEE_BIT), get_his_her(pc));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You miss a kick at %S's head.\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
pc.PAUSE += 2; //increment pause_count
}//else
if (do_fatality) {
agg_kills_vict(&pc, vict);
}//if
return 0;
}//do_kick()
int bash(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
if (!victim->Strlen()) {
if (!(crit_ptr = Top(pc.IS_FIGHTING))) {
show("Bash who?\n", pc);
return -1;
}//if
}//if
else {
crit_ptr = ROOM.haveCritNamed(i_th, victim, pc.SEE_BIT);
}//if
if (crit_ptr) {
if (crit_ptr == &pc) {
show("You shouldn't be bashing yourself..\n", pc);
return -1;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, pc.getCurRoomNum(), TRUE, i_th, victim,
pc.SEE_BIT);
}//if
if (!ok_to_do_action(crit_ptr, "SVPFA", -1, pc)) {
return -1;
}//if
if (!(crit_ptr = check_for_diversions(*crit_ptr, "GM", pc)))
return -1;
return do_bash(*crit_ptr, pc);
}//if
else if (door* dptr = door::findDoor(ROOM.DOORS, i_th, victim,
pc.SEE_BIT, ROOM))
return do_bash(*dptr, pc);
else
pc.show(CS_NO_CAN_SEE);
return -1;
}//bash
int do_bash(door& vict, critter& pc) { //bash for doors
String buf(100);
if (pc.isMob()) {
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: MOB sent to do_bash, name: "
<< *(name_of_crit(pc, ~0)) << " address: " << &pc << endl;
}
return -1;
}//if
if (!vict.dr_data->door_data_flags.get(2)) {
show("It isn't even closed.\n", pc);
return -1;
}//if
if (!vict.dr_data->door_data_flags.get(3)) {
show("Its not locked, just open it!\n", pc);
return -1;
}//if
if (!vict.dr_data->door_data_flags.get(7)) {
show("You nearly break your hand on the door. It doesn't budge!\n",
pc);
Sprintf(buf,
"nearly breaks %s hand on the door. It doesn't budge!",
get_his_her(pc));
emote(buf, pc, ROOM, TRUE);
}//if
else if (d(1, 100) < get_percent_lrnd(BASH_SKILL_NUM, pc)) {
Sprintf(buf, "You bust down the %S.\n", name_of_door(vict,
pc.SEE_BIT));
show(buf, pc);
vict.dr_data->door_data_flags.turn_off(2);
vict.dr_data->door_data_flags.turn_off(5);
Sprintf(buf, "busts open the %S!\n", name_of_door(vict, ~0));
emote(buf, pc, ROOM, TRUE);
}//else
else {
Sprintf(buf, "The %S gives a little as you hit it.\n",
name_of_door(vict, pc.SEE_BIT));
show(buf, pc);
Sprintf(buf, "budges the %S with %s hit.\n", name_of_door(vict, ~0),
get_his_her(pc));
emote(buf, pc, ROOM, TRUE);
}//else
pc.PAUSE += d(2,2); //increment pause_count
return 0;
}//do_bash()//door
int do_bash(critter& vict, critter& pc) {
String buf(100);
short do_fatality = FALSE;
if ((vict.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: MOB sent to do_bash.\n");
return -1;
}//if
if (!pc.IS_FIGHTING.haveData(&vict)) {
join_in_battle(pc, vict);
}//if
if (skill_did_hit(pc, BASH_SKILL_NUM, vict)) {
pc.PAUSE += d(1,3); //increment pause_count
exact_raw_damage(d(pc.STR/2, 5) + pc.DEX/2, NORMAL, vict, pc);
vict.PAUSE += d(1,3);
if (vict.HP < 0) {
Sprintf(buf, "crushes the skull of %S with %s fist!!\n",
name_of_crit(vict, ~0), get_his_her(pc));
emote(buf, pc, ROOM, TRUE, &vict);
Sprintf(buf,
"The last thing you feel is %S's fist caving in your temple!!\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf,
"With a mighty blow of your fist you crush %S's skull.\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
do_fatality = TRUE;
}//if fatality
else {
Sprintf(buf, "%S rings your bell!\n",
name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You bash %S!\n", name_of_crit(vict, vict.SEE_BIT));
show(buf, pc);
Sprintf(buf, "bashes %S!\n", name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
}//else
}//if
else { //missed
Sprintf(buf, "nearly falls on %s butt trying to hit %S!\n",
get_his_her(pc), vict.getName());
emote(buf, pc, ROOM, FALSE, &vict);
Sprintf(buf, "%S takes a big swing at you but misses!\n",
name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You try to bash %S but fall on your ass!\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
pc.PAUSE += d(2,2); //increment pause_count
return -1;
}//else
if (do_fatality) {
agg_kills_vict(&pc, vict);
}//if
return 0;
}//do_bash()
int block(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
if (!victim->Strlen()) {
if (!(crit_ptr = Top(pc.IS_FIGHTING))) {
show("Block who?\n", pc);
return -1;
}//if
}//if
else {
crit_ptr = ROOM.haveCritNamed(i_th, victim, pc.SEE_BIT);
}//if
if (crit_ptr) {
if (!pc.IS_FIGHTING.haveData(crit_ptr)) {
show("You aren't fighting that person.\n", pc);
return -1;
}//if
if (!ok_to_do_action(crit_ptr, "PFA", -1, pc)) {
return -1;
}//if
return do_block(*crit_ptr, pc);
}//if
else if (door* dptr = door::findDoor(ROOM.DOORS, i_th, victim,
pc.SEE_BIT, ROOM))
return do_block(*dptr, pc);
else
pc.show(CS_NO_CAN_SEE);
return -1;
}//block
int do_block(critter& vict, critter& pc) {
String buf(100);
if ((vict.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: MOB sent to do_block.\n");
return -1;
}//if
if (!HaveData(&vict, pc.IS_FIGHTING)) {
return -1;
}//if
if (skill_did_hit(pc, BLOCK_SKILL_NUM, vict)) {
pc.PAUSE += d(1,3); //increment pause_count
vict.CRIT_FLAGS.turn_on(21); //now is blocked
Sprintf(buf, "You block %S.\n", name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
Sprintf(buf, "blocks %S.", name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
Sprintf(buf, "%S blocks you.\n", name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
return 0;
}//if
else { //missed
show("You miss the block.\n", pc);
emote("misses the block.", pc, ROOM, TRUE, &vict);
Sprintf(buf, "%S tries but fails to block you.\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
return -1;
}//else
}//do_block()
int do_block(door& vict, critter& pc) {
String buf(100);
if (pc.isMob()) {
mudlog.log(ERROR, "ERROR: MOB sent to do_block.\n");
return -1;
}//if
if (ROOM.isHaven() || ROOM.isNoPK()) {
show("Aggression is not allowed here.\n", pc);
return -1;
}//if
if (!pc.IS_FIGHTING.isEmpty()) {
show("You can't block an entrance while fighting.\n", pc);
return -1;
}//if
if (vict.dr_data->door_data_flags.get(14)) {
show("Someone is already blocking that door!\n", pc);
return -1;
}//if
if (d(1, 100) < get_percent_lrnd(BLOCK_SKILL_NUM, pc)) {
Sprintf(buf, "You start blocking the %S.\n", name_of_door(vict,
pc.SEE_BIT));
show(buf, pc);
vict.dr_data->door_data_flags.turn_on(14);
vict.crit_blocking = &pc;
Sprintf(buf, "starts blocking the %S!\n", name_of_door(vict, ~0));
emote(buf, pc, ROOM, TRUE);
return 0;
}//else
else {
pc.PAUSE += d(1, 2); //increment pause_count
show(
"You can't find a suitable spot, maybe if you tried a little harder.\n",
pc);
}//else
return -1;
}//do_block()//door
int claw(int i_th, const String* victim, critter& pc) {
critter* crit_ptr;
String buf(100);
if (pc.EQ[9] && pc.EQ[10]) {
show("You don't have a free hand!\n", pc);
return -1;
}//if
if (!victim->Strlen()) {
crit_ptr = Top(pc.IS_FIGHTING);
}//if
else {
crit_ptr = ROOM.haveCritNamed(i_th, victim, pc.SEE_BIT);
}//if
if (crit_ptr) {
if (crit_ptr == &pc) {
show("You shouldn't be clawing yourself..\n", pc);
return -1;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, pc.getCurRoomNum(),
TRUE, i_th, victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(crit_ptr, "SVPF", -1, pc)) {
return -1;
}//if
if (!(crit_ptr = check_for_diversions(*crit_ptr, "GM", pc)))
return -1;
return do_claw(*crit_ptr, pc);
}//if
else
show("Claw who?\n", pc);
return -1;
}//claw
int do_claw(critter& vict, critter& pc) {
String buf(100);
short do_fatality = FALSE;
mudlog.log(TRC, "In do_claw.\n");
if ((vict.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: MOB sent to do_claw.\n");
return -1;
}//if
if (!HaveData(&vict, pc.IS_FIGHTING)) {
join_in_battle(pc, vict);
}//if
pc.PAUSE += d(1,3); //increment pause_count
if (skill_did_hit(pc, CLAW_SKILL_NUM, vict)) {
exact_raw_damage((d(pc.STR/2, 5) + pc.LEVEL), NORMAL, vict);
if (vict.HP < 0) {
Sprintf(buf, "rips %S's throat out with %s %s!!\n",
name_of_crit(vict, ~0), get_his_her(pc),
(pc.RACE == AVIAN ? "deadly talons" : "curled hand"));
emote(buf, pc, ROOM, TRUE);
Sprintf(buf,
"You are supprised to see %S holding your larynx!!\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf,
"You rip out %S's larynx with a quick swipe of your %s.\n",
name_of_crit(vict, pc.SEE_BIT),
(pc.RACE == AVIAN ? "deadly talons" : "curled hand"));
show(buf, pc);
do_fatality = TRUE;
}//if fatality
else {
Sprintf(buf,
"%S's %s leave bloody streaks across your body!\n",
name_of_crit(pc, vict.SEE_BIT),
(pc.RACE == AVIAN ? "deadly talons" : "fingers" ));
buf.Cap();
show(buf, vict);
Sprintf(buf,
"Your %s leave bloody streaks across %S's body!\n",
(pc.RACE == AVIAN ? "deadly talons" : "fingers"),
vict.getName(pc));
show(buf, pc);
Sprintf(buf, "claws %S with %s %s!\n",
name_of_crit(vict,~0), get_his_her(pc),
(pc.RACE == AVIAN ? "dedly talons" : "curled hand"));
emote(buf, pc, ROOM, TRUE);
}//else
}//if
else { //missed
Sprintf(buf, "%S takes a big swipe at you but misses!\n",
name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "You try to claw %S but narrowly miss.\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
return -1;
}//else
if (do_fatality) {
agg_kills_vict(&pc, vict);
}//if
return 0;
}//do_claw()
int construct(critter& pc, short do_mob = FALSE) {
String buf(100);
object* toolbox, *ptr, *item1, *item2, *item3, *item4, *item5;
Cell<object*> cll;
// log("In construct.\n");
item1 = item2 = item3 = item4 = item5 = NULL;
if (!pc.pc && !do_mob) //no ordering pets to do yer dirty-work
return -1;
if (!ok_to_do_action(NULL, "mBFPSK", CONSTRUCT_SKILL_NUM, pc)) {
return -1;
}
pc.inv.head(cll);
toolbox = NULL;
while ((ptr = cll.next())) {
if (ptr->OBJ_FLAGS.get(64)) { //if a toolbox
toolbox = ptr;
break;
}//if
}//while
if (!toolbox) {
show("You must have a toolbox in order to construct something.",
pc);
return -1;
}//if
if (toolbox->inv.isEmpty()) {
show("You need components in your toolbox to work with!\n",
pc);
return -1;
}//if
/* found a tool box, make sure its clear of junk */
toolbox->inv.head(cll);
while ((ptr = cll.next())) {
if (!(ptr->OBJ_FLAGS.get(67))) {
Sprintf(buf, "%S is not a component to any construction.\n",
&(ptr->short_desc));
buf.Cap();
show(buf, pc);
show("You have to have a clean toolbox in order to work!!\n",
pc);
return -1;
}//if
if (ptr->OBJ_LEVEL > pc.LEVEL) {
Sprintf(buf, "%S is too advanced for you to work with it.\n",
&(ptr->short_desc));
buf.Cap();
show(buf, pc);
show("You must remove it from your work ", pc);
show("area before you can continue.\n", pc);
return -1;
}//if
}//while
ptr = Top(toolbox->inv);
if (!ptr->obj_proc) {
Sprintf(buf, "ERROR: %S is COMPONENT w/NULL obj_proc.\n",
&(ptr->short_desc));
mudlog.log(ERROR, buf);
return -1;
}//if
if (!ptr->obj_proc->construct_data) {
Sprintf(buf, "ERROR: %S is COMPONENT w/NULL construct_data.\n",
&(ptr->short_desc));
mudlog.log(ERROR, buf);
return -1;
}//if
/* check for all components available */
if (check_l_range(ptr->COMPONENT_ITEM1, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item1 = have_obj_numbered(toolbox->inv, 1,
ptr->COMPONENT_ITEM1, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to construct %S.\n",
&(obj_list[ptr->COMPONENT_ITEM1].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM2, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item2 = have_obj_numbered(toolbox->inv, 1,
ptr->COMPONENT_ITEM2, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to construct %S.\n",
&(obj_list[ptr->COMPONENT_ITEM2].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM3, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item3 = have_obj_numbered(toolbox->inv, 1,
ptr->COMPONENT_ITEM3, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to construct %S.\n",
&(obj_list[ptr->COMPONENT_ITEM3].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM4, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item4 = have_obj_numbered(toolbox->inv, 1,
ptr->COMPONENT_ITEM4, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to construct %S.\n",
&(obj_list[ptr->COMPONENT_ITEM4].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM5, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item5 = have_obj_numbered(toolbox->inv, 1,
ptr->COMPONENT_ITEM5, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to construct %S.\n",
&(obj_list[ptr->COMPONENT_ITEM5].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
/* have all items and levels are compatable */
int targ_num = ptr->COMPONENT_TARG;
// NOTE: Can't use ptr after this, because it might be deleted!!!
if (item1) {
toolbox->loseInv(item1);
drop_eq_effects(*item1, pc, FALSE, FALSE);
recursive_init_unload(*item1, 0);
if (item1->isModified()) {
delete item1;
item1 = NULL;
}//if
}//if
if (item2) {
toolbox->loseInv(item2);
drop_eq_effects(*item2, pc, FALSE, FALSE);
recursive_init_unload(*item2, 0);
if (item2->isModified()) {
delete item2;
item2 = NULL;
}//if
}//if
if (item3) {
toolbox->loseInv(item3);
drop_eq_effects(*item3, pc, FALSE, FALSE);
recursive_init_unload(*item3, 0);
if (item3->isModified()) {
delete item3;
item3 = NULL;
}//if
}//if
if (item4) {
toolbox->loseInv(item4);
drop_eq_effects(*item4, pc, FALSE, FALSE);
recursive_init_unload(*item4, 0);
if (item4->isModified()) {
delete item4;
item4 = NULL;
}//if
}//if
if (item5) {
toolbox->loseInv(item5);
drop_eq_effects(*item5, pc, FALSE, FALSE);
recursive_init_unload(*item5, 0);
if (item5->isModified()) {
delete item5;
item5 = NULL;
}//if
}//if
if (skill_did_hit(pc, CONSTRUCT_SKILL_NUM, pc)) {
toolbox->gainInv(&(obj_list[targ_num]));
recursive_init_loads(obj_list[targ_num], 0);
Sprintf(buf, "You have successfully constructed %S in %S.\n",
obj_list[targ_num].getLongName(),
toolbox->getLongName());
show(buf, pc);
}//if skill_did_hit, ie if pc knew it well enuf not to fail
else {
show("You fiddle with your components, but all you can seem to", pc);
show(" do is bugger them up completely.\n", pc);
}//else
pc.PAUSE += 4;
return 0;
}//construct()
int concoct(critter& pc, short do_mob = FALSE) {
String buf(100);
object* cauldron, *ptr, *item1, *item2, *item3, *item4, *item5;
Cell<object*> cll;
// log("In concoct.\n");
if (!pc.pc && !do_mob) //no ordering pets to do yer dirty-work
return -1;
item1 = item2 = item3 = item4 = item5 = NULL;
if (!ok_to_do_action(NULL, "mBFPSK", BREW_SKILL_NUM, pc)) {
return -1;
}
pc.inv.head(cll);
cauldron = NULL;
while ((ptr = cll.next())) {
if (ptr->OBJ_FLAGS.get(65)) { //if a cauldron
cauldron = ptr;
break;
}//if
}//while
if (!cauldron) {
show("You must have a cauldron in order to brew something.",
pc);
return -1;
}//if
if (IsEmpty(cauldron->inv)) {
show("You need ingredients in your cauldron to brew with!\n",
pc);
return -1;
}//if
/* found a cauldron, make sure its clear of junk */
cauldron->inv.head(cll);
while ((ptr = cll.next())) {
if (!(ptr->OBJ_FLAGS.get(68))) { //concoct component
Sprintf(buf,
"%S will certainly distort the properties of your brew. ",
&(ptr->short_desc));
buf.Cap();
show(buf, pc);
show("You'd better take it out.\n", pc);
return -1;
}//if
if (ptr->OBJ_LEVEL > pc.LEVEL) {
Sprintf(buf, "You do not yet fully comprehend the power of %S.\n",
&(ptr->short_desc));
buf.Cap();
show(buf, pc);
show("Until you better understand it, you shouldn't include", pc);
show(" it in your cauldron.\n", pc);
return -1;
}//if
}//while
ptr = Top(cauldron->inv);
if (!ptr->obj_proc) {
Sprintf(buf, "ERROR: %S is COMPONENT w/NULL obj_proc.\n",
&( ptr->short_desc));
mudlog.log(ERROR, buf);
return -1;
}//if
if (!ptr->obj_proc->construct_data) {
Sprintf(buf, "ERROR: %S is COMPONENT w/NULL construct_data.\n",
&(ptr->short_desc));
mudlog.log(ERROR, buf);
return -1;
}//if
/* check for all components available */
if (check_l_range(ptr->COMPONENT_ITEM1, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item1 = have_obj_numbered(cauldron->inv, 1,
ptr->COMPONENT_ITEM1, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to brew %S.\n",
&(obj_list[ptr->COMPONENT_ITEM1].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM2, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item2 = have_obj_numbered(cauldron->inv, 1,
ptr->COMPONENT_ITEM2, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to brew %S.\n",
&(obj_list[ptr->COMPONENT_ITEM2].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM3, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item3 = have_obj_numbered(cauldron->inv, 1,
ptr->COMPONENT_ITEM3, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to brew %S.\n",
&(obj_list[ptr->COMPONENT_ITEM3].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM4, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item4 = have_obj_numbered(cauldron->inv, 1,
ptr->COMPONENT_ITEM4, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to brew %S.\n",
&(obj_list[ptr->COMPONENT_ITEM4].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
if (check_l_range(ptr->COMPONENT_ITEM5, 1, NUMBER_OF_ITEMS, pc,
FALSE)) {
if (!(item5 = have_obj_numbered(cauldron->inv, 1,
ptr->COMPONENT_ITEM5, pc.SEE_BIT, ROOM))) {
Sprintf(buf, "You need %S in order to brew %S.\n",
&(obj_list[ptr->COMPONENT_ITEM5].short_desc),
&(obj_list[ptr->COMPONENT_TARG].short_desc));
show(buf, pc);
return -1;
}//if
}//if
int targ_num = ptr->COMPONENT_TARG;
// NOTE: Can't use ptr after this, because it might be deleted!!!
/* have all items, and levels are compatable */
if (item1) {
cauldron->loseInv(item1);
drop_eq_effects(*item1, pc, FALSE);
recursive_init_unload(*item1, 0);
if (item1->isModified()) {
delete item1;
item1 = NULL;
}//if
}//if
if (item2) {
cauldron->loseInv(item2);
drop_eq_effects(*item2, pc, FALSE);
recursive_init_unload(*item2, 0);
if (item2->isModified()) {
delete item2;
item2 = NULL;
}//if
}//if
if (item3) {
cauldron->loseInv(item3);
drop_eq_effects(*item3, pc, FALSE);
recursive_init_unload(*item3, 0);
if (item3->isModified()) {
delete item3;
item3 = NULL;
}//if
}//if
if (item4) {
cauldron->loseInv(item4);
drop_eq_effects(*item4, pc, FALSE);
recursive_init_unload(*item4, 0);
if (item4->isModified()) {
delete item4;
item4 = NULL;
}//if
}//if
if (item5) {
cauldron->loseInv(item5);
drop_eq_effects(*item5, pc, FALSE);
recursive_init_unload(*item5, 0);
if (item5->isModified()) {
delete item5;
item5 = NULL;
}//if
}//if
if (skill_did_hit(pc, BREW_SKILL_NUM, pc)) {
pc.gainInv(&(obj_list[targ_num]));
recursive_init_loads(obj_list[targ_num], 0);
Sprintf(buf, "You have successfully brewed %S.\n",
&(obj_list[targ_num].short_desc));
show(buf, pc);
}//if skill_did_hit, ie if pc knew it well enuf not to fail
else {
show("You try to remember the recipe, but you must have", pc);
show(" forgotten something because this stuff stinks and your ", pc);
show("ingredients are ruined!!\n", pc);
}//else
pc.PAUSE += 4;
return 0;
}//concoct()
int scribe(const String* spell, critter& pc, short do_mob = FALSE) {
String buf(100);
object* pen, *parchment;
int spell_num;
/* default is that mob's can't scribe, ie no 'ordering' them to scribe */
if (!pc.pc && !do_mob)
return -1;
// log("In scribe.\n");
// level of spell can't be higher than parchment level
// and or pen level.
// Can only scribe spells the pc knows of course, unless its
// a SMOB
// Must be wielding pen
// Must be holding parchment
// Resulting scroll goes to inventory
if (spell->Strlen() == 0) {
show("Please specify which spell you wish to scribe.\n", pc);
return -1;
}//if
if (!ok_to_do_action(NULL, "mBFPr", spell_num, pc)) {
return -1;
}
pen = pc.EQ[9];
if (!pen || !pen->OBJ_FLAGS.get(66)) {
show("You must be wielding a pen in order to scribe.\n", pc);
return -1;
}//if
// pen is valid, check for parchment //
parchment = pc.EQ[10];
if (!parchment || !parchment->OBJ_FLAGS.get(69)) {
show("You must be holding a parchment in order to scribe.\n", pc);
return -1;
}//if
// parchment and pen are valid, check on spell //
spell_num = SSCollection::instance().getNumForName(*spell);
if (spell_num == -1) {
show("That spell is in need of research.\n", pc);
return -1;
}//if
/* does pc know the spell?? */
int p_learned = get_percent_lrnd(spell_num, pc);
if (p_learned == -1) {
show("You don't know of that spell.\n", pc);
return -1;
}//if
// have valid spell number, now check levels
int spell_lvl = SSCollection::instance().getSS(spell_num).getMinLevel();
if (spell_lvl > pen->OBJ_LEVEL) {
show("Your pen is too weak to convey such magic.\n", pc);
return -1;
}//if
if (spell_lvl > parchment->OBJ_LEVEL) {
show("Your parchment cannot hold such strong words of magic.\n", pc);
return -1;
}//if
// have all items, levels are compatable //
int scroll_num;
if (!lost_concentration(pc, spell_num)) {
if ((scroll_num = SSCollection::instance().getSS(spell_num).getScrollNum()) != -1) {
recursive_init_unload(*(pc.EQ[10]), 0);
remove_eq_effects(*(pc.EQ[10]), pc, FALSE, FALSE, 10);
if (pc.EQ[10]->isModified())
delete pc.EQ[10];
pc.EQ[10] = NULL; //no more parchment
pc.gainInv(&(obj_list[scroll_num]));
recursive_init_loads(obj_list[scroll_num], 0);
Sprintf(buf, "You have successfully scribed %S.\n",
&(obj_list[scroll_num].short_desc));
show(buf, pc);
pc.MANA -= get_mana_cost(spell_num, pc);
pc.PAUSE += 4;
}//if
else { //scroll object not created yet
Sprintf(buf, "ERROR: need to create scroll for spell: %i.\n",
spell_num);
mudlog.log(ERROR, buf);
show("As you finish the last phrase the parchement grows hot and",
pc);
show(" bursts into flame.\nThis spell just doesn't take to paper",
pc);
show(" very well!\n", pc);
if (pc.EQ[10]->isModified())
delete pc.EQ[10];
pc.EQ[10] = NULL; //no more parchment
}//else
}//if !lost concentration, if he/she knew it well enuf
else {
show("You suddenly lose your train of thought, and as you mark", pc);
show(" through that last line, you know the parchment is useless.\n",
pc);
if (pc.EQ[10]->isModified())
delete pc.EQ[10];
pc.EQ[10] = NULL; //no more parchment
pc.PAUSE += 4;
pc.MANA -= (get_mana_cost(spell_num, pc) / 2);
}//else
return 0;
}//scribe()
///*********************************************************************///
//************************ auxillary functions **************************//
///*********************************************************************///
short did_spell_hit(const critter& agg, const int spell_type,
const critter& vict, int lvl = -1,
short is_canned = FALSE) {
int j = 100;
switch (spell_type)
{
case NORMAL:
j = vict.AC;
break;
case FIRE: case D_BREATH:
j = vict.HEAT_RESIS;
break;
case ICE:
j = vict.COLD_RESIS;
break;
case ELECTRICITY:
j = vict.ELEC_RESIS;
break;
case CRONIC:
j = ((18 - vict.CON) * 5 + 25);
break;
case AGILITY:
j = ((18 - vict.DEX) * 5 + 25);
break;
case COERCION:
case CHARM:
j = ((18 - vict.INT) * 5 + 25);
if (agg.ALIGN < -850)
j += (int)((float)j * .25);
else if (agg.ALIGN > 250)
j += (int)((float)j * ((float)agg.ALIGN / 4000.0));
break;
default:
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: default in did_spell_hit, spelltype: "
<< spell_type << endl;
}
j = 100;
}//switch
j += vict.SPEL_RESIS; //gen resistance to spells
if (is_canned) {
j -= (vict.LEVEL - lvl) * 10;
}//if
else {
j -= (vict.LEVEL - agg.LEVEL) * 10;
}//else
j += 200;
if (j < 0)
j = 0;
else if (j > 400)
j = 400;
if ((spell_type == COERCION) || (spell_type == CHARM)) {
if (vict.getLevel() > agg.getLevel()) {
return FALSE;
}
}
return (d(1, 75) < d(1, j));
}//did_spell_hit
short skill_did_hit(critter& agg, int spell_num, critter& vict) {
int percent_lrnd = 0;
if (agg.pc) {
agg.SKILLS_KNOWN.Find(spell_num, percent_lrnd);
}//if
else { //else not a pc
int foo = (agg.getLevel() - SSCollection::instance().getSS(spell_num).getMinLevel());
if (foo > 0) {
percent_lrnd = max((50 + (foo * 15)), 100);
}
else {
percent_lrnd = 10;
}
}//else
if ((spell_num == CONSTRUCT_SKILL_NUM) || (spell_num == BREW_SKILL_NUM))
return (d(1, 100) < d(1, (percent_lrnd * 2 + 2 * (agg.DEX + agg.INT))));
else if ((spell_num == BODYSLAM_SKILL_NUM) ||
(spell_num == HURL_SKILL_NUM))
return (d(1, vict.CRIT_WT_CARRIED) < d(1, percent_lrnd + agg.STR * 10));
else if ((spell_num == BACKSTAB_SKILL_NUM) ||
(spell_num == CIRCLE_SKILL_NUM)) {
int rnd1 = d(1, (agg.HIT * 3 + agg.DEX * 5 + agg.LEVEL * 2));
int rnd2 = d(1, (2 * vict.DEX + vict.LEVEL + max(-vict.AC / 2, 25)));
return (((float)(rnd1) * (float)(percent_lrnd) / 100.0) >
((float)(rnd2)));
}
else {
return (d(1, ((agg.HIT + agg.DEX + 2 * agg.LEVEL) * (percent_lrnd / 4))) >
d(1, ((vict.DEX + 2 * vict.LEVEL) * 15)));
}
}//skill_did_hit
int sneak(critter& pc, int smob_too = FALSE) {
String buf(100);
if (pc.isMob())
return -1; //no MOB's allowed!!
if (!smob_too && !pc.pc) {
return -1;
}//if
if (pc.isFrozen()) {
show("You are too frozen to do anything.\n", pc);
return -1;
}//if
if (pc.CRIT_FLAGS.get(17)) {
pc.CRIT_FLAGS.turn_off(17);
show("You stop sneaking around.\n", pc);
}//if
else {
if (get_percent_lrnd(SNEAK_SKILL_NUM, pc) > 0) {
pc.CRIT_FLAGS.turn_on(17);
show("You start sneaking.\n", pc);
}//if
else {
show("You couldn't sneak up on a sleeping Ogrue!!\n", pc);
}//else
}//else, not sneaking right now
return 0;
}//sneak
int hide(critter& pc, int smob_too = FALSE) {
String buf(100);
if (pc.isMob())
return -1; //no MOB's allowed!!
if (!smob_too && !pc.pc) {
return -1;
}//if
if (pc.isFrozen()) {
show("You are too frozen to hide.\n", pc);
return -1;
}//if
if (pc.CRIT_FLAGS.get(22)) {
pc.CRIT_FLAGS.turn_off(22);
show("You stop hiding.\n", pc);
}//if
else {
if (get_percent_lrnd(HIDE_SKILL_NUM, pc) > 0) {
pc.CRIT_FLAGS.turn_on(22);
show("You start hiding.\n", pc);
}//if
else {
show("You are not skilled in this stealthy art!!\n", pc);
}//else
}//else, not hiding right now
return 0;
}//hide
/* Basically, just hide for rangers. */
int blend(critter& pc, int smob_too = FALSE) {
String buf(100);
if (pc.isMob())
return -1; //no MOB's allowed!!
if (!smob_too && !pc.pc) {
return -1;
}//if
if (pc.isFrozen()) {
show("You are too frozen to hide.\n", pc);
return -1;
}//if
if (pc.CRIT_FLAGS.get(22)) {
pc.CRIT_FLAGS.turn_off(22);
show("You step out of hiding.\n", pc);
}//if
else {
if (get_percent_lrnd(BLEND_SKILL_NUM, pc) > 0) {
pc.CRIT_FLAGS.turn_on(22);
show("You blend into the background.\n", pc);
}//if
else {
show("You are not skilled in this stealthy art!!\n", pc);
}//else
}//else, not hiding right now
return 0;
}//blend
int scan(critter& pc) {
if (!ok_to_do_action(NULL, "KSPF", SCAN_SKILL_NUM, pc)) {
return -1;
}//if
return ROOM.doScan(pc);
}//scan