summaryrefslogblamecommitdiff
path: root/src/map/magic-interpreter.hpp
blob: 2414a7a5b7113b1ec9a4ba6df0422c54be2f31b3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                       

                             





                   




















                               
 


                                                                                         




            


















                           







                  

                       

             

             



                         
 



                   
                         


                           
                                  



                           
                              

                                
        
             


                     



                  
                  
                       
                                                                                                            

                              
                                                                                                                        




                              



                 
                                                                                        
 





                         
 

                         


                           



                     
                           










                                             



                     



                   


                                

              

                                    

                                        
                 


                              
                   
                  



                     



             


















                                 
 






                        
                   



                         
                   





                                 
                   








                                                      
                                   

              


                                



                                   
                                  


                                



                     
                
                

                

                        
                           

                

              



                 






                                 
 


                                           

               

                         
                            

           




                                  
                                                                    




                              



            

                     
           


                 


                                                                                                     
 

                    

                     



                                                                           
 
                   








                             

                              








                         

              
                
                          
                                                                          
 

                       
 
                  

                     
                                                                            


                                

                           








                                 


                    

                  





                           


                                 
 

                                     
                              



              
                       
                           
                            
                          
                      


                    
                   
                           

                        


                
                                  

                               



                           

                                
                         
              

                      


                                                                                                                                
 

                         


                                                                                                                               
              


                   

                                                                                        
 
                                                        
 
                   

                                                   
                                                                                                    
                             

                                                                                                                                                                          

                                                                                                   
                              



                                            


                                                              


                                                                                 
                                                                             
 
                                                 



                                                                                                               
                                                             
                                                                            
 
                                 
 


                                                                                                                                         
                                                                  
                                                          
 
                                                                    



                                                                  
                                                                  
 

                                                                    



                                            
                                                        
 
                                            

                                               

                       
                


                  


               
                

                   

         

                                             
                                                      
 
                                           
/* 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 */
        const ScriptCode *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
{
    StatusChange 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;

// must be called after itemdb initialisation
int magic_init(const char *);
void spell_update_location(invocation_t * invocation);

#endif /* !defined (MAGIC_INTERPRETER_H) */