summaryrefslogtreecommitdiff
path: root/src/map/magic-stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/magic-stmt.c')
-rw-r--r--src/map/magic-stmt.c99
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--;
}