//===== Hercules Plugin ======================================
//= *setmobdata/getmobdata script command
//===== By: ==================================================
//= AnnieRuru
//===== Current Version: =====================================
//= 1.1
//===== Compatible With: =====================================
//= Hercules 2015-11-08
//===== Description: =========================================
//= *getmobdata to retrieve the monster's information
//= *setmobdata to modify the monster attribute
//===== Topic ================================================
//= http://herc.ws/board/topic/11097-setmobdata-getmobdata/
//===== Additional Comments: =================================
//= This is not the same setmobdata/getmobdata from [Lance] mob controller system
//============================================================
#include "common/hercules.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "map/mob.h"
#include "map/script.h"
#include "map/battle.h"
#include "common/memmgr.h"
#include "common/HPMDataCheck.h"
HPExport struct hplugin_info pinfo = {
"setmobdata", // Plugin name
SERVER_TYPE_MAP,// Which server types this plugin works with?
"1.1", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
enum mobdata_type {
MOBDATA_MOBID = 1,
MOBDATA_LEVEL,
MOBDATA_HP,
MOBDATA_MAXHP,
MOBDATA_ATK,
MOBDATA_MATK,
MOBDATA_DEF,
MOBDATA_MDEF,
MOBDATA_HIT,
MOBDATA_FLEE,
MOBDATA_CRITICAL,
MOBDATA_PERFECT_DODGE,
MOBDATA_STR,
MOBDATA_AGI,
MOBDATA_VIT,
MOBDATA_INT,
MOBDATA_DEX,
MOBDATA_LUK,
MOBDATA_ATTACK_RANGE,
MOBDATA_RACE,
MOBDATA_ELEMENT_TYPE,
MOBDATA_ELEMENT_LEVEL,
MOBDATA_MODE,
MOBDATA_MOVESPEED,
MOBDATA_ATTACK_DELAY,
MOBDATA_ATTACK_MOTION,
MOBDATA_DAMAGE_MOTION,
MOBDATA_BLOCKIMMUNE,
MOBDATA_NORANDOMWALK,
};
struct monster_data {
unsigned int norandomwalk: 1;
unsigned int blockimmune: 1;
};
BUILDIN(setmobdata) {
int mob_id = script_getnum(st,2),
type = script_getnum(st,3);
struct block_list *bl = map->id2bl( mob_id );
if ( bl == NULL ) {
ShowWarning( "buildin_setmobdata: Attempted to retrieve a non-existed GID %d.\n", mob_id );
return false;
}
if ( bl->type != BL_MOB ) {
ShowWarning( "buildin_setmobdata: Attempted to retrieve not a monster. GID %d.\n", mob_id );
return false;
}
{
TBL_MOB *md = (TBL_MOB*)bl;
switch( type ) {
case MOBDATA_MOBID :
ShowWarning( "buildin_setmobdata: Attempted to change MobID with type MOBDATA_MOBID.\n" );
break;
case MOBDATA_LEVEL : md->level = script_getnum(st,4); break;
case MOBDATA_HP : md->status.hp = script_getnum(st,4); break;
case MOBDATA_MAXHP : md->status.max_hp = script_getnum(st,4); break;
case MOBDATA_ATK : md->status.rhw.atk = script_getnum(st,4); break;
case MOBDATA_MATK : md->status.rhw.atk2 = script_getnum(st,4); break;
case MOBDATA_DEF : md->status.def = script_getnum(st,4); break;
case MOBDATA_MDEF : md->status.mdef = script_getnum(st,4); break;
case MOBDATA_HIT : md->status.hit = script_getnum(st,4); break;
case MOBDATA_FLEE : md->status.flee = script_getnum(st,4); break;
case MOBDATA_CRITICAL : md->status.cri = script_getnum(st,4); break;
case MOBDATA_PERFECT_DODGE : md->status.flee2 = script_getnum(st,4); break;
case MOBDATA_STR : md->status.str = script_getnum(st,4); break;
case MOBDATA_AGI : md->status.agi = script_getnum(st,4); break;
case MOBDATA_VIT : md->status.vit = script_getnum(st,4); break;
case MOBDATA_INT : md->status.int_ = script_getnum(st,4); break;
case MOBDATA_DEX : md->status.dex = script_getnum(st,4); break;
case MOBDATA_LUK : md->status.luk = script_getnum(st,4); break;
case MOBDATA_ATTACK_RANGE : md->status.rhw.range = script_getnum(st,4); break;
case MOBDATA_RACE : md->status.race = script_getnum(st,4); break;
case MOBDATA_ELEMENT_TYPE : md->status.def_ele = script_getnum(st,4); break;
case MOBDATA_ELEMENT_LEVEL : md->status.ele_lv = script_getnum(st,4); break;
case MOBDATA_MODE : md->status.mode = script_getnum(st,4); break;
case MOBDATA_MOVESPEED : md->status.speed = script_getnum(st,4); break;
case MOBDATA_ATTACK_DELAY : md->status.adelay = script_getnum(st,4); break;
case MOBDATA_ATTACK_MOTION : md->status.amotion = script_getnum(st,4); break;
case MOBDATA_DAMAGE_MOTION : md->status.dmotion = script_getnum(st,4); break;
case MOBDATA_BLOCKIMMUNE : {
struct monster_data *mmd = getFromMOBDATA( md, 0 );
CREATE( mmd, struct monster_data, 1 );
mmd->blockimmune = script_getnum(st,4) > 0;
addToMOBDATA( md, mmd, 0, true );
break;
}
case MOBDATA_NORANDOMWALK : {
struct monster_data *mmd = getFromMOBDATA( md, 0 );
CREATE( mmd, struct monster_data, 1 );
mmd->norandomwalk = script_getnum(st,4) > 0;
addToMOBDATA( md, mmd, 0, true );
break;
}
default :
ShowError( "buildin_setmobdata: Attempted to use non-existing type %d.\n", type );
return false;
}
}
return true;
}
BUILDIN(getmobdata) {
int mob_id = script_getnum(st,2),
type = script_getnum(st,3);
struct block_list *bl = map->id2bl( mob_id );
if ( bl == NULL ) {
ShowWarning( "buildin_getmobdata: Attempted to retrieve a non-existed GID %d.\n", mob_id );
return false;
}
if ( bl->type != BL_MOB ) {
ShowWarning( "buildin_getmobdata: Attempted to retrieve not a monster. GID %d.\n", mob_id );
return false;
}
{
TBL_MOB *md = (TBL_MOB*)bl;
switch( type ) {
case MOBDATA_MOBID : script_pushint( st, md->class_ ); break;
case MOBDATA_LEVEL : script_pushint( st, md->level ); break;
case MOBDATA_HP : script_pushint( st, md->status.hp ); break;
case MOBDATA_MAXHP : script_pushint( st, md->status.max_hp ); break;
case MOBDATA_ATK : script_pushint( st, md->status.rhw.atk ); break;
case MOBDATA_MATK : script_pushint( st, md->status.rhw.atk2 ); break;
case MOBDATA_DEF : script_pushint( st, md->status.def ); break;
case MOBDATA_MDEF : script_pushint( st, md->status.mdef ); break;
case MOBDATA_HIT : script_pushint( st, md->status.hit ); break;
case MOBDATA_FLEE : script_pushint( st, md->status.flee ); break;
case MOBDATA_CRITICAL : script_pushint( st, md->status.cri ); break;
case MOBDATA_PERFECT_DODGE : script_pushint( st, md->status.flee2 ); break;
case MOBDATA_STR : script_pushint( st, md->status.str ); break;
case MOBDATA_AGI : script_pushint( st, md->status.agi ); break;
case MOBDATA_VIT : script_pushint( st, md->status.vit ); break;
case MOBDATA_INT : script_pushint( st, md->status.int_ ); break;
case MOBDATA_DEX : script_pushint( st, md->status.dex ); break;
case MOBDATA_LUK : script_pushint( st, md->status.luk ); break;
case MOBDATA_ATTACK_RANGE : script_pushint( st, md->status.rhw.range ); break;
case MOBDATA_RACE : script_pushint( st, md->status.race ); break;
case MOBDATA_ELEMENT_TYPE : script_pushint( st, md->status.def_ele ); break;
case MOBDATA_ELEMENT_LEVEL : script_pushint( st, md->status.ele_lv ); break;
case MOBDATA_MODE : script_pushint( st, md->status.mode ); break;
case MOBDATA_MOVESPEED : script_pushint( st, md->status.speed ); break;
case MOBDATA_ATTACK_DELAY : script_pushint( st, md->status.adelay ); break;
case MOBDATA_ATTACK_MOTION : script_pushint( st, md->status.amotion ); break;
case MOBDATA_DAMAGE_MOTION : script_pushint( st, md->status.dmotion ); break;
case MOBDATA_BLOCKIMMUNE : {
struct monster_data *mmd = getFromMOBDATA( md, 0 );
if (( mmd = getFromMOBDATA( md, 0 ) )) {
script_pushint( st, mmd->blockimmune );
break;
}
else {
script_pushint( st, 0 );
break;
}
}
case MOBDATA_NORANDOMWALK : {
struct monster_data *mmd = getFromMOBDATA( md, 0 );
if (( mmd = getFromMOBDATA( md, 0 ) )) {
script_pushint( st, mmd->norandomwalk );
break;
}
else {
script_pushint( st, 0 );
break;
}
}
default :
ShowError( "buildin_getmobdata: Attempted to use non-existing type %d.\n", type );
return false;
}
}
return true;
}
int mob_randomwalk_pre( struct mob_data *md, int64 *tick ) {
struct monster_data *mmd;
if (( mmd = getFromMOBDATA( md, 0 ) ))
if ( mmd->norandomwalk )
hookStop();
return 0;
}
int battle_check_target_post( int retVal, struct block_list *src, struct block_list *target, int *flag ) {
if ( retVal == 1 && target->type == BL_MOB ) {
struct block_list *t_bl;
struct monster_data *mmd;
if ( ( t_bl = battle->get_master(target) ) == NULL )
t_bl = target;
if (( mmd = getFromMOBDATA( (TBL_MOB*)t_bl, 0 ) ))
if ( mmd->blockimmune )
return -1;
}
return retVal;
}
void script_hardcoded_constants_pre(void) {
script->set_constant("MOBDATA_MOBID",MOBDATA_MOBID,false);
script->set_constant("MOBDATA_LEVEL",MOBDATA_LEVEL,false);
script->set_constant("MOBDATA_HP",MOBDATA_HP,false);
script->set_constant("MOBDATA_MAXHP",MOBDATA_MAXHP,false);
script->set_constant("MOBDATA_ATK",MOBDATA_ATK,false);
script->set_constant("MOBDATA_MATK",MOBDATA_MATK,false);
script->set_constant("MOBDATA_DEF",MOBDATA_DEF,false);
script->set_constant("MOBDATA_MDEF",MOBDATA_MDEF,false);
script->set_constant("MOBDATA_HIT",MOBDATA_HIT,false);
script->set_constant("MOBDATA_FLEE",MOBDATA_FLEE,false);
script->set_constant("MOBDATA_CRITICAL",MOBDATA_CRITICAL,false);
script->set_constant("MOBDATA_PERFECT_DODGE",MOBDATA_PERFECT_DODGE,false);
script->set_constant("MOBDATA_STR",MOBDATA_STR,false);
script->set_constant("MOBDATA_AGI",MOBDATA_AGI,false);
script->set_constant("MOBDATA_VIT",MOBDATA_VIT,false);
script->set_constant("MOBDATA_INT",MOBDATA_INT,false);
script->set_constant("MOBDATA_DEX",MOBDATA_DEX,false);
script->set_constant("MOBDATA_LUK",MOBDATA_LUK,false);
script->set_constant("MOBDATA_ATTACK_RANGE",MOBDATA_ATTACK_RANGE,false);
script->set_constant("MOBDATA_RACE",MOBDATA_RACE,false);
script->set_constant("MOBDATA_ELEMENT_TYPE",MOBDATA_ELEMENT_TYPE,false);
script->set_constant("MOBDATA_ELEMENT_LEVEL",MOBDATA_ELEMENT_LEVEL,false);
script->set_constant("MOBDATA_MODE",MOBDATA_MODE,false);
script->set_constant("MOBDATA_MOVESPEED",MOBDATA_MOVESPEED,false);
script->set_constant("MOBDATA_ATTACK_DELAY",MOBDATA_ATTACK_DELAY,false);
script->set_constant("MOBDATA_ATTACK_MOTION",MOBDATA_ATTACK_MOTION,false);
script->set_constant("MOBDATA_DAMAGE_MOTION",MOBDATA_DAMAGE_MOTION,false);
script->set_constant("MOBDATA_BLOCKIMMUNE",MOBDATA_BLOCKIMMUNE,false);
script->set_constant("MOBDATA_NORANDOMWALK",MOBDATA_NORANDOMWALK,false);
script->set_constant("MD_CANMOVE",MD_CANMOVE,false);
script->set_constant("MD_LOOTER",MD_LOOTER,false);
script->set_constant("MD_AGGRESSIVE",MD_AGGRESSIVE,false);
script->set_constant("MD_ASSIST",MD_ASSIST,false);
script->set_constant("MD_CASTSENSOR_IDLE",MD_CASTSENSOR_IDLE,false);
script->set_constant("MD_BOSS",MD_BOSS,false);
script->set_constant("MD_PLANT",MD_PLANT,false);
script->set_constant("MD_CANATTACK",MD_CANATTACK,false);
script->set_constant("MD_DETECTOR",MD_DETECTOR,false);
script->set_constant("MD_CASTSENSOR_CHASE",MD_CASTSENSOR_CHASE,false);
script->set_constant("MD_CHANGECHASE",MD_CHANGECHASE,false);
script->set_constant("MD_ANGRY",MD_ANGRY,false);
script->set_constant("MD_CHANGETARGET_MELEE",MD_CHANGETARGET_MELEE,false);
script->set_constant("MD_CHANGETARGET_CHASE",MD_CHANGETARGET_CHASE,false);
script->set_constant("MD_TARGETWEAK",MD_TARGETWEAK,false);
return;
}
HPExport void plugin_init (void) {
addScriptCommand("setmobdata","iii",setmobdata);
addScriptCommand("getmobdata","ii",getmobdata);
addHookPre( "mob->randomwalk", mob_randomwalk_pre );
addHookPost( "battle->check_target", battle_check_target_post );
addHookPre( "script->hardcoded_constants", script_hardcoded_constants_pre );
}