summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/mob.c30
-rw-r--r--src/map/script.c126
-rw-r--r--src/map/unit.c2
5 files changed, 106 insertions, 55 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 41c2f9c16..b1e211189 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3439,7 +3439,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
else
state |= BCT_ENEMY; //However, all else are enemies.
} else {
- if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
+ //if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
}
if (md->master_id && (s_bl = map_id2bl(md->master_id)) == NULL)
diff --git a/src/map/map.h b/src/map/map.h
index 19b039b06..1035d014b 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -870,6 +870,7 @@ struct mob_data {
unsigned steal_coin_flag : 1;
unsigned soul_change_flag : 1; // Celest
unsigned alchemist: 1;
+ unsigned no_random_walk: 1;
int provoke_flag; // Celest
} state;
struct guardian_data* guardian_data;
diff --git a/src/map/mob.c b/src/map/mob.c
index 0600ff531..3fbe92375 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -906,6 +906,9 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
return 0;
}
+ if(bl->type == BL_MOB && ((TBL_MOB *)bl)->master_id && ((TBL_MOB *)bl)->master_id != md->master_id) // Just in case something screws up
+ md->master_id = ((TBL_MOB *)bl)->master_id;
+
if(status_get_mode(&md->bl)&MD_CANMOVE)
{ //If the mob can move, follow around. [Check by Skotlex]
@@ -997,7 +1000,7 @@ int mob_randomwalk(struct mob_data *md,int tick)
nullpo_retr(0, md);
- if(DIFF_TICK(md->next_walktime,tick)>0 || !unit_can_move(&md->bl))
+ if(DIFF_TICK(md->next_walktime,tick)>0 || md->state.no_random_walk || !unit_can_move(&md->bl))
return 0;
d =12-md->move_fail_count;
@@ -1509,6 +1512,23 @@ int mob_deleteslave_sub(struct block_list *bl,va_list ap)
mob_damage(NULL,md,md->hp,1);
return 0;
}
+
+int mob_convertslave_sub(struct block_list *bl,va_list ap)
+{
+ struct mob_data *md;
+ int id, master;
+
+ nullpo_retr(0, bl);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, md = (struct mob_data *)bl);
+
+ id=va_arg(ap,int);
+ master=va_arg(ap,int);
+
+ if(md->master_id > 0 && md->master_id == id )
+ md->master_id = master;
+ return 0;
+}
/*==========================================
*
*------------------------------------------
@@ -1520,6 +1540,14 @@ int mob_deleteslave(struct mob_data *md)
map_foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
return 0;
}
+
+int mob_convertslave(struct mob_data *md)
+{
+ nullpo_retr(0, md);
+
+ map_foreachinmap(mob_convertslave_sub, md->bl.m, BL_MOB,md->bl.id,md->master_id);
+ return 0;
+}
// Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
int mob_respawn(int tid, unsigned int tick, int id,int data )
{
diff --git a/src/map/script.c b/src/map/script.c
index 26da3ee8f..ae509106d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -425,6 +425,7 @@ int buildin_mobwalk(struct script_state *st);
int buildin_getmobdata(struct script_state *st);
int buildin_setmobdata(struct script_state *st);
int buildin_mobattack(struct script_state *st);
+int buildin_mobrandomwalk(struct script_state *st);
int buildin_mobstop(struct script_state *st);
int buildin_mobassist(struct script_state *st);
int buildin_mobtalk(struct script_state *st);
@@ -761,6 +762,7 @@ struct {
{buildin_spawnmob,"spawnmob","*"},
{buildin_removemob,"removemob","*"},
{buildin_mobwalk,"mobwalk","*"},
+ {buildin_mobrandomwalk,"mobrandomwalk","*"},
{buildin_getmobdata,"getmobdata","*"},
{buildin_setmobdata,"setmobdata","*"},
{buildin_mobattack,"mobattack","*"},
@@ -10469,18 +10471,23 @@ int buildin_removemob(struct script_state *st) {
}
int buildin_mobwalk(struct script_state *st){
- int id,x,y;
+ int id,x,y = 0;
struct block_list *bl = NULL;
id = conv_num(st, & (st->stack->stack_data[st->start+2]));
x = conv_num(st, & (st->stack->stack_data[st->start+3]));
- y = conv_num(st, & (st->stack->stack_data[st->start+4]));
+ if(st->end > st->start+4)
+ y = conv_num(st, & (st->stack->stack_data[st->start+4]));
bl = map_id2bl(id);
- if(bl && bl->type == BL_MOB)
- push_val(st->stack,C_INT,unit_walktoxy(bl,x,y,0)); // We'll use harder calculations.
- else
+ if(bl && bl->type == BL_MOB){
+ if(y)
+ push_val(st->stack,C_INT,unit_walktoxy(bl,x,y,0)); // We'll use harder calculations.
+ else
+ push_val(st->stack,C_INT,unit_walktobl(bl,map_id2bl(x),1,65025));
+ } else {
push_val(st->stack,C_INT,0);
+ }
return 0;
}
@@ -10491,9 +10498,9 @@ int buildin_getmobdata(struct script_state *st) {
struct mob_data *md = 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 argiment!\n");
+ ShowWarning("buildin_getmobdata: Error in argument!\n");
} else {
- num=st->stack->stack_data[st->start+2].u.num;
+ 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_);
setd_sub(st,map_id2sd(st->rid),name,1,(void *)(int)md->level);
@@ -10626,9 +10633,10 @@ int buildin_mobattack(struct script_state *st) {
if (sd) bl = &sd->bl;
md = (struct mob_data *)map_id2bl(id);
if (md && md->bl.type == BL_MOB) {
- md->target_id = sd->bl.id;
+ md->target_id = bl->id;
md->special_state.ai = 1;
- md->min_chase = distance_bl(bl,&md->bl) + md->db->range2;
+ //md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;
+ unit_walktobl(&md->bl, bl, 65025, 2);
}
}
@@ -10645,12 +10653,22 @@ int buildin_mobstop(struct script_state *st) {
if(bl && bl->type == BL_MOB){
unit_stop_attack(bl);
unit_stop_walking(bl,0);
- ((TBL_MOB*)bl)->master_id = bl->id; // Quick hack to stop random walking.
+ ((TBL_MOB *)bl)->target_id = 0;
}
return 0;
}
+int buildin_mobrandomwalk(struct script_state *st){
+ int id = conv_num(st, &(st->stack->stack_data[st->start+2]));
+ int flag = conv_num(st, &(st->stack->stack_data[st->start+3]));
+ struct mob_data *md = (struct mob_data *)map_id2bl(id);
+ if(md->bl.type == BL_MOB){
+ md->state.no_random_walk = flag>0?0:1;
+ }
+ return 0;
+}
+
int buildin_mobassist(struct script_state *st) {
int id;
char *target;
@@ -10671,7 +10689,8 @@ int buildin_mobassist(struct script_state *st) {
md->target_id = ud->target;
else if (ud->skilltarget)
md->target_id = ud->skilltarget;
- md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;
+ if(md->target_id)
+ unit_walktobl(&md->bl, map_id2bl(md->target_id), 65025, 2);
}
}
}
@@ -11353,9 +11372,12 @@ int run_script_main(struct script_state *st)
if(st->state == END) {
script_free_stack (st->stack);
st->stack = NULL;
+ aFree(st);
+ st = NULL;
+ return 0;
}
- return 0;
+ return 1;
}
/*==========================================
@@ -11411,45 +11433,47 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid)
st->rid = rid;
st->oid = oid;
st->sleep.timer = -1;
- // let's run that stuff
- run_script_main(st);
- if(st->state != END){
- if(st->sleep.tick > 0)
- { //Delay execution
- st->sleep.charid = sd?sd->char_id:0;
- st->sleep.timer = add_timer(gettick()+st->sleep.tick,
- run_script_timer, st->sleep.charid, (int)st);
- linkdb_insert(&sleep_db, (void*)st->oid, st);
- } else if (sd) {
- // script is not finished, store data in sd.
- sd->npc_script = st->script;
- sd->npc_scriptroot = rootscript;
- sd->npc_scriptstate = st->state;
- sd->stack = st->stack;
- if (bck_stack) //Get rid of the backup as it can't be restored.
- script_free_stack (bck_stack);
- }
- return st->pos;
- }
- //Script finished.
- if (sd)
- { //Clear or restore previous script.
- sd->npc_script = bck_script;
- sd->npc_scriptroot = bck_scriptroot;
- sd->npc_scriptstate = bck_scriptstate;
- sd->stack = bck_stack;
- //Since the script is done, save any changed account variables [Skotlex]
- if (sd->state.reg_dirty&2)
- intif_saveregistry(sd,2);
- if (sd->state.reg_dirty&1)
- intif_saveregistry(sd,1);
- }
- if(st->stack) {
- script_free_stack (st->stack);
- st->stack = NULL;
+ if(run_script_main(st)){
+ if(st->state != END){
+ pos = st->pos;
+ if(st->sleep.tick > 0)
+ { //Delay execution
+ st->sleep.charid = sd?sd->char_id:0;
+ st->sleep.timer = add_timer(gettick()+st->sleep.tick,
+ run_script_timer, st->sleep.charid, (int)st);
+ linkdb_insert(&sleep_db, (void*)st->oid, st);
+ } else if (sd) {
+ // script is not finished, store data in sd.
+ sd->npc_script = st->script;
+ sd->npc_scriptroot = rootscript;
+ sd->npc_scriptstate = st->state;
+ sd->stack = st->stack;
+ if (bck_stack) //Get rid of the backup as it can't be restored.
+ script_free_stack (bck_stack);
+ aFree(st);
+ }
+ return pos;
+ } else {
+ if(st->stack)
+ script_free_stack(st->stack);
+ aFree(st);
+ }
+ } else {
+ //Script finished.
+ if (sd)
+ { //Clear or restore previous script.
+ sd->npc_script = bck_script;
+ sd->npc_scriptroot = bck_scriptroot;
+ sd->npc_scriptstate = bck_scriptstate;
+ sd->stack = bck_stack;
+ //Since the script is done, save any changed account variables [Skotlex]
+ if (sd->state.reg_dirty&2)
+ intif_saveregistry(sd,2);
+ if (sd->state.reg_dirty&1)
+ intif_saveregistry(sd,1);
+ }
}
- aFree(st);
return 0;
}
@@ -11457,10 +11481,6 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid)
* 指定ノードをsleep_dbから削除
*------------------------------------------
*/
-/*==========================================
- * 指定ノードをsleep_dbから削除
- *------------------------------------------
- */
struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n)
{
struct linkdb_node *retnode;
diff --git a/src/map/unit.c b/src/map/unit.c
index cf7d88aea..f0ce5c9ca 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1041,6 +1041,7 @@ int unit_stop_attack(struct block_list *bl)
delete_timer( ud->attacktimer, unit_attack_timer );
ud->attacktimer = -1;
+ ud->target = 0;
return 0;
}
@@ -1086,6 +1087,7 @@ int unit_attack(struct block_list *src,int target_id,int type)
if(battle_check_target(src,target,BCT_ENEMY)<=0 ||
!status_check_skilluse(src, target, 0, 0)
) {
+ ShowWarning("%d can't attack. :(",src->id);
unit_unattackable(src);
return 1;
}