Code:
die(victim, ch);
if (GROUP(ch) && (local_gold > 0) && PRF_FLAGGED(ch, PRF_AUTOSPLIT) ) {
generic_find("corpse", FIND_OBJ_ROOM, ch, &tmp_char, &corpse_obj);
if (corpse_obj) {
do_get(ch, "all.coin corpse", 0, 0);
do_split(ch, local_buf, 0, 0);
}
/* need to remove the gold from the corpse */
} else if (!IS_NPC(ch) && (ch != victim) && PRF_FLAGGED(ch, PRF_AUTOGOLD)) {
do_get(ch, "all.coin corpse", 0, 0);
}
if (!IS_NPC(ch) && (ch != victim) && PRF_FLAGGED(ch, PRF_AUTOLOOT)) {
do_get(ch, "all corpse", 0, 0);
}
if (IS_NPC(victim) && !IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOSAC)) {
do_sac(ch,"corpse",0,0);
}
return (-1);
}
return (dam);
}
This code needs to be rewritten - the problem is that noone seems to have thought about this use case.
There are some options.
Code:
die(victim, ch);
- if (GROUP(ch) && (local_gold > 0) && PRF_FLAGGED(ch, PRF_AUTOSPLIT) ) {
+ if (!IS_NPC(ch) && GROUP(ch) && (local_gold > 0) && PRF_FLAGGED(ch, PRF_AUTOSPLIT) ) {
generic_find("corpse", FIND_OBJ_ROOM, ch, &tmp_char, &corpse_obj);
if (corpse_obj) {
do_get(ch, "all.coin corpse", 0, 0);
do_split(ch, local_buf, 0, 0);
}
/* need to remove the gold from the corpse */
} else if (!IS_NPC(ch) && (ch != victim) && PRF_FLAGGED(ch, PRF_AUTOGOLD)) {
do_get(ch, "all.coin corpse", 0, 0);
}
if (!IS_NPC(ch) && (ch != victim) && PRF_FLAGGED(ch, PRF_AUTOLOOT)) {
do_get(ch, "all corpse", 0, 0);
}
if (IS_NPC(victim) && !IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOSAC)) {
do_sac(ch,"corpse",0,0);
}
return (-1);
}
return (dam);
}
The easy fix doesn't "work" though - if my zombie kills the mob, nothing is looted, split or sac'ed.
Also, a long standing bug in this code is that if you are carrying too much to take all, do_sac just dumps the items on the ground.
Code:
static int perform_auto_actions(struct char_data *ch, struct char_data *victim, long gold) {
char gold_buf[256];
struct char_data *tmp_char;
struct obj_data *corpse_obj;
struct char_data *master = ch;
sprintf(gold_buf,"%ld", gold);
if (ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) {
master = ch->master;
}
if (GROUP(master) && (gold > 0) && !IS_NPC(master) && PRF_FLAGGED(master, PRF_AUTOSPLIT) ) {
generic_find("corpse", FIND_OBJ_ROOM, master, &tmp_char, &corpse_obj);
if (corpse_obj) {
do_get(master, "all.coin corpse", 0, 0);
do_split(master, local_buf, 0, 0);
}
} else if (!IS_NPC(master) && (master != victim) && PRF_FLAGGED(master, PRF_AUTOGOLD)) {
do_get(master, "all.coin corpse", 0, 0);
}
if (!IS_NPC(master) && (master != victim) && PRF_FLAGGED(master, PRF_AUTOLOOT)) {
do_get(master, "all corpse", 0, 0);
}
if (IS_NPC(victim) && !IS_NPC(master) && PRF_FLAGGED(master, PRF_AUTOSAC)) {
generic_find("corpse", FIND_OBJ_ROOM, master, &tmp_char, &corpse_obj);
if (corpse_obj) {
if (!corpse_obj->contents) {
do_sac(ch,"corpse",0,0);
}
}
}
}
/* This function returns the following codes:
* < 0 Victim died.
* = 0 No damage.
* > 0 How much damage done. */
int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype)
{
long local_gold = 0, happy_gold = 0;
if (GET_POS(victim) <= POS_DEAD) {
/* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */
if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET))
return (-1);
log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.",
GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch));
die(victim, ch);
return (-1); /* -je, 7/7/92 */
}
/* peaceful rooms */
if (ch->nr != real_mobile(DG_CASTER_PROXY) &&
ch != victim && ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL)) {
send_to_char(ch, "This room just has such a peaceful, easy feeling...\r\n");
return (0);
}
/* shopkeeper and MOB_NOKILL protection */
if (!ok_damage_shopkeeper(ch, victim) || MOB_FLAGGED(victim, MOB_NOKILL)) {
send_to_char(ch, "This mob is protected.\r\n");
return (0);
}
/* You can't damage an immortal! */
if (!IS_NPC(victim) && ((GET_LEVEL(victim) >= LVL_IMMORT) && PRF_FLAGGED(victim, PRF_NOHASSLE)))
dam = 0;
if (victim != ch) {
/* Start the attacker fighting the victim */
if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL))
set_fighting(ch, victim);
/* Start the victim fighting the attacker */
if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL)) {
set_fighting(victim, ch);
if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch))
remember(victim, ch);
}
}
/* If you attack a pet, it hates your guts */
if (victim->master == ch)
stop_follower(victim);
/* If the attacker is invisible, he becomes visible */
if (AFF_FLAGGED(ch, AFF_INVISIBLE) || AFF_FLAGGED(ch, AFF_HIDE))
appear(ch);
/* Cut damage in half if victim has sanct, to a minimum 1 */
if (AFF_FLAGGED(victim, AFF_SANCTUARY) && dam >= 2)
dam /= 2;
/* Check for PK if this is not a PK MUD */
if (!CONFIG_PK_ALLOWED) {
check_killer(ch, victim);
if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim))
dam = 0;
}
/* Set the maximum damage per round and subtract the hit points */
dam = MAX(MIN(dam, 100), 0);
GET_HIT(victim) -= dam;
/* Gain exp for the hit */
if (ch != victim)
gain_exp(ch, GET_LEVEL(victim) * dam);
update_pos(victim);
/* skill_message sends a message from the messages file in lib/misc.
* dam_message just sends a generic "You hit $n extremely hard.".
* skill_message is preferable to dam_message because it is more
* descriptive.
*
* If we are _not_ attacking with a weapon (i.e. a spell), always use
* skill_message. If we are attacking with a weapon: If this is a miss or a
* death blow, send a skill_message if one exists; if not, default to a
* dam_message. Otherwise, always send a dam_message. */
if (!IS_WEAPON(attacktype))
skill_message(dam, ch, victim, attacktype);
else {
if (GET_POS(victim) == POS_DEAD || dam == 0) {
if (!skill_message(dam, ch, victim, attacktype))
dam_message(dam, ch, victim, attacktype);
} else {
dam_message(dam, ch, victim, attacktype);
}
}
/* Use send_to_char -- act() doesn't send message if you are DEAD. */
switch (GET_POS(victim)) {
case POS_MORTALLYW:
act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
send_to_char(victim, "You are mortally wounded, and will die soon, if not aided.\r\n");
break;
case POS_INCAP:
act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
send_to_char(victim, "You are incapacitated and will slowly die, if not aided.\r\n");
break;
case POS_STUNNED:
act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, TO_ROOM);
send_to_char(victim, "You're stunned, but will probably regain consciousness again.\r\n");
break;
case POS_DEAD:
act("$n is dead! R.I.P.", FALSE, victim, 0, 0, TO_ROOM);
send_to_char(victim, "You are dead! Sorry...\r\n");
break;
default: /* >= POSITION SLEEPING */
if (dam > (GET_MAX_HIT(victim) / 4))
send_to_char(victim, "That really did HURT!\r\n");
if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 4)) {
send_to_char(victim, "%sYou wish that your wounds would stop BLEEDING so much!%s\r\n",
CCRED(victim, C_SPR), CCNRM(victim, C_SPR));
if (ch != victim && MOB_FLAGGED(victim, MOB_WIMPY))
do_flee(victim, NULL, 0, 0);
}
if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) &&
GET_HIT(victim) < GET_WIMP_LEV(victim) && GET_HIT(victim) > 0) {
send_to_char(victim, "You wimp out, and attempt to flee!\r\n");
do_flee(victim, NULL, 0, 0);
}
break;
}
/* Help out poor linkless people who are attacked */
if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED) {
do_flee(victim, NULL, 0, 0);
if (!FIGHTING(victim)) {
act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM);
GET_WAS_IN(victim) = IN_ROOM(victim);
char_from_room(victim);
char_to_room(victim, 0);
}
}
/* stop someone from fighting if they're stunned or worse */
if (GET_POS(victim) <= POS_STUNNED && FIGHTING(victim) != NULL)
stop_fighting(victim);
/* Uh oh. Victim died. */
if (GET_POS(victim) == POS_DEAD) {
if (ch != victim && (IS_NPC(victim) || victim->desc)) {
if (GROUP(ch))
group_gain(ch, victim);
else
solo_gain(ch, victim);
}
if (!IS_NPC(victim)) {
mudlog(BRF, LVL_IMMORT, TRUE, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch), world[IN_ROOM(victim)].name);
if (MOB_FLAGGED(ch, MOB_MEMORY))
forget(ch, victim);
}
/* Cant determine GET_GOLD on corpse, so do now and store */
if (IS_NPC(victim)) {
if ((IS_HAPPYHOUR) && (IS_HAPPYGOLD))
{
happy_gold = (long)(GET_GOLD(victim) * (((float)(HAPPY_GOLD))/(float)100));
happy_gold = MAX(0, happy_gold);
increase_gold(victim, happy_gold);
}
local_gold = GET_GOLD(victim);
}
die(victim, ch);
perform_auto_actions(ch, victim, local_gold);
return (-1);
}
return (dam);
}
* Browser code == untested, uncompiled, bugridden and generally nasty code. Take it as inspiration.