ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
(Generate patch)

Comparing deliantra/server/server/monster.C (file contents):
Revision 1.49 by root, Fri Dec 26 12:59:39 2008 UTC vs.
Revision 1.56 by root, Sat Dec 27 08:41:44 2008 UTC

35 * set to sane values. 35 * set to sane values.
36 */ 36 */
37object * 37object *
38check_enemy (object *npc, rv_vector * rv) 38check_enemy (object *npc, rv_vector * rv)
39{ 39{
40
41 /* if this is pet, let him attack the same enemy as his owner 40 /* if this is pet, let him attack the same enemy as his owner
42 * TODO: when there is no ower enemy, try to find a target, 41 * TODO: when there is no ower enemy, try to find a target,
43 * which CAN attack the owner. */ 42 * which CAN attack the owner. */
44 if ((npc->attack_movement & HI4) == PETMOVE) 43 if ((npc->attack_movement & HI4) == PETMOVE)
45 { 44 {
231 * Currently, this is only called from move_monster, and 230 * Currently, this is only called from move_monster, and
232 * if enemy is set, then so should be rv. 231 * if enemy is set, then so should be rv.
233 * returns 1 if the monster should wake up, 0 otherwise. 232 * returns 1 if the monster should wake up, 0 otherwise.
234 */ 233 */
235int 234int
236check_wakeup (object *op, object *enemy, rv_vector * rv) 235check_wakeup (object *op, object *enemy, rv_vector *rv)
237{ 236{
238 int radius = op->stats.Wis > MIN_MON_RADIUS ? op->stats.Wis : MIN_MON_RADIUS;
239
240 /* Trim work - if no enemy, no need to do anything below */ 237 /* Trim work - if no enemy, no need to do anything below */
241 if (!enemy) 238 if (!enemy)
242 return 0; 239 return 0;
243 240
241 int radius = max (op->stats.Wis, MIN_MON_RADIUS);
242
243 if (op->flag [FLAG_BLIND])
244 /* blinded monsters can only find nearby objects to attack */ 244 /* blinded monsters can only find nearby objects to attack */
245 if (QUERY_FLAG (op, FLAG_BLIND))
246 radius = MIN_MON_RADIUS; 245 radius = MIN_MON_RADIUS;
247 246 else if (op->map
247 && !enemy->invisible
248 && !stand_in_light (enemy)
249 && (!op->flag[FLAG_SEE_IN_DARK] || !op->flag [FLAG_SEE_INVISIBLE]))
248 /* This covers the situation where the monster is in the dark 250 /* This covers the situation where the monster is in the dark
249 * and has an enemy. If the enemy has no carried light (or isnt 251 * and has an enemy. If the enemy has no carried light (or isnt
250 * glowing!) then the monster has trouble finding the enemy. 252 * glowing!) then the monster has trouble finding the enemy.
251 * Remember we already checked to see if the monster can see in 253 * Remember we already checked to see if the monster can see in
252 * the dark. */ 254 * the dark. */
253 255 radius = min (radius, MIN_MON_RADIUS + MAX_DARKNESS - op->map->darklevel ());
254 else if (op->map && op->map->darkness > 0 && enemy && !enemy->invisible && 256 else if (!op->flag [FLAG_SLEEP])
255 !stand_in_light (enemy) && (!QUERY_FLAG (op, FLAG_SEE_IN_DARK) || !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
256 {
257 int dark = radius / (op->map->darkness);
258
259 radius = (dark > MIN_MON_RADIUS) ? (dark + 1) : MIN_MON_RADIUS;
260 }
261 else if (!QUERY_FLAG (op, FLAG_SLEEP))
262 return 1; 257 return 1;
258
259 if (enemy->flag [FLAG_STEALTH])
260 radius = radius / 2 + 1;
263 261
264 /* enemy should already be on this map, so don't really need to check 262 /* enemy should already be on this map, so don't really need to check
265 * for that. 263 * for that.
266 */ 264 */
267 if (rv->distance < (unsigned int) (QUERY_FLAG (enemy, FLAG_STEALTH) ? (radius / 2) + 1 : radius)) 265 if (rv->distance <= radius)
268 { 266 {
269 CLEAR_FLAG (op, FLAG_SLEEP); 267 CLEAR_FLAG (op, FLAG_SLEEP);
270 return 1; 268 return 1;
271 } 269 }
270
272 return 0; 271 return 0;
273} 272}
274 273
275int 274int
276move_randomly (object *op) 275move_randomly (object *op)
324 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed)); 323 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed));
325 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */ 324 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
326 op->last_heal %= 32; 325 op->last_heal %= 32;
327 326
328 /* So if the monster has gained enough HP that they are no longer afraid */ 327 /* So if the monster has gained enough HP that they are no longer afraid */
329 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp)) 328 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short)(((float)op->run_away / 100.f) * (float)op->stats.maxhp))
330 CLEAR_FLAG (op, FLAG_RUN_AWAY); 329 CLEAR_FLAG (op, FLAG_RUN_AWAY);
331 330
332 if (op->stats.hp > op->stats.maxhp) 331 if (op->stats.hp > op->stats.maxhp)
333 op->stats.hp = op->stats.maxhp; 332 op->stats.hp = op->stats.maxhp;
334 } 333 }
335 334
336 /* generate sp, if applicable */ 335 /* generate sp, if applicable */
337 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) 336 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
338 { 337 {
339 /* last_sp is in funny units. Dividing by speed puts 338 /* last_sp is in funny units. Dividing by speed puts
340 * the regeneration rate on a basis of time instead of 339 * the regeneration rate on a basis of time instead of
341 * #moves the monster makes. The scaling by 8 is 340 * #moves the monster makes. The scaling by 8 is
342 * to capture 8th's of a sp fraction regens 341 * to capture 8th's of a sp fraction regens
343 * 342 *
344 * Cast to sint32 before comparing to maxhp since otherwise an (sint16) 343 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
345 * overflow might produce monsters with negative sp. 344 * overflow might produce monsters with negative sp.
346 */ 345 */
347 346
348 op->last_sp += (int) ((float) (8 * op->stats.Pow) / FABS (op->speed)); 347 op->last_sp += (int) ((float) (8 * op->stats.Pow) / fabsf (op->speed));
349 op->stats.sp = MIN (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */ 348 op->stats.sp = min (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
350 op->last_sp %= 128; 349 op->last_sp %= 128;
351 } 350 }
352 351
353 /* this should probably get modified by many more values. 352 /* this should probably get modified by many more values.
354 * (eg, creatures resistance to fear, level, etc. ) 353 * (eg, creatures resistance to fear, level, etc. )
358 357
359 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) 358 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
360 return QUERY_FLAG (op, FLAG_FREED); 359 return QUERY_FLAG (op, FLAG_FREED);
361 360
362 if (QUERY_FLAG (op, FLAG_SLEEP) || QUERY_FLAG (op, FLAG_BLIND) || 361 if (QUERY_FLAG (op, FLAG_SLEEP) || QUERY_FLAG (op, FLAG_BLIND) ||
363 ((op->map->darkness > 0) && !QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !QUERY_FLAG (op, FLAG_SEE_INVISIBLE))) 362 ((op->map->darklevel () > 0) && !QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
364 if (!check_wakeup (op, enemy, &rv)) 363 if (!check_wakeup (op, enemy, &rv))
365 return 0; 364 return 0;
366 365
367 /* check if monster pops out of hidden spot */ 366 /* check if monster pops out of hidden spot */
368 if (op->flag [FLAG_HIDDEN]) 367 if (op->flag [FLAG_HIDDEN])
444 && !on_same_map (op, owner) 443 && !on_same_map (op, owner)
445 && !owner->flag [FLAG_REMOVED]) 444 && !owner->flag [FLAG_REMOVED])
446 return follow_owner (op, owner); 445 return follow_owner (op, owner);
447 446
448 /* doppleganger code to change monster facing to that of the nearest 447 /* doppleganger code to change monster facing to that of the nearest
449 * player. Hmm. The code is here, but no monster in the current 448 * player. Hmm. The code is here, but no monster in the current
450 * arch set uses it. 449 * arch set uses it.
451 */ 450 */
452 if ((op->race != NULL) && strcmp (op->race, "doppleganger") == 0) 451 if (op->race && strcmp (op->race, "doppleganger") == 0)
453 { 452 {
454 op->face = enemy->face; 453 op->face = enemy->face;
455 op->name = enemy->name; 454 op->name = enemy->name;
456 } 455 }
457 456
505 if (monster_use_bow (op, part, enemy, dir)) 504 if (monster_use_bow (op, part, enemy, dir))
506 return 0; 505 return 0;
507 } /* for processing of all parts */ 506 } /* for processing of all parts */
508 } /* If not scared */ 507 } /* If not scared */
509 508
510
511 part = rv.part; 509 part = rv.part;
512 dir = rv.direction; 510 dir = rv.direction;
511
512#if DEVEL
513 // if the enemy is a player, we have los. if los says we
514 // can directly reach the player, we do not deviate.
515 // for non-players, we never deviate
516 if (enemy->contr && enemy->contr->darkness_at (op->map, op->x, op->y) == LOS_BLOCKED)
517 {
518 int sdir = 0;
519
520 for (int dir = 1; dir <= 8; ++dir)
521 {
522 mapxy pos (op); pos.move (dir);
523 if (pos.normalise ())
524 {
525 mapspace &ms = pos.ms ();
526
527 if (ms.smell > op->ms ().smell)
528 {
529 printf ("%s: found smell, following it, apparently (%d, %d)\n",& op->name,op->ms().smell,ms.smell);//D
530 op->ms ().smell = ms.smell - 1;
531 sdir = dir;
532
533 // perturbing the path might let the monster lose track,
534 // but it will also wide the actual path, spreading information
535 if (!rndm (20))
536 sdir += absdir (1 - rndm (2) * 2);
537 }
538 }
539 }
540
541 if (sdir)
542 dir = sdir;
543 else
544 // no better smell found, so assume the player jumped, and erase this smell
545 {if (op->ms ().smell) printf ("erasing smell %d\n", op->ms ().smell);//D
546 ordered_mapwalk_begin (op, -1, -1, 1, 1)
547 if (m)
548 m->at (nx, ny).smell = 0;
549 ordered_mapwalk_end
550 }//D
551 }
552
553#endif
513 554
514 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY)) 555 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
515 dir = absdir (dir + 4); 556 dir = absdir (dir + 4);
516 557
517 if (QUERY_FLAG (op, FLAG_CONFUSED)) 558 if (QUERY_FLAG (op, FLAG_CONFUSED))
571 } 612 }
572 613
573 if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY)) 614 if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY))
574 { 615 {
575 /* Try move around corners if !close */ 616 /* Try move around corners if !close */
576 int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || RANDOM () & 1) ? 1 : 2; 617 int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || rndm (2)) ? 1 : 2;
577 618
578 for (diff = 1; diff <= maxdiff; diff++) 619 for (diff = 1; diff <= maxdiff; diff++)
579 { 620 {
580 /* try different detours */ 621 /* try different detours */
581 int m = 1 - (RANDOM () & 2); /* Try left or right first? */ 622 int m = 1 - rndm (2) * 2; /* Try left or right first? */
582 623
583 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m))) 624 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m)))
584 return 0; 625 return 0;
585 } 626 }
586 } 627 }
613 { 654 {
614 object *nearest_player = get_nearest_player (op); 655 object *nearest_player = get_nearest_player (op);
615 656
616 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv)) 657 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv))
617 { 658 {
618 op->enemy = NULL; 659 op->enemy = 0;
619 enemy = nearest_player; 660 enemy = nearest_player;
620 } 661 }
621 } 662 }
622 663
623 if (!QUERY_FLAG (op, FLAG_SCARED) && can_hit (part, enemy, &rv)) 664 if (!QUERY_FLAG (op, FLAG_SCARED) && can_hit (part, enemy, &rv))
1689 radius = max (MIN_MON_RADIUS, op->stats.Wis / 5 + 1); 1730 radius = max (MIN_MON_RADIUS, op->stats.Wis / 5 + 1);
1690 else 1731 else
1691 { /* a level/INT/Dex adjustment for hiding */ 1732 { /* a level/INT/Dex adjustment for hiding */
1692 int bonus = op->level / 2 + op->stats.Int / 5; 1733 int bonus = op->level / 2 + op->stats.Int / 5;
1693 1734
1694 if (enemy->type == PLAYER) 1735 if (enemy->is_player ())
1695 { 1736 {
1696 if (object *sk_hide = find_skill_by_number (enemy, SK_HIDING)) 1737 if (object *sk_hide = find_skill_by_number (enemy, SK_HIDING))
1697 bonus -= sk_hide->level; 1738 bonus -= sk_hide->level;
1698 else 1739 else
1699 { 1740 {
1716 radius /= 2; 1757 radius /= 2;
1717 hide_discovery /= 3; 1758 hide_discovery /= 3;
1718 } 1759 }
1719 1760
1720 /* Radii adjustment for enemy standing in the dark */ 1761 /* Radii adjustment for enemy standing in the dark */
1721 if (op->map->darkness > 0 && !stand_in_light (enemy)) 1762 if (op->map->darklevel () > 0 && !stand_in_light (enemy))
1722 { 1763 {
1723 /* on dark maps body heat can help indicate location with infravision 1764 /* on dark maps body heat can help indicate location with infravision
1724 * undead don't have body heat, so no benefit detecting them. 1765 * undead don't have body heat, so no benefit detecting them.
1725 */ 1766 */
1726 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !is_true_undead (enemy)) 1767 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !is_true_undead (enemy))
1727 radius += op->map->darkness / 2; 1768 radius += op->map->darklevel () / 2;
1728 else 1769 else
1729 radius -= op->map->darkness / 2; 1770 radius -= op->map->darklevel () / 2;
1730 1771
1731 /* op next to a monster (and not in complete darkness) 1772 /* op next to a monster (and not in complete darkness)
1732 * the monster should have a chance to see you. 1773 * the monster should have a chance to see you.
1733 */ 1774 */
1734 if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1) 1775 if (radius < MIN_MON_RADIUS && op->map->darklevel () < 5 && rv->distance <= 1)
1735 radius = MIN_MON_RADIUS; 1776 radius = MIN_MON_RADIUS;
1736 } /* if on dark map */ 1777 } /* if on dark map */
1737 1778
1738 /* Lets not worry about monsters that have incredible detection 1779 /* Lets not worry about monsters that have incredible detection
1739 * radii, we only need to worry here about things the player can 1780 * radii, we only need to worry here about things the player can
1856 return 1; 1897 return 1;
1857 } 1898 }
1858 else if (enemy->flag [FLAG_HIDDEN]) 1899 else if (enemy->flag [FLAG_HIDDEN])
1859 return 0; 1900 return 0;
1860 1901
1861 /* Invisible enemy. Break apart the check for invis undead/invis looker 1902 /* Invisible enemy. Break apart the check for invis undead/invis looker
1862 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values, 1903 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
1863 * and making it a conditional makes the code pretty ugly. 1904 * and making it a conditional makes the code pretty ugly.
1864 */ 1905 */
1865 if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE)) 1906 if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE))
1866 if (makes_invisible_to (enemy, looker)) 1907 if (makes_invisible_to (enemy, looker))
1867 return 0; 1908 return 0;
1868 } 1909 }
1869 else if (looker->type == PLAYER) /* for players, a (possible) shortcut */ 1910 else if (looker->is_player ()) /* for players, a (possible) shortcut */
1870 if (player_can_view (looker, enemy)) 1911 if (player_can_view (looker, enemy))
1871 return 1; 1912 return 1;
1872 1913
1873 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen 1914 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
1874 * unless they carry a light or stand in light. Darkness doesnt 1915 * unless they carry a light or stand in light. Darkness doesnt
1877 * we care about the enemy maps status, not the looker. 1918 * we care about the enemy maps status, not the looker.
1878 * only relevant for tiled maps, but it is possible that the 1919 * only relevant for tiled maps, but it is possible that the
1879 * enemy is on a bright map and the looker on a dark - in that 1920 * enemy is on a bright map and the looker on a dark - in that
1880 * case, the looker can still see the enemy 1921 * case, the looker can still see the enemy
1881 */ 1922 */
1882 if (enemy->map->darkness > 0 && !stand_in_light (enemy) 1923 if (enemy->map->darklevel () > 0
1924 && !stand_in_light (enemy)
1883 && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS))) 1925 && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS)))
1884 return 0; 1926 return 0;
1885 1927
1886 return 1; 1928 return 1;
1887} 1929}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines