diff options
Diffstat (limited to 'src/map/magic-interpreter.hpp')
-rw-r--r-- | src/map/magic-interpreter.hpp | 708 |
1 files changed, 431 insertions, 277 deletions
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp index 7d529ee..01775b3 100644 --- a/src/map/magic-interpreter.hpp +++ b/src/map/magic-interpreter.hpp @@ -1,5 +1,4 @@ -#ifndef TMWA_MAP_MAGIC_INTERPRETER_HPP -#define TMWA_MAP_MAGIC_INTERPRETER_HPP +#pragma once // magic-interpreter.hpp - Old magic. // // Copyright © 2004-2011 The Mana World Development Team @@ -20,200 +19,356 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. -# include "../sanity.hpp" +#include "fwd.hpp" -# include "magic-interpreter.t.hpp" +#include "magic-interpreter.t.hpp" -# include <cassert> +#include <cassert> -# include "../strings/fwd.hpp" -# include "../strings/rstring.hpp" +#include <memory> -# include "magic.hpp" -# include "map.hpp" -# include "script.hpp" -# include "skill.t.hpp" +#include "../strings/fwd.hpp" +#include "../strings/rstring.hpp" -struct fun_t; -struct op_t; -struct expr_t; -struct val_t; -struct location_t; -struct area_t; -struct spell_t; -struct invocation; +#include "../generic/fwd.hpp" +#include "../sexpr/variant.hpp" + +#include "../net/timer.t.hpp" + +#include "../mmo/ids.hpp" +#include "../mmo/utils.hpp" + +#include "map.hpp" +#include "script.hpp" +#include "skill.t.hpp" + + +namespace tmwa +{ +namespace magic +{ struct location_t { map_local *m; int x, y; }; -struct area_t +struct AreaUnion +{ + dumb_ptr<area_t> a_union[2]; +}; +struct AreaRect +{ + location_t loc; + int width, height; +}; +struct AreaBar +{ + location_t loc; + int width, depth; + DIR dir; +}; + +using AreaVariantBase = Variant< + location_t, + AreaUnion, + AreaRect, + AreaBar +>; + +struct area_t : AreaVariantBase { - union au - { - location_t a_loc; - struct - { - location_t loc; - int width, depth; - DIR dir; - } a_bar; - struct - { - location_t loc; - int width, height; - } a_rect; - dumb_ptr<area_t> a_union[2]; - - au() { really_memzero_this(this); } - ~au() = default; - au(const au&) = default; - au& operator = (const au&) = default; - } a; int size; - AREA ty; + + area_t() = delete; + area_t(area_t&&) = default; + area_t(const area_t&) = delete; + area_t& operator = (area_t&&) = default; + area_t& operator = (const area_t&) = delete; + + area_t(location_t v, int sz) : AreaVariantBase(std::move(v)), size(sz) {} + area_t(AreaUnion v, int sz) : AreaVariantBase(std::move(v)), size(sz) {} + area_t(AreaRect v, int sz) : AreaVariantBase(std::move(v)), size(sz) {} + area_t(AreaBar v, int sz) : AreaVariantBase(std::move(v)), size(sz) {} }; -struct val_t +struct ValUndef +{ +}; +struct ValInt +{ + int v_int; +}; +struct ValDir +{ + DIR v_dir; +}; +struct ValString +{ + dumb_string v_string; +}; +struct ValEntityInt +{ + BlockId v_eid; +}; +struct ValEntityPtr +{ + dumb_ptr<block_list> v_entity; +}; +struct ValLocation +{ + location_t v_location; +}; +struct ValArea +{ + dumb_ptr<area_t> v_area; +}; +struct ValSpell +{ + dumb_ptr<spell_t> v_spell; +}; +struct ValInvocationInt +{ + BlockId v_iid; +}; +struct ValInvocationPtr +{ + dumb_ptr<invocation> v_invocation; +}; +struct ValFail +{ +}; +struct ValNegative1 { - union vu - { - int v_int; - DIR v_dir; - dumb_string v_string; - /* Used ONLY during operation/function invocation; otherwise we use v_int */ - dumb_ptr<block_list> v_entity; - dumb_ptr<area_t> v_area; - location_t v_location; - /* Used ONLY during operation/function invocation; otherwise we use v_int */ - dumb_ptr<invocation> v_invocation; - dumb_ptr<spell_t> v_spell; - - vu() { really_memzero_this(this); } - ~vu() = default; - vu(const vu&) = default; - vu& operator = (const vu&) = default; - } v; - TYPE ty; }; +using ValVariantBase = Variant< + ValUndef, + ValInt, + ValDir, + ValString, + ValEntityInt, + ValEntityPtr, + ValLocation, + ValArea, + ValSpell, + ValInvocationInt, + ValInvocationPtr, + ValFail, + ValNegative1 +>; +struct val_t : ValVariantBase +{ + val_t() noexcept : ValVariantBase(ValUndef{}) {} + val_t(val_t&&) = default; + val_t(const val_t&) = delete; + val_t& operator = (val_t&&) = default; + val_t& operator = (const val_t&) = delete; + + val_t(ValUndef v) : ValVariantBase(std::move(v)) {} + val_t(ValInt v) : ValVariantBase(std::move(v)) {} + val_t(ValDir v) : ValVariantBase(std::move(v)) {} + val_t(ValString v) : ValVariantBase(std::move(v)) {} + val_t(ValEntityInt v) : ValVariantBase(std::move(v)) {} + val_t(ValEntityPtr v) : ValVariantBase(std::move(v)) {} + val_t(ValLocation v) : ValVariantBase(std::move(v)) {} + val_t(ValArea v) : ValVariantBase(std::move(v)) {} + val_t(ValSpell v) : ValVariantBase(std::move(v)) {} + val_t(ValInvocationInt v) : ValVariantBase(std::move(v)) {} + val_t(ValInvocationPtr v) : ValVariantBase(std::move(v)) {} + val_t(ValFail v) : ValVariantBase(std::move(v)) {} + val_t(ValNegative1 v) : ValVariantBase(std::move(v)) {} +}; + + /* ----------- */ /* Expressions */ /* ----------- */ -# define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */ +#define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */ + +struct e_area_t; struct e_location_t { dumb_ptr<expr_t> m, x, y; + + e_location_t() noexcept : m(), x(), y() {} +}; +struct ExprAreaUnion +{ + dumb_ptr<e_area_t> a_union[2]; +}; +struct ExprAreaRect +{ + e_location_t loc; + dumb_ptr<expr_t> width, height; +}; +struct ExprAreaBar +{ + e_location_t loc; + dumb_ptr<expr_t> width, depth, dir; }; -struct e_area_t +using ExprAreaVariantBase = Variant< + e_location_t, + ExprAreaUnion, + ExprAreaRect, + ExprAreaBar +>; + +struct e_area_t : ExprAreaVariantBase { - union a0 - { - e_location_t a_loc; - struct - { - e_location_t loc; - dumb_ptr<expr_t> width, depth, dir; - } a_bar; - struct - { - e_location_t loc; - dumb_ptr<expr_t> width, height; - } a_rect; - dumb_ptr<e_area_t> a_union[2]; - - a0() { really_memzero_this(this); } - ~a0() = default; - a0(const a0&) = default; - a0& operator = (const a0&) = default; - } a; - AREA ty; -}; - -struct expr_t -{ - union eu - { - val_t e_val; - e_location_t e_location; - e_area_t e_area; - struct - { - fun_t *funp; - int line_nr, column; - int args_nr; - dumb_ptr<expr_t> args[MAX_ARGS]; - } e_funapp; - int e_id; - struct - { - dumb_ptr<expr_t> expr; - int id; - } e_field; - - eu() { really_memzero_this(this); } - ~eu() = default; - eu(const eu&) = default; - eu& operator = (const eu&) = default; - } e; - EXPR ty; -}; - -struct effect_t + e_area_t() = delete; + e_area_t(e_area_t&&) = default; + e_area_t(const e_area_t&) = delete; + e_area_t& operator = (e_area_t&&) = default; + e_area_t& operator = (const e_area_t&) = delete; + + e_area_t(e_location_t v) : ExprAreaVariantBase(std::move(v)) {} + e_area_t(ExprAreaUnion v) : ExprAreaVariantBase(std::move(v)) {} + e_area_t(ExprAreaRect v) : ExprAreaVariantBase(std::move(v)) {} + e_area_t(ExprAreaBar v) : ExprAreaVariantBase(std::move(v)) {} +}; + +struct ExprFunApp +{ + fun_t *funp; + int line_nr, column; + int args_nr; + dumb_ptr<expr_t> args[MAX_ARGS]; +}; +struct ExprId +{ + int e_id; +}; +struct ExprField +{ + dumb_ptr<expr_t> expr; + int id; +}; + +using ExprVariantBase = Variant< + val_t, + e_location_t, + e_area_t, + ExprFunApp, + ExprId, + ExprField +>; +struct expr_t : ExprVariantBase +{ + expr_t() = delete; + expr_t(expr_t&&) = default; + expr_t(const expr_t&) = delete; + expr_t& operator = (expr_t&&) = default; + expr_t& operator = (const expr_t&) = delete; + + expr_t(val_t v) : ExprVariantBase(std::move(v)) {} + expr_t(e_location_t v) : ExprVariantBase(std::move(v)) {} + expr_t(e_area_t v) : ExprVariantBase(std::move(v)) {} + expr_t(ExprFunApp v) : ExprVariantBase(std::move(v)) {} + expr_t(ExprId v) : ExprVariantBase(std::move(v)) {} + expr_t(ExprField v) : ExprVariantBase(std::move(v)) {} +}; + + +struct effect_t; + +struct EffectSkip +{ +}; +struct EffectAbort +{ +}; +struct EffectAssign +{ + int id; + dumb_ptr<expr_t> expr; +}; +struct EffectForEach +{ + int id; + dumb_ptr<expr_t> area; + dumb_ptr<effect_t> body; + FOREACH_FILTER filter; +}; +struct EffectFor +{ + int id; + dumb_ptr<expr_t> start, stop; + dumb_ptr<effect_t> body; +}; +struct EffectIf +{ + dumb_ptr<expr_t> cond; + dumb_ptr<effect_t> true_branch, false_branch; +}; +struct EffectSleep +{ + dumb_ptr<expr_t> e_sleep; /* sleep time */ +}; +struct EffectScript +{ + dumb_ptr<const ScriptBuffer> e_script; +}; +struct EffectBreak +{ +}; +struct EffectOp +{ + op_t *opp; + int args_nr; + int line_nr, column; + dumb_ptr<expr_t> args[MAX_ARGS]; +}; +struct EffectEnd +{ +}; +struct EffectCall +{ + std::vector<int> *formalv; + dumb_ptr<std::vector<dumb_ptr<expr_t>>> actualvp; + dumb_ptr<effect_t> body; +}; + +using EffectVariantBase = Variant< + EffectSkip, + EffectAbort, + EffectAssign, + EffectForEach, + EffectFor, + EffectIf, + EffectSleep, + EffectScript, + EffectBreak, + EffectOp, + EffectEnd, + EffectCall +>; +struct effect_t : EffectVariantBase { dumb_ptr<effect_t> next; - union e0 - { - struct - { - int id; - dumb_ptr<expr_t> expr; - } e_assign; - struct - { - int id; - dumb_ptr<expr_t> area; - dumb_ptr<effect_t> body; - FOREACH_FILTER filter; - } e_foreach; - struct - { - int id; - dumb_ptr<expr_t> start, stop; - dumb_ptr<effect_t> body; - } e_for; - struct - { - dumb_ptr<expr_t> cond; - dumb_ptr<effect_t> true_branch, false_branch; - } e_if; - dumb_ptr<expr_t> e_sleep; /* sleep time */ - dumb_ptr<const ScriptBuffer> e_script; - struct - { - op_t *opp; - int args_nr; - int line_nr, column; - dumb_ptr<expr_t> args[MAX_ARGS]; - } e_op; - struct - { - std::vector<int> *formalv; - dumb_ptr<std::vector<dumb_ptr<expr_t>>> actualvp; - dumb_ptr<effect_t> body; - } e_call; - - e0() { really_memzero_this(this); } - ~e0() = default; - e0(const e0&) = default; - e0& operator = (const e0&) = default; - } e; - EFFECT ty; + + effect_t() = delete; + effect_t(effect_t&&) = default; + effect_t(const effect_t&) = delete; + effect_t& operator = (effect_t&&) = default; + effect_t& operator = (const effect_t&) = delete; + + effect_t(EffectSkip v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectAbort v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectAssign v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectForEach v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectFor v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectIf v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectSleep v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectScript v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectBreak v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectOp v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectEnd v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} + effect_t(EffectCall v, dumb_ptr<effect_t> n) : EffectVariantBase(std::move(v)), next(n) {} }; /* ---------- */ @@ -223,34 +378,67 @@ struct effect_t struct component_t { dumb_ptr<component_t> next; - int item_id; + ItemNameId item_id; int count; }; +struct spellguard_t; +struct GuardCondition +{ + dumb_ptr<expr_t> s_condition; +}; +struct GuardMana +{ + dumb_ptr<expr_t> s_mana; +}; +struct GuardCastTime +{ + dumb_ptr<expr_t> s_casttime; +}; +struct GuardComponents +{ + dumb_ptr<component_t> s_components; +}; +struct GuardCatalysts +{ + dumb_ptr<component_t> s_catalysts; +}; +struct GuardChoice +{ + dumb_ptr<spellguard_t> s_alt; /* either `next' or `s.s_alt' */ +}; struct effect_set_t { dumb_ptr<effect_t> effect, at_trigger, at_end; }; -struct spellguard_t +using SpellGuardVariantBase = Variant< + GuardCondition, + GuardMana, + GuardCastTime, + GuardComponents, + GuardCatalysts, + GuardChoice, + effect_set_t +>; +struct spellguard_t : SpellGuardVariantBase { dumb_ptr<spellguard_t> next; - union su - { - dumb_ptr<expr_t> s_condition; - dumb_ptr<expr_t> s_mana; - dumb_ptr<expr_t> s_casttime; - dumb_ptr<component_t> s_components; - dumb_ptr<component_t> s_catalysts; - dumb_ptr<spellguard_t> s_alt; /* either `next' or `s.s_alt' */ - effect_set_t s_effect; - su() { really_memzero_this(this); } - ~su() = default; - su(const su&) = default; - su& operator = (const su&) = default; - } s; - SPELLGUARD ty; + + spellguard_t() = delete; + spellguard_t(spellguard_t&&) = default; + spellguard_t(const spellguard_t&) = delete; + spellguard_t& operator = (spellguard_t&&) = default; + spellguard_t& operator = (const spellguard_t&) = delete; + + spellguard_t(GuardCondition v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(GuardMana v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(GuardCastTime v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(GuardComponents v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(GuardCatalysts v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(GuardChoice v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} + spellguard_t(effect_set_t v, dumb_ptr<spellguard_t> n) : SpellGuardVariantBase(std::move(v)), next(n) {} }; /* ------ */ @@ -309,17 +497,15 @@ struct magic_conf_t /* Execution environment */ // these are not an enum they're a nasty intern hack -# define VAR_MIN_CASTTIME 0 -# define VAR_OBSCURE_CHANCE 1 -# define VAR_CASTER 2 -# define VAR_SPELLPOWER 3 -# define VAR_SPELL 4 -# define VAR_INVOCATION 5 -# define VAR_TARGET 6 -# define VAR_SCRIPTTARGET 7 -# define VAR_LOCATION 8 - -struct magic_config; +#define VAR_MIN_CASTTIME 0 +#define VAR_OBSCURE_CHANCE 1 +#define VAR_CASTER 2 +#define VAR_SPELLPOWER 3 +#define VAR_SPELL 4 +#define VAR_INVOCATION 5 +#define VAR_TARGET 6 +#define VAR_SCRIPTTARGET 7 +#define VAR_LOCATION 8 struct env_t { @@ -329,7 +515,7 @@ struct env_t val_t& VAR(size_t i) { assert (varu); - if (varu[i].ty == TYPE::UNDEF) + if (varu[i].is<ValUndef>()) return base_env->varv[i].val; else return varu[i]; @@ -337,47 +523,53 @@ struct env_t }; -# define MAX_STACK_SIZE 32 +struct CarForEach +{ + int id; + bool ty_is_spell_not_entity; + dumb_ptr<effect_t> body; + dumb_ptr<std::vector<BlockId>> entities_vp; + int index; +}; +struct CarFor +{ + int id; + dumb_ptr<effect_t> body; + int current; + int stop; +}; +struct CarProc +{ + int args_nr; + int *formalap; + dumb_ptr<val_t[]> old_actualpa; +}; -struct cont_activation_record_t +using CarVariantBase = Variant< + CarForEach, + CarFor, + CarProc +>; + +struct cont_activation_record_t : CarVariantBase { dumb_ptr<effect_t> return_location; - union cu - { - struct - { - int id; - TYPE ty; - dumb_ptr<effect_t> body; - dumb_ptr<std::vector<int>> entities_vp; - int index; - } c_foreach; - struct - { - int id; - dumb_ptr<effect_t> body; - int current; - int stop; - } c_for; - struct - { - int args_nr; - int *formalap; - dumb_ptr<val_t[]> old_actualpa; - } c_proc; - - cu() { really_memzero_this(this); } - ~cu() = default; - cu(const cu&) = default; - cu& operator = (const cu&) = default; - } c; - CONT_STACK ty; + + cont_activation_record_t() = delete; + cont_activation_record_t(cont_activation_record_t&&) = default; + cont_activation_record_t(const cont_activation_record_t&) = delete; + cont_activation_record_t& operator = (cont_activation_record_t&&) = default; + cont_activation_record_t& operator = (const cont_activation_record_t&) = delete; + + cont_activation_record_t(CarForEach v, dumb_ptr<effect_t> rl) : CarVariantBase(std::move(v)), return_location(rl) {} + cont_activation_record_t(CarFor v, dumb_ptr<effect_t> rl) : CarVariantBase(std::move(v)), return_location(rl) {} + cont_activation_record_t(CarProc v, dumb_ptr<effect_t> rl) : CarVariantBase(std::move(v)), return_location(rl) {} }; struct status_change_ref_t { StatusChange sc_type; - int bl_id; + BlockId bl_id; }; struct invocation : block_list @@ -387,66 +579,30 @@ struct invocation : block_list dumb_ptr<env_t> env; dumb_ptr<spell_t> spell; - int caster; /* this is the person who originally invoked the spell */ - int subject; /* when this person dies, the spell dies with it */ + BlockId caster; /* this is the person who originally invoked the spell */ + BlockId subject; /* when this person dies, the spell dies with it */ Timer timer; /* spell timer, if any */ - int stack_size; - cont_activation_record_t stack[MAX_STACK_SIZE]; + std::vector<cont_activation_record_t> stack; int script_pos; /* Script position; if nonzero, resume the script we were running. */ dumb_ptr<effect_t> current_effect; - dumb_ptr<effect_t> trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */ - dumb_ptr<effect_t> end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ + dumb_ptr<effect_t> trigger_effect; /* If non-nullptr, this is used to spawn a cloned effect based on the same environment */ + dumb_ptr<effect_t> end_effect; /* If non-nullptr, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ /* Status change references: for status change updates, keep track of whom we updated where */ std::vector<status_change_ref_t> status_change_refv; }; +} // namespace magic -inline dumb_ptr<invocation> block_list::as_spell() { return dumb_ptr<invocation>(static_cast<invocation *>(this)); } -inline dumb_ptr<invocation> block_list::is_spell() { return bl_type == BL::SPELL ? as_spell() : nullptr; } - -extern magic_conf_t magic_conf; /* Global magic conf */ -extern env_t magic_default_env; /* Fake default environment */ - -/** - * Adds a component selection to a component holder (which may initially be NULL) - */ -void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count); - -dumb_ptr<teleport_anchor_t> magic_find_anchor(XString name); - -dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, - dumb_ptr<map_session_data> caster, int spellpower, XString param); - -void magic_free_env(dumb_ptr<env_t> env); - -/** - * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components) - */ -effect_set_t *spell_trigger(dumb_ptr<spell_t> spell, - dumb_ptr<map_session_data> caster, - dumb_ptr<env_t> env, int *near_miss); - -dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, dumb_ptr<env_t> env); - -/** - * Bind a spell to a subject (this is a no-op for `local' spells). - */ -void spell_bind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); - -// 1 on failure -int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation); - -/** - * Clones a spell to run the at_effect field - */ -dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source); - -dumb_ptr<spell_t> magic_find_spell(XString invocation); +// inlines for map.hpp +inline dumb_ptr<magic::invocation> block_list::as_spell() { return dumb_ptr<magic::invocation>(static_cast<magic::invocation *>(this)); } +inline dumb_ptr<magic::invocation> block_list::is_spell() { return bl_type == BL::SPELL ? as_spell() : nullptr; } +namespace magic +{ /* The following is used only by the parser: */ struct args_rec_t { @@ -465,7 +621,5 @@ struct proc_t , body() {} }; - -void spell_update_location(dumb_ptr<invocation> invocation); - -#endif // TMWA_MAP_MAGIC_INTERPRETER_HPP +} // namespace magic +} // namespace tmwa |