/* * 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 <sys/types.h> #include "include/global.h" #include "include/bug.h" #include "include/utils.h" #include "include/handler.h" #include "include/db.h" #include "include/comm.h" #include "include/constants.h" #include "include/opinion.h" #include "include/trap.h" #include "include/fight.h" #include "include/spec_procs.h" #include "include/spell_parser.h" #include "include/multiclass.h" #include "include/hash.h" #include "include/act_off.h" #include "include/act_obj.h" #include "include/limits.h" #include "include/act_skills.h" #define _MOB_ACTIONS_C #include "include/mob_actions.h" void mobile_guardian(struct char_data *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; struct room_direction_data *exitp; struct room_data *rp; 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 MobHunt(struct char_data *ch) { int res, k; if (ch->persist <= 0) { res = choose_exit(ch->in_room, ch->old_room, 2000); if (res > -1) { go_direction(ch, res); } else { if (ch->specials.hunting) { if (ch->specials.hunting->in_room == ch->in_room) { if (CanHate(ch, ch->specials.hunting) && (!IS_AFFECTED(ch->specials.hunting, AFF_HIDE))) { if (check_peaceful(ch, "You CAN'T fight here!\n\r")) { act("$n fumes at $N", TRUE, ch, 0, ch->specials.hunting, TO_ROOM); } else { if (IsHumanoid(ch)) { act("$n screams 'Time to die, $N'", TRUE, ch, 0, ch->specials.hunting, TO_ROOM); } else if (IsAnimal(ch)) { act("$n growls.", TRUE, ch, 0, 0, TO_ROOM); } hit(ch, ch->specials.hunting, 0); return; } } } } REMOVE_BIT(ch->specials.act, ACT_HUNTING); ch->specials.hunting = 0; ch->hunt_dist = 0; } } else if (ch->specials.hunting) { if (ch->hunt_dist <= 50) ch->hunt_dist = 50; for (k = 1; k <= 2 && ch->specials.hunting; k++) { ch->persist -= 1; res = dir_track(ch, ch->specials.hunting); if (res != -1) { go_direction(ch, res); } else { ch->persist = 0; ch->specials.hunting = 0; ch->hunt_dist = 0; } } } else { ch->persist = 0; } } void MobScavenge(struct char_data *ch) { struct obj_data *best_obj, *obj; int max; 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) { register struct char_data *ch, *tmp_ch; int k; void do_move(struct char_data *ch, char *argument, int cmd); void do_get(struct char_data *ch, char *argument, int cmd); 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("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("Attempting to call a non-existing MOB func. (mobact.c)"); log(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.\n\r")) { 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.\n\r")) { 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.\n\r")) { 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 ((!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, *targ, *tmp_ch; int t, found; damsel = 0; targ = 0; 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); } } } }