summaryrefslogblamecommitdiff
path: root/src/emap/script.c
blob: 778ebe043f7496406b711eab4a4645943b931900 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                         
                                            
 

                            



                   
                        
                          
                          
                            


                       
 

                               

                                
                        
                     
                            
                           
                                 
                                
                             
 

                         
                                                              



                                             



                                         
               
 

                         
                                                              



                                             



                                         



                         
                                                              








                                             
                                                              





                                             
 
                            




                     
                                      





                                                              



                                                               




                                                                       
                                                                       
 





                                                                    





                                                                        





                                                                 
                                  
                                  

 
                                                                                  
                                        































                                                                              




                                                                   
 



                                     

                               
                  


                             

                                   
                  
                                                    
                          
                             
                   
     







                                                    

                                        
                  
                             
                   
     

                                   
                  







                            
                                   
                   
     



                                              
                   




                                               



                                     
                  



                                      
     

                                     
                  




                                                               





                                                  

                                   
                  
                                         


                               

                                     
                  
                                         


                               

                                        
                  


                             








                                              





                                                  

 


                                                           
 


                                        


                                               
                      


                             

                                   
                         
                   
                          
     





                                        

                                        
                         


                             

                                   
                         


                       

                                 
                         




                                 
                         


                        

                                     
                         


                          

                                     
                         


                         

                                    
                         


                           

                                   
                         
                   
                                            
     

                                     
                         
                   
                                            
     

                                        
                      


                             






                                                   





                                     


             




                                                                   
 




                                     





                                                  

                                     
                  






                                                                                                             





                                                      

 


                                                             
 


                                        


                                               
                         


                                        

                                     
                         


                        

                                        
                         


                          


                









                                                                
                                                            













                                                         
                                                                           


                                                         
                                                            




                             



                                                                  




                                     

                                                                
                                                               

                                                           


                                



                                                           




                                     

                                                            
                                                               

                                                       

                                
// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// Copyright (c) 2014 - 2015 Evol developers

#include "common/hercules.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common/HPMi.h"
#include "common/memmgr.h"
#include "common/nullpo.h"
#include "map/achievement.h"
#include "map/npc.h"
#include "map/pc.h"
#include "map/script.h"

#include "plugins/HPMHooking.h"

#include "ecommon/enum/gender.h"

#include "emap/script.h"
#include "emap/map.h"
#include "emap/data/itemd.h"
#include "emap/data/npcd.h"
#include "emap/struct/itemdext.h"
#include "emap/struct/npcdext.h"
#include "emap/skill_const.h"

#define getExt2() \
    TBL_NPC *nd = NULL; \
    int num = (int)reference_uid(script->add_str(".id"), 0); \
    int id = (int)i64db_iget(n->vars, num); \
    if (!id) \
        id = st->oid; \
    nd = map->id2nd(id); \
    if (!nd) \
        return; \
    struct NpcdExt *ext = npcd_get(nd); \
    if (!ext) \
        return;

#define getExt2Ret(r) \
    TBL_NPC *nd = NULL; \
    int num = (int)reference_uid(script->add_str(".id"), 0); \
    int id = (int)i64db_iget(n->vars, num); \
    if (!id) \
        id = st->oid; \
    nd = map->id2nd(id); \
    if (!nd) \
        return r; \
    struct NpcdExt *ext = npcd_get(nd); \
    if (!ext) \
        return r;

#define getExt1() \
    TBL_NPC *nd = NULL; \
    int num = (int)reference_uid(script->add_str(".id"), 0); \
    int id = (int)i64db_iget(n->vars, num); \
    if (!id) \
        id = st->oid; \
    nd = map->id2nd(id); \
    if (!nd) \
        return; \

#define getExt1Return(r) \
    TBL_NPC *nd = NULL; \
    int num = (int)reference_uid(script->add_str(".id"), 0); \
    int id = (int)i64db_iget(n->vars, num); \
    if (!id) \
        id = st->oid; \
    nd = map->id2nd(id); \
    if (!nd) \
        return r;

int escript_reload_pre(void)
{
    map_clear_data();
    return 0;
}

void escript_load_parameters_pre(void)
{
    script->constdb_comment("Evol parameters");
    script->set_constant("ClientVersion", 10000, true, false);
    script->constdb_comment(NULL);
}

void escript_hardcoded_constants_pre(void)
{
    script->constdb_comment("Evol constants");
    script->set_constant("MAX_SLOTS", MAX_SLOTS, false, false);

    // genders: for use with the Sex param
    script->set_constant("Gender", SP_SEX, true, false);
    script->set_constant("GENDER_FEMALE", GENDER_FEMALE, false, false);
    script->set_constant("GENDER_MALE", GENDER_MALE, false, false);
    script->set_constant("GENDER_HIDDEN", GENDER_HIDDEN, false, false);

    // for servers that do not use sex/gender
    script->set_constant("BodyType", SP_SEX, true, false);
    script->set_constant("BODYTYPE_1", GENDER_HIDDEN, false, false);
    script->set_constant("BODYTYPE_2", GENDER_FEMALE, false, false);
    script->set_constant("BODYTYPE_3", GENDER_MALE, false, false);

    // npc subtypes
    script->set_constant("NPCSUBTYPE_WARP", WARP, false, false);
    script->set_constant("NPCSUBTYPE_SHOP", SHOP, false, false);
    script->set_constant("NPCSUBTYPE_SCRIPT", SCRIPT, false, false);
    script->set_constant("NPCSUBTYPE_CASHSHOP", CASHSHOP, false, false);
    script->set_constant("NPCSUBTYPE_TOMB", TOMB, false, false);

    // new item types
#ifdef IT_VIRTUAL
    script->set_constant("IT_VIRTUAL", IT_VIRTUAL, false, false);
#endif

    script->constdb_comment(NULL);
    eskill_addskill_conststants();
}

// stripped copy from script_load_translations without actual translation loading.
void escript_load_translations_pre(void)
{
    if (map->minimal)
    {
        hookStop();
        return;
    }

    script->translation_db = strdb_alloc(DB_OPT_DUP_KEY, NAME_LENGTH * 2 + 1);

    if (script->languages)
    {
        int i;
        for (i = 0; i < script->max_lang_id; i++)
            aFree(script->languages[i]);
        aFree(script->languages);
    }
    script->languages = NULL;
    script->max_lang_id = 0;

    script->add_language("English");

    if (script->string_list)
        aFree(script->string_list);

    script->string_list = NULL;
    script->string_list_pos = 0;
    script->string_list_size = 0;

    map->default_lang_id = 0;
    hookStop();
}

void eset_reg_npcscope_num_pre(struct script_state **stPtr,
                               struct reg_db **nPtr,
                               int64 *num __attribute__ ((unused)),
                               const char **namePtr,
                               int *val)
{
    struct script_state *st = *stPtr;
    struct reg_db *n = *nPtr;
    const char *name = *namePtr;

    if (!strcmp(name, ".lang"))
    {
        getExt2();
        ext->language = *val;
        hookStop();
    }
    else if (!strcmp(name, ".sex"))
    {
        getExt1();
        clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
        nd->vd.sex = *val;
        clif->spawn(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".bodytype"))
    {
        getExt1();
        clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
        nd->vd.sex = *val;
        clif->spawn(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".distance"))
    {
        getExt1();
        nd->area_size = *val;
        hookStop();
    }
    else if (!strcmp(name, ".dir"))
    {
        getExt1();
        int newdir = *val;

        if (newdir < 0)
            newdir = 0;
        else if (newdir > 7)
            newdir = 7;

        nd->dir = newdir;
        npc->enable(nd->exname, 1);
        hookStop();
    }
    else if (!strcmp(name, ".x"))
    {
        ShowWarning("you cant assign '.x'\n");
        script->reportsrc(st);
        hookStop();
    }
    else if (!strcmp(name, ".y"))
    {
        ShowWarning("you cant assign '.y'.\n");
        script->reportsrc(st);
        hookStop();
    }
    else if (!strcmp(name, ".class"))
    {
        getExt1();
        int class_ = *val;
        if (nd->class_ != class_)
            npc->setclass(nd, class_);
        hookStop();
    }
    else if (!strcmp(name, ".speed"))
    {
        getExt1();
        unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
        nd->speed = *val;
        nd->ud->state.speed_changed = 1;
        hookStop();
    }
    else if (!strcmp(name, ".chat"))
    {
        ShowWarning("you cant assign '.chat'.\n");
        script->reportsrc(st);
        hookStop();
    }
    else if (!strcmp(name, ".sit"))
    {
        getExt1();
        nd->vd.dead_sit = (*val) ? 2 : 0;
        clif->sitting(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".stand"))
    {
        getExt1();
        nd->vd.dead_sit = (*val) ? 0 : 2;
        clif->sitting(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".walkmask"))
    {
        getExt2();
        ext->walkMask = *val;
        hookStop();
    }
    else if (!strcmp(name, ".alwaysVisible"))
    {
        getExt1();
        if (*val)
            map_alwaysVisible_add(&nd->bl);
        else
            map_alwaysVisible_delete(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".srcId"))
    {
        ShowWarning("you cant assign '.srcId'\n");
        script->reportsrc(st);
        hookStop();
    }
}

int eget_val_npcscope_num_pre(struct script_state **stPtr,
                              struct reg_db **nPtr,
                              struct script_data **dataPtr)
{
    struct script_state *st = *stPtr;
    struct reg_db *n = *nPtr;
    struct script_data *data = *dataPtr;
    const char *name = reference_getname(data);
    if (!strcmp(name, ".lang"))
    {
        getExt2Ret(0);
        hookStop();
        return ext->language;
    }
    else if (!strcmp(name, ".sex"))
    {
        getExt1Return(0);
        hookStop();
        return nd->vd.sex;
    }
    else if (!strcmp(name, ".bodytype"))
    {
        getExt1Return(0);
        hookStop();
        return nd->vd.sex;
    }
    else if (!strcmp(name, ".distance"))
    {
        getExt1Return(0);
        hookStop();
        return nd->area_size;
    }
    else if (!strcmp(name, ".dir"))
    {
        getExt1Return(0);
        hookStop();
        return nd->dir;
    }
    else if (!strcmp(name, ".x"))
    {
        getExt1Return(0);
        hookStop();
        return nd->bl.x;
    }
    else if (!strcmp(name, ".y"))
    {
        getExt1Return(0);
        hookStop();
        return nd->bl.y;
    }
    else if (!strcmp(name, ".class"))
    {
        getExt1Return(0);
        hookStop();
        return nd->class_;
    }
    else if (!strcmp(name, ".speed"))
    {
        getExt1Return(0);
        hookStop();
        return nd->speed;
    }
    else if (!strcmp(name, ".chat"))
    {
        getExt1Return(0);
        hookStop();
        return nd->chat_id;
    }
    else if (!strcmp(name, ".sit"))
    {
        getExt1Return(0);
        hookStop();
        return nd->vd.dead_sit == 2 ? 1 : 0;
    }
    else if (!strcmp(name, ".stand"))
    {
        getExt1Return(0);
        hookStop();
        return nd->vd.dead_sit == 0 ? 1 : 0;
    }
    else if (!strcmp(name, ".walkmask"))
    {
        getExt2Ret(0);
        hookStop();
        return ext->walkMask;
    }
    else if (!strcmp(name, ".alwaysVisible"))
    {
        getExt1Return(0);
        bool res = map_alwaysVisible_find(&nd->bl);
        hookStop();
        return res;
    }
    else if (!strcmp(name, ".srcId"))
    {
        getExt1Return(0);
        hookStop();
        return nd->src_id;
    }
    return 0;
}

void eset_reg_npcscope_str_pre(struct script_state **stPtr,
                               struct reg_db **nPtr,
                               int64 *num __attribute__ ((unused)),
                               const char **namePtr,
                               const char **strPtr)
{
    struct script_state *st = *stPtr;
    struct reg_db *n = *nPtr;
    const char *name = *namePtr;
    const char *str = *strPtr;

    if (!strcmp(name, ".map$"))
    {
        ShowWarning("you cant assign '.map$'.\n");
        script->reportsrc(st);
        hookStop();
    }
    else if (!strcmp(name, ".name$"))
    {
        getExt1();
        npc->setdisplayname(nd, str);
//      not working because cant sent brodcast with translated npc name. need add for_each function for this.
//        clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
//        safestrncpy(nd->name, str, sizeof(nd->name));
//        clif->spawn(&nd->bl);
        hookStop();
    }
    else if (!strcmp(name, ".extname$"))
    {
        ShowWarning("you cant assign '.extname$'.\n");
        script->reportsrc(st);
        hookStop();
    }
}

char *eget_val_npcscope_str_pre(struct script_state **stPtr,
                                struct reg_db **nPtr,
                                struct script_data **dataPtr)
{
    struct script_state *st = *stPtr;
    struct reg_db *n = *nPtr;
    struct script_data *data = *dataPtr;
    const char *name = reference_getname(data);
    if (!strcmp(name, ".map$"))
    {
        getExt1Return(0);
        hookStop();
        return map->list[nd->bl.m].name;
    }
    else if (!strcmp(name, ".name$"))
    {
        getExt1Return(0);
        hookStop();
        return nd->name;
    }
    else if (!strcmp(name, ".extname$"))
    {
        getExt1Return(0);
        hookStop();
        return nd->exname;
    }
    return NULL;
}

void escript_run_use_script_pre(struct map_session_data **sdPtr,
                                struct item_data **itemDataPtr,
                                int *oidPtr)
{
    nullpo_retv(*itemDataPtr);
    struct map_session_data *sd = *sdPtr;
    struct item_data *itemData = *itemDataPtr;
    const int oid = *oidPtr;
    if (oid == 0)
    {
        pc->setreg(sd, script->add_variable("@useType"), 0);
        script->current_item_id = itemData->nameid;
        script->run(itemData->script, 0, sd->bl.id, oid);
        script->current_item_id = 0;
    }
    else
    {
        struct ItemdExt *data = itemd_get(itemData);
        if (!data)
        {
            data->tmpUseType = 0;
            hookStop();
            return;
        }

        pc->setreg(sd, script->add_variable("@useType"), data->tmpUseType);
        script->current_item_id = itemData->nameid;
        script->run(itemData->script, 0, sd->bl.id, oid);
        script->current_item_id = 0;
        pc->setreg(sd, script->add_variable("@useType"), 0);
        data->tmpUseType = 0;
    }
    hookStop();
}

void script_run_item_amount_script(TBL_PC *sd,
                                   struct script_code *itemScript,
                                   int itemId,
                                   int amount)
{
    if (!itemScript)
        return;

    script->current_item_id = itemId;
    pc->setreg(sd, script->add_variable("@itemId"), itemId);
    pc->setreg(sd, script->add_variable("@itemAmount"), amount);
    script->run(itemScript, 0, sd->bl.id, npc->fake_nd->bl.id);
    pc->setreg(sd, script->add_variable("@itemId"), 0);
    pc->setreg(sd, script->add_variable("@itemAmount"), 0);
    script->current_item_id = 0;
}

void script_run_card_script(TBL_PC *sd,
                            struct script_code *itemScript,
                            int itemId,
                            int cardId)
{
    if (!itemScript)
        return;

    script->current_item_id = itemId;
    pc->setreg(sd, script->add_variable("@itemId"), itemId);
    pc->setreg(sd, script->add_variable("@cardId"), cardId);
    script->run(itemScript, 0, sd->bl.id, npc->fake_nd->bl.id);
    pc->setreg(sd, script->add_variable("@itemId"), 0);
    pc->setreg(sd, script->add_variable("@cardId"), 0);
    script->current_item_id = 0;
}