summaryrefslogtreecommitdiff
path: root/src/map/magic-stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/magic-stmt.cpp')
-rw-r--r--src/map/magic-stmt.cpp512
1 files changed, 200 insertions, 312 deletions
diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp
index 28bcbe8..fd02d45 100644
--- a/src/map/magic-stmt.cpp
+++ b/src/map/magic-stmt.cpp
@@ -55,61 +55,19 @@ namespace magic
/* used for local spell effects */
constexpr Species INVISIBLE_NPC = wrap<Species>(127);
-//#define DEBUG
-
-#ifdef DEBUG
-static
-void print_val(val_t *v)
-{
- switch (v->ty)
- {
- case TYPE::UNDEF:
- FPRINTF(stderr, "UNDEF"_fmt);
- break;
- case TYPE::INT:
- FPRINTF(stderr, "%d"_fmt, v->v.v_int);
- break;
- case TYPE::DIR:
- FPRINTF(stderr, "dir%d"_fmt, v->v.v_int);
- break;
- case TYPE::STRING:
- FPRINTF(stderr, "`%s'"_fmt, v->v.v_string);
- break;
- default:
- FPRINTF(stderr, "ty%d"_fmt, v->ty);
- break;
- }
-}
-
-static
-void dump_env(env_t *env)
-{
- int i;
- for (i = 0; i < env->base_env->vars_nr; i++)
- {
- val_t *v = &env->vars[i];
- val_t *bv = &env->base_env->vars[i];
-
- FPRINTF(stderr, "%02x %30s "_fmt, i, env->base_env->var_name[i]);
- print_val(v);
- FPRINTF(stderr, "\t("_fmt);
- print_val(bv);
- FPRINTF(stderr, ")\n"_fmt);
- }
-}
-#endif
-
static
void clear_activation_record(cont_activation_record_t *ar)
{
- switch (ar->ty)
+ MATCH (*ar)
{
- case CONT_STACK::FOREACH:
- ar->c.c_foreach.entities_vp.delete_();
- break;
- case CONT_STACK::PROC:
- ar->c.c_proc.old_actualpa.delete_();
- break;
+ CASE (CarForEach&, c_foreach)
+ {
+ c_foreach.entities_vp.delete_();
+ }
+ CASE (CarProc&, c_proc)
+ {
+ c_proc.old_actualpa.delete_();
+ }
}
}
@@ -129,10 +87,10 @@ void clear_stack(dumb_ptr<invocation> invocation_)
{
int i;
- for (i = 0; i < invocation_->stack_size; i++)
+ for (i = 0; i < invocation_->stack.size(); i++)
clear_activation_record(&invocation_->stack[i]);
- invocation_->stack_size = 0;
+ invocation_->stack.clear();
}
void spell_free_invocation(dumb_ptr<invocation> invocation_)
@@ -254,8 +212,7 @@ BlockId trigger_spell(BlockId subject, BlockId spell)
spell_bind(map_id_is_player(subject), invocation_);
magic_clear_var(&invocation_->env->varu[VAR_CASTER]);
- invocation_->env->varu[VAR_CASTER].ty = TYPE::ENTITY;
- invocation_->env->varu[VAR_CASTER].v.v_int = static_cast<int32_t>(unwrap<BlockId>(subject));
+ invocation_->env->varu[VAR_CASTER] = ValEntityInt{subject};
return invocation_->bl_id;
}
@@ -327,11 +284,11 @@ int op_sfx(dumb_ptr<env_t>, Slice<val_t> args)
{
interval_t delay = static_cast<interval_t>(ARGINT(2));
- if (ARG_TYPE(0) == TYPE::ENTITY)
+ if (args[0].is<ValEntityPtr>())
{
entity_effect(ARGENTITY(0), ARGINT(1), delay);
}
- else if (ARG_TYPE(0) == TYPE::LOCATION)
+ else if (args[0].is<ValLocation>())
{
local_spell_effect(ARGLOCATION(0).m,
ARGLOCATION(0).x,
@@ -346,8 +303,10 @@ int op_sfx(dumb_ptr<env_t>, Slice<val_t> args)
static
int op_instaheal(dumb_ptr<env_t> env, Slice<val_t> args)
{
- dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY)
- ? map_id2bl(wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_CASTER).v.v_int))) : nullptr;
+ assert (!env->VAR(VAR_CASTER).is<ValEntityPtr>());
+ ValEntityInt *caster_id = env->VAR(VAR_CASTER).get_if<ValEntityInt>();
+ dumb_ptr<block_list> caster = caster_id
+ ? map_id2bl(caster_id->v_eid) : nullptr;
dumb_ptr<block_list> subject = ARGENTITY(0);
if (!caster)
caster = subject;
@@ -557,8 +516,10 @@ static
int op_status_change(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
- BlockId invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION
- ? wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int)) : BlockId();
+ assert (!env->VAR(VAR_INVOCATION).is<ValInvocationPtr>());
+ ValInvocationInt *ii = env->VAR(VAR_INVOCATION).get_if<ValInvocationInt>();
+ BlockId invocation_id = ii
+ ? ii->v_iid : BlockId();
dumb_ptr<invocation> invocation_ = map_id_is_spell(invocation_id);
assert (!ARGINT(3));
@@ -609,8 +570,9 @@ int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args)
spell_free_invocation(old_invocation);
}
+ ValInvocationInt *ii = env->VAR(VAR_INVOCATION).get_if<ValInvocationInt>();
subject->attack_spell_override =
- trigger_spell(subject->bl_id, wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int)));
+ trigger_spell(subject->bl_id, ii->v_iid);
subject->attack_spell_charges = charges;
if (subject->attack_spell_override)
@@ -778,11 +740,14 @@ int op_spawn(dumb_ptr<env_t>, Slice<val_t> args)
static
ZString get_invocation_name(dumb_ptr<env_t> env)
{
- dumb_ptr<invocation> invocation_;
+ assert (!env->VAR(VAR_INVOCATION).is<ValInvocationPtr>());
- if (env->VAR(VAR_INVOCATION).ty != TYPE::INVOCATION)
+ ValInvocationInt *ii = env->VAR(VAR_INVOCATION).get_if<ValInvocationInt>();
+ if (!ii)
return "?"_s;
- invocation_ = map_id_is_spell(wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_INVOCATION).v.v_int)));
+
+ dumb_ptr<invocation> invocation_;
+ invocation_ = map_id_is_spell(ii->v_iid);
if (invocation_)
return invocation_->spell->name;
@@ -945,7 +910,7 @@ int op_gain_exp(dumb_ptr<env_t>, Slice<val_t> args)
return 1;
pc_gainexp_reason(c, ARGINT(1), ARGINT(2),
- PC_GAINEXP_REASON(ARGINT(3)));
+ static_cast<PC_GAINEXP_REASON>(ARGINT(3)));
return 0;
}
@@ -1024,109 +989,84 @@ void spell_effect_report_termination(BlockId invocation_id, BlockId bl_id,
static
dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_)
{
- if (!invocation_->stack_size)
+ if (invocation_->stack.empty())
return nullptr;
else
{
cont_activation_record_t *ar =
- invocation_->stack + (invocation_->stack_size - 1);
- switch (ar->ty)
+ &invocation_->stack.back();
+ MATCH (*ar)
{
- case CONT_STACK::PROC:
+ CASE (const CarProc&, c_proc)
{
dumb_ptr<effect_t> ret = ar->return_location;
- for (int i = 0; i < ar->c.c_proc.args_nr; i++)
+ for (int i = 0; i < c_proc.args_nr; i++)
{
val_t *var =
- &invocation_->env->varu[ar->c.c_proc.formalap[i]];
+ &invocation_->env->varu[c_proc.formalap[i]];
magic_clear_var(var);
- *var = ar->c.c_proc.old_actualpa[i];
+ *var = std::move(c_proc.old_actualpa[i]);
}
// pop the stack
clear_activation_record(ar);
- --invocation_->stack_size;
+ invocation_->stack.pop_back();
return ret;
}
-
- case CONT_STACK::FOREACH:
+ CASE (CarForEach&, c_foreach)
{
BlockId entity_id;
- val_t *var = &invocation_->env->varu[ar->c.c_foreach.id];
+ val_t *var = &invocation_->env->varu[c_foreach.id];
do
{
// This >= is really supposed to be a ==, but
// I have no clue if it's actually safe to change it.
- if (ar->c.c_foreach.index >= ar->c.c_foreach.entities_vp->size())
+ if (c_foreach.index >= c_foreach.entities_vp->size())
{
// pop the stack
dumb_ptr<effect_t> ret = ar->return_location;
clear_activation_record(ar);
- --invocation_->stack_size;
+ invocation_->stack.pop_back();
return ret;
}
entity_id =
- (*ar->c.c_foreach.entities_vp)[ar->c.c_foreach.index++];
+ (*c_foreach.entities_vp)[c_foreach.index++];
}
while (!entity_id || !map_id2bl(entity_id));
magic_clear_var(var);
- var->ty = ar->c.c_foreach.ty;
- var->v.v_int = static_cast<int32_t>(unwrap<BlockId>(entity_id));
+ if (c_foreach.ty_is_spell_not_entity)
+ *var = ValInvocationInt{entity_id};
+ else
+ *var = ValEntityInt{entity_id};
- return ar->c.c_foreach.body;
+ return c_foreach.body;
}
-
- case CONT_STACK::FOR:
- if (ar->c.c_for.current > ar->c.c_for.stop)
+ CASE (CarFor&, c_for)
+ {
+ if (c_for.current > c_for.stop)
{
dumb_ptr<effect_t> ret = ar->return_location;
// pop the stack
clear_activation_record(ar);
- --invocation_->stack_size;
+ invocation_->stack.pop_back();
return ret;
}
- magic_clear_var(&invocation_->env->varu[ar->c.c_for.id]);
- invocation_->env->varu[ar->c.c_for.id].ty = TYPE::INT;
- invocation_->env->varu[ar->c.c_for.id].v.v_int =
- ar->c.c_for.current++;
+ magic_clear_var(&invocation_->env->varu[c_for.id]);
+ invocation_->env->varu[c_for.id] = ValInt{c_for.current++};
- return ar->c.c_for.body;
-
- default:
- FPRINTF(stderr,
- "[magic] INTERNAL ERROR: While executing spell `%s': stack corruption\n"_fmt,
- invocation_->spell->name);
- return nullptr;
+ return c_for.body;
+ }
}
+ abort();
}
}
static
-cont_activation_record_t *add_stack_entry(dumb_ptr<invocation> invocation_,
- CONT_STACK ty, dumb_ptr<effect_t> return_location)
-{
- cont_activation_record_t *ar =
- invocation_->stack + invocation_->stack_size++;
- if (invocation_->stack_size >= MAX_STACK_SIZE)
- {
- FPRINTF(stderr,
- "[magic] Execution stack size exceeded in spell `%s'; truncating effect\n"_fmt,
- invocation_->spell->name);
- invocation_->stack_size--;
- return nullptr;
- }
-
- ar->ty = ty;
- ar->return_location = return_location;
- return ar;
-}
-
-static
void find_entities_in_area_c(dumb_ptr<block_list> target,
std::vector<BlockId> *entities_vp,
FOREACH_FILTER filter)
@@ -1193,19 +1133,46 @@ void find_entities_in_area(area_t& area_,
std::vector<BlockId> *entities_vp,
FOREACH_FILTER filter)
{
- area_t *area = &area_; // temporary hack to "keep diff small". Heh.
- switch (area->ty)
+ MATCH (area_)
{
- case AREA::UNION:
- find_entities_in_area(*area->a.a_union[0], entities_vp, filter);
- find_entities_in_area(*area->a.a_union[1], entities_vp, filter);
- break;
-
- default:
+ CASE (const AreaUnion&, a)
+ {
+ find_entities_in_area(*a.a_union[0], entities_vp, filter);
+ find_entities_in_area(*a.a_union[1], entities_vp, filter);
+ }
+ CASE (const location_t&, a_loc)
{
+ (void)a_loc;
+ // TODO this can be simplified
map_local *m;
int x, y, width, height;
- magic_area_rect(&m, &x, &y, &width, &height, *area);
+ magic_area_rect(&m, &x, &y, &width, &height, area_);
+ map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter),
+ m,
+ x, y,
+ x + width, y + height,
+ BL::NUL /* filter elsewhere */);
+ }
+ CASE (const AreaRect&, a_rect)
+ {
+ (void)a_rect;
+ // TODO this can be simplified
+ map_local *m;
+ int x, y, width, height;
+ magic_area_rect(&m, &x, &y, &width, &height, area_);
+ map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter),
+ m,
+ x, y,
+ x + width, y + height,
+ BL::NUL /* filter elsewhere */);
+ }
+ CASE (const AreaBar&, a_bar)
+ {
+ (void)a_bar;
+ // TODO this is wrong
+ map_local *m;
+ int x, y, width, height;
+ magic_area_rect(&m, &x, &y, &width, &height, area_);
map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter),
m,
x, y,
@@ -1217,17 +1184,20 @@ void find_entities_in_area(area_t& area_,
static
dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation,
- dumb_ptr<effect_t> foreach,
+ const EffectForEach *foreach,
dumb_ptr<effect_t> return_location)
{
+ const EffectForEach& e_foreach = *foreach;
+
val_t area;
- FOREACH_FILTER filter = foreach->e.e_foreach.filter;
- int id = foreach->e.e_foreach.id;
- dumb_ptr<effect_t> body = foreach->e.e_foreach.body;
+ FOREACH_FILTER filter = e_foreach.filter;
+ int id = e_foreach.id;
+ dumb_ptr<effect_t> body = e_foreach.body;
- magic_eval(invocation->env, &area, foreach->e.e_foreach.area);
+ magic_eval(invocation->env, &area, e_foreach.area);
- if (area.ty != TYPE::AREA)
+ auto va = area.get_if<ValArea>();
+ if (!va)
{
magic_clear_var(&area);
FPRINTF(stderr,
@@ -1235,27 +1205,23 @@ dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation,
invocation->spell->name);
return return_location;
}
- else
- {
- cont_activation_record_t *ar =
- add_stack_entry(invocation, CONT_STACK::FOREACH, return_location);
-
- if (!ar)
- return return_location;
+ {
std::vector<BlockId> entities_v;
- find_entities_in_area(*area.v.v_area,
+ find_entities_in_area(*va->v_area,
&entities_v, filter);
entities_v.shrink_to_fit();
// iterator_pair will go away when this gets properly containerized.
random_::shuffle(entities_v);
- ar->c.c_foreach.id = id;
- ar->c.c_foreach.body = body;
- ar->c.c_foreach.index = 0;
- ar->c.c_foreach.entities_vp.new_(std::move(entities_v));
- ar->c.c_foreach.ty =
- (filter == FOREACH_FILTER::SPELL) ? TYPE::INVOCATION : TYPE::ENTITY;
+ CarForEach c_foreach;
+ c_foreach.id = id;
+ c_foreach.body = body;
+ c_foreach.index = 0;
+ c_foreach.entities_vp.new_(std::move(entities_v));
+ c_foreach.ty_is_spell_not_entity =
+ (filter == FOREACH_FILTER::SPELL);
+ invocation->stack.emplace_back(c_foreach, return_location);
magic_clear_var(&area);
@@ -1265,18 +1231,19 @@ dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation,
static
dumb_ptr<effect_t> run_for (dumb_ptr<invocation> invocation,
- dumb_ptr<effect_t> for_,
+ const EffectFor *for_,
dumb_ptr<effect_t> return_location)
{
- cont_activation_record_t *ar;
- int id = for_->e.e_for.id;
+ const EffectFor& e_for = *for_;
+
+ int id = e_for.id;
val_t start;
val_t stop;
- magic_eval(invocation->env, &start, for_->e.e_for.start);
- magic_eval(invocation->env, &stop, for_->e.e_for.stop);
+ magic_eval(invocation->env, &start, e_for.start);
+ magic_eval(invocation->env, &stop, e_for.stop);
- if (start.ty != TYPE::INT || stop.ty != TYPE::INT)
+ if (!start.is<ValInt>() || !stop.is<ValInt>())
{
magic_clear_var(&start);
magic_clear_var(&stop);
@@ -1286,109 +1253,44 @@ dumb_ptr<effect_t> run_for (dumb_ptr<invocation> invocation,
return return_location;
}
- ar = add_stack_entry(invocation, CONT_STACK::FOR, return_location);
-
- if (!ar)
- return return_location;
+ CarFor c_for;
- ar->c.c_for.id = id;
- ar->c.c_for.current = start.v.v_int;
- ar->c.c_for.stop = stop.v.v_int;
- ar->c.c_for.body = for_->e.e_for.body;
+ c_for.id = id;
+ c_for.current = start.get_if<ValInt>()->v_int;
+ c_for.stop = stop.get_if<ValInt>()->v_int;
+ c_for.body = e_for.body;
+ invocation->stack.emplace_back(c_for, return_location);
return return_to_stack(invocation);
}
static
dumb_ptr<effect_t> run_call(dumb_ptr<invocation> invocation,
+ const EffectCall *call,
dumb_ptr<effect_t> return_location)
{
- dumb_ptr<effect_t> current = invocation->current_effect;
- cont_activation_record_t *ar;
- int args_nr = current->e.e_call.formalv->size();
- int *formals = current->e.e_call.formalv->data();
+ const EffectCall& e_call = *call;
+
+ int args_nr = e_call.formalv->size();
+ int *formals = e_call.formalv->data();
auto old_actuals = dumb_ptr<val_t[]>::make(args_nr);
- ar = add_stack_entry(invocation, CONT_STACK::PROC, return_location);
- ar->c.c_proc.args_nr = args_nr;
- ar->c.c_proc.formalap = formals;
- ar->c.c_proc.old_actualpa = old_actuals;
+ CarProc c_proc;
+ c_proc.args_nr = args_nr;
+ c_proc.formalap = formals;
+ c_proc.old_actualpa = old_actuals;
+ invocation->stack.emplace_back(c_proc, return_location);
+
for (int i = 0; i < args_nr; i++)
{
val_t *env_val = &invocation->env->varu[formals[i]];
magic_copy_var(&old_actuals[i], env_val);
- magic_eval(invocation->env, env_val, (*current->e.e_call.actualvp)[i]);
+ magic_eval(invocation->env, env_val, (*e_call.actualvp)[i]);
}
- return current->e.e_call.body;
+ return e_call.body;
}
-#ifdef DEBUG
-static
-void print_cfg(int i, effect_t *e)
-{
- int j;
- for (j = 0; j < i; j++)
- PRINTF(" "_fmt);
-
- PRINTF("%p: "_fmt, e);
-
- if (!e)
- {
- puts(" -- end --");
- return;
- }
-
- switch (e->ty)
- {
- case EFFECT::SKIP:
- puts("SKIP");
- break;
- case EFFECT::END:
- puts("END");
- break;
- case EFFECT::ABORT:
- puts("ABORT");
- break;
- case EFFECT::ASSIGN:
- puts("ASSIGN");
- break;
- case EFFECT::FOREACH:
- puts("FOREACH");
- print_cfg(i + 1, e->e.e_foreach.body);
- break;
- case EFFECT::FOR:
- puts("FOR");
- print_cfg(i + 1, e->e.e_for.body);
- break;
- case EFFECT::IF:
- puts("IF");
- for (j = 0; j < i; j++)
- PRINTF(" "_fmt);
- puts("THEN");
- print_cfg(i + 1, e->e.e_if.true_branch);
- for (j = 0; j < i; j++)
- PRINTF(" "_fmt);
- puts("ELSE");
- print_cfg(i + 1, e->e.e_if.false_branch);
- break;
- case EFFECT::SLEEP:
- puts("SLEEP");
- break;
- case EFFECT::SCRIPT:
- puts("NpcSubtype::SCRIPT");
- break;
- case EFFECT::BREAK:
- puts("BREAK");
- break;
- case EFFECT::OP:
- puts("OP");
- break;
- }
- print_cfg(i, e->next);
-}
-#endif
-
/**
* Execute a spell invocation until we abort, finish, or hit the next `sleep'.
*
@@ -1404,83 +1306,77 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
const BlockId invocation_id = invocation_->bl_id;
#define REFRESH_INVOCATION invocation_ = map_id_is_spell(invocation_id); if (!invocation_) return interval_t::zero();
-#ifdef DEBUG
- FPRINTF(stderr, "Resuming execution: invocation of `%s'\n"_fmt,
- invocation_->spell->name);
- print_cfg(1, invocation_->current_effect);
-#endif
while (invocation_->current_effect)
{
dumb_ptr<effect_t> e = invocation_->current_effect;
dumb_ptr<effect_t> next = e->next;
int i;
-#ifdef DEBUG
- FPRINTF(stderr, "Next step of type %d\n"_fmt, e->ty);
- dump_env(invocation_->env);
-#endif
-
- switch (e->ty)
+ MATCH (*e)
{
- case EFFECT::SKIP:
- break;
-
- case EFFECT::ABORT:
+ CASE (const EffectSkip&, e_)
+ {
+ (void)e_;
+ }
+ CASE (const EffectAbort&, e_)
+ {
+ (void)e_;
invocation_->flags |= INVOCATION_FLAG::ABORTED;
invocation_->end_effect = nullptr;
- FALLTHROUGH;
- case EFFECT::END:
clear_stack(invocation_);
next = nullptr;
- break;
-
- case EFFECT::ASSIGN:
+ }
+ CASE (const EffectEnd&, e_)
+ {
+ (void)e_;
+ clear_stack(invocation_);
+ next = nullptr;
+ }
+ CASE (const EffectAssign&, e_assign)
+ {
magic_eval(invocation_->env,
- &invocation_->env->varu[e->e.e_assign.id],
- e->e.e_assign.expr);
- break;
-
- case EFFECT::FOREACH:
- next = run_foreach(invocation_, e, next);
- break;
-
- case EFFECT::FOR:
- next = run_for (invocation_, e, next);
- break;
-
- case EFFECT::IF:
- if (magic_eval_int(invocation_->env, e->e.e_if.cond))
- next = e->e.e_if.true_branch;
+ &invocation_->env->varu[e_assign.id],
+ e_assign.expr);
+ }
+ CASE (const EffectForEach&, e_foreach)
+ {
+ next = run_foreach(invocation_, &e_foreach, next);
+ }
+ CASE (const EffectFor&, e_for)
+ {
+ next = run_for (invocation_, &e_for, next);
+ }
+ CASE (const EffectIf&, e_if)
+ {
+ if (magic_eval_int(invocation_->env, e_if.cond))
+ next = e_if.true_branch;
else
- next = e->e.e_if.false_branch;
- break;
-
- case EFFECT::SLEEP:
+ next = e_if.false_branch;
+ }
+ CASE (const EffectSleep&, e_)
{
interval_t sleeptime = static_cast<interval_t>(
- magic_eval_int(invocation_->env, e->e.e_sleep));
+ magic_eval_int(invocation_->env, e_.e_sleep));
invocation_->current_effect = next;
if (sleeptime > interval_t::zero())
return sleeptime;
- break;
}
-
- case EFFECT::SCRIPT:
+ CASE (const EffectScript&, e_)
{
dumb_ptr<map_session_data> caster = map_id_is_player(invocation_->caster);
if (caster)
{
dumb_ptr<env_t> env = invocation_->env;
ZString caster_name = (caster ? caster->status_key.name : CharName()).to__actual();
- argrec_t arg[3] =
+ argrec_t arg[1] =
{
- {"@target"_s, env->VAR(VAR_TARGET).ty == TYPE::ENTITY ? 0 : env->VAR(VAR_TARGET).v.v_int},
- {"@caster"_s, static_cast<int32_t>(unwrap<BlockId>(invocation_->caster))},
{"@caster_name$"_s, caster_name},
};
+ assert (!env->VAR(VAR_SCRIPTTARGET).is<ValEntityPtr>());
+ ValEntityInt *ei = env->VAR(VAR_SCRIPTTARGET).get_if<ValEntityInt>();
BlockId message_recipient =
- env->VAR(VAR_SCRIPTTARGET).ty == TYPE::ENTITY
- ? wrap<BlockId>(static_cast<uint32_t>(env->VAR(VAR_SCRIPTTARGET).v.v_int))
+ ei
+ ? ei->v_eid
: invocation_->caster;
dumb_ptr<map_session_data> recipient = map_id_is_player(message_recipient);
@@ -1495,7 +1391,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
// dealing with an NPC
int newpos = run_script_l(
- ScriptPointer(&*e->e.e_script, invocation_->script_pos),
+ ScriptPointer(&*e_.e_script, invocation_->script_pos),
message_recipient, invocation_->bl_id,
arg);
/* Returns the new script position, or -1 once the script is finished */
@@ -1511,42 +1407,35 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
clif_clearchar_id(invocation_->bl_id, BeingRemoveWhy::DEAD, caster->sess);
}
REFRESH_INVOCATION; // Script may have killed the caster
- break;
}
-
- case EFFECT::BREAK:
+ CASE (const EffectBreak&, e_)
+ {
+ (void)e_;
next = return_to_stack(invocation_);
- break;
-
- case EFFECT::OP:
+ }
+ CASE (const EffectOp&, e_op)
{
- op_t *op = e->e.e_op.opp;
+ op_t *op = e_op.opp;
val_t args[MAX_ARGS];
- for (i = 0; i < e->e.e_op.args_nr; i++)
- magic_eval(invocation_->env, &args[i], e->e.e_op.args[i]);
+ for (i = 0; i < e_op.args_nr; i++)
+ magic_eval(invocation_->env, &args[i], e_op.args[i]);
if (!magic_signature_check("effect"_s, op->name, op->signature,
- Slice<val_t>(args, e->e.e_op.args_nr),
- e->e.e_op.line_nr,
- e->e.e_op.column))
- op->op(invocation_->env, Slice<val_t>(args, e->e.e_op.args_nr));
+ Slice<val_t>(args, e_op.args_nr),
+ e_op.line_nr,
+ e_op.column))
+ op->op(invocation_->env, Slice<val_t>(args, e_op.args_nr));
- for (i = 0; i < e->e.e_op.args_nr; i++)
+ for (i = 0; i < e_op.args_nr; i++)
magic_clear_var(&args[i]);
REFRESH_INVOCATION; // Effect may have killed the caster
- break;
}
-
- case EFFECT::CALL:
- next = run_call(invocation_, next);
- break;
-
- default:
- FPRINTF(stderr,
- "[magic] INTERNAL ERROR: Unknown effect %d\n"_fmt,
- e->ty);
+ CASE (const EffectCall&, e_call)
+ {
+ next = run_call(invocation_, &e_call, next);
+ }
}
if (!next)
@@ -1610,8 +1499,7 @@ int spell_attack(BlockId caster_id, BlockId target_id)
if (invocation_ && caster->attack_spell_charges > 0)
{
magic_clear_var(&invocation_->env->varu[VAR_TARGET]);
- invocation_->env->varu[VAR_TARGET].ty = TYPE::ENTITY;
- invocation_->env->varu[VAR_TARGET].v.v_int = static_cast<int32_t>(unwrap<BlockId>(target_id));
+ invocation_->env->varu[VAR_TARGET] = ValEntityInt{target_id};
invocation_->current_effect = invocation_->trigger_effect;
invocation_->flags &= ~INVOCATION_FLAG::ABORTED;