1 | /* |
1 | /* |
2 | * static char *rcsid_monster_c = |
2 | * static char *rcsid_monster_c = |
3 | * "$Id: monster.C,v 1.4 2006/08/29 08:01:37 root Exp $"; |
3 | * "$Id: monster.C,v 1.7 2006/09/07 10:01:58 pippijn Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
268 | else if(!QUERY_FLAG(op,FLAG_SLEEP)) return 1; |
268 | else if(!QUERY_FLAG(op,FLAG_SLEEP)) return 1; |
269 | |
269 | |
270 | /* enemy should already be on this map, so don't really need to check |
270 | /* enemy should already be on this map, so don't really need to check |
271 | * for that. |
271 | * for that. |
272 | */ |
272 | */ |
273 | if (rv->distance < (QUERY_FLAG(enemy, FLAG_STEALTH)?(radius/2)+1:radius)) { |
273 | if (rv->distance < (unsigned int) (QUERY_FLAG(enemy, FLAG_STEALTH) ? (radius / 2) + 1 : radius)) { |
274 | CLEAR_FLAG(op,FLAG_SLEEP); |
274 | CLEAR_FLAG(op,FLAG_SLEEP); |
275 | return 1; |
275 | return 1; |
276 | } |
276 | } |
277 | return 0; |
277 | return 0; |
278 | } |
278 | } |
… | |
… | |
363 | */ |
363 | */ |
364 | if(QUERY_FLAG(op, FLAG_SCARED) &&!(RANDOM()%20)) { |
364 | if(QUERY_FLAG(op, FLAG_SCARED) &&!(RANDOM()%20)) { |
365 | CLEAR_FLAG(op,FLAG_SCARED); /* Time to regain some "guts"... */ |
365 | CLEAR_FLAG(op,FLAG_SCARED); /* Time to regain some "guts"... */ |
366 | } |
366 | } |
367 | |
367 | |
368 | if (INVOKE_OBJECT (MOVE, op, ARG_OBJECT (op->enemy)))//TODO: should go away |
368 | if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) |
369 | return 0; |
369 | return QUERY_FLAG (op, FLAG_FREED); |
370 | |
370 | |
371 | if ( QUERY_FLAG(op, FLAG_SLEEP) || QUERY_FLAG(op, FLAG_BLIND) || |
371 | if ( QUERY_FLAG(op, FLAG_SLEEP) || QUERY_FLAG(op, FLAG_BLIND) || |
372 | ((op->map->darkness>0) && !QUERY_FLAG(op,FLAG_SEE_IN_DARK) && |
372 | ((op->map->darkness>0) && !QUERY_FLAG(op,FLAG_SEE_IN_DARK) && |
373 | !QUERY_FLAG(op,FLAG_SEE_INVISIBLE))) { |
373 | !QUERY_FLAG(op,FLAG_SEE_INVISIBLE))) { |
374 | if(!check_wakeup(op,enemy,&rv)) |
374 | if(!check_wakeup(op,enemy,&rv)) |
… | |
… | |
453 | * arch set uses it. |
453 | * arch set uses it. |
454 | */ |
454 | */ |
455 | if ( (op->race != NULL)&& strcmp(op->race,"doppleganger") == 0) |
455 | if ( (op->race != NULL)&& strcmp(op->race,"doppleganger") == 0) |
456 | { |
456 | { |
457 | op->face = enemy->face; |
457 | op->face = enemy->face; |
458 | if (op->name) |
|
|
459 | free_string(op->name); |
|
|
460 | add_refcount(op->name = enemy->name); |
458 | op->name = enemy->name; |
461 | } |
459 | } |
462 | |
460 | |
463 | /* Calculate range information for closest body part - this |
461 | /* Calculate range information for closest body part - this |
464 | * is used for the 'skill' code, which isn't that smart when |
462 | * is used for the 'skill' code, which isn't that smart when |
465 | * it comes to figuring it out - otherwise, giants throw boulders |
463 | * it comes to figuring it out - otherwise, giants throw boulders |
… | |
… | |
648 | free_object(op); |
646 | free_object(op); |
649 | return 1; |
647 | return 1; |
650 | } |
648 | } |
651 | return 0; |
649 | return 0; |
652 | } |
650 | } |
|
|
651 | |
653 | int can_hit(object *ob1,object *ob2, rv_vector *rv) { |
652 | int can_hit(object *ob1,object *ob2, rv_vector *rv) { |
654 | object *more; |
653 | object *more; |
655 | rv_vector rv1; |
654 | rv_vector rv1; |
656 | |
655 | |
657 | if(QUERY_FLAG(ob1,FLAG_CONFUSED)&&!(RANDOM()%3)) |
656 | if(QUERY_FLAG(ob1,FLAG_CONFUSED)&&!(RANDOM()%3)) |
… | |
… | |
768 | * I'm not sure if it really make sense to pre-select spells (events |
767 | * I'm not sure if it really make sense to pre-select spells (events |
769 | * could be different by the time the monster goes again). |
768 | * could be different by the time the monster goes again). |
770 | */ |
769 | */ |
771 | if(head->spellitem==NULL) { |
770 | if(head->spellitem==NULL) { |
772 | if((spell_item=monster_choose_random_spell(head))==NULL) { |
771 | if((spell_item=monster_choose_random_spell(head))==NULL) { |
773 | LOG(llevMonster,"Turned off spells in %s\n",head->name); |
772 | LOG(llevMonster,"Turned off spells in %s\n",&head->name); |
774 | CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */ |
773 | CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */ |
775 | return 0; |
774 | return 0; |
776 | } |
775 | } |
777 | if (spell_item->type == SPELLBOOK) { |
776 | if (spell_item->type == SPELLBOOK) { |
778 | if (!spell_item->inv) { |
777 | if (!spell_item->inv) { |
779 | LOG(llevError,"spellbook %s does not contain a spell?\n", spell_item->name); |
778 | LOG(llevError,"spellbook %s does not contain a spell?\n", &spell_item->name); |
780 | return 0; |
779 | return 0; |
781 | } |
780 | } |
782 | spell_item=spell_item->inv; |
781 | spell_item=spell_item->inv; |
783 | } |
782 | } |
784 | } |
783 | } |
… | |
… | |
887 | break; |
886 | break; |
888 | } |
887 | } |
889 | |
888 | |
890 | if(!skill && !head->chosen_skill) { |
889 | if(!skill && !head->chosen_skill) { |
891 | LOG(llevDebug,"Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", |
890 | LOG(llevDebug,"Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", |
892 | head->name,head->count); |
891 | &head->name,head->count); |
893 | CLEAR_FLAG(head, FLAG_READY_SKILL); |
892 | CLEAR_FLAG(head, FLAG_READY_SKILL); |
894 | return 0; |
893 | return 0; |
895 | } |
894 | } |
896 | /* use skill */ |
895 | /* use skill */ |
897 | return do_skill(head, part, head->chosen_skill,dir,NULL); |
896 | return do_skill(head, part, head->chosen_skill,dir,NULL); |
… | |
… | |
959 | |
958 | |
960 | if ( at_least_one ) |
959 | if ( at_least_one ) |
961 | return 0; |
960 | return 0; |
962 | |
961 | |
963 | LOG(llevError,"Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", |
962 | LOG(llevError,"Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", |
964 | head->name,head->count); |
963 | &head->name,head->count); |
965 | CLEAR_FLAG(head, FLAG_READY_RANGE); |
964 | CLEAR_FLAG(head, FLAG_READY_RANGE); |
966 | return 0; |
965 | return 0; |
967 | } |
966 | } |
968 | |
967 | |
969 | int monster_use_bow(object *head, object *part, object *pl, int dir) { |
968 | int monster_use_bow(object *head, object *part, object *pl, int dir) { |
… | |
… | |
1641 | if(enemy->hide && (rv->distance <= 1) && (RANDOM()%100<=hide_discovery)) { |
1640 | if(enemy->hide && (rv->distance <= 1) && (RANDOM()%100<=hide_discovery)) { |
1642 | make_visible(enemy); |
1641 | make_visible(enemy); |
1643 | /* inform players of new status */ |
1642 | /* inform players of new status */ |
1644 | if(enemy->type==PLAYER && player_can_view(enemy,op)) |
1643 | if(enemy->type==PLAYER && player_can_view(enemy,op)) |
1645 | new_draw_info_format(NDI_UNIQUE,0, enemy, |
1644 | new_draw_info_format(NDI_UNIQUE,0, enemy, |
1646 | "You are discovered by %s!",op->name); |
1645 | "You are discovered by %s!",&op->name); |
1647 | return 1; /* detected enemy */ |
1646 | return 1; /* detected enemy */ |
1648 | } |
1647 | } |
1649 | else if (enemy->invisible) { |
1648 | else if (enemy->invisible) { |
1650 | /* Change this around - instead of negating the invisible, just |
1649 | /* Change this around - instead of negating the invisible, just |
1651 | * return true so that the mosnter that managed to detect you can |
1650 | * return true so that the mosnter that managed to detect you can |