summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt1
-rw-r--r--src/map/clif.c1
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/mob.c18
-rw-r--r--src/map/npc.h1
-rw-r--r--src/map/npc_chat.c14
-rw-r--r--src/map/pc.c2
-rw-r--r--src/map/script.c387
8 files changed, 422 insertions, 4 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 719f535c5..3c7e8db1c 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -5,6 +5,7 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. EV
GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
2006/03/15
+ * BL_PC and BL_MOB control script commands (experimental) [Lance]
* Made an adjustment to addspiritball() to allow Gunslingers to summon up to 10 spheres [reddozen]
* Fixed Tarot Card of Fate using time instead of time2 which is the one
that actually holds the effect duration. [Skotlex]
diff --git a/src/map/clif.c b/src/map/clif.c
index 802bbea15..040644127 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9109,6 +9109,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <
#ifdef PCRE_SUPPORT
map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, message, strlen(message), &sd->bl);
+ map_foreachinrange(mob_chat_sub, &sd->bl, AREA_SIZE, BL_MOB, message, strlen(message), &sd->bl);
#endif
// Celest
diff --git a/src/map/map.h b/src/map/map.h
index 8f697a33b..bc79073b5 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -872,6 +872,8 @@ struct mob_data {
int skilltarget;
int def_ele;
int master_id,master_dist;
+
+ struct npc_data *nd;
short skillx,skilly,skillid,skilllv,skillidx;
unsigned int skilldelay[MAX_MOBSKILL];
diff --git a/src/map/mob.c b/src/map/mob.c
index b469ab12e..e239ce836 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2281,15 +2281,27 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int drop_rate;
int base_drop_delay;
int race;
+ char buffer[64];
nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
max_hp = status_get_max_hp(&md->bl);
race = status_get_race(&md->bl);
- if(src && src->type == BL_PC) {
- sd = (struct map_session_data *)src;
- mvp_sd = sd;
+ if(src){
+ if(md->nd){
+ sprintf(buffer, "$@%d_attacker", md->bl.id);
+ set_var(NULL, buffer, src->id);
+ sprintf(buffer, "$@%d_attacktype", md->bl.id);
+ set_var(NULL, buffer, src->type);
+ sprintf(buffer, "%s::OnDamage", md->nd->exname);
+ npc_event_do(buffer);
+ return 0;
+ }
+ if(src->type == BL_PC) {
+ sd = (struct map_session_data *)src;
+ mvp_sd = sd;
+ }
}
if(md->bl.prev==NULL){
diff --git a/src/map/npc.h b/src/map/npc.h
index de885a99c..5d41c87a0 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -16,6 +16,7 @@
#ifdef PCRE_SUPPORT
void npc_chat_finalize(struct npc_data *nd);
+int mob_chat_sub(struct block_list *bl, va_list ap);
#endif
int npc_chat_sub(struct block_list *bl, va_list ap);
int npc_event_dequeue(struct map_session_data *sd);
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index 6c5b513e8..7d8e0e21f 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -372,6 +372,20 @@ void npc_chat_finalize(struct npc_data *nd)
aFree(npcParse);
}
+int mob_chat_sub(struct block_list *bl, va_list ap){
+ int len;
+ unsigned char *msg = NULL;
+ struct map_session_data *sd = NULL;
+ struct mob_data *md = (struct mob_data *)bl;
+ if(md->nd){
+ msg = va_arg(ap,unsigned char*);
+ len = va_arg(ap,int);
+ sd = va_arg(ap,struct map_session_data *);
+ npc_chat_sub(&md->nd->bl, msg, len, sd);
+ }
+ return 0;
+}
+
/**
* Handler called whenever a global message is spoken in a NPC's area
*/
diff --git a/src/map/pc.c b/src/map/pc.c
index b671514ed..5673e91dc 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -4491,7 +4491,7 @@ int pc_stop_following (struct map_session_data *sd)
int pc_follow(struct map_session_data *sd,int target_id)
{
struct block_list *bl = map_id2bl(target_id);
- if (bl == NULL || bl->type != BL_PC)
+ if (bl == NULL /*|| bl->type != BL_PC*/)
return 1;
if (sd->followtimer != -1)
pc_stop_following(sd);
diff --git a/src/map/script.c b/src/map/script.c
index 33d06ddbb..2de03d940 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -404,6 +404,26 @@ int buildin_callshop(struct script_state *st); // [Skotlex]
int buildin_equip(struct script_state *st);
int buildin_autoequip(struct script_state *st);
int buildin_setbattleflag(struct script_state *st);
+// [zBuffer] List of player cont commands --->
+int buildin_pcwalkxy(struct script_state *st);
+int buildin_pctalk(struct script_state *st);
+int buildin_pcemote(struct script_state *st);
+int buildin_pcfollow(struct script_state *st);
+int buildin_pcstopfollow(struct script_state *st);
+// <--- [zBuffer] List of player cont commands
+// [zBuffer] List of mob control commands --->
+int buildin_spawnmob(struct script_state *st);
+int buildin_removemob(struct script_state *st);
+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_mobstop(struct script_state *st);
+int buildin_mobassist(struct script_state *st);
+int buildin_mobtalk(struct script_state *st);
+int buildin_mobemote(struct script_state *st);
+int buildin_mobattach(struct script_state *st);
+// <--- [zBuffer] List of mob control commands
void push_val(struct script_stack *stack,int type,int val);
int run_func(struct script_state *st);
@@ -711,6 +731,26 @@ struct {
{buildin_setitemscript,"setitemscript","is"}, //Set NEW item bonus script. Lupus
{buildin_disguise,"disguise","i"}, //disguise player. Lupus
{buildin_undisguise,"undisguise","i"}, //undisguise player. Lupus
+ // [zBuffer] List of player cont commands --->
+ {buildin_pcwalkxy,"pcwalkxy","iii"},
+ {buildin_pctalk,"pctalk","is"},
+ {buildin_pcemote,"pcemote","ii"},
+ {buildin_pcfollow,"pcfollow","ii"},
+ {buildin_pcstopfollow,"pcstopfollow","i"},
+ // <--- [zBuffer] List of player cont commands
+ // [zBuffer] List of mob control commands --->
+ {buildin_spawnmob,"spawnmob","*"},
+ {buildin_removemob,"removemob","*"},
+ {buildin_mobwalk,"mobwalk","*"},
+ {buildin_getmobdata,"getmobdata","*"},
+ {buildin_setmobdata,"setmobdata","*"},
+ {buildin_mobattack,"mobattack","*"},
+ {buildin_mobstop,"mobstop","*"},
+ {buildin_mobassist,"mobassist","*"},
+ {buildin_mobtalk,"mobtalk","*"},
+ {buildin_mobemote,"mobemote","*"},
+ {buildin_mobattach,"mobattach","*"},
+// <--- [zBuffer] List of mob control commands
{NULL,NULL,NULL},
};
@@ -9787,6 +9827,353 @@ int buildin_delmonsterdrop(struct script_state *st)
}
*/
+// [zBuffer] List of player cont commands --->
+int buildin_pcwalkxy(struct script_state *st){
+ int id, x, y;
+ struct map_session_data *sd = 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(id)
+ sd = map_id2sd(id);
+ else
+ sd = script_rid2sd(st);
+
+ if(sd)
+ pc_walktoxy(sd, x, y);
+
+ return 0;
+}
+
+int buildin_pctalk(struct script_state *st){
+ int id;
+ char *str;
+ char message[255];
+ struct map_session_data *sd = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start + 2]));
+ str = conv_str(st, & (st->stack->stack_data[st->start + 3]));
+
+ if(id)
+ sd = map_id2sd(id);
+ else
+ sd = script_rid2sd(st);
+
+ if(sd){
+ memcpy(message, sd->status.name, NAME_LENGTH);
+ strcat(message," : ");
+ strncat(message,str, 254); //Prevent overflow possibility. [Skotlex]
+ clif_message(&(sd->bl), message);
+ clif_displaymessage(sd->fd, message);
+ }
+
+ return 0;
+}
+
+int buildin_pcemote(struct script_state *st) {
+ int id, emo;
+ struct map_session_data *sd = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start + 2]));
+ emo = conv_num(st, & (st->stack->stack_data[st->start + 3]));
+
+ if(id)
+ sd = map_id2sd(id);
+ else
+ sd = script_rid2sd(st);
+
+ if(sd)
+ clif_emotion(&sd->bl,emo);
+
+ return 0;
+
+}
+
+int buildin_pcfollow(struct script_state *st) {
+ int id, targetid;
+ struct map_session_data *sd = NULL;
+
+
+ id = conv_num(st, & (st->stack->stack_data[st->start + 2]));
+ targetid = conv_num(st, & (st->stack->stack_data[st->start + 3]));
+
+ if(id)
+ sd = map_id2sd(id);
+ else
+ sd = script_rid2sd(st);
+
+ if(sd)
+ pc_follow(sd, targetid);
+
+ return 0;
+}
+
+int buildin_pcstopfollow(struct script_state *st) {
+ int id;
+ struct map_session_data *sd = NULL;
+
+
+ id = conv_num(st, & (st->stack->stack_data[st->start + 2]));
+
+ if(id)
+ sd = map_id2sd(id);
+ else
+ sd = script_rid2sd(st);
+
+ if(sd)
+ pc_stop_following(sd);
+
+ return 0;
+}
+// <--- [zBuffer] List of player cont commands
+// [zBuffer] List of mob control commands --->
+int buildin_spawnmob(struct script_state *st){
+ int class_,x,y,id;
+ char *str,*map,*event="";
+ struct mob_data *md = NULL;
+
+ // Who?
+ str =conv_str(st,& (st->stack->stack_data[st->start+2]));
+ // What?
+ class_ =conv_num(st,& (st->stack->stack_data[st->start+3]));
+ // Where?
+ map =conv_str(st,& (st->stack->stack_data[st->start+4]));
+ x =conv_num(st,& (st->stack->stack_data[st->start+5]));
+ y =conv_num(st,& (st->stack->stack_data[st->start+6]));
+ // When?
+ if( st->end > st->start+8 )
+ event=conv_str(st,& (st->stack->stack_data[st->start+7]));
+
+ id = mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class_,1,event);
+ if(id){
+ md = (struct mob_data *)map_id2bl(id);
+ if(md){
+ md->mode = md->db->mode;
+ }
+ push_val(st->stack,C_INT,id);
+ }
+
+ return 0;
+}
+
+int buildin_removemob(struct script_state *st) {
+ int id;
+ struct mob_data *md = NULL;
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+
+ md = (struct mob_data *)map_id2bl(id);
+ if(md)
+ mob_delete(md);
+
+ return 0;
+}
+
+int buildin_mobwalk(struct script_state *st){
+ int id,x,y;
+ struct mob_data *md = 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]));
+
+ md = (struct mob_data *)map_id2bl(id);
+ if(md)
+ push_val(st->stack,C_INT,mob_walktoxy(md,x,y,0)); // We'll use harder calculations.
+
+ return 0;
+}
+
+int buildin_getmobdata(struct script_state *st) {
+ int num, id;
+ char *name;
+ 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");
+ } else {
+ num=st->stack->stack_data[st->start+2].u.num;
+ name=(char *)(str_buf+str_data[num&0x00ffffff].str);
+ setd_sub(map_id2sd(st->rid),name,0,(void *)md->class_);
+ setd_sub(map_id2sd(st->rid),name,1,(void *)md->level);
+ setd_sub(map_id2sd(st->rid),name,2,(void *)md->hp);
+ setd_sub(map_id2sd(st->rid),name,3,(void *)md->max_hp);
+ setd_sub(map_id2sd(st->rid),name,4,(void *)md->master_id);
+ setd_sub(map_id2sd(st->rid),name,5,(void *)md->bl.m);
+ setd_sub(map_id2sd(st->rid),name,6,(void *)md->bl.x);
+ setd_sub(map_id2sd(st->rid),name,7,(void *)md->bl.y);
+ setd_sub(map_id2sd(st->rid),name,8,(void *)md->speed);
+ setd_sub(map_id2sd(st->rid),name,9,(void *)md->mode);
+ setd_sub(map_id2sd(st->rid),name,10,(void *)md->state.state);
+ setd_sub(map_id2sd(st->rid),name,11,(void *)md->special_state.ai);
+ setd_sub(map_id2sd(st->rid),name,12,(void *)md->db->option);
+ setd_sub(map_id2sd(st->rid),name,13,(void *)md->db->sex);
+ setd_sub(map_id2sd(st->rid),name,14,(void *)md->db->view_class);
+ setd_sub(map_id2sd(st->rid),name,15,(void *)md->db->hair);
+ setd_sub(map_id2sd(st->rid),name,16,(void *)md->db->hair_color);
+ setd_sub(map_id2sd(st->rid),name,17,(void *)md->db->head_buttom);
+ setd_sub(map_id2sd(st->rid),name,18,(void *)md->db->head_mid);
+ setd_sub(map_id2sd(st->rid),name,19,(void *)md->db->head_top);
+ setd_sub(map_id2sd(st->rid),name,20,(void *)md->db->clothes_color);
+ setd_sub(map_id2sd(st->rid),name,21,(void *)md->db->equip);
+ setd_sub(map_id2sd(st->rid),name,22,(void *)md->db->weapon);
+ setd_sub(map_id2sd(st->rid),name,23,(void *)md->db->shield);
+ setd_sub(map_id2sd(st->rid),name,24,(void *)md->dir);
+ }
+ return 0;
+}
+
+int buildin_setmobdata(struct script_state *st){
+ int num, id, i = 0;
+ char *name;
+ struct script_data dat;
+ 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_setmobdata: Error in argiment!\n");
+ } else {
+#define INCREMENT dat.type=C_NAME; dat.u.num=add_str((unsigned char *) name)+(i<<24); get_val(st,&dat); i++
+#define VALUE(x) x = (dat.u.num == -1)? x : dat.u.num
+ num=st->stack->stack_data[st->start+2].u.num;
+ name=(char *)(str_buf+str_data[num&0x00ffffff].str);
+ INCREMENT; VALUE(md->class_); INCREMENT; VALUE(md->level);
+ INCREMENT; VALUE(md->hp); INCREMENT; VALUE(md->max_hp);
+ INCREMENT; VALUE(md->hp); INCREMENT; VALUE(md->master_id);
+ INCREMENT; VALUE(md->bl.m); INCREMENT; VALUE(md->bl.x);
+ INCREMENT; VALUE(md->bl.y); INCREMENT; VALUE(md->speed);
+ INCREMENT; VALUE(md->mode); INCREMENT; VALUE(md->state.state);
+ INCREMENT; VALUE(md->special_state.ai); INCREMENT; VALUE(md->db->option);
+ INCREMENT; VALUE(md->db->sex); INCREMENT; VALUE(md->db->view_class);
+ INCREMENT; VALUE(md->db->hair); INCREMENT; VALUE(md->db->hair_color);
+ INCREMENT; VALUE(md->db->head_buttom); INCREMENT; VALUE(md->db->head_mid);
+ INCREMENT; VALUE(md->db->head_top); INCREMENT; VALUE(md->db->clothes_color);
+ INCREMENT; VALUE(md->db->equip); INCREMENT; VALUE(md->db->weapon);
+ INCREMENT; VALUE(md->dir);
+ }
+ return 0;
+}
+
+int buildin_mobattack(struct script_state *st) {
+ int id;
+ char *target;
+ struct mob_data *md = NULL;
+ struct map_session_data *sd = NULL;
+ struct block_list *bl = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+ target = conv_str(st, & (st->stack->stack_data[st->start+3]));
+
+ if((sd = map_nick2sd(target)) != NULL || (bl = map_id2bl(atoi(target))) != NULL) {
+ if(sd) {
+ md = (struct mob_data *)map_id2bl(id);
+ if(md) {
+ md->target_id = sd->bl.id;
+ md->state.targettype = ATTACKABLE;
+ md->special_state.ai = 1;
+ md->min_chase = distance_bl(bl,&md->bl) + md->db->range2;
+ }
+ } else {
+ if(bl->type == BL_MOB || bl->type == BL_PC) {
+ md = (struct mob_data *)map_id2bl(id);
+ if(md) {
+ md->target_id = bl->id;
+ md->state.targettype = ATTACKABLE;
+ md->special_state.ai = 1;
+ md->min_chase = distance_bl(bl,&md->bl) + md->db->range2;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int buildin_mobstop(struct script_state *st) {
+ int id;
+ struct mob_data *md = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+
+ md = (struct mob_data *)map_id2bl(id);
+ if(md){
+ mob_stopattack(md);
+ mob_stop_walking(md,0);
+ md->master_id = md->bl.id; // Quick hack to stop random walking.
+ }
+
+ return 0;
+}
+
+int buildin_mobassist(struct script_state *st) {
+ int id;
+ char *target;
+ struct mob_data *md = NULL;
+ struct block_list *bl = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+ target = conv_str(st, & (st->stack->stack_data[st->start+3]));
+
+ if((bl =&(map_nick2sd(target)->bl)) || (bl = map_id2bl(atoi(target)))) {
+ md = (struct mob_data *)map_id2bl(id);
+ if(md) {
+ md->master_id = bl->id;
+ if(bl->type == BL_PC)
+ md->target_id = map_id2sd(bl->id)->attacktarget;
+ else if(bl->type == BL_MOB)
+ md->target_id = ((struct mob_data *)bl)->target_id;
+ if(map_id2bl(md->target_id)){
+ md->state.targettype = ATTACKABLE;
+ md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int buildin_mobtalk(struct script_state *st)
+{
+ char *str;
+ int id;
+ char message[255];
+
+ struct mob_data *md = NULL;
+
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+ str=conv_str(st,& (st->stack->stack_data[st->start+3]));
+
+ md = (struct mob_data *)map_id2bl(id);
+ if(md) {
+ memcpy(message, md->name, NAME_LENGTH);
+ strcat(message," : ");
+ strncat(message,str, 254); //Prevent overflow possibility. [Skotlex]
+ clif_message(&(md->bl), message);
+ }
+
+ return 0;
+}
+
+int buildin_mobemote(struct script_state *st) {
+ int id, emo;
+ struct mob_data *md = NULL;
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+ emo = conv_num(st, & (st->stack->stack_data[st->start+3]));
+ if((md = (struct mob_data *)map_id2bl(id)))
+ clif_emotion(&md->bl,emo);
+ return 0;
+}
+
+int buildin_mobattach(struct script_state *st){
+ int id;
+ struct mob_data *md = NULL;
+ id = conv_num(st, & (st->stack->stack_data[st->start+2]));
+ if((md = (struct mob_data *)map_id2bl(id)))
+ md->nd = (struct npc_data *)map_id2bl(st->oid);
+ return 0;
+}
+
+// <--- [zBuffer] List of mob control commands
//
// 実行部main
//