… | |
… | |
368 | dir ? 0 : INS_BELOW_ORIGINATOR); |
368 | dir ? 0 : INS_BELOW_ORIGINATOR); |
369 | |
369 | |
370 | return dir; |
370 | return dir; |
371 | } |
371 | } |
372 | |
372 | |
|
|
373 | static bool |
|
|
374 | mergable_owner (object *o1, object *o2) |
|
|
375 | { |
|
|
376 | if (o1 == o2) |
|
|
377 | return 1; |
|
|
378 | |
|
|
379 | if (!o1 || !o2) |
|
|
380 | return 0; |
|
|
381 | |
|
|
382 | if (o1->flag [FLAG_FRIENDLY] != o1->flag [FLAG_FRIENDLY]) |
|
|
383 | return 0; |
|
|
384 | |
|
|
385 | if (o1->is_player () || o2->is_player ()) |
|
|
386 | return 0; |
|
|
387 | |
|
|
388 | return 1; |
|
|
389 | } |
|
|
390 | |
373 | /* Returns true if it is ok to put spell *op on the space/may provided. |
391 | /* Returns true if it is ok to put spell *op on the space/may provided. |
374 | * immune_stop is basically the attacktype of the spell (why |
392 | * immune_stop is basically the attacktype of the spell (why |
375 | * passed as a different value, not sure of). If immune_stop |
393 | * passed as a different value, not sure of). If immune_stop |
376 | * has the AT_MAGIC bit set, and there is a counterwall |
394 | * has the AT_MAGIC bit set, and there is a counterwall |
377 | * on the space, the object doesn't get placed. if immune stop |
395 | * on the space, the object doesn't get placed. if immune stop |
378 | * does not have AT_MAGIC, then counterwalls do not effect the spell. |
396 | * does not have AT_MAGIC, then counterwalls do not effect the spell. |
379 | * |
|
|
380 | */ |
397 | */ |
381 | int |
398 | int |
382 | ok_to_put_more (maptile *m, sint16 x, sint16 y, object *op, int immune_stop) |
399 | ok_to_put_more (maptile *m, sint16 x, sint16 y, object *op, int immune_stop) |
383 | { |
400 | { |
384 | if (!xy_normalise (m, x, y)) |
401 | if (!xy_normalise (m, x, y)) |
… | |
… | |
387 | mapspace &ms = m->at (x, y); |
404 | mapspace &ms = m->at (x, y); |
388 | ms.update (); |
405 | ms.update (); |
389 | |
406 | |
390 | if (OB_TYPE_MOVE_BLOCK (op, ms.move_block)) |
407 | if (OB_TYPE_MOVE_BLOCK (op, ms.move_block)) |
391 | return 0; |
408 | return 0; |
|
|
409 | |
|
|
410 | int max_effects = 5; // max. number of similar spells per mapspace |
392 | |
411 | |
393 | for (object *tmp = ms.bot; tmp; tmp = tmp->above) |
412 | for (object *tmp = ms.bot; tmp; tmp = tmp->above) |
394 | { |
413 | { |
395 | /* If there is a counterspell on the space, and this |
414 | /* If there is a counterspell on the space, and this |
396 | * object is using magic, don't progress. I believe we could |
415 | * object is using magic, don't progress. I believe we could |
… | |
… | |
415 | // (and those shouldn't go away from |
434 | // (and those shouldn't go away from |
416 | // sanctuary) see also: permanent lava |
435 | // sanctuary) see also: permanent lava |
417 | && (immune_stop & AT_MAGIC)) |
436 | && (immune_stop & AT_MAGIC)) |
418 | return 0; |
437 | return 0; |
419 | |
438 | |
420 | /* This is to prevent 'out of control' spells. Basically, this |
|
|
421 | * limits one spell effect per space per spell. This is definately |
|
|
422 | * needed for performance reasons, and just for playability I believe. |
|
|
423 | * there are no such things as multispaced spells right now, so |
|
|
424 | * we don't need to worry about the head. |
|
|
425 | */ |
|
|
426 | if (tmp->stats.maxhp == op->stats.maxhp |
|
|
427 | && tmp->type == op->type |
439 | if (tmp->type == op->type) |
428 | && tmp->subtype == op->subtype) |
|
|
429 | return 0; |
|
|
430 | |
|
|
431 | /* |
|
|
432 | * Combine similar spell effects into one spell effect. Needed for |
|
|
433 | * performance reasons with meteor swarm and the like, but also for |
|
|
434 | * playability reasons. |
|
|
435 | */ |
|
|
436 | if (tmp->arch == op->arch /* no harm if not comparing by name here */ |
|
|
437 | && tmp->type == op->type |
|
|
438 | && tmp->subtype == op->subtype |
|
|
439 | && tmp->owner == op->owner |
|
|
440 | && ((tmp->subtype == SP_EXPLOSION) || (tmp->subtype == SP_CONE && tmp->stats.sp == op->stats.sp))) |
|
|
441 | { |
440 | { |
442 | tmp->stats.dam = MAX (tmp->stats.dam, op->stats.dam); |
441 | if (tmp->subtype == op->subtype |
443 | tmp->range = MAX (tmp->range, op->range); |
442 | && tmp->arch == op->arch /* no harm if not comparing by name here */) |
444 | tmp->duration = MAX (tmp->duration, op->duration); |
443 | { |
|
|
444 | /* This is to prevent 'out of control' spells. Basically, this |
|
|
445 | * limits one spell effect per space per spell. This is definately |
|
|
446 | * needed for performance reasons, and just for playability I believe. |
|
|
447 | * there are no such things as multispaced spells right now, so |
|
|
448 | * we don't need to worry about the head. |
|
|
449 | */ |
|
|
450 | if (tmp->stats.maxhp == op->stats.maxhp) |
|
|
451 | return 0; |
|
|
452 | |
|
|
453 | /* |
|
|
454 | * Combine similar spell effects into one spell effect. Needed for |
|
|
455 | * performance reasons with meteor swarm and the like, but also for |
|
|
456 | * playability reasons. |
|
|
457 | */ |
|
|
458 | if (((tmp->subtype == SP_EXPLOSION) || (tmp->subtype == SP_CONE && tmp->stats.sp == op->stats.sp))) |
|
|
459 | if (mergable_owner (tmp, op)) |
|
|
460 | { |
|
|
461 | // if same owner, then combine, but reduce advantage of multiple spells |
|
|
462 | max_it (tmp->stats.dam, op->stats.dam); |
|
|
463 | max_it (tmp->range , op->range); |
|
|
464 | max_it (tmp->duration , op->duration); |
|
|
465 | return 0; |
|
|
466 | } |
|
|
467 | } |
|
|
468 | |
|
|
469 | // if there are too many spell effects on this space, |
|
|
470 | // then don't allow more of them, for performance reasons. |
|
|
471 | if (tmp->type == SPELL_EFFECT |
|
|
472 | && !--max_effects) |
445 | return 0; |
473 | return 0; |
446 | } |
474 | } |
447 | |
475 | |
448 | /* Perhaps we should also put checks in for no magic and unholy |
476 | /* Perhaps we should also put checks in for no magic and unholy |
449 | * ground to prevent it from moving along? |
477 | * ground to prevent it from moving along? |
450 | */ |
478 | */ |