diff options
Diffstat (limited to 'src/map/magic-stmt.c')
-rw-r--r-- | src/map/magic-stmt.c | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c index 9760674..c9984af 100644 --- a/src/map/magic-stmt.c +++ b/src/map/magic-stmt.c @@ -10,6 +10,7 @@ clif_spawn_fake_npc_for_player(struct map_session_data *sd, int fake_npc_id); //#define DEBUG +#ifdef DEBUG static void print_val(val_t *v) { @@ -37,6 +38,7 @@ dump_env(env_t *env) fprintf(stderr, ")\n"); } } +#endif static void clear_activation_record(cont_activation_record_t *ar) @@ -504,40 +506,6 @@ op_override_attack(env_t *env, int args_nr, val_t *args) return 0; } -static int // ret -1: not a string, ret 1: no such item, ret 0: OK -find_item(val_t *args, int index, struct item *item, int *stackable) -{ - struct item_data *item_data; - int must_add_sequentially; - - if (TY(index) == TY_INT) - item_data = itemdb_exists(ARGINT(index)); - else if (TY(index) == TY_STRING) - item_data = itemdb_searchname(ARGSTR(index)); - else - return -1; - - if (!item_data) - return 1; - - must_add_sequentially = (item_data->type == 4 - || item_data->type == 5 - || item_data->type == 7 - || item_data->type == 8); /* Very elegant. */ - - - if (stackable) - *stackable = !must_add_sequentially; - - memset(item, 0, sizeof(struct item)); - item->nameid = item_data->nameid; - item->identify = 1; - - return 0; -} - -#define GET_ARG_ITEM(index, dest, stackable) switch(find_item(args, index, &dest, &stackable)) { case -1 : return 1; case 1 : return 0; } - static int op_create_item(env_t *env, int args_nr, val_t *args) { @@ -916,7 +884,7 @@ return_to_stack(invocation_t *invocation) } while (!entity_id || !map_id2bl(entity_id)); magic_clear_var(var); - var->ty = TY_ENTITY; + var->ty = ar->c.c_foreach.ty; var->v.v_int = entity_id; return ar->c.c_foreach.body; @@ -966,6 +934,17 @@ find_entities_in_area_c(entity_t *target, va_list va) int **entities_p = va_arg(va, int **); int filter = va_arg(va, int); +/* The following macro adds an entity to the result list: */ +#define ADD_ENTITY(e) \ + if (*entities_nr_p == *entities_allocd_p) { \ + /* Need more space */ \ + (*entities_allocd_p) += 32; \ + *entities_p = realloc(*entities_p, sizeof(int) * (*entities_allocd_p)); \ + } \ + (*entities_p)[(*entities_nr_p)++] = e; + + + switch (target->type) { case BL_PC: @@ -974,8 +953,16 @@ find_entities_in_area_c(entity_t *target, va_list va) || (filter == FOREACH_FILTER_TARGET && map[target->m].flag.pvp)) break; - else - return 0; + else if (filter == FOREACH_FILTER_SPELL) { /* Check all spells bound to the caster */ + invocation_t *invoc = ((character_t *) target) -> active_spells; + /* Add all spells locked onto thie PC */ + + while (invoc) { + ADD_ENTITY(invoc->bl.id); + invoc = invoc->next_invocation; + } + } + return 0; case BL_MOB: if (filter == FOREACH_FILTER_MOB @@ -985,18 +972,24 @@ find_entities_in_area_c(entity_t *target, va_list va) else return 0; + case BL_SPELL: + if (filter == FOREACH_FILTER_SPELL) { + invocation_t *invocation = (invocation_t *) target; + + /* Check whether the spell is `bound'-- if so, we'll consider it iff we see the caster (case BL_PC). */ + if (invocation->flags & INVOCATION_FLAG_BOUND) + return 0; + else + break; /* Add the spell */ + } else + return 0; + default: return 0; } - if (*entities_nr_p == *entities_allocd_p) { - /* Need more space */ - (*entities_allocd_p) += 32; - *entities_p = realloc(*entities_p, sizeof(int) * (*entities_allocd_p)); - } - - (*entities_p)[(*entities_nr_p)++] = target->id; - + ADD_ENTITY(target->id); +#undef ADD_ENTITY return 0; } @@ -1069,6 +1062,7 @@ run_foreach(invocation_t *invocation, effect_t *foreach, effect_t *return_locati ar->c.c_foreach.index = 0; ar->c.c_foreach.entities_nr = entities_nr; ar->c.c_foreach.entities = entities; + ar->c.c_foreach.ty = (filter == FOREACH_FILTER_SPELL) ? TY_INVOCATION : TY_ENTITY; magic_clear_var(&area); @@ -1132,6 +1126,7 @@ run_call(invocation_t *invocation, effect_t *return_location) return current->e.e_call.body; } +#ifdef DEBUG static void print_cfg(int i, effect_t *e) { @@ -1185,6 +1180,7 @@ print_cfg(int i, effect_t *e) } print_cfg(i, e->next); } +#endif /** @@ -1199,6 +1195,9 @@ print_cfg(int i, effect_t *e) static int spell_run(invocation_t *invocation, int allow_delete) { + const int invocation_id = invocation->bl.id; +#define REFRESH_INVOCATION invocation = (invocation_t *) map_id2bl(invocation_id); if (!invocation) return 0; + #ifdef DEBUG fprintf(stderr, "Resuming execution: invocation of `%s'\n", invocation->spell->name); print_cfg(1, invocation->current_effect); @@ -1289,6 +1288,7 @@ spell_run(invocation_t *invocation, int allow_delete) invocation->script_pos = 0; clif_clearchar_id(invocation->bl.id, 1, caster->fd); } + REFRESH_INVOCATION; // Script may have killed the caster break; } @@ -1310,6 +1310,8 @@ spell_run(invocation_t *invocation, int allow_delete) for (i = 0; i < e->e.e_op.args_nr; i++) magic_clear_var(&args[i]); + + REFRESH_INVOCATION; // Effect may have killed the caster break; } @@ -1331,6 +1333,7 @@ spell_run(invocation_t *invocation, int allow_delete) if (allow_delete) try_to_finish_invocation(invocation); return 0; +#undef REFRESH_INVOCATION } @@ -1375,7 +1378,11 @@ spell_attack(int caster_id, int target_id) invocation->flags &= ~INVOCATION_FLAG_ABORTED; spell_execute_d(invocation, 0 /* don't delete the invocation if done */); - if (!(invocation->flags & INVOCATION_FLAG_ABORTED)) // If we didn't abort: + // If the caster died, we need to refresh here: + invocation = (invocation_t *)map_id2bl(caster->attack_spell_override); + + if (invocation + && !(invocation->flags & INVOCATION_FLAG_ABORTED)) // If we didn't abort: caster->attack_spell_charges--; } |