summaryrefslogtreecommitdiff
path: root/src/map/magic-interpreter.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/magic-interpreter.hpp')
-rw-r--r--src/map/magic-interpreter.hpp500
1 files changed, 500 insertions, 0 deletions
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp
new file mode 100644
index 0000000..e040975
--- /dev/null
+++ b/src/map/magic-interpreter.hpp
@@ -0,0 +1,500 @@
+/* Magic interpreter */
+
+#ifndef MAGIC_INTERPRETER_HPP
+#define MAGIC_INTERPRETER_HPP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "../common/nullpo.hpp"
+
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "magic.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "party.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+#include "trade.hpp"
+
+#include "../common/timer.hpp"
+#include "../common/socket.hpp"
+
+#define SPELLARG_NONE 0 /* No spell parameter */
+#define SPELLARG_PC 1 /* Spell parameter describes pc (defaults to self) */
+#define SPELLARG_STRING 2 /* Spell parameter describes pc (defaults to self) */
+
+/* ------ */
+/* Values */
+/* ------ */
+
+#define TY_UNDEF 0
+#define TY_INT 1
+#define TY_DIR 2
+#define TY_STRING 3
+#define TY_ENTITY 5
+#define TY_LOCATION 6
+#define TY_AREA 7
+#define TY_SPELL 8
+#define TY_INVOCATION 9
+#define TY_FAIL 127
+
+#define DIR_S 0
+#define DIR_SW 1
+#define DIR_W 2
+#define DIR_NW 3
+#define DIR_N 4
+#define DIR_NE 5
+#define DIR_E 6
+#define DIR_SE 7
+
+struct expr;
+struct val;
+struct location;
+struct area;
+struct spell;
+struct invocation;
+
+typedef struct location
+{
+ int m;
+ int x, y;
+} location_t;
+
+#define AREA_LOCATION 0
+#define AREA_UNION 1
+#define AREA_RECT 2
+#define AREA_BAR 3
+
+typedef struct area
+{
+ union a
+ {
+ location_t a_loc;
+ struct
+ {
+ location_t loc;
+ int width, depth, dir;
+ } a_bar;
+ struct
+ {
+ location_t loc;
+ int width, height;
+ } a_rect;
+ struct area *a_union[2];
+ } a;
+ int size;
+ unsigned char ty;
+} area_t;
+
+typedef struct val
+{
+ union v
+ {
+ int v_int;
+ char *v_string;
+ entity_t *v_entity; /* Used ONLY during operation/function invocation; otherwise we use v_int */
+ area_t *v_area;
+ location_t v_location;
+ struct invocation *v_invocation; /* Used ONLY during operation/function invocation; otherwise we use v_int */
+ struct spell *v_spell;
+ } v;
+ unsigned char ty;
+} val_t;
+
+/* ----------- */
+/* Expressions */
+/* ----------- */
+
+#define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */
+
+#define EXPR_VAL 0
+#define EXPR_LOCATION 1
+#define EXPR_AREA 2
+#define EXPR_FUNAPP 3
+#define EXPR_ID 4
+#define EXPR_SPELLFIELD 5
+
+typedef struct e_location
+{
+ struct expr *m, *x, *y;
+} e_location_t;
+
+typedef struct e_area
+{
+ union a0
+ {
+ e_location_t a_loc;
+ struct
+ {
+ e_location_t loc;
+ struct expr *width, *depth, *dir;
+ } a_bar;
+ struct
+ {
+ e_location_t loc;
+ struct expr *width, *height;
+ } a_rect;
+ struct e_area *a_union[2];
+ } a;
+ unsigned char ty;
+} e_area_t;
+
+typedef struct expr
+{
+ union e
+ {
+ val_t e_val;
+ e_location_t e_location;
+ e_area_t e_area;
+ struct
+ {
+ int id, line_nr, column;
+ int args_nr;
+ struct expr *args[MAX_ARGS];
+ } e_funapp;
+ int e_id;
+ struct
+ {
+ struct expr *expr;
+ int id;
+ } e_field;
+ } e;
+ unsigned char ty;
+} expr_t;
+
+/* ------- */
+/* Effects */
+/* ------- */
+
+#define EFFECT_SKIP 0
+#define EFFECT_ABORT 1
+#define EFFECT_ASSIGN 2
+#define EFFECT_FOREACH 3
+#define EFFECT_FOR 4
+#define EFFECT_IF 5
+#define EFFECT_SLEEP 6
+#define EFFECT_SCRIPT 7
+#define EFFECT_BREAK 8
+#define EFFECT_OP 9
+#define EFFECT_END 10
+#define EFFECT_CALL 11
+
+#define FOREACH_FILTER_MOB 1
+#define FOREACH_FILTER_PC 2
+#define FOREACH_FILTER_ENTITY 3
+#define FOREACH_FILTER_TARGET 4
+#define FOREACH_FILTER_SPELL 5
+#define FOREACH_FILTER_NPC 6
+
+typedef struct effect
+{
+ struct effect *next;
+ union e0
+ {
+ struct
+ {
+ int id;
+ expr_t *expr;
+ } e_assign;
+ struct
+ {
+ int id;
+ expr_t *area;
+ struct effect *body;
+ unsigned char filter;
+ } e_foreach;
+ struct
+ {
+ int id;
+ expr_t *start, *stop;
+ struct effect *body;
+ } e_for;
+ struct
+ {
+ expr_t *cond;
+ struct effect *true_branch, *false_branch;
+ } e_if;
+ expr_t *e_sleep; /* sleep time */
+ unsigned char *e_script;
+ struct
+ {
+ int id;
+ int args_nr;
+ int line_nr, column;
+ expr_t *args[MAX_ARGS];
+ } e_op;
+ struct
+ {
+ int args_nr, *formals;
+ expr_t **actuals;
+ struct effect *body;
+ } e_call;
+ } e;
+ unsigned char ty;
+} effect_t;
+
+/* ---------- */
+/* Components */
+/* ---------- */
+
+typedef struct component
+{
+ struct component *next;
+ int item_id;
+ int count;
+} component_t;
+
+/* ----------- */
+/* Spellguards */
+/* ----------- */
+
+#define SPELLGUARD_CONDITION 0
+#define SPELLGUARD_COMPONENTS 1
+#define SPELLGUARD_CATALYSTS 2
+#define SPELLGUARD_CHOICE 3
+#define SPELLGUARD_MANA 4
+#define SPELLGUARD_CASTTIME 5
+#define SPELLGUARD_EFFECT 6
+
+typedef struct effect_set
+{
+ effect_t *effect, *at_trigger, *at_end;
+} effect_set_t;
+
+typedef struct spellguard
+{
+ struct spellguard *next;
+ union s
+ {
+ expr_t *s_condition;
+ expr_t *s_mana;
+ expr_t *s_casttime;
+ component_t *s_components;
+ component_t *s_catalysts;
+ struct spellguard *s_alt; /* either `next' or `s.s_alt' */
+ effect_set_t s_effect;
+ } s;
+ unsigned char ty;
+} spellguard_t;
+
+/* ------ */
+/* Spells */
+/* ------ */
+
+typedef struct letdef
+{
+ int id;
+ expr_t *expr;
+} letdef_t;
+
+#define SPELL_FLAG_LOCAL (1 << 0) // spell associated not with caster but with place
+#define SPELL_FLAG_SILENT (1 << 1) // spell invocation never uttered
+#define SPELL_FLAG_NONMAGIC (1 << 2) // `magic word' only: don't require spellcasting ability
+
+typedef struct spell
+{
+ char *name;
+ char *invocation;
+ int index; // Relative location in the definitions file
+ int flags;
+ int arg;
+ int spellarg_ty;
+
+ int letdefs_nr;
+ letdef_t *letdefs;
+
+ spellguard_t *spellguard;
+} spell_t;
+
+/* ------- */
+/* Anchors */
+/* ------- */
+
+typedef struct teleport_anchor
+{
+ char *name;
+ char *invocation;
+ expr_t *location;
+} teleport_anchor_t;
+
+/* ------------------- */
+/* The big config blob */
+/* ------------------- */
+
+typedef struct
+{
+ int vars_nr;
+ const char **var_name;
+ val_t *vars; /* Initial assignments, if any, or NULL */
+
+ int obscure_chance;
+ int min_casttime;
+
+ int spells_nr;
+ spell_t **spells;
+
+ int anchors_nr; /* NEGATIVE iff we have sorted the anchors */
+ teleport_anchor_t **anchors;
+} magic_conf_t;
+
+/* Execution environment */
+
+#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;
+
+typedef struct env
+{
+ magic_conf_t *base_env;
+ val_t *vars;
+} env_t;
+
+#define MAX_STACK_SIZE 32
+
+#define CONT_STACK_FOREACH 0
+#define CONT_STACK_FOR 1
+#define CONT_STACK_PROC 2
+
+typedef struct cont_activation_record
+{
+ effect_t *return_location;
+ union c
+ {
+ struct
+ {
+ int id, ty;
+ effect_t *body;
+ int entities_nr;
+ int *entities;
+ int index;
+ } c_foreach;
+ struct
+ {
+ int id;
+ effect_t *body;
+ int current;
+ int stop;
+ } c_for;
+ struct
+ {
+ int args_nr, *formals;
+ val_t *old_actuals;
+ } c_proc;
+ } c;
+ unsigned char ty;
+} cont_activation_record_t;
+
+typedef struct status_change_ref
+{
+ int sc_type;
+ int bl_id;
+} status_change_ref_t;
+
+#define INVOCATION_FLAG_BOUND (1 << 0) /* Bound directly to the caster (i.e., ignore its location) */
+#define INVOCATION_FLAG_ABORTED (1 << 1) /* Used `abort' to terminate */
+#define INVOCATION_FLAG_STOPATTACK (1 << 2) /* On magical attacks: if we run out of steam, stop attacking altogether */
+
+typedef struct invocation
+{
+ struct block_list bl;
+
+ struct invocation *next_invocation; /* used for spells directly associated with a caster: they form a singly-linked list */
+ int flags;
+
+ env_t *env;
+ 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 */
+
+ int timer; /* spell timer, if any */
+
+ int stack_size;
+ cont_activation_record_t stack[MAX_STACK_SIZE];
+
+ int script_pos; /* Script position; if nonzero, resume the script we were running. */
+ effect_t *current_effect;
+ effect_t *trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */
+ 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. */
+
+ /* Status change references: for status change updates, keep track of whom we updated where */
+ int status_change_refs_nr;
+ status_change_ref_t *status_change_refs;
+
+} invocation_t;
+
+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 (component_t ** component_holder, int id, int count);
+
+teleport_anchor_t *magic_find_anchor (char *name);
+
+/**
+ * The parameter `param' must have been dynamically allocated; ownership is transferred to the resultant env_t.
+ */
+env_t *spell_create_env (magic_conf_t * conf, spell_t * spell,
+ character_t * caster, int spellpower, char *param);
+
+void magic_free_env (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 (spell_t * spell, character_t * caster,
+ env_t * env, int *near_miss);
+
+invocation_t *spell_instantiate (effect_set_t * effect, env_t * env);
+
+/**
+ * Bind a spell to a subject (this is a no-op for `local' spells).
+ */
+void spell_bind (character_t * subject, invocation_t * invocation);
+
+int // 1 on failure
+ spell_unbind (character_t * subject, invocation_t * invocation);
+
+/**
+ * Clones a spell to run the at_effect field
+ */
+invocation_t *spell_clone_effect (invocation_t * source);
+
+spell_t *magic_find_spell (char *invocation);
+
+/* The following is used only by the parser: */
+typedef struct args_rec
+{
+ int args_nr;
+ expr_t **args;
+} args_rec_t;
+
+typedef struct
+{
+ char *name;
+ int args_nr;
+ int *args;
+ effect_t *body;
+} proc_t;
+
+#endif /* !defined (MAGIC_INTERPRETER_H) */