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.6 by root, Tue Sep 12 20:55:18 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.6 2006/09/12 20:55:18 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)
709 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]))
710 { 704 {
711 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.");
712 return 0; 706 return 0;
713 } 707 }
708
714 /* basically want to get proper map/coordinates for this object */ 709 /* basically want to get proper map/coordinates for this object */
715 710
716 if (!(tmp = fix_summon_pet (at, op, dir, GOLEM))) 711 if (!(tmp = fix_summon_pet (at, op, dir, GOLEM)))
717 { 712 {
718 new_draw_info (NDI_UNIQUE, 0, op, "Your spell fails."); 713 new_draw_info (NDI_UNIQUE, 0, op, "Your spell fails.");
720 } 715 }
721 716
722 if (op->type == PLAYER) 717 if (op->type == PLAYER)
723 { 718 {
724 tmp->type = GOLEM; 719 tmp->type = GOLEM;
725 set_owner (tmp, op); 720 tmp->set_owner (op);
726 set_spell_skill (op, caster, spob, tmp); 721 set_spell_skill (op, caster, spob, tmp);
727 op->contr->ranges[range_golem] = tmp; 722 op->contr->ranges[range_golem] = tmp;
728 op->contr->golem_count = tmp->count;
729 /* give the player control of the golem */ 723 /* give the player control of the golem */
730 op->contr->shoottype = range_golem; 724 op->contr->shoottype = range_golem;
731 } 725 }
732 else 726 else
733 { 727 {
734 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 728 if (QUERY_FLAG (op, FLAG_FRIENDLY))
735 { 729 {
736 object *owner = get_owner (op); 730 object *owner = op->owner;
737 731
738 if (owner != NULL) 732 if (owner)
739 { /* For now, we transfer ownership */ 733 { /* For now, we transfer ownership */
740 set_owner (tmp, owner); 734 tmp->set_owner (owner);
741 tmp->attack_movement = PETMOVE; 735 tmp->attack_movement = PETMOVE;
742 add_friendly_object (tmp); 736 add_friendly_object (tmp);
743 SET_FLAG (tmp, FLAG_FRIENDLY); 737 SET_FLAG (tmp, FLAG_FRIENDLY);
744 } 738 }
745 } 739 }
917 * with all the checks in the 'for' portion itself. Much 911 * with all the checks in the 'for' portion itself. Much
918 * more readable to break some of the conditions out. 912 * more readable to break some of the conditions out.
919 */ 913 */
920 for (tr = spell_ob->randomitems->items; tr; tr = tr->next) 914 for (tr = spell_ob->randomitems->items; tr; tr = tr->next)
921 { 915 {
916 if (!tr->item)
917 continue;
918
922 if (level < tr->magic) 919 if (level < tr->magic)
923 break; 920 break;
924 921
925 lasttr = tr; 922 lasttr = tr;
926 923
927 if (stringarg && tr->item->name == sparam) 924 if (tr->item->name == sparam)
928 break;
929
930 if (!tr->next || !tr->next->item)
931 break; 925 break;
932 } 926 }
933 927
934 if (!lasttr) 928 if (!lasttr)
935 { 929 {
937 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.");
938 return 0; 932 return 0;
939 } 933 }
940 934
941 summon_arch = lasttr->item; 935 summon_arch = lasttr->item;
942 nrof = lasttr->nrof; 936 nrof = lasttr->nrof;
943 } 937 }
944 else if (spell_ob->race && !strcmp (spell_ob->race, "GODCULTMON")) 938 else if (spell_ob->race && !strcmp (spell_ob->race, "GODCULTMON"))
945 { 939 {
946 object *god = find_god (determine_god (op)), *mon, *owner; 940 object *god = find_god (determine_god (op)), *mon, *owner;
947 int summon_level, tries; 941 int summon_level, tries;
948 942
949 if (!god && ((owner = get_owner (op)) != NULL)) 943 if (!god && ((owner = op->owner) != NULL))
950 god = find_god (determine_god (owner)); 944 god = find_god (determine_god (owner));
951 945
952 /* 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 */
953 if (!god) 947 if (!god)
954 return 0; 948 return 0;
1043 tmp = arch_to_object (atmp); 1037 tmp = arch_to_object (atmp);
1044 if (atmp == summon_arch) 1038 if (atmp == summon_arch)
1045 { 1039 {
1046 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1040 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1047 { 1041 {
1048 set_owner (tmp, op); 1042 tmp->set_owner (op);
1049 set_spell_skill (op, caster, spell_ob, tmp); 1043 set_spell_skill (op, caster, spell_ob, tmp);
1050 tmp->enemy = op->enemy; 1044 tmp->enemy = op->enemy;
1051 tmp->type = 0; 1045 tmp->type = 0;
1052 CLEAR_FLAG (tmp, FLAG_SLEEP); 1046 CLEAR_FLAG (tmp, FLAG_SLEEP);
1053 1047
1061 tmp->stats.exp = 0; 1055 tmp->stats.exp = 0;
1062 1056
1063 if (spell_ob->attack_movement) 1057 if (spell_ob->attack_movement)
1064 tmp->attack_movement = spell_ob->attack_movement; 1058 tmp->attack_movement = spell_ob->attack_movement;
1065 1059
1066 if (get_owner (op)) 1060 if (op->owner)
1067 set_owner (tmp, get_owner (op)); 1061 tmp->set_owner (op->owner);
1068 } 1062 }
1069 } 1063 }
1070 } 1064 }
1071 1065
1072 if (tmp->speed > MIN_ACTIVE_SPEED) 1066 if (tmp->speed > MIN_ACTIVE_SPEED)
1091 head->stats.exp = 0; 1085 head->stats.exp = 0;
1092 head = insert_ob_in_map (head, head->map, op, 0); 1086 head = insert_ob_in_map (head, head->map, op, 0);
1093 1087
1094 if (head && head->randomitems) 1088 if (head && head->randomitems)
1095 { 1089 {
1096 object *tmp;
1097
1098 create_treasure (head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0); 1090 create_treasure (head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0);
1091
1099 for (tmp = head->inv; tmp; tmp = tmp->below) 1092 for (object *tmp = head->inv; tmp; tmp = tmp->below)
1100 if (!tmp->nrof)
1101 SET_FLAG (tmp, FLAG_NO_DROP); 1093 SET_FLAG (tmp, FLAG_NO_DROP);
1102 } 1094 }
1103 } /* for i < nrof */ 1095 } /* for i < nrof */
1104 1096
1105 return 1; 1097 return 1;
1106} 1098}
1113 object *realowner = ob; 1105 object *realowner = ob;
1114 1106
1115 if (realowner == NULL) 1107 if (realowner == NULL)
1116 return NULL; 1108 return NULL;
1117 1109
1118 while (get_owner (realowner) != NULL) 1110 while (realowner->owner != NULL)
1119 { 1111 {
1120 realowner = get_owner (realowner); 1112 realowner = realowner->owner;
1121 } 1113 }
1122 return realowner; 1114 return realowner;
1123} 1115}
1124 1116
1125/* 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