/* ************************************************************************
* 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 "utils.h"
#include "structs.h"
#include "db.h"
#include "comm.h"
#include "spells.h"
extern struct char_data *character_list;
extern struct index_data *mob_index;
extern struct room_data *world;
extern struct descriptor_data *descriptor_list;
void hit(struct char_data *ch, struct char_data *victim, int type);
char *strdup(char *source);
int check4enemies(struct char_data *ch, int type)
{
struct char_data *tmp;
if(!ch->player.title) return(0);
if(IS_SET(world[ch->in_room].room_flags,LAWFUL))
return;
for(tmp=world[ch->in_room].people; tmp; tmp = tmp->next_in_room){
if(!IS_NPC(tmp) && !strcmp(ch->player.title,GET_NAME(tmp))){
switch(type){
case 1:
act("$n screams 'Ah, it's $N!",FALSE,ch,0,tmp,TO_ROOM);
hit(ch,tmp,TYPE_UNDEFINED);
break;
case 2:
hit(ch,tmp,SKILL_BACKSTAB);
break;
}
return(1);
}
}
if((GET_LEVEL(ch) > (IMO>>1)) && !IS_SET(ch->specials.act,ACT_AGGRESSIVE)){
tmp=(struct char_data *)get_char_vis(ch,ch->player.title);
if(tmp && !IS_NPC(tmp) && (GET_LEVEL(tmp) >= MIN(250,GET_LEVEL(ch))))
if(!IS_SET(world[tmp->in_room].room_flags,LAWFUL))
teleport(ch,tmp->in_room);
}
return(0);
}
void mobile_activity(void)
{
register struct char_data *ch;
struct descriptor_data *d;
struct char_data *tmp_ch,*cho_ch,*vict, *p, *nextchar;
struct obj_data *obj, *best_obj, *worst_obj;
int t,door, found, max, min, tarlev;
int minac,minhp;
char buf[128];
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 = nextchar){
nextchar=ch->next;
if(IS_MOB(ch)){
if (IS_SET(ch->specials.act, ACT_SPEC)) {
if (!mob_index[ch->nr].func) {
sprintf(buf,"Attempting to call missing MOB func for %s.",GET_NAME(ch));
log(buf);
REMOVE_BIT(ch->specials.act, ACT_SPEC);
} else {
if((*mob_index[ch->nr].func) (ch, 0, ""))
continue;
}
}
if(IS_SET(ch->specials.act, ACT_HEALER)){
if(IS_AFFECTED(ch, AFF_POISON)){
spell_remove_poison(GET_LEVEL(ch),ch,ch,0);
spell_heal(GET_LEVEL(ch),ch,ch,0);
} else if(IS_AFFECTED(ch, AFF_BLIND)){
spell_heal(GET_LEVEL(ch),ch,ch,0);
} else if(ch->specials.fighting) {
spell_cure_critic(GET_LEVEL(ch),ch,ch,0);
} else if((GET_LEVEL(ch) >= (IMO/2))&&(GET_HIT(ch) < GET_MAX_HIT(ch))) {
spell_heal(GET_LEVEL(ch),ch,ch,0);
}
}
if(vict=ch->specials.fighting){
if(IS_SET(ch->specials.act,ACT_GUARD))
found=cityguard(ch,0,0);
if(IS_SET(ch->specials.act,ACT_CASTER))
found=magic_user(ch,0,0);
if(IS_SET(ch->specials.act,ACT_KICKER))
found=kickbasher(ch,0,0);
if(IS_SET(ch->specials.act, ACT_HUNTER)){
if(!IS_NPC(vict)){
if(!ch->player.title){
ch->player.title = strdup(GET_NAME(vict));
} else if(str_cmp(ch->player.title,GET_NAME(vict))){
free(ch->player.title);
ch->player.title = strdup(GET_NAME(vict));
}
}
}
if((vict=ch->specials.fighting) && IS_NPC(vict)){
if(IS_AFFECTED(vict,AFF_CHARM) && (vict->master)){
if(ch->in_room == vict->master->in_room){
if(number(1,3)==2){
stop_fighting(ch);
hit(ch,vict->master,TYPE_UNDEFINED);
}
} else {
stop_fighting(ch);
stop_fighting(vict);
act("$n and $N shake hands warmly.",TRUE,ch,0,vict,TO_ROOM);
}
}
}
if(IS_SET(ch->specials.act, ACT_SMART)){
if((vict=ch->specials.fighting)&&IS_NPC(vict)){
if(GET_HIT(vict) > GET_HIT(ch))
do_flee(ch);
} else {
vict=0;
minhp=0; /* minhp is actually max level now */
for(tmp_ch=world[ch->in_room].people;tmp_ch;
tmp_ch=tmp_ch->next_in_room)
if(!IS_NPC(tmp_ch))
if((tmp_ch->specials.fighting==ch)&&((t=GET_LEVEL(tmp_ch))>minhp)){
minhp=t; vict=tmp_ch;
}
if(vict && (vict != ch->specials.fighting)&&
(GET_POS(vict) > POSITION_DEAD)){
act("$n decides that $N is a juicier target.",
FALSE,ch,0,vict,TO_ROOM);
stop_fighting(ch);
hit(ch,vict,TYPE_UNDEFINED);
}
}
}
} else if(AWAKE(ch) && !(ch->specials.fighting)) {
if(IS_SET(ch->specials.act, ACT_DUMPER)){
t=number(1,200);
if(t < 5){
obj = read_object(1298,VIRTUAL);
if(obj){
obj_to_room(obj,ch->in_room);
act("$n takes a dump.",TRUE,ch,0,0,TO_ROOM);
obj->obj_flags.value[0]=t;
if(GET_LEVEL(ch) < IMO)
teleport(ch,0);
}
}
}
if(IS_SET(ch->specials.act, ACT_HUNTER)){
if(ch->player.title)
check4enemies(ch,1);
}
if(IS_SET(ch->specials.act, ACT_SCAVENGER)) {
if(world[ch->in_room].contents && !number(0,10)) {
for(max = 1, best_obj = 0, obj = world[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) {
obj_from_room(best_obj);
obj_to_char(best_obj, ch);
act("$n gets $p.",FALSE,ch,best_obj,0,TO_ROOM);
sprintf(buf,"%s",best_obj->name);
if(GET_ITEM_TYPE(best_obj) == ITEM_WEAPON)
do_wield(ch,buf,0);
else if(best_obj->obj_flags.cost > 0)
do_wear(ch,buf,0);
}
}
} /* Scavenger */
if (!IS_SET(ch->specials.act, ACT_SENTINEL) &&
(GET_POS(ch) == POSITION_STANDING) &&
((door = number(0, 47)) <= 5) && CAN_GO(ch,door) &&
!IS_SET(world[EXIT(ch, door)->to_room].room_flags, NO_MOB)) {
if (ch->specials.last_direction == door) {
ch->specials.last_direction = -1;
} else {
if (!IS_SET(ch->specials.act, ACT_STAY_ZONE)) {
ch->specials.last_direction = door;
do_move(ch, "", ++door);
} else {
if (world[EXIT(ch, door)->to_room].zone == world[ch->in_room].zone) {
ch->specials.last_direction = door;
do_move(ch, "", ++door);
}
}
}
} /* if SENTINEL */
if (IS_AFFECTED(ch,AFF_CHARM) && (ch->master)){
if(ch->master->specials.fighting && !ch->specials.fighting){
if(ch->in_room == ch->master->in_room){
act("$n comes to the aid of $N.",1,ch,0,ch->master,TO_ROOM);
hit(ch,ch->master->specials.fighting,0);
}
}
} else if (IS_SET(ch->specials.act,ACT_AGGRESSIVE)) {
found = FALSE;
for(tmp_ch = world[ch->in_room].people; tmp_ch;
tmp_ch = tmp_ch->next_in_room) {
if(IS_AFFECTED(tmp_ch,AFF_PROTECT_EVIL) &&
(GET_ALIGNMENT(ch) < -350) && number(0,16))
continue;
if(!IS_NPC(tmp_ch) && CAN_SEE(ch, tmp_ch) && (GET_LEVEL(tmp_ch)<IMO)) {
if (!IS_SET(ch->specials.act, ACT_WIMPY) || !AWAKE(tmp_ch)) {
if(!found){
cho_ch=tmp_ch;
found = TRUE;
} else {
if(number(1,7) <= 3)
cho_ch=tmp_ch;
} /* else */
} /* if IS_SET */
} /* if IS_NPC */
} /* for */
if(found)
hit(ch, cho_ch, 0);
} else if (IS_SET(ch->specials.act,ACT_SEMIAGGR)) {
found = FALSE;
tarlev = GET_LEVEL(ch);
for(tmp_ch=world[ch->in_room].people;tmp_ch;tmp_ch=tmp_ch->next_in_room){
if(GET_LEVEL(tmp_ch) >= tarlev){
if(!IS_NPC(tmp_ch) && CAN_SEE(ch, tmp_ch) && (GET_LEVEL(tmp_ch)<IMO)) {
if(!found){
cho_ch=tmp_ch;
found = TRUE;
} else {
if(number(1,7) <= 4)
cho_ch=tmp_ch;
}
}
}
}
if(found)
hit(ch, cho_ch, 0);
} else if (IS_SET(ch->specials.act,ACT_HELPER)) {
for(tmp_ch=world[ch->in_room].people;tmp_ch;tmp_ch=tmp_ch->next_in_room){
if(vict=tmp_ch->specials.fighting){
if(IS_NPC(tmp_ch) && (GET_LEVEL(vict) >= MIN(250,GET_LEVEL(ch))) &&
CAN_SEE(ch,tmp_ch) && CAN_SEE(ch,vict) && (!IS_NPC(vict))){
if((number(1,7)==3)&&
(!IS_SET(world[ch->in_room].room_flags,LAWFUL))){
act("$n decides to assist $N.",1,ch,0,tmp_ch,TO_ROOM);
hit(ch,vict,0);
break;
}
}
}
} /* for */
} /* is HELPER */
} /* If AWAKE(ch) */
} /* If IS_MOB(ch) */
}
}