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

Comparing deliantra/server/server/pets.C (file contents):
Revision 1.4 by root, Sun Sep 10 15:59:57 2006 UTC vs.
Revision 1.19 by root, Wed Jan 3 20:32:13 2007 UTC

1
2/*
3 * static char *rcsid_pets_c =
4 * "$Id: pets.C,v 1.4 2006/09/10 15:59:57 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
28*/ 22*/
29 23
30#include <global.h> 24#include <global.h>
31#ifndef __CEXTRACT__
32# include <sproto.h> 25#include <sproto.h>
33#endif
34 26
35/* given that 'pet' is a friendly object, this function returns a 27/* given that 'pet' is a friendly object, this function returns a
36 * monster the pet should attack, NULL if nothing appropriate is 28 * monster the pet should attack, NULL if nothing appropriate is
37 * found. it basically looks for nasty things around the owner 29 * found. it basically looks for nasty things around the owner
38 * of the pet to attack. 30 * of the pet to attack.
39 * this is now tilemap aware. 31 * this is now tilemap aware.
40 */ 32 */
41
42object * 33object *
43get_pet_enemy (object *pet, rv_vector * rv) 34get_pet_enemy (object *pet, rv_vector * rv)
44{ 35{
45 object *owner, *tmp, *attacker, *tmp3; 36 object *owner, *tmp, *attacker, *tmp3;
46 int i; 37 int i;
47 sint16 x, y; 38 sint16 x, y;
48 mapstruct *nm; 39 maptile *nm;
49 int search_arr[SIZEOFFREE]; 40 int search_arr[SIZEOFFREE];
50 int mflags; 41 int mflags;
51 42
52 attacker = pet->attacked_by; /*pointer to attacking enemy */ 43 attacker = pet->attacked_by; /*pointer to attacking enemy */
53 pet->attacked_by = NULL; /*clear this, since we are dealing with it */ 44 pet->attacked_by = NULL; /*clear this, since we are dealing with it */
54 45
55 if ((owner = get_owner (pet)) != NULL) 46 if ((owner = pet->owner) != NULL)
56 { 47 {
57 /* If the owner has turned on the pet, make the pet 48 /* If the owner has turned on the pet, make the pet
58 * unfriendly. 49 * unfriendly.
59 */ 50 */
60 if ((check_enemy (owner, rv)) == pet) 51 if ((check_enemy (owner, rv)) == pet)
88 */ 79 */
89 pet->enemy = NULL; 80 pet->enemy = NULL;
90 else 81 else
91 return tmp; 82 return tmp;
92 } 83 }
84
93 get_search_arr (search_arr); 85 get_search_arr (search_arr);
94 86
95 if (owner->type == PLAYER && owner->contr->petmode > pet_normal) 87 if (owner->type == PLAYER && owner->contr->petmode > pet_normal)
96 { 88 {
97 if (owner->contr->petmode == pet_sad) 89 if (owner->contr->petmode == pet_sad)
121 x = owner->x + freearr_x[search_arr[i]]; 113 x = owner->x + freearr_x[search_arr[i]];
122 y = owner->y + freearr_y[search_arr[i]]; 114 y = owner->y + freearr_y[search_arr[i]];
123 nm = owner->map; 115 nm = owner->map;
124 /* Only look on the space if there is something alive there. */ 116 /* Only look on the space if there is something alive there. */
125 mflags = get_map_flags (nm, &nm, x, y, &x, &y); 117 mflags = get_map_flags (nm, &nm, x, y, &x, &y);
118
126 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE) 119 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
127 { 120 {
128 for (tmp = get_map_ob (nm, x, y); tmp != NULL; tmp = tmp->above) 121 for (tmp = GET_MAP_OB (nm, x, y); tmp != NULL; tmp = tmp->above)
129 { 122 {
130 object *tmp2 = tmp->head == NULL ? tmp : tmp->head; 123 object *tmp2 = tmp->head == NULL ? tmp : tmp->head;
131 124
132 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) && 125 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) &&
133 (tmp2->type != PLAYER)) || 126 (tmp2->type != PLAYER)) ||
165 } 158 }
166 159
167 /* No threat to owner, check to see if the pet has an attacker */ 160 /* No threat to owner, check to see if the pet has an attacker */
168 if (attacker) 161 if (attacker)
169 { 162 {
170 /* need to be sure this is the right one! */
171 if (attacker->count == pet->attacked_by_count)
172 {
173 /* also need to check to make sure it is not freindly */ 163 /* also need to check to make sure it is not freindly */
174 /* or otherwise non-hostile, and is an appropriate target */ 164 /* or otherwise non-hostile, and is an appropriate target */
175 if (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && on_same_map (pet, attacker)) 165 if (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && on_same_map (pet, attacker))
176 { 166 {
177 pet->enemy = attacker; 167 pet->enemy = attacker;
168
178 if (check_enemy (pet, rv) != NULL) 169 if (check_enemy (pet, rv) != NULL)
179 return attacker; 170 return attacker;
180 else 171 else
181 pet->enemy = NULL; 172 pet->enemy = NULL;
182 }
183 } 173 }
184 } 174 }
185 175
186 /* Don't have an attacker or legal enemy, so look for a new one!. 176 /* Don't have an attacker or legal enemy, so look for a new one!.
187 * This looks for one around where the pet is. Thus, you could lead 177 * This looks for one around where the pet is. Thus, you could lead
198 nm = pet->map; 188 nm = pet->map;
199 /* Only look on the space if there is something alive there. */ 189 /* Only look on the space if there is something alive there. */
200 mflags = get_map_flags (nm, &nm, x, y, &x, &y); 190 mflags = get_map_flags (nm, &nm, x, y, &x, &y);
201 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE) 191 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
202 { 192 {
203 for (tmp = get_map_ob (nm, x, y); tmp != NULL; tmp = tmp->above) 193 for (tmp = GET_MAP_OB (nm, x, y); tmp != NULL; tmp = tmp->above)
204 { 194 {
205 object *tmp2 = tmp->head == NULL ? tmp : tmp->head; 195 object *tmp2 = tmp->head == NULL ? tmp : tmp->head;
206 196
207 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) && 197 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) &&
208 (tmp2->type != PLAYER)) || 198 (tmp2->type != PLAYER)) ||
252 for (obl = first_friendly_object; obl != NULL; obl = next) 242 for (obl = first_friendly_object; obl != NULL; obl = next)
253 { 243 {
254 object *ob = obl->ob; 244 object *ob = obl->ob;
255 245
256 next = obl->next; 246 next = obl->next;
257 if (get_owner (ob) == owner) 247 if (ob->owner == owner)
258 { 248 {
259 if (!QUERY_FLAG (ob, FLAG_REMOVED)) 249 if (!QUERY_FLAG (ob, FLAG_REMOVED))
260 remove_ob (ob); 250 ob->remove ();
261 remove_friendly_object (ob); 251 remove_friendly_object (ob);
262 free_object (ob); 252 ob->destroy ();
263 } 253 }
264 } 254 }
265} 255}
266 256
267/* 257/*
270 * Thus the map isn't loaded yet, and we have to remove 260 * Thus the map isn't loaded yet, and we have to remove
271 * the pet... 261 * the pet...
272 * Interesting enough, we don't use the passed map structure in 262 * Interesting enough, we don't use the passed map structure in
273 * this function. 263 * this function.
274 */ 264 */
275
276void 265void
277remove_all_pets (mapstruct *map) 266remove_all_pets (maptile *map)
278{ 267{
279 objectlink *obl, *next; 268 objectlink *obl, *next;
280 object *owner; 269 object *owner;
281 270
282 for (obl = first_friendly_object; obl != NULL; obl = next) 271 for (obl = first_friendly_object; obl != NULL; obl = next)
283 { 272 {
284 next = obl->next; 273 next = obl->next;
285 if (obl->ob->type != PLAYER && QUERY_FLAG (obl->ob, FLAG_FRIENDLY) && 274 if (obl->ob->type != PLAYER && QUERY_FLAG (obl->ob, FLAG_FRIENDLY) &&
286 (owner = get_owner (obl->ob)) != NULL && !on_same_map (owner, obl->ob)) 275 (owner = obl->ob->owner) != NULL && !on_same_map (owner, obl->ob))
287 { 276 {
288 /* follow owner checks map status for us */ 277 /* follow owner checks map status for us */
289 follow_owner (obl->ob, owner); 278 follow_owner (obl->ob, owner);
290 } 279 }
291 } 280 }
296{ 285{
297 object *tmp; 286 object *tmp;
298 int dir; 287 int dir;
299 288
300 if (!QUERY_FLAG (ob, FLAG_REMOVED)) 289 if (!QUERY_FLAG (ob, FLAG_REMOVED))
301 remove_ob (ob); 290 ob->remove ();
302 291
303 if (owner->map == NULL) 292 if (owner->map == NULL)
304 { 293 {
305 LOG (llevError, "Can't follow owner (%d): no map.\n", &owner->name); 294 LOG (llevError, "Can't follow owner (%d): no map.\n", &owner->name);
306 goto fail; 295 goto fail;
334 323
335 return 0; 324 return 0;
336 325
337fail: 326fail:
338 remove_friendly_object (ob); 327 remove_friendly_object (ob);
339 free_object (ob); 328 ob->destroy ();
340 329
341 return 1; 330 return 1;
342} 331}
343 332
344void 333void
345pet_move (object *ob) 334pet_move (object *ob)
346{ 335{
347 int dir, tag, i; 336 int dir, i;
348 sint16 dx, dy; 337 sint16 dx, dy;
349 object *ob2, *owner; 338 object *ob2, *owner;
350 mapstruct *m; 339 maptile *m;
351 340
352 /* Check to see if player pulled out */ 341 /* Check to see if player pulled out */
353 if ((owner = get_owner (ob)) == NULL) 342 if ((owner = ob->owner) == NULL)
354 { 343 {
355 remove_ob (ob); /* Will be freed when returning */ 344 ob->remove (); /* Will be freed when returning */
356 remove_friendly_object (ob); 345 remove_friendly_object (ob);
357 free_object (ob); 346 ob->destroy ();
358 LOG (llevMonster, "Pet: no owner, leaving.\n"); 347 LOG (llevMonster, "Pet: no owner, leaving.\n");
359 return; 348 return;
360 } 349 }
361 350
362 /* move monster into the owners map if not in the same map */ 351 /* move monster into the owners map if not in the same map */
390 get_rangevector (ob, ob->owner, &rv, 0); 379 get_rangevector (ob, ob->owner, &rv, 0);
391 dir = rv.direction; 380 dir = rv.direction;
392 } 381 }
393 ob->direction = dir; 382 ob->direction = dir;
394 383
395 tag = ob->count;
396 /* move_ob returns 0 if the object couldn't move. If that is the 384 /* move_ob returns 0 if the object couldn't move. If that is the
397 * case, lets do some other work. 385 * case, lets do some other work.
398 */ 386 */
399 if (!(move_ob (ob, dir, ob))) 387 if (!(move_ob (ob, dir, ob)))
400 { 388 {
401 object *part; 389 object *part;
402 390
403 /* the failed move_ob above may destroy the pet, so check here */ 391 /* the failed move_ob above may destroy the pet, so check here */
404 if (was_destroyed (ob, tag)) 392 if (ob->destroyed ())
405 return; 393 return;
406 394
407 for (part = ob; part != NULL; part = part->more) 395 for (part = ob; part != NULL; part = part->more)
408 { 396 {
409 dx = part->x + freearr_x[dir]; 397 dx = part->x + freearr_x[dir];
410 dy = part->y + freearr_y[dir]; 398 dy = part->y + freearr_y[dir];
411 m = get_map_from_coord (part->map, &dx, &dy); 399 m = get_map_from_coord (part->map, &dx, &dy);
412 if (!m) 400 if (!m)
413 continue; 401 continue;
414 402
415 for (ob2 = get_map_ob (m, dx, dy); ob2 != NULL; ob2 = ob2->above) 403 for (ob2 = GET_MAP_OB (m, dx, dy); ob2 != NULL; ob2 = ob2->above)
416 { 404 {
417 object *new_ob; 405 object *new_ob;
418 406
419 new_ob = ob2->head ? ob2->head : ob2; 407 new_ob = ob2->head ? ob2->head : ob2;
420 if (new_ob == ob) 408 if (new_ob == ob)
421 break; 409 break;
422 if (new_ob == ob->owner) 410 if (new_ob == ob->owner)
423 return; 411 return;
424 if (get_owner (new_ob) == ob->owner) 412 if (new_ob->owner == ob->owner)
425 break; 413 break;
426 414
427 /* Hmm. Did we try to move into an enemy monster? If so, 415 /* Hmm. Did we try to move into an enemy monster? If so,
428 * make it our enemy. 416 * make it our enemy.
429 */ 417 */
466fix_summon_pet (archetype *at, object *op, int dir, int is_golem) 454fix_summon_pet (archetype *at, object *op, int dir, int is_golem)
467{ 455{
468 archetype *atmp; 456 archetype *atmp;
469 object *tmp = NULL, *prev = NULL, *head = NULL; 457 object *tmp = NULL, *prev = NULL, *head = NULL;
470 458
471 for (atmp = at; atmp != NULL; atmp = atmp->more) 459 for (atmp = at; atmp; atmp = atmp->more)
472 { 460 {
473 tmp = arch_to_object (atmp); 461 tmp = arch_to_object (atmp);
462
474 if (atmp == at) 463 if (atmp == at)
475 { 464 {
476 if (!is_golem) 465 if (!is_golem)
477 SET_FLAG (tmp, FLAG_MONSTER); 466 SET_FLAG (tmp, FLAG_MONSTER);
467
478 set_owner (tmp, op); 468 tmp->set_owner (op);
479 if (op->type == PLAYER) 469 if (op->type == PLAYER)
480 { 470 {
481 tmp->stats.exp = 0; 471 tmp->stats.exp = 0;
482 add_friendly_object (tmp); 472 add_friendly_object (tmp);
483 SET_FLAG (tmp, FLAG_FRIENDLY); 473 SET_FLAG (tmp, FLAG_FRIENDLY);
486 } 476 }
487 else 477 else
488 { 478 {
489 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 479 if (QUERY_FLAG (op, FLAG_FRIENDLY))
490 { 480 {
491 object *owner = get_owner (op); 481 object *owner = op->owner;
492 482
493 if (owner != NULL) 483 if (owner)
494 { /* For now, we transfer ownership */ 484 { /* For now, we transfer ownership */
495 set_owner (tmp, owner); 485 tmp->set_owner (owner);
496 tmp->attack_movement = PETMOVE; 486 tmp->attack_movement = PETMOVE;
497 add_friendly_object (tmp); 487 add_friendly_object (tmp);
498 SET_FLAG (tmp, FLAG_FRIENDLY); 488 SET_FLAG (tmp, FLAG_FRIENDLY);
499 } 489 }
500 } 490 }
501 } 491 }
492
502 if (op->type != PLAYER || !is_golem) 493 if (op->type != PLAYER || !is_golem)
503 { 494 {
504 tmp->attack_movement = PETMOVE; 495 tmp->attack_movement = PETMOVE;
505 tmp->speed_left = -1; 496 tmp->speed_left = -1;
506 tmp->type = 0; 497 tmp->type = 0;
508 } 499 }
509 else 500 else
510 tmp->type = GOLEM; 501 tmp->type = GOLEM;
511 502
512 } 503 }
504
513 if (head == NULL) 505 if (!head)
514 head = tmp; 506 head = tmp;
507
515 tmp->x = op->x + freearr_x[dir] + tmp->arch->clone.x; 508 tmp->x = op->x + freearr_x[dir] + tmp->arch->clone.x;
516 tmp->y = op->y + freearr_y[dir] + tmp->arch->clone.y; 509 tmp->y = op->y + freearr_y[dir] + tmp->arch->clone.y;
517 tmp->map = op->map; 510 tmp->map = op->map;
511
518 if (tmp->invisible) 512 if (tmp->invisible)
519 tmp->invisible = 0; 513 tmp->invisible = 0;
514
520 if (head != tmp) 515 if (head != tmp)
521 tmp->head = head, prev->more = tmp; 516 tmp->head = head, prev->more = tmp;
517
522 prev = tmp; 518 prev = tmp;
523 } 519 }
520
524 head->direction = dir; 521 head->direction = dir;
525 522
526 /* need to change some monster attr to prevent problems/crashing */ 523 /* need to change some monster attr to prevent problems/crashing */
527 head->last_heal = 0; 524 head->last_heal = 0;
528 head->last_eat = 0; 525 head->last_eat = 0;
539 536
540 return head; 537 return head;
541} 538}
542 539
543/* updated this to allow more than the golem 'head' to attack */ 540/* updated this to allow more than the golem 'head' to attack */
544
545/* op is the golem to be moved. */ 541/* op is the golem to be moved. */
546
547void 542void
548move_golem (object *op) 543move_golem (object *op)
549{ 544{
550 int made_attack = 0; 545 int made_attack = 0;
551 object *tmp; 546 object *tmp;
552 tag_t tag;
553 547
554 if (QUERY_FLAG (op, FLAG_MONSTER)) 548 if (QUERY_FLAG (op, FLAG_MONSTER))
555 return; /* Has already been moved */ 549 return; /* Has already been moved */
556 550
557 if (get_owner (op) == NULL) 551 if (op->owner == NULL)
558 { 552 {
559 LOG (llevDebug, "Golem without owner destructed.\n"); 553 LOG (llevDebug, "Golem without owner destructed.\n");
560 remove_ob (op); 554 op->remove ();
561 free_object (op); 555 op->destroy ();
562 return; 556 return;
563 } 557 }
558
564 /* It would be nice to have a cleaner way of what message to print 559 /* It would be nice to have a cleaner way of what message to print
565 * when the golem expires than these hard coded entries. 560 * when the golem expires than these hard coded entries.
566 * Note it is intentional that a golems duration is based on its 561 * Note it is intentional that a golems duration is based on its
567 * hp, and not duration 562 * hp, and not duration
568 */ 563 */
569 if (--op->stats.hp < 0) 564 if (--op->stats.hp < 0)
570 { 565 {
571 if (op->msg) 566 if (op->msg)
572 new_draw_info (NDI_UNIQUE, 0, op->owner, op->msg); 567 new_draw_info (NDI_UNIQUE, 0, op->owner, op->msg);
568
573 op->owner->contr->ranges[range_golem] = NULL; 569 op->owner->contr->ranges[range_golem] = 0;
574 op->owner->contr->golem_count = 0;
575 remove_friendly_object (op); 570 remove_friendly_object (op);
576 remove_ob (op); 571 op->remove ();
577 free_object (op); 572 op->destroy ();
578 return; 573 return;
579 } 574 }
580 575
581 /* Do golem attacks/movement for single & multisq golems. 576 /* Do golem attacks/movement for single & multisq golems.
582 * Assuming here that op is the 'head' object. Pass only op to 577 * Assuming here that op is the 'head' object. Pass only op to
583 * move_ob (makes recursive calls to other parts) 578 * move_ob (makes recursive calls to other parts)
584 * move_ob returns 0 if the creature was not able to move. 579 * move_ob returns 0 if the creature was not able to move.
585 */ 580 */
586 tag = op->count;
587 if (move_ob (op, op->direction, op)) 581 if (move_ob (op, op->direction, op))
588 return; 582 return;
589 if (was_destroyed (op, tag)) 583
584 if (op->destroyed ())
590 return; 585 return;
591 586
592 for (tmp = op; tmp; tmp = tmp->more) 587 for (tmp = op; tmp; tmp = tmp->more)
593 { 588 {
594 sint16 x = tmp->x + freearr_x[op->direction], y = tmp->y + freearr_y[op->direction]; 589 sint16 x = tmp->x + freearr_x[op->direction], y = tmp->y + freearr_y[op->direction];
595 object *victim; 590 object *victim;
596 mapstruct *m; 591 maptile *m;
597 int mflags; 592 int mflags;
598 593
599 m = op->map; 594 m = op->map;
600 mflags = get_map_flags (m, &m, x, y, &x, &y); 595 mflags = get_map_flags (m, &m, x, y, &x, &y);
601 596
602 if (mflags & P_OUT_OF_MAP) 597 if (mflags & P_OUT_OF_MAP)
603 continue; 598 continue;
604 599
605 for (victim = get_map_ob (op->map, x, y); victim; victim = victim->above) 600 for (victim = GET_MAP_OB (op->map, x, y); victim; victim = victim->above)
606 if (QUERY_FLAG (victim, FLAG_ALIVE)) 601 if (QUERY_FLAG (victim, FLAG_ALIVE))
607 break; 602 break;
608 603
609 /* We used to call will_hit_self to make sure we don't 604 /* We used to call will_hit_self to make sure we don't
610 * hit ourselves, but that didn't work, and I don't really 605 * hit ourselves, but that didn't work, and I don't really
666 char buf[MAX_BUF]; 661 char buf[MAX_BUF];
667 662
668 /* Because there can be different golem spells, player may want to 663 /* Because there can be different golem spells, player may want to
669 * 'lose' their old golem. 664 * 'lose' their old golem.
670 */ 665 */
671 if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) 666 if (op->type == PLAYER && op->contr->ranges[range_golem])
672 { 667 {
673 new_draw_info (NDI_UNIQUE, 0, op, "You dismiss your existing golem."); 668 new_draw_info (NDI_UNIQUE, 0, op, "You dismiss your existing golem.");
674 remove_ob (op->contr->ranges[range_golem]); 669 op->contr->ranges[range_golem]->remove ();
675 free_object (op->contr->ranges[range_golem]); 670 op->contr->ranges[range_golem]->destroy ();
676 op->contr->ranges[range_golem] = NULL; 671 op->contr->ranges[range_golem] = 0;
677 op->contr->golem_count = (uint32) - 1;
678 } 672 }
679 673
680 if (spob->other_arch) 674 if (spob->other_arch)
681 at = spob->other_arch; 675 at = spob->other_arch;
682 else if (spob->race) 676 else if (spob->race)
686 if (!god) 680 if (!god)
687 { 681 {
688 new_draw_info_format (NDI_UNIQUE, 0, op, "You must worship a god to cast %s.", &spob->name); 682 new_draw_info_format (NDI_UNIQUE, 0, op, "You must worship a god to cast %s.", &spob->name);
689 return 0; 683 return 0;
690 } 684 }
685
691 at = determine_holy_arch (god, spob->race); 686 at = determine_holy_arch (god, spob->race);
687
692 if (!at) 688 if (!at)
693 { 689 {
694 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no %s for you to call.", &god->name, &spob->race); 690 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no %s for you to call.", &god->name, &spob->race);
695 return 0; 691 return 0;
696 } 692 }
702 } 698 }
703 699
704 if (!dir) 700 if (!dir)
705 dir = find_free_spot (NULL, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1); 701 dir = find_free_spot (NULL, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
706 702
707 if ((dir == -1) || ob_blocked (&at->clone, op->map, op->x + freearr_x[dir], op->y + freearr_y[dir])) 703 if (dir == -1 || ob_blocked (&at->clone, op->map, op->x + freearr_x[dir], op->y + freearr_y[dir]))
708 { 704 {
709 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); 705 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
710 return 0; 706 return 0;
711 } 707 }
708
712 /* basically want to get proper map/coordinates for this object */ 709 /* basically want to get proper map/coordinates for this object */
713 710
714 if (!(tmp = fix_summon_pet (at, op, dir, GOLEM))) 711 if (!(tmp = fix_summon_pet (at, op, dir, GOLEM)))
715 { 712 {
716 new_draw_info (NDI_UNIQUE, 0, op, "Your spell fails."); 713 new_draw_info (NDI_UNIQUE, 0, op, "Your spell fails.");
718 } 715 }
719 716
720 if (op->type == PLAYER) 717 if (op->type == PLAYER)
721 { 718 {
722 tmp->type = GOLEM; 719 tmp->type = GOLEM;
723 set_owner (tmp, op); 720 tmp->set_owner (op);
724 set_spell_skill (op, caster, spob, tmp); 721 set_spell_skill (op, caster, spob, tmp);
725 op->contr->ranges[range_golem] = tmp; 722 op->contr->ranges[range_golem] = tmp;
726 op->contr->golem_count = tmp->count;
727 /* give the player control of the golem */ 723 /* give the player control of the golem */
728 op->contr->shoottype = range_golem; 724 op->contr->shoottype = range_golem;
729 } 725 }
730 else 726 else
731 { 727 {
732 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 728 if (QUERY_FLAG (op, FLAG_FRIENDLY))
733 { 729 {
734 object *owner = get_owner (op); 730 object *owner = op->owner;
735 731
736 if (owner != NULL) 732 if (owner)
737 { /* For now, we transfer ownership */ 733 { /* For now, we transfer ownership */
738 set_owner (tmp, owner); 734 tmp->set_owner (owner);
739 tmp->attack_movement = PETMOVE; 735 tmp->attack_movement = PETMOVE;
740 add_friendly_object (tmp); 736 add_friendly_object (tmp);
741 SET_FLAG (tmp, FLAG_FRIENDLY); 737 SET_FLAG (tmp, FLAG_FRIENDLY);
742 } 738 }
743 } 739 }
740
744 SET_FLAG (tmp, FLAG_MONSTER); 741 SET_FLAG (tmp, FLAG_MONSTER);
745 } 742 }
746 743
747 /* make the speed positive. */ 744 /* make the speed positive. */
748 tmp->speed = FABS (tmp->speed); 745 tmp->speed = FABS (tmp->speed);
751 /* players can't cope with too strong summonings. */ 748 /* players can't cope with too strong summonings. */
752 /* but monsters can. reserve these for players. */ 749 /* but monsters can. reserve these for players. */
753 if (op->type == PLAYER) 750 if (op->type == PLAYER)
754 { 751 {
755 tmp->stats.hp += spob->duration + SP_level_duration_adjust (caster, spob); 752 tmp->stats.hp += spob->duration + SP_level_duration_adjust (caster, spob);
753
756 if (!spob->stats.dam) 754 if (!spob->stats.dam)
757 tmp->stats.dam += SP_level_dam_adjust (caster, spob); 755 tmp->stats.dam += SP_level_dam_adjust (caster, spob);
758 else 756 else
759 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob); 757 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob);
758
760 tmp->speed += .02 * SP_level_range_adjust (caster, spob); 759 tmp->speed += .02 * SP_level_range_adjust (caster, spob);
761 tmp->speed = MIN (tmp->speed, 1.0); 760 tmp->speed = MIN (tmp->speed, 1.0);
761
762 if (spob->attacktype) 762 if (spob->attacktype)
763 tmp->attacktype = spob->attacktype; 763 tmp->attacktype = spob->attacktype;
764 } 764 }
765
765 tmp->stats.wc -= SP_level_range_adjust (caster, spob); 766 tmp->stats.wc -= SP_level_range_adjust (caster, spob);
766 767
767 /* limit the speed to 0.3 for non-players, 1 for players. */ 768 /* limit the speed to 0.3 for non-players, 1 for players. */
768 769
769 /* make experience increase in proportion to the strength. 770 /* make experience increase in proportion to the strength.
787 788
788 tmp->attacktype |= god->attacktype; 789 tmp->attacktype |= god->attacktype;
789 memcpy (tmp->resist, god->resist, sizeof (tmp->resist)); 790 memcpy (tmp->resist, god->resist, sizeof (tmp->resist));
790 tmp->race = god->race; 791 tmp->race = god->race;
791 tmp->slaying = god->slaying; 792 tmp->slaying = god->slaying;
793
792 /* safety, we must allow a god's servants some reasonable attack */ 794 /* safety, we must allow a god's servants some reasonable attack */
793 if (!(tmp->attacktype & AT_PHYSICAL)) 795 if (!(tmp->attacktype & AT_PHYSICAL))
794 tmp->attacktype |= AT_PHYSICAL; 796 tmp->attacktype |= AT_PHYSICAL;
795 } 797 }
796 798
887 /* This should not happen */ 889 /* This should not happen */
888 LOG (llevDebug, "choose_cult_monster() mon_nr was set, but did not find a monster\n"); 890 LOG (llevDebug, "choose_cult_monster() mon_nr was set, but did not find a monster\n");
889 return NULL; 891 return NULL;
890} 892}
891 893
892
893
894int 894int
895summon_object (object *op, object *caster, object *spell_ob, int dir, const char *stringarg) 895summon_object (object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
896{ 896{
897 sint16 x, y, nrof = 1, i; 897 sint16 x, y, nrof = 1, i;
898 archetype *summon_arch; 898 archetype *summon_arch;
899 int ndir; 899 int ndir;
900 900
901 if (spell_ob->other_arch) 901 if (spell_ob->other_arch)
902 {
903 summon_arch = spell_ob->other_arch; 902 summon_arch = spell_ob->other_arch;
904 }
905 else if (spell_ob->randomitems) 903 else if (spell_ob->randomitems)
906 { 904 {
907 int level = caster_level (caster, spell_ob); 905 int level = caster_level (caster, spell_ob);
908 treasure *tr, *lasttr = NULL;; 906 treasure *tr, *lasttr = NULL;
909 907
908 shstr_cmp sparam (stringarg);
909
910 /* In old code, this was a very convuluted for statement, 910 /* In old code, this was a very convoluted for statement,
911 * with all the checks in the 'for' portion itself. Much 911 * with all the checks in the 'for' portion itself. Much
912 * more readable to break some of the conditions out. 912 * more readable to break some of the conditions out.
913 */ 913 */
914 for (tr = spell_ob->randomitems->items; tr; tr = tr->next) 914 for (tr = spell_ob->randomitems->items; tr; tr = tr->next)
915 { 915 {
916 if (!tr->item)
917 continue;
918
916 if (level < tr->magic) 919 if (level < tr->magic)
917 break; 920 break;
921
918 lasttr = tr; 922 lasttr = tr;
919 if (stringarg && !strcmp (tr->item->name, stringarg)) 923
924 if (tr->item->name == sparam)
920 break; 925 break;
921 if (tr->next == NULL || tr->next->item == NULL)
922 break;
923 } 926 }
927
924 if (!lasttr) 928 if (!lasttr)
925 { 929 {
926 LOG (llevError, "Treasurelist %s did not generate a valid entry in summon_object\n", &spell_ob->randomitems->name); 930 LOG (llevError, "Treasurelist %s did not generate a valid entry in summon_object\n", &spell_ob->randomitems->name);
927 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to summon any monsters."); 931 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to summon any monsters.");
928 return 0; 932 return 0;
929 } 933 }
934
930 summon_arch = lasttr->item; 935 summon_arch = lasttr->item;
931 nrof = lasttr->nrof; 936 nrof = lasttr->nrof;
932
933 } 937 }
934 else if (spell_ob->race && !strcmp (spell_ob->race, "GODCULTMON")) 938 else if (spell_ob->race && !strcmp (spell_ob->race, "GODCULTMON"))
935 { 939 {
936 object *god = find_god (determine_god (op)), *mon, *owner; 940 object *god = find_god (determine_god (op)), *mon, *owner;
937 int summon_level, tries; 941 int summon_level, tries;
938 942
939 if (!god && ((owner = get_owner (op)) != NULL)) 943 if (!god && ((owner = op->owner) != NULL))
940 {
941 god = find_god (determine_god (owner)); 944 god = find_god (determine_god (owner));
942 } 945
943 /* If we can't find a god, can't get what monster to summon */ 946 /* If we can't find a god, can't get what monster to summon */
944 if (!god) 947 if (!god)
945 return 0; 948 return 0;
946 949
947 if (!god->race) 950 if (!god->race)
948 { 951 {
949 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no creatures that you may summon!", &god->name); 952 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no creatures that you may summon!", &god->name);
950 return 0; 953 return 0;
951 } 954 }
955
952 /* the summon level */ 956 /* the summon level */
953 summon_level = caster_level (caster, spell_ob); 957 summon_level = caster_level (caster, spell_ob);
954 if (summon_level == 0) 958 if (summon_level == 0)
955 summon_level = 1; 959 summon_level = 1;
960
956 tries = 0; 961 tries = 0;
957 do 962 do
958 { 963 {
959 mon = choose_cult_monster (op, god, summon_level); 964 mon = choose_cult_monster (op, god, summon_level);
960 if (!mon) 965 if (!mon)
961 { 966 {
962 new_draw_info_format (NDI_UNIQUE, 0, op, "%s fails to send anything.", &god->name); 967 new_draw_info_format (NDI_UNIQUE, 0, op, "%s fails to send anything.", &god->name);
963 return 0; 968 return 0;
964 } 969 }
970
965 ndir = dir; 971 ndir = dir;
972
966 if (!ndir) 973 if (!ndir)
967 ndir = find_free_spot (mon, op->map, op->x, op->y, 1, SIZEOFFREE); 974 ndir = find_free_spot (mon, op->map, op->x, op->y, 1, SIZEOFFREE);
975
968 if (ndir == -1 || ob_blocked (mon, op->map, op->x + freearr_x[ndir], op->y + freearr_y[ndir])) 976 if (ndir == -1 || ob_blocked (mon, op->map, op->x + freearr_x[ndir], op->y + freearr_y[ndir]))
969 { 977 {
970 ndir = -1; 978 ndir = -1;
971 if (++tries == 5) 979 if (++tries == 5)
972 { 980 {
974 return 0; 982 return 0;
975 } 983 }
976 } 984 }
977 } 985 }
978 while (ndir == -1); 986 while (ndir == -1);
987
979 if (mon->level > (summon_level / 2)) 988 if (mon->level > (summon_level / 2))
980 nrof = random_roll (1, 2, op, PREFER_HIGH); 989 nrof = random_roll (1, 2, op, PREFER_HIGH);
981 else 990 else
982 nrof = die_roll (2, 2, op, PREFER_HIGH); 991 nrof = die_roll (2, 2, op, PREFER_HIGH);
992
983 summon_arch = mon->arch; 993 summon_arch = mon->arch;
984 } 994 }
985 else 995 else
986 {
987 summon_arch = NULL; 996 summon_arch = 0;
988 }
989 997
990 if (spell_ob->stats.dam) 998 if (spell_ob->stats.dam)
991 nrof += spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob); 999 nrof += spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
992 1000
993 if (!summon_arch) 1001 if (!summon_arch)
1029 tmp = arch_to_object (atmp); 1037 tmp = arch_to_object (atmp);
1030 if (atmp == summon_arch) 1038 if (atmp == summon_arch)
1031 { 1039 {
1032 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1040 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1033 { 1041 {
1034 set_owner (tmp, op); 1042 tmp->set_owner (op);
1035 set_spell_skill (op, caster, spell_ob, tmp); 1043 set_spell_skill (op, caster, spell_ob, tmp);
1036 tmp->enemy = op->enemy; 1044 tmp->enemy = op->enemy;
1037 tmp->type = 0; 1045 tmp->type = 0;
1038 CLEAR_FLAG (tmp, FLAG_SLEEP); 1046 CLEAR_FLAG (tmp, FLAG_SLEEP);
1047
1039 if (op->type == PLAYER || QUERY_FLAG (op, FLAG_FRIENDLY)) 1048 if (op->type == PLAYER || QUERY_FLAG (op, FLAG_FRIENDLY))
1040 { 1049 {
1041 /* If this is not set, we make it friendly */ 1050 /* If this is not set, we make it friendly */
1042 if (!QUERY_FLAG (spell_ob, FLAG_MONSTER)) 1051 if (!QUERY_FLAG (spell_ob, FLAG_MONSTER))
1043 { 1052 {
1044 SET_FLAG (tmp, FLAG_FRIENDLY); 1053 SET_FLAG (tmp, FLAG_FRIENDLY);
1045 add_friendly_object (tmp); 1054 add_friendly_object (tmp);
1046 tmp->stats.exp = 0; 1055 tmp->stats.exp = 0;
1056
1047 if (spell_ob->attack_movement) 1057 if (spell_ob->attack_movement)
1048 tmp->attack_movement = spell_ob->attack_movement; 1058 tmp->attack_movement = spell_ob->attack_movement;
1059
1049 if (get_owner (op)) 1060 if (op->owner)
1050 set_owner (tmp, get_owner (op)); 1061 tmp->set_owner (op->owner);
1051 } 1062 }
1052 } 1063 }
1053 } 1064 }
1065
1054 if (tmp->speed > MIN_ACTIVE_SPEED) 1066 if (tmp->speed > MIN_ACTIVE_SPEED)
1055 tmp->speed_left = -1; 1067 tmp->speed_left = -1;
1056 } 1068 }
1069
1057 if (head == NULL) 1070 if (head == NULL)
1058 head = tmp; 1071 head = tmp;
1059 else 1072 else
1060 { 1073 {
1061 tmp->head = head; 1074 tmp->head = head;
1062 prev->more = tmp; 1075 prev->more = tmp;
1063 } 1076 }
1077
1064 prev = tmp; 1078 prev = tmp;
1065 tmp->x = op->x + x + tmp->arch->clone.x; 1079 tmp->x = op->x + x + tmp->arch->clone.x;
1066 tmp->y = op->y + y + tmp->arch->clone.y; 1080 tmp->y = op->y + y + tmp->arch->clone.y;
1067 tmp->map = op->map; 1081 tmp->map = op->map;
1068 } 1082 }
1083
1069 head->direction = freedir[ndir]; 1084 head->direction = freedir[ndir];
1070 head->stats.exp = 0; 1085 head->stats.exp = 0;
1071 head = insert_ob_in_map (head, head->map, op, 0); 1086 head = insert_ob_in_map (head, head->map, op, 0);
1087
1072 if (head && head->randomitems) 1088 if (head && head->randomitems)
1073 { 1089 {
1074 object *tmp;
1075
1076 create_treasure (head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0); 1090 create_treasure (head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0);
1091
1077 for (tmp = head->inv; tmp; tmp = tmp->below) 1092 for (object *tmp = head->inv; tmp; tmp = tmp->below)
1078 if (!tmp->nrof)
1079 SET_FLAG (tmp, FLAG_NO_DROP); 1093 SET_FLAG (tmp, FLAG_NO_DROP);
1080 } 1094 }
1081 } /* for i < nrof */ 1095 } /* for i < nrof */
1096
1082 return 1; 1097 return 1;
1083} 1098}
1084 1099
1085/* recursively look through the owner property of objects until the real owner 1100/* recursively look through the owner property of objects until the real owner
1086is found */ 1101is found */
1090 object *realowner = ob; 1105 object *realowner = ob;
1091 1106
1092 if (realowner == NULL) 1107 if (realowner == NULL)
1093 return NULL; 1108 return NULL;
1094 1109
1095 while (get_owner (realowner) != NULL) 1110 while (realowner->owner != NULL)
1096 { 1111 {
1097 realowner = get_owner (realowner); 1112 realowner = realowner->owner;
1098 } 1113 }
1099 return realowner; 1114 return realowner;
1100} 1115}
1101 1116
1102/* determines if checks so pets don't attack players or other pets should be 1117/* determines if checks so pets don't attack players or other pets should be

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines