/* * file: mobact.c , mobile action module. part of dikumud * usage: procedures generating 'intelligent' behavior in the mobiles. * copyright (c) 1990, 1991 - see 'license.doc' for complete information. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "global.h" #include "bug.h" #include "utils.h" #include "act_obj.h" #include "act_off.h" #include "comm.h" #include "constants.h" #include "db.h" #include "handler.h" #include "hash.h" #include "mudlimits.h" #include "multiclass.h" #include "opinion.h" #include "spells.h" #include "spell_parser.h" #include "fight.h" #include "trap.h" #include "act_skills.h" #include "spec_procs.h" #include "tracking.h" #define _MOB_ACTIONS_C #include "mob_actions.h" void mobile_guardian(struct char_data *ch) { if (DEBUG > 2) log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch)); if (ch->in_room > -1) { if ((!ch->master) || (!IS_AFFECTED(ch, AFF_CHARM))) return; if (ch->master->specials.fighting) { if (!SameRace(ch->master->specials.fighting, ch)) { if (IsHumanoid(ch)) { act("$n screams 'I must protect my master!'", FALSE, ch, 0, 0, TO_ROOM); } else { act("$n growls angrily!", FALSE, ch, 0, 0, TO_ROOM); } if (CAN_SEE(ch, ch->master->specials.fighting)) hit(ch, ch->master->specials.fighting, 0); } } } } void mobile_wander(struct char_data *ch) { int door = 0; struct room_direction_data *exitp = NULL; struct room_data *rp = NULL; if (DEBUG > 2) log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch)); if ((!(IS_AFFECTED(ch, AFF_CHARM))) && (ch->master)) stop_follower(ch); if (RIDDEN(ch)) { if (RIDDEN(ch)->specials.fighting) return; if (IS_AFFECTED(ch, AFF_CHARM)) return; } if (!((GET_POS(ch) == POSITION_STANDING) && ((door = number(0, (MAX_NUM_EXITS - 1) * 3)) < MAX_NUM_EXITS) && exit_ok(exitp = EXIT(ch, door), &rp) && !IS_SET(rp->room_flags, NO_MOB) && !IS_SET(rp->room_flags, DEATH)) ) return; if (IsHumanoid(ch) ? CAN_GO_HUMAN(ch, door) : CAN_GO(ch, door)) { if (ch->specials.last_direction == door) { ch->specials.last_direction = -1; } else { if (!IS_SET(ch->specials.act, ACT_STAY_ZONE) || (rp->zone == real_roomp(ch->in_room)->zone)) { ch->specials.last_direction = door; go_direction(ch, door); } } } } void MobScavenge(struct char_data *ch) { struct obj_data *best_obj = NULL; struct obj_data *obj = NULL; int max = 0; if (DEBUG > 2) log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch)); if ((real_roomp(ch->in_room))->contents && !number(0, 5)) { for (max = 1, best_obj = 0, obj = (real_roomp(ch->in_room))->contents; obj; obj = obj->next_content) { if (CAN_GET_OBJ(ch, obj)) { if (obj->obj_flags.cost > max) { best_obj = obj; max = obj->obj_flags.cost; } } } /* for */ if (best_obj) { if (CheckForAnyTrap(ch, best_obj)) return; obj_from_room(best_obj); obj_to_char(best_obj, ch); act("$n gets $p.", FALSE, ch, best_obj, 0, TO_ROOM); if (IS_SET(ch->specials.act, ACT_USE_ITEM)) { switch (GET_ITEM_TYPE(best_obj)) { case ITEM_WEAPON: { if (!ch->equipment[WIELD] && !ch->equipment[WIELD_TWOH]) { do_wield(ch, best_obj->name, 0); } } break; case ITEM_ARMOR: { do_wear(ch, best_obj->name, 0); } break; } } } } } void mobile_activity(void) { struct char_data *ch = NULL; struct char_data *tmp_ch = NULL; int k = 0; if (DEBUG > 2) log_info("called %s with no arguments", __PRETTY_FUNCTION__); for (ch = character_list; ch; ch = ch->next) if (IS_MOB(ch)) { /* * Examine call for special procedure * some status checking for errors */ if ((ch->in_room < 0) || !hash_find(&room_db, ch->in_room)) { log_info("Char not in correct room. moving to 3 "); char_from_room(ch); char_to_room(ch, 3); } if (IS_SET(ch->specials.act, ACT_SPEC) && !no_specials) { if (!mob_index[ch->nr].func) { log_error("Mob %s attempting to call a non-existing MOB func.", ch->player.name); REMOVE_BIT(ch->specials.act, ACT_SPEC); } else { if ((*mob_index[ch->nr].func) (ch, 0, "")) continue; } } /* * check to see if the monster is possessed */ if (AWAKE(ch) && (!ch->specials.fighting) && (!ch->desc) && (!IS_SET(ch->specials.act, ACT_POLYSELF))) { AssistFriend(ch); if (IS_SET(ch->specials.act, ACT_SCAVENGER)) { MobScavenge(ch); } /* Scavenger */ if (IS_SET(ch->specials.act, ACT_HUNTING)) { MobHunt(ch); } else if ((!IS_SET(ch->specials.act, ACT_SENTINEL))) mobile_wander(ch); if (GET_HIT(ch) > (GET_MAX_HIT(ch) / 3)) { if (IS_SET(ch->specials.act, ACT_HATEFUL)) { tmp_ch = FindAHatee(ch); if (tmp_ch) { if (check_peaceful(ch, "You ask your enemy to step outside.\r\n")) { if (IsHumanoid(ch)) act("$n growls '$N, would you care to step outside?'", TRUE, ch, 0, tmp_ch, TO_ROOM); else if (IsAnimal(ch)) act("$n snarls at $N...", TRUE, ch, 0, tmp_ch, TO_ROOM); } else { if (IsHumanoid(ch)) { act("$n screams 'I'm gonna kill you!'", TRUE, ch, 0, 0, TO_ROOM); } else if (IsAnimal(ch)) { act("$n growls", TRUE, ch, 0, 0, TO_ROOM); } hit(ch, tmp_ch, 0); } } } if (!ch->specials.fighting) { if (IS_SET(ch->specials.act, ACT_AFRAID)) { if ((tmp_ch = FindAFearee(ch)) != NULL) { do_flee(ch, "", 0); } } } } else { if (IS_SET(ch->specials.act, ACT_AFRAID)) { if ((tmp_ch = FindAFearee(ch)) != NULL) { do_flee(ch, "", 0); } else { if (IS_SET(ch->specials.act, ACT_HATEFUL)) { tmp_ch = FindAHatee(ch); if (tmp_ch) { if (check_peaceful (ch, "You ask your enemy to step outside.\r\n")) { act("$n growls '$N, would you care to step outside?'", TRUE, ch, 0, tmp_ch, TO_ROOM); } else { if (IsHumanoid(ch)) { act("$n screams 'I'm gonna get you!'", TRUE, ch, 0, 0, TO_ROOM); } else if (IsAnimal(ch)) { act("$n growls", TRUE, ch, 0, 0, TO_ROOM); } hit(ch, tmp_ch, 0); } } } } } } if (IS_SET(ch->specials.act, ACT_AGGRESSIVE)) { for (k = 0; k <= 5; k++) { tmp_ch = FindVictim(ch); if (tmp_ch) { if (check_peaceful (ch, "You can't seem to exercise your violent tendencies.\r\n")) { act("$n growls impotently", TRUE, ch, 0, 0, TO_ROOM); return; } hit(ch, tmp_ch, 0); k = 10; } } } if (IS_SET(ch->specials.act, ACT_GUARDIAN)) mobile_guardian(ch); } /* If AWAKE(ch) */ } /* If IS_MOB(ch) */ } int SameRace(struct char_data *ch1, struct char_data *ch2) { if (DEBUG > 3) log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch1), SAFE_NAME(ch2)); if ((!ch1) || (!ch2)) return (FALSE); if (ch1 == ch2) return (TRUE); if (IS_NPC(ch1) && (IS_NPC(ch2))) { if (mob_index[ch1->nr].virtual == mob_index[ch2->nr].virtual) return (TRUE); else return (FALSE); } if (in_group(ch1, ch2)) return (TRUE); if (GET_RACE(ch1) == GET_RACE(ch2)) { return (TRUE); } return (FALSE); } void AssistFriend(struct char_data *ch) { struct char_data *damsel = NULL; struct char_data *targ = NULL; struct char_data *tmp_ch = NULL; int t = 0; int found = FALSE; if (DEBUG > 3) log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(ch)); if (check_peaceful(ch, "")) return; /* * find the people who are fighting */ for (tmp_ch = (real_roomp(ch->in_room))->people; tmp_ch; tmp_ch = tmp_ch->next_in_room) { if (CAN_SEE(ch, tmp_ch)) { if (!IS_SET(ch->specials.act, ACT_WIMPY)) { if (IS_NPC(tmp_ch) && (SameRace(tmp_ch, ch))) { if (tmp_ch->specials.fighting) damsel = tmp_ch; } } } } if (damsel) { /* * check if the people in the room are fighting. */ found = FALSE; for (t = 1; t <= 8 && !found; t++) { targ = FindAnyVictim(damsel); if (targ) { if (targ->specials.fighting) if (SameRace(targ->specials.fighting, ch)) found = TRUE; } } if (targ) if (targ->in_room == ch->in_room) { if (!IS_AFFECTED(ch, AFF_CHARM) || ch->master != targ) { hit(ch, targ, 0); } } } }