// $Id: battle.cc,v 1.24.2.35 2000/05/31 03:52:25 greear Exp $
// $Revision: 1.24.2.35 $ $Author: greear $ $Date: 2000/05/31 03:52:25 $
//
//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
//
///********************** Battle and related functions ******************///
#include "battle.h"
#include "misc.h"
#include "misc2.h"
#include "spec_prc.h"
#include <iostream.h>
#include <fstream.h>
#include "commands.h"
#include "command2.h"
#include "command3.h"
#include <stdio.h>
#include "classes.h"
#include <string2.h>
#include <bitfield.h>
#include "spells.h"
#include "spells2.h"
#include "skills.h"
#include <PtrArray.h>
#include "load_wld.h"
#include "const.h"
#include "Filters.h"
#include "batl_prc.h"
#include "clients.h"
short can_start_battle(critter& targ, critter& pc, short do_msg) {
String buf(100);
if ((targ.isMob()) || (pc.isMob())) {
mudlog.log(ERROR, "ERROR: can_start battle sent SMOB's.\n");
return FALSE;
}//if
if (room_list[targ.getCurRoomNum()].isHaven()) {
if (do_msg) {
Sprintf(buf, "%S is in a peaceful room.\n",
name_of_crit(targ, pc.SEE_BIT));
buf.Cap();
pc.show(buf);
}//if
return FALSE;
}//if
else if (room_list[targ.getCurRoomNum()].isNoPK() &&
(pc.pc && targ.pc)) {
if (do_msg) {
Sprintf(buf, "%S is in a safe room.\n",
name_of_crit(targ, pc.SEE_BIT));
buf.Cap();
pc.show(buf);
}//if
return FALSE;
}//if
else if (ROOM.isHaven()) {
if (do_msg) {
pc.show("But you are in such peaceful room!\n");
}//if
return FALSE;
}//if
else if (ROOM.isNoPK() && (pc.pc && targ.pc)) {
if (do_msg) {
pc.show("You are in a safe room.\n");
}//if
return FALSE;
}//if
return TRUE;
}//can_start_battle()
void do_battle() {
Cell<room*> rcell;
embattled_rooms.head(rcell);
room* r_ptr;
Cell<critter*> crit_cell;
critter* crit_ptr, *vict_ptr;
short is_embattled, i;
//log("In do_battle()\n");
// batlog << "Size of embattled_rooms: " << Size(embattled_rooms)
// << endl;
r_ptr = rcell.next();
while (r_ptr) {
is_embattled = FALSE;
List<critter*> tmp_list(r_ptr->getCrits());
tmp_list.head(crit_cell);
while ((crit_ptr = crit_cell.next())) {
if (!r_ptr->haveCritter(crit_ptr)) {
continue;
}
if (mudlog.ofLevel(DBG)) {
mudlog << "In large while, crit_ptr: " << crit_ptr << flush
<< " name: "
<< crit_ptr->getName() << " size of IS_FIGHTING: "
<< crit_ptr->IS_FIGHTING.size() << endl << endl;
}//if
// NOTE: The aggressor can never die, but the HP can go
// as low as needed, so that the next round may kill.
if (!crit_ptr->IS_FIGHTING.isEmpty()) {
is_embattled = TRUE;
if (crit_ptr->isUsingClient()) {
crit_ptr->show(CTAG_BATTLE(crit_ptr->whichClient() ));
}
else if (crit_ptr->isUsingColor()) {
crit_ptr->show(*(crit_ptr->getBattleColor()));
}
int atks = crit_ptr->ATTACKS;
if (crit_ptr->ATTACKS > 4)
atks = 4;
if (crit_ptr->ATTACKS < 1)
atks = 1;
/* check for second attack */
if ((crit_ptr->isPc()) && (crit_ptr->PAUSE < 1) && (d(1,100) < d(1,
(get_percent_lrnd(SECOND_ATTACK_SKILL_NUM, *(crit_ptr)) +
crit_ptr->LEVEL) * (int)((float)(crit_ptr->DEX) / 9.0)))) atks++;
for (i = 0; i< atks; i++) {
if (!crit_ptr->IS_FIGHTING.isEmpty()) {
//if first hit kills, abort
vict_ptr = Top(crit_ptr->IS_FIGHTING);
if (mudlog.ofLevel(DBG)) {
mudlog << "In do_battle, within for loop, i: "
<< i << " aggressor: "
<< *(name_of_crit(*crit_ptr, ~0)) << " addr: "
<< crit_ptr << flush << " victim addr: "
<< vict_ptr << " vict_name: "
<< *(name_of_crit(*vict_ptr, ~0)) << endl;
}
int show_vict_tags = TRUE;
if ((vict_ptr = check_for_diversions(*vict_ptr, "GM",
*crit_ptr))) {
if (vict_ptr->isUsingClient()) {
vict_ptr->show(CTAG_BATTLE(vict_ptr->whichClient()));
}
else if (vict_ptr->isUsingColor()) {
show(*(vict_ptr->getBattleColor()), *vict_ptr);
}
//do reg attack
do_battle_round(*crit_ptr, *vict_ptr, 9, show_vict_tags);
if (crit_ptr->isNpc()) {
do_battle_proc(*crit_ptr);
}//if
}//if not a mirror
// NOTE: vict_ptr could be deleted at this point!!
if (vict_ptr && r_ptr->haveCritter(vict_ptr)) {
//Vict CANNOT be deleted at this point..or you're screwed!
if (vict_ptr->isUsingClient()) {
vict_ptr->show(CTAG_END_BATTLE(vict_ptr->whichClient()));
}
else if (vict_ptr->isUsingColor()) {
vict_ptr->show(*(vict_ptr->getDefaultColor()));
}
}//if
}//if
}//for /* now check for dual wield */
if (!IsEmpty(crit_ptr->IS_FIGHTING) &&
crit_ptr->CRIT_FLAGS.get(16) && (crit_ptr->PAUSE <= 0)) {
int val = (int)(((float)(get_percent_lrnd(DUAL_WIELD_SKILL_NUM,
*crit_ptr)) *
(float)(crit_ptr->DEX) / 10.0));
if (d(1,100) < d(1, val)) {
vict_ptr = Top(crit_ptr->IS_FIGHTING);
if (vict_ptr->isUsingClient()) {
vict_ptr->show(CTAG_BATTLE(vict_ptr->whichClient()));
}
else if (vict_ptr->isUsingColor()) {
vict_ptr->show(*(vict_ptr->getBattleColor()));
}
int show_vict_tags = TRUE; //Show tags if needed.
do_battle_round(*crit_ptr, *vict_ptr, 10, show_vict_tags);
// Tags will only be shown in do_battle_round if
// the victim died.
if (show_vict_tags) {
if (vict_ptr->isUsingClient()) {
vict_ptr->show(CTAG_END_BATTLE(vict_ptr->whichClient()));
}
else if (vict_ptr->isUsingColor()) {
vict_ptr->show(*(vict_ptr->getDefaultColor()));
}
}//if
}//if
}//if
if (crit_ptr->isUsingClient()) {
crit_ptr->show(CTAG_END_BATTLE(crit_ptr->whichClient()));
}
else if (crit_ptr->isUsingColor()) {
crit_ptr->show(*(crit_ptr->getDefaultColor()));
}
}//if
}//while
// Take anyone affected by Flesh-to-Stone out of battle.
List<critter*> tmp_list2(r_ptr->getCrits());
tmp_list2.head(crit_cell);
critter* walker;
while ((walker = crit_cell.next())) {
if (is_affected_by(FLESH_TO_STONE_SKILL_NUM, *walker)) {
/* quit battle */
Cell<critter*> cll(walker->IS_FIGHTING);
critter* tmp_ptr;
while ((tmp_ptr = cll.next())) {
tmp_ptr->IS_FIGHTING.loseData(walker);
}//while
walker->IS_FIGHTING.clear();
}//if
}//while
if (!is_embattled) {
r_ptr = embattled_rooms.lose(rcell);
}//if
else
r_ptr = rcell.next();
}//while
}//do_battle
void gain_xp(critter& crit, const long exp, const short show_output) {
crit.EXP += exp;
if (show_output) {
String buf(100);
Sprintf(buf, "You gain %i experience points.\n", exp);
crit.show(buf);
}//if
if (crit.EXP >= levels[crit.LEVEL]) {
if (crit.LEVEL >= 30) {
crit.EXP = levels[crit.LEVEL] - 1;
//can't level past 30
}
else {
gain_level(crit);
}
}//if
}//gain_xp
void do_battle_round(critter& agg, critter& vict, int posn_of_weapon,
int& show_vict_tags) {
float damage, weapon_dam, pos_mult, xp_damage;
short is_wielding = FALSE;
short tp, td;
String buf(81);
String aggbuf(25);
String victbuf(25);
String wmsg(25);
String aggendbuf(50);
String victendbuf(50);
String otherbuf(50);
char dam_str[50];
int i;
if (mudlog.ofLevel(DBG)) {
mudlog << "In do_battle_round, agg addr: " << &agg << " name: "
<< *(name_of_crit(agg, ~0)) << " vict addr: " << &vict
<< " vict name: " << *(name_of_crit(vict, ~0))
<< " posn of weapon: " << posn_of_weapon << endl;
}
if (agg.isParalyzed()) {
agg.emote("is paralyzed, unable to fight back!");
agg.show("You are paralyzed, unable to move a muscle!\n");
return;
}//if
/* its cheaper to set than test, then set if needed */
agg.CRIT_FLAGS.turn_off(17); //no sneak
agg.CRIT_FLAGS.turn_off(22); //no hide
if ((agg.POS == POS_SIT) || (agg.POS == POS_REST) || (agg.POS == POS_SLEEP)
|| (agg.POS == POS_MED) || (agg.POS == POS_PRONE)) {
if (agg.CRIT_FLAGS.get(15)) { //if is perm_sleeped
if (d(1,4) == 2) {
agg.CRIT_FLAGS.turn_off(15);
agg.emote("seems to come out of a deep slumber!\n");
agg.setPosn(POS_STAND);
}//if
// TODO: Is this spell different from perm sleep??
stat_spell_cell* ss_ptr = is_affected_by(SLEEP_SKILL_NUM, agg);
if (ss_ptr) {
agg.affected_by.loseData(ss_ptr);
delete ss_ptr;
}//if
}//if
else if (!agg.isParalyzed() && (agg.PAUSE <= 0)) {
agg.emote("stands ready to fight.\n");
agg.setPosn(POS_STAND); //auto stand if possible
}//if
}//if
if (agg.CRIT_FLAGS.get(21)) { //if blocked
agg.CRIT_FLAGS.turn_off(21);
return;
}//if
if (agg.EQ[posn_of_weapon]) { //wielded
is_wielding = TRUE;
}//if
if (posn_of_weapon == 10) { //if doing dual_wield
if (!agg.eq[posn_of_weapon])
return;
else if (!(agg.eq[posn_of_weapon]->OBJ_FLAGS.get(57)))
return;
}//if
int j = (vict.DEX * 3) - (vict.AC / 10) + vict.LEVEL + (agg.POS * 5);
i = (agg.DEX * 3) + (agg.HIT * 2) + agg.LEVEL + (vict.POS * 5);
if ((!vict.isStunned() && (d(1, j) > d(1, i))) ||
(agg.POS == POS_STUN)) { //missed, stunned
if (agg.POS == POS_STUN) {
agg.show("You lie immobilized by the thought of imminent death.\n"
);
}//if
else {
// log("In the else, missed.\n");
Sprintf(buf, "%S misses you.\n", name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
vict.show(buf);
Sprintf(buf, "You miss %S.\n", name_of_crit(vict, agg.SEE_BIT));
agg.show(buf);
Sprintf(buf, "misses %S.", name_of_crit(vict, ~0));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE, &vict);
}//else
return;
}//if
td = tp = FALSE;
float chance = 0.0;
if ((vict.getPause() <= 0) && (!vict.isParalyzed())) {
// bigger means less likely to hit, should range from around 1-600
chance = (float)(d(1, 600)) * (float)agg.DEX / 18.0;
if ((chance < 100.0) && vict.isStanding()) {
td = (d(1, get_percent_lrnd(DODGE_SKILL_NUM, vict, TRUE) + vict.DEX * 2) > d(4,25));
}//if
// Don't parry & dodge at the same time...
if ((!td && vict.EQ[9]) && (vict.isStanding() || vict.isSitting())) {
// bigger means less likely to hit, should range from around 1-600
chance = (float)(d(1, 800)) * ((float)(agg.DEX)) / 18.0;
if (chance < 100.0) {
tp = (d(1, get_percent_lrnd(PARRY_SKILL_NUM, vict, TRUE) + vict.DEX) > d(4,25));
}
}//if
}//if
if (td) {
Sprintf(buf, "dodges %S's blow.", name_of_crit(agg, ~0));
emote(buf, vict, room_list[agg.getCurRoomNum()], TRUE, &agg);
Sprintf(buf, "%S dodges your blow.\n", name_of_crit(vict, agg.SEE_BIT));
buf.Cap();
agg.show(buf);
Sprintf(buf, "You dodge %S's blow.\n", name_of_crit(agg, vict.SEE_BIT));
vict.show(buf);
return;
}//if td
if (tp) {
Sprintf(buf, "parries %S's blow.", name_of_crit(agg, ~0));
emote(buf, vict, room_list[agg.getCurRoomNum()], TRUE, &agg);
Sprintf(buf, "%S parries your blow.\n",
name_of_crit(vict, agg.SEE_BIT));
buf.Cap();
agg.show(buf);
Sprintf(buf, "You parry %S's blow.\n",
name_of_crit(agg, vict.SEE_BIT));
vict.show(buf);
return;
}//if tp
/* else, did hit */
// log("Did hit..going into messages.\n");
if (is_wielding) { //wielded
weapon_dam = d((agg.EQ[posn_of_weapon])->OBJ_DAM_DICE_COUNT,
(agg.EQ[posn_of_weapon])->OBJ_DAM_DICE_SIDES);
}//if
else {
weapon_dam = d(agg.BH_DICE_COUNT, agg.BH_DICE_SIDES);
//batlog << "no weapon, weapon_dam: " << weapon_dam << endl;
}//else
// log("About to enter switch.\n");
switch (vict.POS) {
case POS_STAND:
pos_mult = 1.0;
break;
case POS_PRONE: case POS_REST: case POS_SIT:
pos_mult = 1.5;
break;
case POS_SLEEP:
pos_mult = 2.0;
break;
case POS_MED:
pos_mult = 3.0;
break;
case POS_STUN:
pos_mult = 4.0;
break;
default:
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: Default called on switch in battle.cc\n"
<< "ERROR: Here is bad vict.pos: " << vict.POS << endl;
}
pos_mult = 1.0;
break;
}//switch
/* no modifiers have been added yet, exact_raw... does that */
damage = ((float)agg.STR/3.0 + (float)agg.DAM + weapon_dam) *
pos_mult;
if (is_wielding) {
if (((agg.EQ[posn_of_weapon])->obj_flags).get(41))
wmsg = "slash";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(42))
wmsg = "smash";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(43))
wmsg = "pierce";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(44))
wmsg = "whip";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(45))
wmsg = "shoot";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(46))
wmsg = "sting";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(47))
wmsg = "sting";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(48))
wmsg = "sting";
else if (((agg.EQ[posn_of_weapon])->obj_flags).get(49))
wmsg = "jab";
else {
wmsg = "injure";
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: got to default finding wmsg, battle.cc, obj#: "
<< agg.EQ[posn_of_weapon]->OBJ_NUM << endl
<< "ERROR: Name of offending critter: "
<< *(name_of_crit(agg, ~0)) << endl;
}
}//else
}//if wielding
else {
wmsg = "hit"; //bare handed
}//else
if (agg.pc && (d(1,10) > 5)) { //1 in 5, !MOB chance of chance
if (d(1, 600) <
(agg.getLevel() / 5) *
(get_percent_lrnd(CRITICAL_STRIKE_SKILL_NUM, agg))) {
agg.show("You score a critical strike!!\n");
damage *= 2.0;
}//if
}//if
xp_damage = vict.HP + 1;
if (is_wielding && is_affected_by(FROST_BLADE_SKILL_NUM,
*(agg.EQ[posn_of_weapon]))) {
damage = (float)(exact_raw_damage((int)damage, ICE, vict, agg));
}//if
else if (is_wielding && is_affected_by(FIRE_BLADE_SKILL_NUM,
*(agg.EQ[posn_of_weapon]))) {
damage = (float)(exact_raw_damage((int)damage, FIRE, vict, agg));
}//if
else {
damage = (float)(exact_raw_damage((int)damage, NORMAL, vict, agg));
}//else
if ( xp_damage > damage ) { // if damage is more than enough to kill victim
sprintf (dam_str, " [dam > victim hp: %d]", (int)damage); //let imms know hp was exceeded by damage
xp_damage = damage; // set xp gain damage to actual hp lost by victim
}
else {
// Set up a string to let imms see exact damage delt/recieved
sprintf(dam_str, " [%d]", (int)damage);
}
if (damage < 3) {
Sprintf(aggbuf, "You bruise%s %S ",
agg.isImmort()?dam_str:"", name_of_crit(vict, agg.SEE_BIT));
Sprintf(victbuf, "%S bruises%s you ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S bruises %S ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}//if
else if (damage < 7) {
Sprintf(aggbuf, "You barely %S%s %S ", &wmsg, agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
Sprintf(victbuf, "%S barely %Ss%s you ",
name_of_crit(agg, vict.SEE_BIT), &wmsg, vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S barely %Ss %S ", name_of_crit(agg, ~0),
&wmsg, name_of_crit(vict, ~0));
}//if
else if (damage < 11) {
Sprintf(aggbuf, "You %S%s %S ", &wmsg, agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
if (strcmp("slash", wmsg) == 0) {
Sprintf(victbuf, "%S slashes%s you ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S slashes %S ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}
else {
Sprintf(victbuf, "%S %Ss%s you ", name_of_crit(agg, vict.SEE_BIT),
&wmsg, vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S %Ss %S ", name_of_crit(agg, ~0), &wmsg,
name_of_crit(vict, ~0));
}
}//if
else if (damage < 15) {
Sprintf(aggbuf, "You %S%s %S hard ", &wmsg, agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
if (strcmp("slash", wmsg) == 0) {
Sprintf(victbuf, "%S slashes you hard%s ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S slashes %S hard ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}
else {
Sprintf(victbuf, "%S %Ss you hard%s ", name_of_crit(agg, vict.SEE_BIT), &wmsg,
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S %Ss %S hard ", name_of_crit(agg, ~0), &wmsg,
name_of_crit(vict, ~0));
}
}//if
else if (damage < 20) {
Sprintf(aggbuf, "You %S%s %S very hard ", &wmsg, agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
if (strcmp("slash", wmsg) == 0) {
Sprintf(victbuf, "%S slashes you very hard%s ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S slashes %S very hard ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}
else {
Sprintf(victbuf, "%S %Ss%s you very hard ", name_of_crit(agg, vict.SEE_BIT),
&wmsg, vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S %Ss %S very hard ", name_of_crit(agg, ~0),
&wmsg, name_of_crit(vict, ~0));
}
}//if
else if (damage < 25) {
Sprintf(aggbuf, "You OBLITERATE%s %S ", agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
Sprintf(victbuf, "%S OBLITERATES%s you ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S OBLITERATES %S ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}//if
else if (damage < 36) {
Sprintf(aggbuf, "You LIQUIFY%s %S ", agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
Sprintf(victbuf, "%S LIQUIFIES%s you ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S LIQUIFIES %S ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}//if
else if (damage >= 36) {
Sprintf(aggbuf, "You ANNIHILATE%s %S ", agg.isImmort()?dam_str:"",
name_of_crit(vict, agg.SEE_BIT));
Sprintf(victbuf, "%S ANNIHILATES%s you ", name_of_crit(agg, vict.SEE_BIT),
vict.isImmort()?dam_str:"");
Sprintf(otherbuf, "%S ANNIHILATES %S ", name_of_crit(agg, ~0),
name_of_crit(vict, ~0));
}//if
if (agg.eq[posn_of_weapon]) {
Sprintf(aggendbuf, "with your %S.\n",
name_of_obj(*(agg.EQ[posn_of_weapon]), agg.SEE_BIT));
Sprintf(victendbuf, "with %s %S.\n", get_his_her(agg),
name_of_obj(*(agg.EQ[posn_of_weapon]), ~0));
}
else {
if ((agg.RACE == DRAGON) || (agg.RACE == ANIMAL) ||
(agg.RACE == MONSTER)) {
aggbuf.dropFromEnd(1); //rid of trailing space
aggendbuf = ".\n";
victbuf.dropFromEnd(1); //rid of trailing space
victendbuf = ".\n";
}//if
else {
aggendbuf = "with your fist.\n";
Sprintf(victendbuf, "with %s fist.\n", get_his_her(agg));
}//else
}//else
// changed to reflect only actual hp lost, not damage inflicted
gain_xp(agg, (int)(xp_damage * 1.5), FALSE); //fighting xp
buf = aggbuf;
buf+= aggendbuf;
buf.Cap();
agg.show(buf);
buf = victbuf;
buf+= victendbuf;
buf.Cap();
vict.show(buf);
buf = otherbuf;
buf+= victendbuf;
buf.Cap();
show_all_but_2(agg, vict, buf, room_list[agg.getCurRoomNum()]);
// In theory, any damage higher than 40 will have a chance of breaking
// the spell, with damage much higher having a better chance
if ((d(5, (int)damage) > 200) && vict.isParalyzed()) {
Sprintf(buf, "The force of %S's blow breaks the stone you are encased in!\n",
name_of_crit(agg, vict.SEE_BIT));
vict.show(buf);
Sprintf(buf, "The force of your blow breaks the stone %S is encased in!\n",
name_of_crit(vict, agg.SEE_BIT));
agg.show(buf);
Sprintf(buf, "blow breaks the stone %S is encased in!\n",
name_of_crit(vict, agg.SEE_BIT));
agg.pemote(buf);
rem_effects_crit(FLESH_TO_STONE_SKILL_NUM, vict, FALSE);
stat_spell_cell* ssc = vict.isAffectedBy(FLESH_TO_STONE_SKILL_NUM);
if (ssc) {
vict.affected_by.loseData(ssc);
delete ssc;
}
}
// log("Testing for consequences..\n");
if ((vict.HP <= 0) && ((vict.POS == POS_SIT) || (vict.POS == POS_REST)
|| (vict.POS == POS_PRONE) || (vict.POS == POS_SLEEP)
|| (vict.POS == POS_STAND))) {
vict.setPosn(POS_STUN);
emote("is stunned.", vict, room_list[vict.getCurRoomNum()], TRUE);
vict.show("You are stunned!!\n");
}//if
else if (vict.HP <= 0) {
//emote("is dead!!", vict, room_list[vict.getCurRoomNum()], TRUE);
agg_kills_vict(&agg, vict, show_vict_tags, TRUE);
}//if
else if (vict.HP <= vict.WIMPY) {
int is_dead = FALSE;
flee(vict, is_dead);
}//if wimpy
}//do_battle_round
// Convenience method for when we don't care about dealing
// with tags.
void agg_kills_vict(critter* agg, critter& vict, int do_msg = TRUE) {
int show_vict_tags = FALSE;
agg_kills_vict(agg, vict, show_vict_tags, do_msg);
}
void agg_kills_vict(critter* agg, critter& vict, int& show_vict_tags,
int do_msg) {
Cell<critter*> cll2(vict.IS_FIGHTING);
critter *ptr2;
String buf(100);
if (do_msg) {
emote("is dead!", vict, room_list[vict.getCurRoomNum()], TRUE);
}
while ((ptr2 = cll2.next())) { // others no longer fighting vict.
ptr2->IS_FIGHTING.loseData(&vict);
}//while
if (agg && agg->mob && agg->mob->proc_data &&
agg->mob->proc_data->temp_proc) { //rem from hunting, tracking
Cell<String*> cll(agg->HUNTING);
String* ptr;
while ((ptr = cll.next())) {
if (vict.isNamed(*ptr)) {
delete ptr;
ptr = agg->HUNTING.lose(cll);
break;
}//if
}//while
if (vict.isNamed(agg->TRACKING)) {
agg->setTrackingTarget(NULL_STRING);
}
}//if
float val = ((float)(vict.ALIGN) / 10.0);
// TODO: adjust so that the extremes are harder to reach.
if (agg) {
agg->ALIGN -= (int)(val);
if (agg->ALIGN < -1000)
agg->ALIGN = -1000;
else if (agg->ALIGN > 1000)
agg->ALIGN = 1000;
}
vict.IS_FIGHTING.clear(); //vict no longer fighting others
if (vict.pc && agg && agg->pc) {
doShowList(&vict, Selectors::instance().CC_gets_info_allow,
Selectors::instance().CC_none, pc_list,
CS_PKILLED_INFO,
agg->getName(), vict.getName(), vict.getCurRoomNum());
agg->pc->pk_count++;
vict.pc->pk_count--;
}//if
else if (vict.pc && agg) {
doShowList(&vict, Selectors::instance().CC_gets_info_allow,
Selectors::instance().CC_none, pc_list,
CS_KILLED_INFO,
vict.getName(), agg->getName(), vict.getCurRoomNum());
vict.pc->died_count++;
}
if (agg) {
disburse_xp(*agg, vict); //take care of xp
}
dead_crit_to_corpse(vict, show_vict_tags); //remove all traces of vict
if (agg) {
do_just_killed_procs(*agg); //autoloot etc
}
}//agg_kills_vict;
void damage_magic_shields(float damage, critter& vict) {
float dam=(float)damage;
int spells_used=0;
if (is_affected_by(STONE_SKIN_SKILL_NUM, vict)) { spells_used++;
dam*=(100.0+STONE_SKIN_EFFECT_DRM)/100.0; }
if (is_affected_by(SANCTUARY_SKILL_NUM, vict)) { spells_used++;
dam*=(100.0+SANCTUARY_EFFECT_DRM)/100.0; }
if (is_affected_by(ARMOR_SKILL_NUM, vict)) spells_used++;
if (is_affected_by(MAGIC_SHIELD_SKILL_NUM, vict)) spells_used++;
if (is_affected_by(SHADOWS_BLESSING_SKILL_NUM, vict)) spells_used++;
if (is_affected_by(DIVINE_PROTECTION_SKILL_NUM, vict)) spells_used++;
if (is_affected_by(PRISMATIC_GLOBE_SKILL_NUM, vict)) spells_used++;
if (spells_used >= 2) {
vict.MOV -= (int)((damage-dam)/5);
vict.MANA -= (int)((damage-dam)/5);
if (vict.MOV < 0) vict.MOV=0;
if (vict.MANA < 0) vict.MANA=0;
}
else if (spells_used == 1) {
vict.MANA -= (int)((damage-dam)/5);
if (vict.MANA < 0) vict.MANA=0;
}
}
int exact_raw_damage(int damage, int damage_type, critter& vict, critter& agg) {
int armor_value = 100;
float dam = (float)damage;
switch (damage_type) {
case FIRE: case D_BREATH:
armor_value = vict.HEAT_RESIS;
break;
case ICE:
armor_value = vict.COLD_RESIS;
break;
case ELECTRICITY:
armor_value = vict.ELEC_RESIS;
break;
}//switch
armor_value += 100;
if (armor_value < 0) {
armor_value = 0;
}//if
dam = dam * ((float)armor_value/200.0);
damage_magic_shields(dam, vict);
dam = (dam * (((float)vict.getDamRecMod())/100.0) *
((float)(agg.DAM_GIV_MOD)/100.0));
int pl;
if (agg.pc &&
(pl = get_percent_lrnd(ENHANCED_DAMAGE_SKILL_NUM, agg)) > 0) {
dam += (float)(d(1, pl/20));
}//if
if ((agg.ALIGN < -350) && vict.CRIT_FLAGS.get(24)) {
dam -= (float)(d(1, 10));
if (dam < 0)
dam = 0;
}//if
if ((agg.ALIGN > 350) && vict.CRIT_FLAGS.get(25)) {
dam -= (float)(d(1, 10));
if (dam < 0)
dam = 0;
}//if
if (is_affected_by(ABSORB_BLOWS_SKILL_NUM, vict)) {
vict.MANA -= (short)dam;
if (vict.MANA < 0) {
dam *= 2;
vict.MANA = 0;
}//if
else {
dam = -(dam/1.5);
}//else
}//if
if (is_affected_by(EARTHMELD_SKILL_NUM, vict)) {
if ((pl = get_percent_lrnd(EARTHMELD_SKILL_NUM, agg)) > d(1,115)) {
dam *= (100.0 - ((float)(pl))/7.0) / 100.0;
}//if
}//if
// Gonna make low level mobs a little weaker across the board to
// help out the newbies!
if (agg.isNPC() && (agg.getLevel() < 10)) {
dam *= 0.75;
}
if (vict.isImmort() && vict.isNoHassle()
&& vict.getImmLevel() >= agg.getImmLevel()) {
dam = 0.0;
if (mudlog.ofLevel(INF)) {
mudlog << "INFO: setting damage to zero because of !hassle.\n"
<< endl;
}//if
}//if
// Special checks for Flesh-to-Stone
if (is_affected_by(FLESH_TO_STONE_SKILL_NUM, vict)) {
if (dam > 3.0) {
dam = 3.0;
}
}
if (is_affected_by(FLESH_TO_STONE_SKILL_NUM, agg)) {
// Just in case someone lets some damage slip through...
if (dam > 5.0) {
dam = 5.0;
}
}
vict.HP -= (int)(dam);
return abs((int)dam); //negative damages mess up error messages
}//exact_raw_damage
int exact_raw_damage(int damage, int damage_type, critter& vict) {
int armor_value = 100;
float dam = (float)damage;
switch (damage_type) {
case FIRE: case D_BREATH:
armor_value = vict.HEAT_RESIS;
break;
case ICE:
armor_value = vict.COLD_RESIS;
break;
case ELECTRICITY:
armor_value = vict.ELEC_RESIS;
break;
}//switch
armor_value += 100;
if (armor_value < 0) {
armor_value = 0;
}//if
dam *= ((float)armor_value/200.0);
damage_magic_shields(dam, vict);
dam *= (((float)vict.getDamRecMod())/100.0);
// Give PC's a slight edge, maybe modify after the game has mature
// players.
if (!vict.isPc()) {
dam *= 0.90;
}
vict.HP -= (int)(dam);
return (int)dam;
}//exact_raw_damage
void disburse_xp(critter& agg, const critter& vict) {
Cell<critter*> cll;
critter* crit_ptr;
int tot_levs = 0;
long xp_to_be_gained = (vict.EXP/config.experienceDivisor+30-agg.getLevel());
long xp_per_level;
//log("In disburse_xp.\n");
if (mudlog.ofLevel(DBG)) {
mudlog << "In disburse_xp, agg: " << *(agg.getName())
<< " " << agg.getIdNum() << " vict: " << *(vict.getName())
<< " " << vict.getIdNum() << endl;
}
if (IsEmpty(agg.GROUPEES)) { //solitary person
gain_xp(agg, xp_to_be_gained, TRUE);
}//if
else { //in a group
agg.GROUPEES.head(cll);
while ((crit_ptr = cll.next())) {
if (crit_ptr->getCurRoomNum() == agg.getCurRoomNum()) {
tot_levs += crit_ptr->getLevel();
}
}//while
xp_per_level = (xp_to_be_gained / tot_levs);
agg.GROUPEES.head(cll);
while ((crit_ptr = cll.next())) {
if (crit_ptr->getCurRoomNum() == agg.getCurRoomNum()) {
gain_xp(*crit_ptr, xp_per_level * (crit_ptr->LEVEL), TRUE);
}
}//while
}//in a group
}//disburse_xp
/*
RJY [Trice] added this function for the sole reason of debugging.
with this function I can set a br point in GDB directly and not
have to weed through another functions crap ;)
AsPer Bens request I tried to use crit->show and crit->emote but got compiler
errors, dropped back to crit.show and crit.emote and got even more errors, not
sure what I am doing wrong. Instead of commiting BS code I left in the legecy
C style code.
-Ron [12/20/99]
*/
void avian_gain_level(critter& crit) {
object* junk = NULL;
String buf(2048);
if ( crit.RACE == AVIAN ) { // For sanity reasons
switch( crit.LEVEL )
{
case 5: {
Sprintf(buf, "writhes in agony as %s nose transforms into a beak.", get_his_her(crit));
pemote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
crit.show("You writhe in agony as your nose hardens to form a beak!\n");
}
break;
case 10: {
Sprintf(buf, "howls as wings sprout from %s back.", get_his_her(crit));
emote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
show("Sharp pains shoot from your back as a pair of wings begin to form.\n", crit );
if ( crit.EQ[12] ) {
Sprintf(buf, "new wings destroy %S sending it to the ground",
long_name_of_obj(*(crit.EQ[12]), ~0));
pemote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
Sprintf(buf,"Your wings smash %S crumbling it to the ground",
long_name_of_obj(*(crit.EQ[12]), ~0));
crit.show(buf);
junk = crit.EQ[12];
remove_eq_effects(*(crit.EQ[12]), crit, FALSE, FALSE, 12);
crit.gainInv(crit.EQ[12]);
recursive_init_unload(obj_list[crit.EQ[12]->OBJ_NUM], 0);
if (crit.EQ[12]->IN_LIST) {
delete crit.EQ[12];
}//if
crit.EQ[12] = NULL;
}
}
break;
case 15: {
Sprintf(buf, "howls as %s wings grow to full length.", get_his_her(crit));
emote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
crit.show("Excruciating pain befalls you as your wings take full form.\n");
if( crit.EQ[4] ) {
Sprintf(buf, "wings destroy %S sending it to the ground",
long_name_of_obj(*(crit.EQ[4]), ~0));
pemote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
Sprintf(buf, "Your wings smash %S crumbling it to the ground",
crit.EQ[4]->getLongName(crit));
crit.show(buf);
junk = crit.EQ[4];
remove_eq_effects(*(crit.EQ[4]), crit, FALSE, FALSE, 4);
crit.gainInv(crit.EQ[4]);
recursive_init_unload(obj_list[crit.EQ[4]->OBJ_NUM], 0);
if (crit.EQ[4]->IN_LIST) {
delete crit.EQ[4];
}//if
crit.EQ[4] = NULL;
}
}
break;
case 20: {
Sprintf(buf, "falls over as %s legs transform in to wicked looking claws.",
get_his_her(crit));
emote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
crit.show("You fall over as your legs transform into mighty claws.\n");
if( crit.EQ[15] ) {
Sprintf(buf, "wings destroy %S sending it to the ground",
long_name_of_obj(*(crit.EQ[15]), ~0));
pemote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
Sprintf(buf, "Your wings smash %S crumbling it to the ground",
long_name_of_obj(*(crit.EQ[15]), ~0) );
crit.show(buf);
junk = crit.EQ[15];
remove_eq_effects(*(crit.EQ[15]), crit, FALSE, FALSE, 15);
crit.gainInv(crit.EQ[15]);
recursive_init_unload(obj_list[crit.EQ[15]->OBJ_NUM], 0);
if (crit.EQ[15]->IN_LIST) {
delete crit.EQ[15];
}//if
crit.EQ[15] = NULL;
}
}
break;
case 25: {
Sprintf(buf, "A magnificant tail erupts from %s back.", get_his_her(crit));
show_all(buf,room_list[crit.getCurRoomNum()]);
crit.show("A magnificant tails forms behind you, the metamorphosis is complete!\n");
if( crit.EQ[13] ) {
Sprintf(buf, "new tail destroys %S sending it to the ground",
long_name_of_obj(*(crit.EQ[13]), ~0));
pemote(buf, crit, room_list[crit.getCurRoomNum()], TRUE);
Sprintf(buf,"Your tail smashes your %S, crumbling it to the ground",
long_name_of_obj(*(crit.EQ[13]), ~0) );
crit.show(buf);
junk = crit.EQ[13];
remove_eq_effects(*(crit.EQ[13]), crit, FALSE, FALSE, 13);
crit.gainInv(crit.EQ[13]);
recursive_init_unload(obj_list[crit.EQ[13]->OBJ_NUM], 0);
if (crit.EQ[13]->IN_LIST) {
delete crit.EQ[13];
}//if
crit.EQ[13] = NULL;
}
}
break;
}
}
}//avain_gain_level
void gain_level(critter& crit) {
if (crit.LEVEL >= 30) {
crit.show("You can learn no more from battle.\n");
if (crit.LEVEL > 40) {
crit.LEVEL = 40; //for those over level 40 by some other means
}//if
return;
}//if
int hp_gain = d(1, crit.CON/2);
int mana_gain = d(1, crit.WIS/2);
int _class = crit.getClass();
switch (_class)
{
case WARRIOR:
case RANGER:
case THIEF:
case BARD:
hp_gain += d(2, crit.CON/2);
break;
case SAGE:
case WIZARD:
case CLERIC:
case ALCHEMIST:
mana_gain += d(2, crit.WIS/2);
break;
default:
if (mudlog.ofLevel(DBG)) {
mudlog << "WARNING: default class in gain_level: " << _class
<< endl;
}
}//switch
crit.LEVEL++;
crit.PRACS += d(2, (int)((float)(crit.INT)/6.0)) + 1;
crit.MA_MAX += mana_gain;
crit.setHP_MAX(crit.getHP_MAX() + hp_gain);
crit.MV_MAX += d(1, crit.DEX);
crit.show("You rise a level.\n");
if ( crit.RACE == DRAGON )
avian_gain_level(crit);
}//gain_level
void dead_crit_to_corpse(critter& vict, int& show_vict_tags) {
object *corpse, *gold;
Cell<object*> ocell;
object* o_ptr;
String buf(81);
if (mudlog.ofLevel(DBG)) {
mudlog << "In dead_crit_to_corpse, vict: " << *(name_of_crit(vict, ~0))
<< " vict addr: " << &vict << endl;
}
if (vict.isMob()) {
mudlog.log(ERROR, "ERROR: mob sent to dead_crit_to_corpse.\n");
return;
}//if
/* first, cut all links to critter */
if (vict.temp_crit) {
//Takes care of shielding and so on.
vict.temp_crit->Clear();
}//if
affected_mobs.loseData(&vict);
proc_action_mobs.loseData(&vict);
vict.doUngroup(1, &NULL_STRING); //no more part of group
vict.doBecomeNonPet(); //dead pets make no sense!
// Get rid of any pets victim may own.
critter* pptr;
while (!vict.PETS.isEmpty()) {
pptr = vict.PETS.popFront();
pptr->doBecomeNonPet();
}
int ngame;
if (vict.mob) {
recursive_init_unload(vict);
ngame = vict.getCurInGame();
if (ngame < 0) {
mudlog << "ERROR: ngame is < zero: "
<< ngame << ", dead_crit_to_corpse, for mob: "
<< *(vict.getName()) << " number: " << vict.getIdNum()
<< endl;
vict.setCurInGame(0); //try to correct things
}//if
}//if
// If we are a Player-run Shop keeper, then have some special fun.
if (vict.isPlayerShopKeeper()) {
// we gotta first update all the player-manipulated
// data, no use making them enter that again and again.
vict.transferShopDataTo(mob_list[vict.getIdNum()]);
// Now save it to disk.
save_player_shop_owner(mob_list[vict.getIdNum()]);
}//if
/* all links have been cut, I hope */
/* Now we will transfer all eq and gold and stuff to a corpse */
// create corpse object.
corpse = obj_to_sobj(obj_list[config.corpseObject],
room_list[vict.getCurRoomNum()].getInv(),
vict.getCurRoomNum());
recursive_init_loads(*corpse, 0);
// Set edible flag on corpse if was on mob.
if (vict.isEdible()) {
corpse->setButcherable(TRUE);
}
corpse->bag->time_till_disolve = 10; // in ticks
Sprintf(buf, "The corpse of %S lies here.",
name_of_crit(vict, ~0));
corpse->in_room_desc = buf;
room_list[vict.getCurRoomNum()].gainInv(corpse);
/* Set the weight to that of the living being. */
corpse->setEmptyWeight(vict.getNakedWeight());
/* gold */
if (vict.GOLD > 0) {
gold = obj_to_sobj(obj_list[config.goldCoinsObject], &(corpse->inv), vict.getCurRoomNum());
obj_list[config.goldCoinsObject].incrementCurInGame();
gold->cur_stats[1] = vict.GOLD; //transfer gold
vict.GOLD = 0;
Put(gold, corpse->inv);
}//if
/* eq */
for (int i = 0; i<MAX_EQ; i++) {
if (vict.EQ[i]) {
remove_eq_effects(*(vict.EQ[i]), vict, TRUE, FALSE, i);
if (vict.EQ[i]->IN_LIST)
vict.EQ[i]->IN_LIST = &(corpse->inv);
Put(vict.EQ[i], corpse->inv);
vict.EQ[i] = NULL;
}//if
}//for
/* inv */
vict.inv.head(ocell);
while ((o_ptr = ocell.next())) {
drop_eq_effects(*o_ptr, vict, FALSE);
if (o_ptr->IN_LIST)
o_ptr->IN_LIST = &(corpse->inv);
corpse->gainInv(o_ptr);
}//while
vict.inv.clear();
/* perm inv for shopkeepers */
if (vict.mob) {
if (vict.mob->proc_data) {
if (vict.mob->proc_data->sh_data) {
vict.PERM_INV.head(ocell);
while ((o_ptr = ocell.next())) {
if (o_ptr->IN_LIST)
o_ptr->IN_LIST = &(corpse->inv);
Put(o_ptr, corpse->inv);
}//while
vict.PERM_INV.clear(); //should NEVER be SOBJ's
}//if
}//if
}//if
if (vict.mob && vict.MOB_FLAGS.get(16)) { //if has skin
if (!corpse->obj_proc) {
corpse->obj_proc = new obj_spec_data;
}//if
corpse->obj_proc->skin_ptr = &(obj_list[vict.mob->skin_num]);
recursive_init_loads(*(corpse->obj_proc->skin_ptr), 0);
corpse->obj_proc->obj_spec_data_flags.turn_on(2);
}//if
else {
if (vict.pc) {
if (!corpse->obj_proc) {
corpse->obj_proc = new obj_spec_data;
}//if
object* ptr = corpse->obj_proc->skin_ptr =
obj_to_sobj(obj_list[config.pcSkinObject], &(corpse->inv),
vict.getCurRoomNum());
recursive_init_loads(*ptr, 0);
ptr->names.append(new String(*(Top(vict.names))));
Sprintf(buf, "the tattered skin of %S", Top(vict.names));
ptr->short_desc = buf;
Sprintf(buf, "The tattered skin of %S lies here.",
Top(vict.names));
ptr->in_room_desc = buf;
Sprintf(buf,
"This large piece of %s skin was recently hacked from the corpse of %S.
You wonder why anyone would want the skin of a %s, but perhaps it is just
a trophy--a symbol of %S's defeat.\n",
get_race_name(vict.RACE),
name_of_crit(vict, ~0), get_race_name(vict.RACE),
name_of_crit(vict, ~0));
ptr->long_desc = buf;
corpse->obj_proc->obj_spec_data_flags.turn_on(2);
}//if
}//else
/* punish and re-enter the pc into the game, if its a pc */
if (vict.pc) {
if (vict.CON > 0) {
vict.MANA = 1;
vict.HP = 1;
vict.MOV = 1;
vict.HUNGER = 20;
vict.THIRST = 20;
vict.setPosn(POS_REST);
if (vict.EXP < 5000000)
vict.EXP -= (vict.EXP/13);
else
vict.EXP -= 500000;
if (show_vict_tags) {
show_vict_tags = FALSE; //Tell calling code not to show more tags.
if (vict.isUsingClient()) {
vict.show(CTAG_END_BATTLE(vict.whichClient()));
}
else if (vict.isUsingColor()) {
vict.show(*(vict.getDefaultColor()));
}
}//if we should show tags here...
Cell<stat_spell_cell*> spcll(vict.affected_by);
stat_spell_cell* sp_ptr;
while ((sp_ptr = spcll.next())) {
rem_effects_crit(sp_ptr->stat_spell, vict, FALSE);
}//while
clear_ptr_list(vict.affected_by);
vict.mini_affected_by.head(spcll);
while ((sp_ptr = spcll.next())) {
rem_effects_crit(sp_ptr->stat_spell, vict, FALSE);
}//while
clear_ptr_list(vict.mini_affected_by);
int nrm = vict.getCurRoomNum();
room_list[nrm].removeCritter(&vict); //decrement's cur in game if NPC
leave_room_effects(room_list[nrm], vict); //takes care of blocking
room_list[config.loginRoom].gainCritter(&vict);
Sprintf(buf, "%S appears in the room looking quite dead!\n",
name_of_crit(vict, ~0));
buf.Cap();
room_list[config.loginRoom].showAllCept(buf, &vict);
vict.show(CS_YOU_DEAD_NL);
vict.show(CS_WELCOME_AGAIN);
vict.show(CS_FARE_BETTER);
look(1, &NULL_STRING, vict); //sos ya can see the temple desc, etc.
vict.save();
}//if not con-death
else { //PERM DEATH!!
int nrm = vict.getCurRoomNum();
vict.show(CS_END_OF_LUCK);
Sprintf(buf,
"gasps a final farewell to the Realm in which %s has dwelt for %i years!",
get_he_she(vict), vict.getAge());
emote(buf, vict, room_list[nrm], TRUE);
doShowList(&vict, Selectors::instance().CC_gets_info_allow,
Selectors::instance().CC_none, pc_list,
CS_PERM_DEATH_INFO,
vict.getName());
vict.doSuicide(); //poor bastard!
}//if perm con death
}//if
else { //then it was a smob
show_vict_tags = FALSE;
int nrm = vict.getCurRoomNum();
room_list[nrm].removeCritter(&vict); //decrement's cur in game if NPC
leave_room_effects(room_list[nrm], vict); //takes care of blocking
if (vict.possessed_by) {
vict.possessed_by->show("Your possessed victim has died.\n");
vict.possessed_by->unPossess();
}
delete &vict;
}//else
}//dead_crit_to_corpse
critter* mob_to_smob(critter& mob, const int room_num, int do_sub,
int i_th, const String* name, int see_bit) {
if (mudlog.ofLevel(DBG)) {
mudlog << "In mob_to_smob: " << *(mob.getName()) << endl;
}
if (!mob.isMob()) {
mudlog.log(ERROR, "ERROR: mob_to_smob called on nonMOB.\n");
do_shutdown = TRUE;
exit(100);
}//if
if (mob.pc) {
mudlog.log(ERROR, "ERROR: mob has pc_data in mob_to_smob.\n");
do_shutdown = TRUE;
exit(113);
}//if
mob.MOB_FLAGS.turn_on(4); //now it can be/should be reset when pulsed
critter* crit_ptr = new critter(mob);
obj_ptr_log << "CRI_CR " << mob.getIdNum() << " " << crit_ptr << "\n";
if (!name || ((room_num < 0) || (room_num > NUMBER_OF_ROOMS))) {
mudlog.log(ERROR,
"ERROR: name NULL or room_num out of range in mob_to_smob.\n");
do_shutdown = TRUE;
exit(100);
}//if
crit_ptr->setCurRoomNum(room_num);
if (do_sub) {
if (!room_list[room_num].sub_a_4_b(crit_ptr, i_th, *name, see_bit)) {
mudlog << "ERROR: crit_sub_a_4_b failed in mob_to_smob, rm# "
<< room_num << " i_th: " << i_th << " name: " << *name << endl;
}//if
}//if
else {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: mob_to_smob, not doing do_sub, mob#: "
<< crit_ptr->getIdNum() << endl;
}//if
}//else
affected_mobs.gainData(crit_ptr); //basically a list of smobs
if (mudlog.ofLevel(DBG)) {
mudlog << "mob_to_smob: returning critter, address: " << crit_ptr
<< endl;
}
crit_ptr->mob->setTicksOld(0);
return crit_ptr;
}//mob_to_smob
critter* mob_to_smob(critter& mob, const int room_num,
int suppress_msg) {
if ((room_num > NUMBER_OF_ROOMS) || (room_num < 0)) {
mudlog.log(ERROR, "ERROR: room_num out of range in mob_to_smob.\n");
do_shutdown = TRUE;
exit(100);
}//if
return mob_to_smob(mob, room_list[room_num], suppress_msg);
}
// Must use this one if we are reading in room, because we
// are using a temporary room to put them in. Should migrate
// to this one, as opposed to the one above anyway..safer.
critter* mob_to_smob(critter& mob, room& rm, int suppress_sub_fail_msg) {
if (mudlog.ofLevel(DBG)) {
mudlog << "In mob_to_smob: " << *(mob.getName()) << endl;
}
/* This function DOES DO SUBSTITUTION itself, calling code need not worry
about it. */
if (!mob.isMob()) {
mudlog.log(ERROR, "ERROR: mob_to_smob called on nonMOB.\n");
core_dump("mob_to_smob1");
}//if
if (mob.pc) {
mudlog.log(ERROR, "ERROR: mob has pc_data in mob_to_smob.\n");
core_dump("mob_to_smob2");
}//if
mob.MOB_FLAGS.turn_on(4); //now it can be/should be reset when pulsed
critter* crit_ptr = new critter(mob);
obj_ptr_log << "CRI_CR " << mob.getIdNum() << " " << crit_ptr << "\n";
crit_ptr->setCurRoomNum(rm.getIdNum());
if (!rm.sub_a_4_b(crit_ptr, (critter*)(&mob), 1)) {
/* note: create golem and others will fail on this now with no bad
effects, so this error message has been commented out. */
if (!suppress_sub_fail_msg) {
mudlog << "ERROR: SubstituteData failed in mob_to_smob, mob#: "
<< crit_ptr->getIdNum() << " name: " << *(crit_ptr->getName())
<< " room# " << rm.getIdNum() << endl;
}//if
// If couldn't substitute, then we need to increment it's
// CUR_IN_GAME
crit_ptr->incrementCurInGame();
}//if
affected_mobs.gainData(crit_ptr); //basically a list of smobs
if (mudlog.ofLevel(DBG)) {
mudlog << "mob_to_smob: returning critter, address: " << crit_ptr
<< endl;
}
crit_ptr->mob->setTicksOld(0);
return crit_ptr;
}//mob_to_smob
object* obj_to_sobj(object& obj, List<object*>* in_list,
int do_sub, int i_th, const String* name, int see_bit,
room& rm) {
//log("In obj_to_sobj.\n");
if (!name || !in_list) {
core_dump("ERROR: name or in_list NULL in obj_to_sobj.\n");
}//if
if (obj.IN_LIST) {
core_dump("ERROR: obj_to_sobj called on SOBJ, version 1.\n");
}//if
if (!in_list) {
core_dump("ERROR: in_list is NULL in obj_to_sobj, version 1!!\n");
}//if
obj.OBJ_FLAGS.turn_on(70); //now it can be/should be reset when pulsed
object* obj_ptr = new object(obj);
obj_ptr_log << "OBJ_CR " << obj.getIdNum() << " " << obj_ptr << "\n";
obj_ptr->IN_LIST = in_list;
obj_ptr->setCurRoomNum(rm.getIdNum(), 0);
if (do_sub) {
if (!obj_sub_a_4_b(obj_ptr, *in_list, i_th, name, see_bit, rm)) {
mudlog.log(ERROR, "ERROR: obj_sub_a_4_b failed in obj_to_sobj.\n");
}//if
}//if
else {
//mudlog << "WARNING: obj_to_sobj, no sub: increment CUR_IN_GAME?"
// << endl;
//obj_list->incrementCurInGame();
}
affected_objects.gainData(obj_ptr); //basically a list of sobjs
return obj_ptr;
}//obj_to_sobj
object* obj_to_sobj(object& obj, List<object*>* in_list, int rm_num) {
//log("In obj_to_sobj, part two.\n");
/* WARNING: this function does NO SUBSTITUTION, you must do it
explicitly in the calling code. */
if (obj.IN_LIST) {
core_dump("ERROR: obj_to_sobj called on SOBJ, version 2.\n");
}//if
if (!in_list) {
core_dump("ERROR: in_list is NULL in obj_to_sobj, version 2!!\n");
}//if
obj.OBJ_FLAGS.turn_on(70); //now it can be/should be reset when pulsed
object* obj_ptr = new object(obj);
obj_ptr_log << "OBJ_CR " << obj.getIdNum() << " " << obj_ptr << "\n";
obj_ptr->IN_LIST = in_list;
obj_ptr->setCurRoomNum(rm_num, 0);
affected_objects.gainData(obj_ptr); //basically a list of sobjs
return obj_ptr;
}//obj_to_sobj