summaryrefslogtreecommitdiff
path: root/src/map/magic-expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/magic-expr.c')
-rw-r--r--src/map/magic-expr.c140
1 files changed, 117 insertions, 23 deletions
diff --git a/src/map/magic-expr.c b/src/map/magic-expr.c
index a300a74..0034441 100644
--- a/src/map/magic-expr.c
+++ b/src/map/magic-expr.c
@@ -214,6 +214,20 @@ make_location(val_t *v)
}
}
+static void
+make_spell(val_t *v)
+{
+ if (v->ty == TY_INVOCATION) {
+ invocation_t *invoc = v->v.v_invocation; //(invocation_t *) map_id2bl(v->v.v_int);
+ if (!invoc)
+ v->ty = TY_FAIL;
+ else {
+ v->ty = TY_SPELL;
+ v->v.v_spell = invoc->spell;
+ }
+ }
+}
+
static int
fun_add(env_t *env, int args_nr, val_t *result, val_t *args)
{
@@ -483,13 +497,13 @@ magic_area_rect(int *m, int *x, int *y, int *width, int *height, area_t *area)
}
}
-static int
-location_in_area(int m, int x, int y, area_t *area)
+int
+magic_location_in_area(int m, int x, int y, area_t *area)
{
switch (area->ty) {
case AREA_UNION:
- return location_in_area(m, x, y, area->a.a_union[0])
- || location_in_area(m, x, y, area->a.a_union[1]);
+ return magic_location_in_area(m, x, y, area->a.a_union[0])
+ || magic_location_in_area(m, x, y, area->a.a_union[1]);
case AREA_LOCATION:
case AREA_RECT:
case AREA_BAR: {
@@ -510,10 +524,10 @@ location_in_area(int m, int x, int y, area_t *area)
static int
fun_is_in(env_t *env, int args_nr, val_t *result, val_t *args)
{
- RESULTINT = location_in_area(ARGLOCATION(0).m,
- ARGLOCATION(0).x,
- ARGLOCATION(0).y,
- ARGAREA(1));
+ RESULTINT = magic_location_in_area(ARGLOCATION(0).m,
+ ARGLOCATION(0).x,
+ ARGLOCATION(0).y,
+ ARGAREA(1));
return 0;
}
@@ -621,31 +635,79 @@ fun_hash_entity(env_t *env, int args_nr, val_t *result, val_t *args)
return 0;
}
+int // ret -1: not a string, ret 1: no such item, ret 0: OK
+magic_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;
+}
+
static int
fun_count_item(env_t *env, int args_nr, val_t *result, val_t *args)
{
character_t *chr = (ETY(0) == BL_PC) ? ARGPC(0) : NULL;
- int item_id;
-
- if (TY(1) == TY_INT)
- item_id = ARGINT(1);
- else if (TY(1) == TY_STRING) {
- struct item_data *bitem = itemdb_searchname(ARGSTR(1));
- if (!bitem) {
- fprintf(stderr, "Unknown item `%s' used in spell\n", ARGSTR(1));
- return 1;
- } else
- item_id = bitem->nameid;
- } else
- return 0;
+ int stackable;
+ struct item item;
+
+ GET_ARG_ITEM(1, item, stackable);
if (!chr)
return 1;
- RESULTINT = pc_count_all_items(chr, item_id);
+ RESULTINT = pc_count_all_items(chr, item.nameid);
return 0;
}
+static int
+fun_is_equipped(env_t *env, int args_nr, val_t *result, val_t *args)
+{
+ character_t *chr = (ETY(0) == BL_PC) ? ARGPC(0) : NULL;
+ int stackable;
+ struct item item;
+ int i;
+ int retval = 0;
+
+ GET_ARG_ITEM(1, item, stackable);
+
+ if (!chr)
+ return 1;
+
+ fprintf(stderr, "Checking for equipped status of item %d\n", item.nameid);
+
+ for (i = 0; i < 11; i++)
+ if (chr->equip_index[i] >= 0
+ && chr->status.inventory[chr->equip_index[i]].nameid == item.nameid) {
+ retval = i + 1;
+ break;
+ }
+
+ RESULTINT = retval;
+ return 0;
+}
static int
fun_is_married(env_t *env, int args_nr, val_t *result, val_t *args)
@@ -885,6 +947,13 @@ fun_element_level(env_t *env, int args_nr, val_t *result, val_t *args)
return 0;
}
+static int
+fun_index(env_t *env, int args_nr, val_t *result, val_t *args)
+{
+ RESULTINT = ARGSPELL(0)->index;
+ return 0;
+}
+
#define BATTLE_RECORD2(sname, name) { sname, "e", 'i', fun_get_##name }
#define BATTLE_RECORD(name) BATTLE_RECORD2(#name, name)
static fun_t functions[] = {
@@ -944,6 +1013,8 @@ static fun_t functions[] = {
{ "element", "e", 'i', fun_element },
{ "element_level", "e", 'i', fun_element_level },
{ "has_shroud", "e", 'i', fun_has_shroud },
+ { "is_equipped", "e.", 'i', fun_is_equipped },
+ { "spell_index", "S", 'i', fun_index },
{ NULL, NULL, '.', NULL }
};
@@ -1167,6 +1238,7 @@ magic_signature_check(char *opname, char *funname, char *signature, int args_nr,
case TY_STRING: stringify(arg, 1); break; /* 100% success rate */
case TY_AREA: make_area(arg); break; /* Only works for locations */
case TY_LOCATION: make_location(arg); break; /* Only works for some areas */
+ case TY_SPELL: make_spell(arg); break; /* Only works for still-active invocatoins */
default: break; /* We'll fail right below */
}
@@ -1241,8 +1313,30 @@ magic_eval(env_t *env, val_t *dest, expr_t *expr)
break;
}
+ case EXPR_SPELLFIELD: {
+ val_t v;
+ int id = expr->e.e_field.id;
+ magic_eval(env, &v, expr->e.e_field.expr);
+
+ if (v.ty == TY_INVOCATION) {
+ invocation_t *t = (invocation_t *) map_id2bl(v.v.v_int);
+
+ if (!t)
+ dest->ty = TY_UNDEF;
+ else {
+ env_t *env = t->env;
+ val_t v = VAR(id);
+ magic_copy_var(dest, &v);
+ }
+ } else {
+ fprintf(stderr, "[magic] Attempt to access field %s on non-spell\n", env->base_env->var_name[id]);
+ dest->ty = TY_FAIL;
+ }
+ break;
+ }
+
default:
- fprintf(stderr, "INTERNAL ERROR: Unknown expression type %d\n", expr->ty);
+ fprintf(stderr, "[magic] INTERNAL ERROR: Unknown expression type %d\n", expr->ty);
break;
}
}