#include <stdlib.h>
#include "kernel.h"
#include "cflags.h"
#include "oflags.h"
#include "lflags.h"
#include "mflags.h"
#include "sflags.h"
#include "pflags.h"
#include "quests.h"
#include "sendsys.h"
#include "verbs.h"
#include "bprintf.h"
#include "commands.h"
#include "move.h"
#include "mud.h"
#include "rooms.h"
#include "log.h"
#include "clone.h"
#include "mobiles.h"
#include "objects.h"
#include "locations.h"
#include "spell.h"
#include "fight.h"
#include "mobile.h"
#include "objsys.h"
/* Calculate damage done by a player 'pl' carrying item 'it'.
* If no item, return damage of player. If it is not a weapon, return -1
* else return damage of player + damage of weapon.
*/
int
dambyitem (int pl, int it)
{
if (it == -1)
return pdam (pl);
return !otstbit (it, OFL_WEAPON) ? -1 : odamage (it) + pdam (pl);
}
/*
* Command function block to handle wielding of weapons.
*/
void
wieldcom (void)
{
int a;
if ((a = ob1) == -1) {
bprintf ("What's that?\n");
return;
} else if (!iscarrby (a, mynum)) {
bprintf ("You're not carrying the %s!\n", item1);
set_weapon (mynum, -1);
return;
} else if (!otstbit (a, OFL_WEAPON)) {
bprintf ("It's not a weapon.\n");
set_weapon (mynum, -1);
return;
}
set_weapon (mynum, a);
send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
"%s wields the %s.\n", pname (mynum), oname (a));
bprintf ("You are now wielding the %s.\n", oname (a));
}
/*
* The killing and hitting command
*/
static void wreckdoor (void);
void
killcom (void)
{
if (pfighting (mynum) >= 0) {
bprintf ("You're already fighting!\n");
return;
}
if (pl1 == -1 && ob1 == -1) {
bprintf ("Kill who?\n");
return;
}
if (EQ (item1, "door")) {
if (!ptstflg (mynum, PFL_WRECK)) {
bprintf ("What are you trying to do? Wreck the door?\n");
} else {
wreckdoor ();
}
return;
}
if (ob1 != -1) {
breakitem (ob1);
return;
}
if (pl1 == -1) {
bprintf ("You can't do that.\n");
return;
}
if (pl1 == mynum) {
bprintf ("Come on, it'll look better tomorrow...\n");
return;
}
if (ploc (pl1) != ploc (mynum)) {
bprintf ("They aren't here.\n");
return;
}
if (testpeace (mynum)) {
bprintf ("Sorry, it's too peaceful for violence.\n");
return;
}
if (ptstflg (pl1, PFL_NOHASSLE)) {
bprintf ("Something interferes with your attack.\n");
return;
}
if (pl1 < max_players && !the_world->w_tournament) {
bprintf ("You cannot attack a player when tournament mode is off!\n");
return;
}
setpfighting (mynum, pl1);
hit_player (mynum, pl1, (ob2 == -1) ? pwpn (mynum) : ob2);
/* Send message if mortal attacks mortal in a tournament
*/
if (pl1 < max_players && plev (mynum) < LVL_WIZARD &&
plev (pl1) < LVL_WIZARD && the_world->w_tournament)
send_msg (DEST_ALL, MODE_QUIET, LVL_WIZARD, LVL_MAX, NOBODY, NOBODY,
"&+r[&+YTournament: &+W%s &*attacked &+W%s&+r]\n",
pname (mynum), pname (pl1));
return;
}
void
breakitem (int x)
{
switch (x) {
case OBJ_VILLAGE_PEBBLE:
bprintf ("The pebble gets annoyed and goes to philosophize elsewhere.\n");
setoloc (OBJ_VILLAGE_PEBBLE, LOC_DEAD_DESTROYED, IN_ROOM);
return;
case OBJ_BLIZZARD_RESET_STONE:
sys_reset ();
break;
case OBJ_QUARRY_ROCK:
bprintf ("You smash it apart to reveal a gem inside.\n");
create (OBJ_QUARRY_GEM);
setoloc (OBJ_QUARRY_GEM, oloc (OBJ_QUARRY_ROCK), ocarrf (OBJ_QUARRY_ROCK));
destroy (OBJ_QUARRY_ROCK);
break;
case -1:
bprintf ("What's that?\n");
break;
default:
bprintf ("You can't do that.\n");
break;
}
}
static void
wreckdoor (void)
{
int a;
char ms[80];
if ((a = fobna ("door")) == -1)
bprintf ("Sorry, no doors here.\n");
else if (state (a) == 0)
bprintf ("It's already open.\n");
else {
setobjstate (a, 0);
bprintf ("The door flies open!\n");
sprintf (ms, "%s hits the door... It flies open!\n", pname (mynum));
sillycom (ms);
sprintf (ms,
"\001dYou hear the distinctive crunch of %s meeting a door.\n\003",
pname (mynum));
broad (ms);
}
}
Boolean
testpeace (int player)
{
return (the_world->w_peace || ltstflg (ploc (player), LFL_PEACEFUL));
}
void
fleecom (void)
{
if (pfighting (mynum) < 0) {
dogocom ();
} else if (carries_obj_type (mynum, OBJ_CASTLE_RUNESWORD) > -1) {
bprintf ("The sword won't let you!\n");
return;
} else {
send_msg (ploc (mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
"%s drops things as %s make a frantic attempt to escape.\n",
pname (mynum), psex (mynum) ? "she" : "he");
setpscore (mynum, pscore (mynum) - pscore (mynum) / 33); /* lose 33% */
setpfighting (mynum, -1);
if (cur_player->i_follow >= 0) {
bprintf ("You stopped following %s.\n", pname (cur_player->i_follow));
cur_player->i_follow = -1;
}
drop_some_objects (mynum);
dogocom ();
}
}
void
hit_player (int attacker, int victim, int weapon)
{
int x, cth, d, w;
int mob = victim - max_players;
if ((x = attacker) >= max_players)
x = victim;
if (attacker >= numchars || victim >= numchars || attacker < 0 ||
victim < 0 || testpeace (victim) || ploc (attacker) != ploc (victim)
|| !is_in_game (attacker) || !is_in_game (victim))
return;
/* if the attacker is played by a human: */
if (attacker < max_players || ststflg (attacker, SFL_OCCUPIED) != 0) {
/* if the attacker is a mortal: */
if (plev (attacker) < LVL_WIZARD || ststflg (attacker, SFL_OCCUPIED) != 0) {
/* if the victim is a mobile: */
if (victim >= max_players) {
if (mtstflg (victim, MFL_BLIND) != 0 && !ststflg (attacker, SFL_BLIND)) {
sendf (attacker, "%s scratches your eyes out! You are blind!\n",
pname (victim));
ssetflg (attacker, SFL_BLIND);
}
if (mob == MOB_CAVE_DRAGON) {
if (iswielded (OBJ_ICECAVE_DAGGER) && iscarrby (OBJ_ICECAVE_DAGGER, attacker)) {
bprintf ("The Dragon glares at you and prepares to blast you "
"out of existence with his\nfiery breath... but the "
"icy blade sinks deep into the dragon's hide.\nThe "
"Dragon shudders.");
setpscore (mynum, pscore (mynum) + 500);
wound_player (attacker, victim, pstr (victim) + 1, -1);
return;
}
}
if (mob == MOB_VALLEY_CHICKEN && !psex (victim)) {
sendf (attacker,
"As you look up you see the sky is somehow different.\n"
"The next second you're crushed to death as the sky hits you!"
"\n");
send_msg (ploc (attacker), 0,
pvis (attacker) > 0 ? pvis (attacker) : LVL_MIN, LVL_MAX,
attacker, NOBODY,
"%s is squashed as %she attacks Chicken Licken.\n",
pname (attacker), psex (attacker) ? "s" : "");
p_crapup (attacker,
"\t\tChicken Licken was right!\n", CRAP_SAVE | CRAP_RETURN);
return;
} else if (mob == MOB_CATACOMB_SERAPH) {
sendf (attacker,
"The Seraph is amused by your foolhardiness. For your "
"impudence, he draws his\nflaming sword and slays you with a "
"single blow.\n");
send_msg (ploc (attacker), 0,
pvis (attacker) > 0 ? pvis (attacker) : LVL_MIN, LVL_MAX,
attacker, NOBODY,
"%s is sliced in half by the Seraph!\n\003",
pname (attacker));
p_crapup (attacker, "\t\tNever pick a fight with an angel..\n",
CRAP_SAVE | CRAP_RETURN);
return;
} else if (mob == MOB_CATACOMB_BEGGAR) {
sendf (attacker,
"You drop everything as you are summoned by The Seraph.\n"
"The Seraph scowls at you contemptuously. For your lack of "
"compassion, he\n"
"draws his flaming sword and slays you with a single "
"blow.\n");
send_msg (ploc (attacker), 0,
pvis (attacker) > 0 ? pvis (attacker) : LVL_MIN, LVL_MAX,
attacker, NOBODY,
"%s is sliced in half by the Seraph!\n\003",
pname (attacker));
p_crapup (attacker,
"\tRemember the ten commandments: Thou Shalt Not Kill\n",
CRAP_SAVE | CRAP_RETURN);
return;
} else if (mob == MOB_SHERWOOD_EMMY) {
sendf (attacker, "Emmy cries out and you look around "
"nervously. Puff then appears with an\n"
"ear splitting bang, shaking her head at "
"you. The next thing you know, Puff\n"
"pounces on top of you!\n");
send_msg (ploc (attacker), 0, pvis (attacker) > 0 ?
pvis (attacker) : LVL_MIN, LVL_MAX, attacker,
NOBODY, "As %s goes to attack Emmy she cries "
"out! Puff then appears and pounces\non top of "
"%s!\n", pname (attacker), him_or_her (attacker));
p_crapup (attacker, "That's what you get for picking on "
"an innocent, sweet, little Emmy!\n",
CRAP_SAVE | CRAP_RETURN);
return;
} else if (mob == MOB_SHERWOOD_LUSIE) {
sendf (attacker, "Li'l Lusie types something on his computer as "
"you go to attack him. After\na few seconds he looks up "
"from the screen and grins at you. The world opens\nup "
"beneath your feet, and you fall into a bottomless pit!\n");
send_msg (ploc (attacker), 0, max (pvis (attacker), LVL_MIN), LVL_MAX,
attacker, NOBODY, "As %s goes to attack Li'l Lusie, "
"Li'l Lusie goes to work on his\ncomputer. Moments "
"later Li'l Lusie looks up and grins at %s.\nThe world "
"then opens up and swallows up %s!\n", pname (attacker),
pname (attacker));
p_crapup (attacker, "\t\tDon't mess with the boy!\n",
CRAP_SAVE | CRAP_RETURN);
return;
} else if (mob == MOB_RUINS_ZEPHERE) {
sendf (attacker, "The mage waves his arms and you don't feel "
"like attacking him anymore.\n");
return;
} else if (mob == MOB_MITHDAN_RED_DRAGON) {
sendf (attacker, "The Dragon snarls as you wake him, turns around, "
"and swallows you in one gulp!\n");
send_msg (ploc (attacker), 0, pvis (attacker) > 0 ? pvis (attacker) :
LVL_MIN, LVL_MAX, attacker, NOBODY, "%s pokes the dragon. "
"The dragon wakes up, snarls, and eats %s!\n",
pname (attacker), him_or_her (attacker));
p_crapup (attacker, "\t\tFamous last words: Hey Bill, watch me goose this "
"sleeping dragon!", CRAP_SAVE | CRAP_RETURN);
return;
}
} /* end if victim is a mobile */
} /* end, the attacker is a mortal */
if (testpeace (attacker))
return;
if ((w = weapon) < 0)
w = pwpn (attacker);
if (w >= 0 && !iscarrby (w, attacker)) {
sendf (attacker,
"You belatedly realize you don't have the %s,\nand are forced "
"to use your hands instead.\n", oname (w));
w = -1;
}
set_weapon (attacker, w);
if (w != -1 && ozone (w) >= num_const_zon) {
send_msg (DEST_ALL, 0, LVL_PROPHET, LVL_MAX, NOBODY, NOBODY,
"&+B[&+CCheat (Weapon)&*: Zone: &+W%s &*Used by: &+W%s&+B]\n",
zname (ozone (w)), pname (attacker));
mudlog ("CHEAT: Weapon from Zone: %s, Used By: %s",
zname (ozone (w)), pname (attacker));
sendf (attacker, "&+WThe weapon crumbles to dust in your hands.\n");
sendf (attacker, "&+WNext time, don't use a cloned weapon!\n");
set_weapon (attacker, -1);
osetbit (w, OFL_DESTROYED);
setoloc (w, LOC_PIT_PIT, IN_ROOM);
}
if (onum (w) == OBJ_CASTLE_RUNESWORD &&
carries_obj_type (victim, OBJ_TOWER_STAFF) > -1) {
sendf (attacker, "The Runesword flashes back from its target, "
"growling in anger!\n");
return;
}
if (weapon >= 0 && dambyitem (attacker, weapon) < 0) {
sendf (attacker, "You can't attack %s with a %s!\n",
pname (victim), oname (weapon));
set_weapon (attacker, -1);
return;
}
if (psitting (attacker)) {
standcom (attacker);
}
/* end, attacker is played by a human */
} else if (weapon < 0 &&
carries_obj_type (victim, OBJ_CATACOMB_SHIELD) == -1 &&
#ifdef LOCMIN_TALON
!iscarrby (OBJ_TALON_TALONSHIELD, victim) &&
#endif
(x = mob_cast_spell (attacker)) >= 0) {
if (cast_spell (attacker, victim, x))
return;
} /* end, the attacker was a mobile */
x = randperc ();
cth = 57 - parmor (victim);
if (carries_obj_type (attacker, OBJ_CASTLE_HORSESHOE) > -1)
cth += 5;
if (victim < max_players) {
if (check_duration (victim, VERB_BLUR))
cth -= 5;
}
if (player_armor (victim) > MAXARMOR)
cth -= MAXARMOR;
else
cth -= player_armor (victim);
/* Add 1/2 damage of wielded weapon for mobiles..full for players.. */
if ((w = weapon) < 0)
w = pwpn (attacker);
if (w >= 0 && iscarrby (w, attacker) && iswielded (w) &&
otstbit (w, OFL_WEAPON)) {
d = odamage (w);
if (attacker >= max_players)
d /= 2;
} else {
d = 0;
}
d += pdam (attacker);
#ifdef LOCMIN_TALON
if (attacker == max_players + MOB_TALON_TALON &&
iswornby (OBJ_TALON_TALONSHIELD, victim)) {
if (d > 45)
d -= 45;
else
d = 0;
}
#endif
d = (x < cth) ? my_random () % (d + 1) : -1; /* damage done */
combatmessage (victim, attacker, weapon, d);
wound_player (attacker, victim, d, -1);
}
/*
* procedure to wound a player.
* attacker = player index of the attacker.
* victim = player index of the victim.
* damage = damage caused by the attacker on the victim.
* hit_type >= 0 verb that caused the magical hit.
* < 0 non-magical hit.
*
* Return true if victim died.
*/
Boolean
wound_player (int attacker, int victim, int damage, int hit_type)
{
int x, q;
char prompt[100];
if (victim < 0 || victim >= numchars || attacker < 0 ||
attacker >= numchars) {
return False;
}
pfighting (victim) = attacker;
if (damage <= 0)
return False;
if (victim >= max_players) {
setpstr (victim, pstr (victim) - damage);
} else if (plev (victim) < LVL_WIZARD) {
setpstr (victim, pstr (victim) - damage);
if (attacker >= max_players) {
if (mtstflg (attacker, MFL_DSCORE) != 0) {
sendf (victim, "You feel weaker as %s's icy touch drains your "
"very life force!\n", pname (attacker));
setpscore (victim, pscore (victim) - 100 * damage);
if (pscore (victim) <= 0) {
setpstr (victim, -1);
}
}
}
strcpy (prompt, players[victim].prompt);
if ((strstr (prompt, "%h")) != NULL) {
strcpy (players[victim].cprompt, build_prompt (victim));
if (ststflg (victim, SFL_NEWSTYLE))
sendf (victim, "\r%s", players[victim].cprompt);
} else {
sendf (victim, "&+W[&*Your strength is now &+C%d&+W]\n", pstr (victim));
}
}
if (pstr (victim) >= 0) {
if (attacker < max_players && (plev (victim) > LVL_HERO ||
(victim >= max_players && zpermanent (pzone (victim))))) {
setpscore (attacker, pscore (attacker) + damage * 2);
}
return False;
}
/* Victim has died */
pfighting (victim) = -1;
if (hit_type >= 0 && hit_type != VERB_ZAP) {
sendf (attacker, "Your last spell did the trick.\n");
}
setpstr (victim, -1);
setpfighting (victim, -1);
sendf (ploc (victim), "%s has died.\n", pname (victim));
send_msg (DEST_ALL, MODE_NSFLAG | MS (SFL_NOSLAIN), LVL_WIZARD, LVL_MAX,
NOBODY, NOBODY, "&+r[&+W%s &*has been &+Yslain &*by &+W%s&+r]\n",
pname (victim), pname (attacker));
if (the_world->w_tournament) {
send_msg (DEST_ALL, 0, LVL_MIN, LVL_WIZARD, NOBODY, NOBODY,
"&+r[&+YTournament: &+W%s &*has died&+r]", pname (victim));
}
dumpstuff (victim, ploc (victim));
if (victim >= max_players) {
/* Kill mobile */
if (attacker < max_players) {
setpscore (attacker, pscore (attacker) + 10 * pdam (victim));
setpkilled (attacker, pkilled (attacker) + 1);
}
if ((q = find_pretender (victim)) >= 0) {
sendf (victim, "*** You have died. ***\n");
unalias (q);
unpolymorph (q);
}
setploc (victim, LOC_DEAD_DEAD);
if (attacker < max_players) {
setpscore (victim, attacker); /* remember who killed the mobile */
if (ststflg (attacker, SFL_AUTOHEAL)) {
sendf (attacker, "You feel your health being restored from the dead soul..\n");
setpstr (attacker, maxstrength (attacker));
setpmagic (attacker, maxmagic (attacker));
}
} else {
setpscore (victim, -1); /* Mobile killing mobile */
}
if (pnum (victim) == MOB_RUINS_MARGOYLE) {
sendf (attacker, "As the monster collapses over, his horn falls off.\n");
setoloc (OBJ_RUINS_HORN, ploc (attacker), IN_ROOM);
}
/* FANTASY */
#ifdef LOCMIN_FANTASY
if (pnum (victim) == MOB_FANTASY_SILVERMONSTER) {
sendf (attacker, "The wall to the west suddenly collapses as the "
"monster lets out its\nlast breath..\n");
setobjstate (OBJ_FANTASY_CAVEWALLOUT, 0);
}
if (pnum (victim) == MOB_FANTASY_JULIUS) {
sendf (attacker, "You grab Julius and order him to tell you where "
"Lord Glaive is as he\nlets out his last breath.. "
"Julius waves his hands and you start to\nfeel faint.. you "
"awaken finding yourself in a different place..\n");
setploc (attacker, LOC_FANTASY_TREE1);
x = real_mynum;
setup_globals (attacker);
trapch (ploc (mynum));
setup_globals (x);
}
#endif
if ((q = victim - max_players) == MOB_EFOREST_LICH)
x = max_players + MOB_EFOREST_ASMODEUS;
else if (q == MOB_EFOREST_ASMODEUS)
x = max_players + MOB_EFOREST_LICH;
else
x = -1;
if (x >= 0) {
if (alive (x) == -1) {
send_msg (DEST_ALL, MODE_NODEAF, LVL_MIN, LVL_MAX, NOBODY, NOBODY,
"A Great Evil has departed from the land.\n");
if (pscore (x) == attacker) {
sendf (attacker, "You have avenged the Elven Forest!\n");
set_quest (attacker, Q_EFOREST);
}
}
}
if (ptemporary (victim))
destruct_mobile (victim, NULL);
} else if (plev (victim) >= LVL_WIZARD)
return False; /* Wizards don't die */
else {
/* Kill mortal */
mudlog ("SYSTEM: %s slain %sby %s", pname (victim),
(hit_type < 0 ? "" : "magically "),
pname (attacker));
if (attacker < max_players &&
(the_world->w_tournament || plev (victim) > LVL_HERO)) {
x = plev (victim);
setpscore (attacker, pscore (attacker) + x * x * x * 10);
}
setpstr (victim, 40);
setpscore (victim, pscore (victim) / 2);
x = real_mynum;
setup_globals (victim);
/* Count of number of deaths */
if (victim < max_players && !the_world->w_tournament)
setpdied (victim, pdied (victim) + 1);
send_msg (DEST_ALL, 0, pvis (victim), LVL_MAX, victim, NOBODY,
"&+B%s &*shouts &+W'&*Huh huh what a wus, %s couldn't even kill me!&+W'\n",
pname (attacker), pname (victim));
crapup ("\t\tOh dear... you seem to be slightly dead.\n",
CRAP_SAVE | CRAP_RETURN);
setup_globals (x);
}
return True;
}
void
combatmessage (int victim, int attacker, int wpn, int ddn)
{
static char *form = "\001p%s\003";
char vic_name[64];
char att_name[64];
char weap[64];
char his[20];
char hard[64];
if (victim < 0 || attacker < 0 || victim >= numchars ||
attacker >= numchars)
return;
sprintf (vic_name, form, pname (victim));
sprintf (att_name, form, pname (attacker));
strcpy (his, his_or_her (attacker));
if (wpn >= 0) {
strcpy (weap, oname (wpn));
} else {
strcpy (weap, "bare hands");
}
if (ddn < 0) { /* Miss */
sendf (attacker, "You missed %s.\n", vic_name);
sendf (victim, "%s missed you.\n", att_name);
send_msg (ploc (victim), MODE_NSFLAG | MS (SFL_NOFIGHT), LVL_MIN, LVL_MAX, victim, attacker,
"%s missed %s.\n", att_name, vic_name);
} else if (ddn < 4) {
sendf (attacker, "You hit %s very lightly.\n", vic_name);
sendf (victim, "%s hit you very lightly.\n", att_name);
send_msg (ploc (victim), MODE_NSFLAG | MS (SFL_NOFIGHT), LVL_MIN, LVL_MAX, victim, attacker,
"%s hit %s very lightly.\n", att_name, vic_name);
} else if (ddn < 7) {
sendf (attacker, "You hit %s lightly.\n", vic_name);
sendf (victim, "%s hit you lightly.\n", att_name);
send_msg (ploc (victim), MODE_NSFLAG | MS (SFL_NOFIGHT), LVL_MIN, LVL_MAX, victim, attacker,
"%s hit %s lightly.\n", att_name, vic_name);
} else if (ddn < 13) {
sendf (attacker, "You hit %s.\n", vic_name);
sendf (victim, "%s hit you.\n", att_name);
send_msg (ploc (victim), MODE_NSFLAG | MS (SFL_NOFIGHT), LVL_MIN, LVL_MAX, victim, attacker,
"%s hit %s.\n", att_name, vic_name);
} else {
if (ddn < 17)
strcpy (hard, " hard");
else if (ddn < 21)
strcpy (hard, " very hard");
else
strcpy (hard, " extremely hard");
sendf (attacker, "You hit %s%s with your %s.\n", vic_name, hard, weap);
sendf (victim, "%s hit you%s with %s %s.\n", att_name, hard, his, weap);
send_msg (ploc (victim), MODE_NSFLAG | MS (SFL_NOFIGHT), LVL_MIN, LVL_MAX, victim, attacker,
"%s hit %s%s with %s %s.\n",
att_name, vic_name, hard, his, weap);
}
}
void
setpfighting (int x, int y)
{
int ct, loc = ploc (x);
pfighting (x) = y;
if (y == -1) {
if (exists (loc)) {
for (ct = 0; ct < lnumchars (loc); ct++) {
if (pfighting (lmob_nr (ct, loc)) == x) {
pfighting (lmob_nr (ct, loc)) = -1;
}
}
}
} else {
pfighting (y) = x;
}
}