From 2e35eff8bfe55314e30aaa2b88bd0bf1e7bd7647 Mon Sep 17 00:00:00 2001 From: Lance Date: Fri, 26 May 2006 18:54:07 +0000 Subject: * Patches to allow everything to work right. + 1 more sample script. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6779 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 1 + db/const.txt | 2 + db/mob_avail.txt | 2 + db/mob_db2.txt | 1 + npc/custom/Lance/Sentry.cpp | 119 ++++++++++++++++++++++++++++++++++++++ npc/sample/monster_controller.cpp | 28 ++++++--- npc/scripts_custom.conf | 3 +- src/map/mob.c | 22 ++++++- src/map/pc.c | 69 ++++++++++++---------- src/map/script.c | 51 ++++++++-------- src/map/unit.c | 4 +- 11 files changed, 236 insertions(+), 66 deletions(-) create mode 100644 npc/custom/Lance/Sentry.cpp diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 80314a053..094897db1 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,7 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2006/05/26 + * Patches to allow everything to work right. + 1 more sample script. [Lance] * Mob control engine tested 99% working so far. [Lance] * Change scripting engine's NPC scope vars to dot (.) style. * Improved and (should be fully) fixed the mob control engine. [Lance] diff --git a/db/const.txt b/db/const.txt index 1e4ee08dd..d97374a77 100644 --- a/db/const.txt +++ b/db/const.txt @@ -710,6 +710,8 @@ AI_ACTION_TYPE_ATTACK 1 AI_ACTION_TYPE_DETECT 2 AI_ACTION_TYPE_DEAD 3 AI_ACTION_TYPE_ASSIST 4 +AI_ACTION_TYPE_KILL 5 +AI_ACTION_TYPE_UNLOCK 6 ALL_CLIENT 0 ALL_SAMEMAP 1 diff --git a/db/mob_avail.txt b/db/mob_avail.txt index c74148d1e..b97c5c032 100644 --- a/db/mob_avail.txt +++ b/db/mob_avail.txt @@ -28,6 +28,8 @@ 1902,14,1,6,6,1101,2105,0,0,0,32,3 // Poki#3 1903,4012,1,21,0,1720,0,102,184,57,16,0 +// Sentry +1904,1286,0 // eAthena Custom Equipped Mobs 1970,1002,10013 diff --git a/db/mob_db2.txt b/db/mob_db2.txt index d5e84a9ee..3baf02364 100644 --- a/db/mob_db2.txt +++ b/db/mob_db2.txt @@ -19,6 +19,7 @@ 1901,VALARIS_WORSHIPPER,Valaris's Worshipper,Valaris's Worshipper,50,8578,0,2706,1480,1,487,590,15,25,1,75,55,1,93,45,10,12,0,6,27,1685,100,868,480,120,0,0,0,0,0,0,0,0,923,500,984,63,1464,2,607,50,610,100,503,300,2405,50,0,0,0,0,4129,1 1902,MC_CAMERI,MC Cameri,MC Cameri,99,668000,0,107250,37895,2,3220,4040,35,45,1,152,96,85,120,95,10,10,2,6,67,1973,100,1068,768,576,13000,5000,608,1000,750,400,923,3800,1466,200,2256,200,2607,800,714,500,617,3000,984,4300,985,5600,0,0,0,0,4147,1 1903,POKI,Poki#3,Poki#3,99,1349000,0,4093000,1526000,9,4892,9113,22,35,1,180,39,67,193,130,10,12,1,7,64,1973,120,500,672,480,92100,7000,603,5500,617,3000,1723,1000,1228,100,1236,500,617,2500,1234,75,1237,125,1722,250,1724,100,1720,50,0,0,0,0 +1904,SENTRY,Sentry,Sentry,99,668000,0,107250,37895,2,3220,4040,35,45,1,152,96,85,120,95,10,10,2,6,67,1973,100,1068,768,576,13000,5000,608,1000,750,400,923,3800,1466,200,2256,200,2607,800,714,500,617,3000,984,4300,985,5600,0,0,0,0,4147,1 // Mobs used for eAthena's Custom Equipped Mobs 1970,PORING_,Pet Poring,Pet Poring,1,50,0,2,1,1,7,10,0,5,1,1,1,1,6,30,10,12,1,3,21,131,400,1872,672,480,0,0,0,0,0,0,0,0,909,7000,1202,100,938,400,512,1000,713,1500,741,5,619,20,0,0,0,0,4001,20 diff --git a/npc/custom/Lance/Sentry.cpp b/npc/custom/Lance/Sentry.cpp new file mode 100644 index 000000000..e76ff18f2 --- /dev/null +++ b/npc/custom/Lance/Sentry.cpp @@ -0,0 +1,119 @@ +//(=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=) +//( (c)2006 eAthena Development Team presents ) +//( ______ __ __ ) +//( /\ _ \/\ \__/\ \ v 1.00.00 ) +//( __\ \ \_\ \ \ ,_\ \ \___ __ ___ __ ) +//( /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ ) +//( /\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \_\.\_ ) +//( \ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ ) +//( \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ ) +//( _ _ _ _ _ _ _ _ _ _ _ _ _ ) +//( / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ ) +//( ( e | A | t | h | e | n | a ) ( S | c | r | i | p | t ) ) +//( \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ ) +//( ) +//(=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=) +// Programmed by [Lance] ver. 1.0 +// --------------------------------------------------------- +// [ Sentry System ] +// - Guards main towns against aggresive monsters and bad +// players. +// [ Customization ] +// - See OnInit: +// ========================================================= + +- script sentry_system -1,{ + function spawn_guardian { + set .mob_id[getarg(0)], spawnmob("Guardian Sentry",1904,.mob_map$[getarg(0)],.mob_x[getarg(0)],.mob_y[getarg(0)]); + mobattach .mob_id[getarg(0)]; // Attach events to this script. + mobrandomwalk .mob_id[getarg(0)], 0; // Prevents random walking. + mobattack .mob_id[getarg(0)]; // Enable all viewing. + return; + } + + function search_entry { + set .@tmp, getarraysize(getarg(0)); + for(set .@i, 0; .@i < .@tmp; set .@i, .@i + 1){ + if(getelementofarray(getarg(0),.@i) == getarg(1)) + break; + } + if(.@i == .@tmp) + return -1; + else + return .@i; + } + + // Script Entry Point - When an event from the script engine is received. + if(getarraysize(.ai_action) == 4){ // Checks if the data is formatted correctly. + set .@tmp, search_entry(.mob_id, .ai_action[AI_ACTION_SRC]); + switch(.ai_action[AI_ACTION_TYPE]){ + case AI_ACTION_TYPE_DETECT: // We see something... + if(.ai_busy[.@tmp] == 0){ // Not busy + switch(.ai_action[AI_ACTION_TAR_TYPE]){ // Check what have we here. + case AI_ACTION_TAR_TYPE_PC: // It's a player + if(getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) > .karma){ // pkarma is higher? + mobtalk .ai_action[AI_ACTION_SRC], "Who goes there!"; + mobemote .ai_action[AI_ACTION_SRC], e_gasp; // ! + mobattack .ai_action[AI_ACTION_SRC],.ai_action[AI_ACTION_TAR]; + // We're currently busy. + set .ai_busy[.@tmp], .ai_action[AI_ACTION_TAR]; + } + break; + case AI_ACTION_TAR_TYPE_MOB: // It's a monster + if(.ai_action[AI_ACTION_TAR] != .ai_action[AI_ACTION_SRC]){ + getmobdata .ai_action[AI_ACTION_TAR], .@temp; + if(.@temp[9]&0x804){ // In Aggressive mode? + mobtalk .ai_action[AI_ACTION_SRC], "Protect the villagers we must!"; + mobemote .ai_action[AI_ACTION_SRC], e_gasp; // ! + mobattack .ai_action[AI_ACTION_SRC],.ai_action[AI_ACTION_TAR]; + // We're currently busy. + set .ai_busy[.@tmp], .ai_action[AI_ACTION_TAR]; + } + } + break; + } + } + break; + case AI_ACTION_TYPE_KILL: // We eliminated the criminal + if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC) + setd "$pkarma_"+.ai_action[AI_ACTION_TAR], 0; + case AI_ACTION_TYPE_UNLOCK: // Target lost :( + if(.@tmp != -1){ + set .ai_busy[.@tmp], 0; // Remove him, we're free. + } + // Walk back to where we came from. + mobwalk .ai_action[AI_ACTION_SRC],.mob_x[.@tmp],.mob_y[.@tmp]; + break; + case AI_ACTION_TYPE_DEAD: // We got killed :( + if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC){ // Attacker is a player? + setd "$pkarma_"+.ai_action[AI_ACTION_TAR], getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) + 5; + } + sleep 10000; // 10 seconds until reinforcements arrive + spawn_guardian .@tmp; + break; + case AI_ACTION_TYPE_ATTACK: // Someone attacked us + if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC){ // Attacker is a player? + setd "$pkarma_"+.ai_action[AI_ACTION_TAR], getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) + 1; + } + // The system's AI will auto attack any attackers. So we leave it here. + break; + } + } + deletearray .ai_action, getarraysize(.ai_action); // Cleans up and frees up memory + end; + +OnInit: + // Customization --------------------------------------------------------------------- + setarray .mob_map$, "prt_fild08.gat", "prt_fild05.gat", "prt_fild06.gat", "prt_gld.gat"; + setarray .mob_x,176,369,29,165; + setarray .mob_y,372,201,187,37; + set .karma, 5; + // ----------------------------------------------------------------------------------- + set .@tmp, getarraysize(.mob_map$); + for(set .@i, 0; .@i < .@tmp; set .@i, .@i + 1){ + spawn_guardian .@i; + } + debugmes "[Sentry System] Spawned " + .@i + " guardians."; + end; + +} \ No newline at end of file diff --git a/npc/sample/monster_controller.cpp b/npc/sample/monster_controller.cpp index 035215300..385059d31 100644 --- a/npc/sample/monster_controller.cpp +++ b/npc/sample/monster_controller.cpp @@ -69,14 +69,26 @@ prontera.gat,180,200,4 script Monster Controller 123,{ break; } - if(.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_ATTACK) - set .@action_type$, "Attacked by"; - else if(.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_DETECT) - set .@action_type$, "Detected"; - else if (.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_ASSIST) - set .@action_type$, "Killed by"; - else - set .@action_type$, "Assisting"; + switch(.ai_action[AI_ACTION_TYPE]){ + case AI_ACTION_TYPE_ATTACK: + set .@action_type$, "Attacked by"; + break; + case AI_ACTION_TYPE_DETECT: + set .@action_type$, "Detected"; + break; + case AI_ACTION_TYPE_DEAD: + set .@action_type$, "Killed by"; + break; + case AI_ACTION_TYPE_ASSIST: + set .@action_type$, "Assisting"; + break; + case AI_ACTION_TYPE_UNLOCK: + set .@action_type$, "Unlocked target"; + break; + case AI_ACTION_TYPE_KILL: + set .@action_type$, "Killed"; + break; + } announce "Details - " + .@action_type$ + " [" + .@action_from$ + "] " + .@action_name$ + "!", bc_all; deletearray .ai_action, 4; diff --git a/npc/scripts_custom.conf b/npc/scripts_custom.conf index 88002b121..8207d8b1a 100644 --- a/npc/scripts_custom.conf +++ b/npc/scripts_custom.conf @@ -20,7 +20,6 @@ //npc: npc/location/to/script.txt // Your scripts go here!! // -------------------------------------------------------------- -//npc: npc/sample/monster_controller.cpp // ----------------------- Basic Scripts ----------------------- // -- Adoption NPC [Fredzilla] npc: npc/custom/adoption.txt @@ -91,6 +90,8 @@ npc: npc/custom/adoption.txt //npc: npc/custom/Lance/FR_WeatherController.c //npc: npc/custom/Lance/FR_MailSystem.c //npc: npc/sample/npc_dynamic_shop.txt +//npc: npc/sample/monster_controller.cpp +//npc: npc/custom/Lance/Sentry.cpp // -------------------------------------------------------------- // -------------------------------------------------------------- diff --git a/src/map/mob.c b/src/map/mob.c index efa632ef9..1b148f629 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -808,7 +808,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) setd_sub(NULL, NULL, ".ai_action", 2, (void *)bl->id, &md->nd->u.scr.script->script_vars); setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars); run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id); - return 0; // We have script handling the work. + return 1; // We have script handling the work. } if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) @@ -997,6 +997,15 @@ int mob_unlocktarget(struct mob_data *md,int tick) { nullpo_retr(0, md); + if(md->nd){ + struct block_list *tbl = map_id2bl(md->target_id); + setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)6, &md->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)(tbl?tbl->type:0), &md->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 2, (void *)(tbl?tbl->id:0), &md->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars); + run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id); + } + md->target_id=0; md->state.skillstate=MSS_IDLE; md->next_walktime=tick+rand()%3000+3000; @@ -2160,6 +2169,17 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) guild_agit_break(md); } + if(src->type == BL_MOB){ + struct mob_data *smd = (struct mob_data *)src; + if(smd->nd){ + setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)5, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)md->bl.type, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 2, (void *)md->bl.id, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 3, (void *)smd->bl.id, &smd->nd->u.scr.script->script_vars); + run_script(smd->nd->u.scr.script, 0, 0, smd->nd->bl.id); + } + } + if(md->nd){ setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)3, &md->nd->u.scr.script->script_vars); setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)src->type, &md->nd->u.scr.script->script_vars); diff --git a/src/map/pc.c b/src/map/pc.c index 2cce8cfa6..771bd5c7e 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4527,37 +4527,48 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) } clif_clearchar_area(&sd->bl,1); - if (src && src->type == BL_PC) { - struct map_session_data *ssd = (struct map_session_data *)src; - if (ssd) { - if (sd->state.event_death) - pc_setglobalreg(sd,"killerrid",(ssd->status.account_id)); - if (ssd->state.event_kill_pc) { - pc_setglobalreg(ssd, "killedrid", sd->bl.id); - npc_script_event(ssd, NPCE_KILLPC); + if (src) { + if(src->type == BL_MOB){ + struct mob_data *smd = (struct mob_data *)src; + if(smd->nd){ + setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)5, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)sd->bl.type, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 2, (void *)sd->bl.id, &smd->nd->u.scr.script->script_vars); + setd_sub(NULL, NULL, ".ai_action", 3, (void *)smd->bl.id, &smd->nd->u.scr.script->script_vars); + run_script(smd->nd->u.scr.script, 0, 0, smd->nd->bl.id); } - if (battle_config.pk_mode && ssd->status.manner >= 0 && battle_config.manner_system) { - ssd->status.manner -= 5; - if(ssd->status.manner < 0) - sc_start(src,SC_NOCHAT,100,0,0); - - // PK/Karma system code (not enabled yet) [celest] - // originally from Kade Online, so i don't know if any of these is correct ^^; - // note: karma is measured REVERSE, so more karma = more 'evil' / less honourable, - // karma going down = more 'good' / more honourable. - // The Karma System way... - /*if (sd->status.karma > ssd->status.karma) { // If player killed was more evil - sd->status.karma--; - ssd->status.karma--; + } else if(src->type == BL_PC){ + struct map_session_data *ssd = (struct map_session_data *)src; + if (ssd) { + if (sd->state.event_death) + pc_setglobalreg(sd,"killerrid",(ssd->status.account_id)); + if (ssd->state.event_kill_pc) { + pc_setglobalreg(ssd, "killedrid", sd->bl.id); + npc_script_event(ssd, NPCE_KILLPC); + } + if (battle_config.pk_mode && ssd->status.manner >= 0 && battle_config.manner_system) { + ssd->status.manner -= 5; + if(ssd->status.manner < 0) + sc_start(src,SC_NOCHAT,100,0,0); + + // PK/Karma system code (not enabled yet) [celest] + // originally from Kade Online, so i don't know if any of these is correct ^^; + // note: karma is measured REVERSE, so more karma = more 'evil' / less honourable, + // karma going down = more 'good' / more honourable. + // The Karma System way... + /*if (sd->status.karma > ssd->status.karma) { // If player killed was more evil + sd->status.karma--; + ssd->status.karma--; + } + else if (sd->status.karma < ssd->status.karma) // If player killed was more good + ssd->status.karma++;*/ + + // or the PK System way... + /* if (sd->status.karma > 0) // player killed is dishonourable? + ssd->status.karma--; // honour points earned + sd->status.karma++; // honour points lost */ + // To-do: Receive exp on certain occasions } - else if (sd->status.karma < ssd->status.karma) // If player killed was more good - ssd->status.karma++;*/ - - // or the PK System way... - /* if (sd->status.karma > 0) // player killed is dishonourable? - ssd->status.karma--; // honour points earned - sd->status.karma++; // honour points lost */ - // To-do: Receive exp on certain occasions } } } else { diff --git a/src/map/script.c b/src/map/script.c index 75ed89db6..d6d5e7123 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10514,37 +10514,38 @@ int buildin_getmobdata(struct script_state *st) { int num, id; char *name; struct mob_data *md = NULL; + struct map_session_data *sd = st->rid?map_id2sd(st->rid):NULL; id = conv_num(st, & (st->stack->stack_data[st->start+2])); if(!(md = (struct mob_data *)map_id2bl(id)) || st->stack->stack_data[st->start+3].type!=C_NAME ){ ShowWarning("buildin_getmobdata: Error in argument!\n"); } else { num=st->stack->stack_data[st->start+3].u.num; name=(char *)(str_buf+str_data[num&0x00ffffff].str); - setd_sub(st,map_id2sd(st->rid),name,0,(void *)(int)md->class_,NULL); - setd_sub(st,map_id2sd(st->rid),name,1,(void *)(int)md->level,NULL); - setd_sub(st,map_id2sd(st->rid),name,2,(void *)(int)md->hp,NULL); - setd_sub(st,map_id2sd(st->rid),name,3,(void *)(int)md->max_hp,NULL); - setd_sub(st,map_id2sd(st->rid),name,4,(void *)(int)md->master_id,NULL); - setd_sub(st,map_id2sd(st->rid),name,5,(void *)(int)md->bl.m,NULL); - setd_sub(st,map_id2sd(st->rid),name,6,(void *)(int)md->bl.x,NULL); - setd_sub(st,map_id2sd(st->rid),name,7,(void *)(int)md->bl.y,NULL); - setd_sub(st,map_id2sd(st->rid),name,8,(void *)(int)md->speed,NULL); - setd_sub(st,map_id2sd(st->rid),name,9,(void *)(int)md->mode,NULL); - setd_sub(st,map_id2sd(st->rid),name,10,(void *)(int)md->special_state.ai,NULL); - setd_sub(st,map_id2sd(st->rid),name,11,(void *)(int)md->db->option,NULL); - setd_sub(st,map_id2sd(st->rid),name,12,(void *)(int)md->vd->sex,NULL); - setd_sub(st,map_id2sd(st->rid),name,13,(void *)(int)md->vd->class_,NULL); - setd_sub(st,map_id2sd(st->rid),name,14,(void *)(int)md->vd->hair_style,NULL); - setd_sub(st,map_id2sd(st->rid),name,15,(void *)(int)md->vd->hair_color,NULL); - setd_sub(st,map_id2sd(st->rid),name,16,(void *)(int)md->vd->head_bottom,NULL); - setd_sub(st,map_id2sd(st->rid),name,17,(void *)(int)md->vd->head_mid,NULL); - setd_sub(st,map_id2sd(st->rid),name,18,(void *)(int)md->vd->head_top,NULL); - setd_sub(st,map_id2sd(st->rid),name,19,(void *)(int)md->vd->cloth_color,NULL); - setd_sub(st,map_id2sd(st->rid),name,20,(void *)(int)md->vd->shield,NULL); - setd_sub(st,map_id2sd(st->rid),name,21,(void *)(int)md->vd->weapon,NULL); - setd_sub(st,map_id2sd(st->rid),name,22,(void *)(int)md->vd->shield,NULL); - setd_sub(st,map_id2sd(st->rid),name,23,(void *)(int)md->ud.dir,NULL); - setd_sub(st,map_id2sd(st->rid),name,24,(void *)(int)md->state.killer,NULL); + setd_sub(st,sd,name,0,(void *)(int)md->class_,NULL); + setd_sub(st,sd,name,1,(void *)(int)md->level,NULL); + setd_sub(st,sd,name,2,(void *)(int)md->hp,NULL); + setd_sub(st,sd,name,3,(void *)(int)md->max_hp,NULL); + setd_sub(st,sd,name,4,(void *)(int)md->master_id,NULL); + setd_sub(st,sd,name,5,(void *)(int)md->bl.m,NULL); + setd_sub(st,sd,name,6,(void *)(int)md->bl.x,NULL); + setd_sub(st,sd,name,7,(void *)(int)md->bl.y,NULL); + setd_sub(st,sd,name,8,(void *)(int)md->speed,NULL); + setd_sub(st,sd,name,9,(void *)(int)(md->mode?md->mode:md->db->mode),NULL); + setd_sub(st,sd,name,10,(void *)(int)md->special_state.ai,NULL); + setd_sub(st,sd,name,11,(void *)(int)md->db->option,NULL); + setd_sub(st,sd,name,12,(void *)(int)md->vd->sex,NULL); + setd_sub(st,sd,name,13,(void *)(int)md->vd->class_,NULL); + setd_sub(st,sd,name,14,(void *)(int)md->vd->hair_style,NULL); + setd_sub(st,sd,name,15,(void *)(int)md->vd->hair_color,NULL); + setd_sub(st,sd,name,16,(void *)(int)md->vd->head_bottom,NULL); + setd_sub(st,sd,name,17,(void *)(int)md->vd->head_mid,NULL); + setd_sub(st,sd,name,18,(void *)(int)md->vd->head_top,NULL); + setd_sub(st,sd,name,19,(void *)(int)md->vd->cloth_color,NULL); + setd_sub(st,sd,name,20,(void *)(int)md->vd->shield,NULL); + setd_sub(st,sd,name,21,(void *)(int)md->vd->weapon,NULL); + setd_sub(st,sd,name,22,(void *)(int)md->vd->shield,NULL); + setd_sub(st,sd,name,23,(void *)(int)md->ud.dir,NULL); + setd_sub(st,sd,name,24,(void *)(int)md->state.killer,NULL); } return 0; } diff --git a/src/map/unit.c b/src/map/unit.c index 610590848..9fc3003a1 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1084,8 +1084,8 @@ int unit_attack(struct block_list *src,int target_id,int type) return 0; } - if(battle_check_target(src,target,BCT_ENEMY)<=0 || - !status_check_skilluse(src, target, 0, 0) + if(!(src->type == BL_MOB && !((TBL_MOB *)src)->state.killer) && (battle_check_target(src,target,BCT_ENEMY)<=0 || + !status_check_skilluse(src, target, 0, 0)) ) { unit_unattackable(src); return 1; -- cgit v1.2.3-70-g09d2