/* ************************************************************************ * 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) */ } }