From 6e2c85e3c1a0cea2230909b4714135369aa35639 Mon Sep 17 00:00:00 2001 From: celest Date: Mon, 10 Jan 2005 10:58:12 +0000 Subject: * Added 'max_eventtimer_length' to script_athena.conf * Removed PCLoginEvent requiring 'PCLoginEvent' for the player to be set to 1 first to be activated git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@945 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/script.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/map/script.h') diff --git a/src/map/script.h b/src/map/script.h index b50c46693..5dd266174 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -2,6 +2,16 @@ #ifndef _SCRIPT_H_ #define _SCRIPT_H_ +extern struct Script_Config { + int warn_func_no_comma; + int warn_cmd_no_comma; + int warn_func_mismatch_paramnum; + int warn_cmd_mismatch_paramnum; + int check_cmdcount; + int check_gotocount; + int max_eventtimer_len; +} script_config; + struct script_data { int type; union { -- cgit v1.2.3-70-g09d2 From f4d39edff58dc2a8db9e517a6ffbe738e36b31e9 Mon Sep 17 00:00:00 2001 From: celest Date: Mon, 10 Jan 2005 15:25:24 +0000 Subject: * Completed adding packet DB reading * Added Shinomori's suggestions for npc timers, * Removed checking for script event timers' length, and added Shinomori's changes git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@947 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog.txt | 5 ++ conf-tmpl/script_athena.conf | 4 +- src/map/clif.c | 110 ++++++++++++++++++++++++------------------- src/map/map.h | 2 +- src/map/npc.c | 4 +- src/map/pc.c | 6 +-- src/map/script.c | 9 ++-- src/map/script.h | 1 - 8 files changed, 75 insertions(+), 66 deletions(-) (limited to 'src/map/script.h') diff --git a/Changelog.txt b/Changelog.txt index fea6df566..1edf9f9ed 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,5 +1,10 @@ Date Added 01/10 + * Completed adding packet DB reading... still needs (a lot) more work in + clif.c [celest] + * Added Shinomori's suggestions for npc timers, thanks again ^^ [celest] + * Removed checking for script event timers' length, and added Shinomori's + changes [celest] * Start adding packet DB reading [celest] * Added 'max_eventtimer_length' (default is 32) to script_athena.conf. [celest] Some event timers with names longer than 24 could cause the server to close diff --git a/conf-tmpl/script_athena.conf b/conf-tmpl/script_athena.conf index d47b0d5b5..45ee734f7 100644 --- a/conf-tmpl/script_athena.conf +++ b/conf-tmpl/script_athena.conf @@ -11,6 +11,4 @@ warn_cmd_mismatch_paramnum: yes check_cmdcount: 8192 -check_gotocount: 512 - -max_eventtimer_length: 32 \ No newline at end of file +check_gotocount: 512 \ No newline at end of file diff --git a/src/map/clif.c b/src/map/clif.c index 00de30b59..54bf3a452 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -55,6 +55,9 @@ #define MAX_PACKET_DB 0x224 int packet_db_ver = -1; +int *packet_db_size; +void (**packet_db_parse_func)(); +short packet_db_pos[MAX_PACKET_DB][20]; static const int packet_len_table[MAX_PACKET_DB] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -10159,11 +10162,14 @@ void clif_parse_debug(int fd,struct map_session_data *sd) { int i, cmd; + if (packet_db_ver < 0) + return; + cmd = RFIFOW(fd,0); printf("packet debug 0x%4X\n",cmd); printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); - for(i=0;i 7) { // minimum packet version allowed + packet_db_size = packet_size_table[packet_db_ver - 5]; + packet_db_parse_func = clif_parse_func_table[packet_db_ver - 7]; - cmd=strtol(str[0],(char **)NULL,0); - if(cmd<=0 || cmd>=MAX_PACKET_DB) - continue; + while(fgets(line,1020,fp)){ + if(line[0]=='/' && line[1]=='/') + continue; + memset(str,0,sizeof(str)); + for(j=0,p=line;j<4 && p;j++){ + str[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if(str[0]==NULL) + continue; - if(str[1]==NULL){ - sprintf(tmp_output, "packet_db: packet len error\n"); - ShowError(tmp_output); - continue; - } - packet_size_table[packet_db_ver - 5][cmd] = atoi(str[1]); + cmd=strtol(str[0],(char **)NULL,0); + if(cmd<=0 || cmd>=MAX_PACKET_DB) + continue; - if(str[2]==NULL){ - ln++; - continue; - } - for(j=0;j 2 /* && packet_db[cmd].pos[0] == 0 */) -// printf("packet_db: %d 0x%x %d %s %p\n",ln,cmd,packet_size_table[packet_db_ver - 5][cmd],str[2],clif_parse_func_table[packet_db_ver - 7][cmd]); + ln++; +// if(packet_size_table[packet_db_ver - 5][cmd] > 2 /* && packet_db[cmd].pos[0] == 0 */) +// printf("packet_db: %d 0x%x %d %s %p | %p\n",ln,cmd,packet_db_size[cmd],str[2],packet_db_parse_func[cmd],clif_parse_func_table[packet_db_ver - 7][cmd]); + } } fclose(fp); sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/packet_db.txt"); @@ -10982,6 +10991,9 @@ int do_init_clif(void) { // Size of packet version 16 (packet db) memcpy(&packet_size_table[11], &packet_size_table[10], sizeof(packet_len_table)); + packet_db_size = packet_size_table[0]; + packet_db_parse_func = clif_parse_func_table[0]; + packetdb_readdb(); set_defaultparse(clif_parse); diff --git a/src/map/map.h b/src/map/map.h index e6ad63b08..26fc3e6c8 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -375,7 +375,7 @@ struct npc_data { char *script; short xs,ys; int guild_id; - int timer,timerid,timeramount,nexttimer,timerrid; + int timer,timerid,timeramount,nexttimer,rid; unsigned int timertick; struct npc_timerevent_list *timer_event; int label_list_num; diff --git a/src/map/npc.c b/src/map/npc.c index d2379e5a8..ff752192a 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -589,7 +589,7 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data) nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,next); } - run_script(nd->u.scr.script,te->pos,nd->u.scr.timerrid,nd->bl.id); + run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id); return 0; } /*========================================== @@ -612,7 +612,7 @@ int npc_timerevent_start(struct npc_data *nd) } nd->u.scr.nexttimer=j; nd->u.scr.timertick=gettick(); - nd->u.scr.timerrid=0; // no players attached by default [celest] + nd->u.scr.rid=0; // reset attached player [celest] if(j>=n) return 0; diff --git a/src/map/pc.c b/src/map/pc.c index 5ff5f06fd..2954dfddf 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6791,14 +6791,12 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) nullpo_retr(0, sd); - Assert(strlen(name) < script_config.max_eventtimer_len); - for(i=0;ieventtimer[i]==-1 ) break; if(ieventtimer[i]=add_timer(gettick()+tick, pc_eventtimer,sd->bl.id,(int)evname); sd->eventcount++; diff --git a/src/map/script.c b/src/map/script.c index 6e00d15cb..64e4a7692 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3893,6 +3893,7 @@ int buildin_initnpctimer(struct script_state *st) npc_settimerevent_tick(nd,0); npc_timerevent_start(nd); + nd->u.scr.rid=st->rid; return 0; } /*========================================== @@ -3985,7 +3986,7 @@ int buildin_attachnpctimer(struct script_state *st) if (sd==NULL) return 0; - nd->u.scr.timerrid = sd->bl.id; + nd->u.scr.rid = sd->bl.id; return 0; } @@ -4001,7 +4002,7 @@ int buildin_detachnpctimer(struct script_state *st) else nd=(struct npc_data *)map_id2bl(st->oid); - nd->u.scr.timerrid = 0; + nd->u.scr.rid = 0; return 0; } @@ -7204,7 +7205,6 @@ int script_config_read(char *cfgName) script_config.warn_cmd_mismatch_paramnum=1; script_config.check_cmdcount=8192; script_config.check_gotocount=512; - script_config.max_eventtimer_len=32; fp=fopen(cfgName,"r"); if(fp==NULL){ @@ -7238,9 +7238,6 @@ int script_config_read(char *cfgName) else if(strcmpi(w1,"check_gotocount")==0) { script_config.check_gotocount = battle_config_switch(w2); } - else if(strcmpi(w1,"max_eventtimer_length")==0) { - script_config.max_eventtimer_len = battle_config_switch(w2); - } else if(strcmpi(w1,"import")==0){ script_config_read(w2); } diff --git a/src/map/script.h b/src/map/script.h index 5dd266174..50aac9dd7 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -9,7 +9,6 @@ extern struct Script_Config { int warn_cmd_mismatch_paramnum; int check_cmdcount; int check_gotocount; - int max_eventtimer_len; } script_config; struct script_data { -- cgit v1.2.3-70-g09d2 From ae093dbdc0e90c640d22e7d3c027ce0288e8625e Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@54d463be-8e91-2dee-dedb-b68131a5f0ec> Date: Sun, 23 Jan 2005 21:52:55 +0000 Subject: Made some more changes, reverted some old ones git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@969 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog.txt | 8 ++++++-- src/common/grfio.h | 4 ++-- src/map/map.c | 10 +++++----- src/map/map.h | 4 ++-- src/map/script.c | 10 +++++----- src/map/script.h | 4 ++-- 6 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src/map/script.h') diff --git a/Changelog.txt b/Changelog.txt index 4defcf648..5253c806c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,11 +1,15 @@ Date Added 01/23 + * Reverted back some of the char* changes [SVN 969] [Ajarn] + * Changed parse_script to now return char* [SVN 969] [Ajarn] + * Converted run_script and run_script_main from unsigned char* to char* + [SVN 969] [Ajarn] * Forgot a couple small changes [SVN 35] [Ajarn] * Changed map_data.gat and map_data_other_server.gat from unsigned char* to char* (this might be needed, because of unicode or something, please correct me if I'm wrong) [SVN 34] [Ajarn] - * Converted decode_zip, enconde_zip, remove_control_chars, mapif_sendall*, + * Converted decode_zip, encode_zip, remove_control_chars, mapif_sendall*, and e_mail_check to use char* instead of unsigned char* (again, please test) [SVN 34] [Ajarn] * Modified skill unit group checking in skill_unit_onplace that might have @@ -18,7 +22,7 @@ Date Added * Fixed an error that was in my last commit (optimising g++ build) [SVN 29] [Ajarn] * Made strlib functions char*, instead of unsigned char*. Strings are meant - to be char. (Shouldn't break anyhting, but might, please test this for me) + to be char. (Shouldn't break anything, but might, please test this for me) [SVN 26] [Ajarn] * Added cast for TXT version [SVN 25] [Ajarn] * Added cast from allocation calls, from void* to intended type [SVN 24] [Ajarn] diff --git a/src/common/grfio.h b/src/common/grfio.h index f39e9af1b..3fa257e2f 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -8,8 +8,8 @@ void* grfio_read(char*); // GRFIO data file read void* grfio_reads(char*,int*); // GRFIO data file read & size get int grfio_size(char*); // GRFIO data file size get -int decode_zip(char *dest, unsigned long* destLen, const char* source, unsigned long sourceLen); -int encode_zip(char *dest, unsigned long* destLen, const char* source, unsigned long sourceLen); +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); // Accessor to GRF filenames char *grfio_setdatafile(const char *str); diff --git a/src/map/map.c b/src/map/map.c index 55d571767..f4124eab8 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1652,8 +1652,8 @@ int map_cache_read(struct map_data *m) { static int map_cache_write(struct map_data *m) { int i; - unsigned long len_new , len_old; - char *write_buf; + unsigned long len_new, len_old; + unsigned char *write_buf; if(!map_cache.fp) { return 0; } for(i = 0;i < map_cache.head.nmaps ; i++) { if(!strcmp(m->name,map_cache.map[i].fn)) { @@ -1669,7 +1669,7 @@ static int map_cache_write(struct map_data *m) { if(map_read_flag >= READ_FROM_BITMAP_COMPRESSED) { // 圧縮保存 // さすがに2倍に膨れる事はないという事で - write_buf = (char*)aMallocA(m->xs * m->ys * 2); + write_buf = (unsigned char*)aMallocA(m->xs * m->ys * 2); len_new = m->xs * m->ys * 2; encode_zip(write_buf,&len_new,m->gat,m->xs * m->ys); map_cache.map[i].compressed = 1; @@ -1706,7 +1706,7 @@ static int map_cache_write(struct map_data *m) { if(map_cache.map[i].fn[0] == 0) { // 新しい場所に登録 if(map_read_flag >= READ_FROM_BITMAP_COMPRESSED) { - write_buf = (char*)aMallocA(m->xs * m->ys * 2); + write_buf = (unsigned char*)aMallocA(m->xs * m->ys * 2); len_new = m->xs * m->ys * 2; encode_zip(write_buf,&len_new,m->gat,m->xs * m->ys); map_cache.map[i].compressed = 1; @@ -1929,7 +1929,7 @@ static int map_readmap(int m,char *fn, char *alias, int *map_cache, int maxmap) struct gat_1cell {float high[4]; int type;} *p=NULL; // read & convert fn // again, might not need to be unsigned char - gat = grfio_read(fn); + gat = (char*)grfio_read(fn); if(gat==NULL) { return -1; // さすがにマップが読めないのはまずいので終了する diff --git a/src/map/map.h b/src/map/map.h index 1b699b960..d4f673d6a 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -510,7 +510,7 @@ enum { struct map_data { char name[24]; - char *gat; // NULLなら下のmap_data_other_serverとして扱う + unsigned char *gat; // NULLなら下のmap_data_other_serverとして扱う char *alias; // [MouseJstr] int *gat_fileused[MAX_CELL_TYPE+1+1]; //もしビットマップを使うならこちらを使う、 //上のgatはキャストされてgat_fileused[0]に指す @@ -563,7 +563,7 @@ struct map_data { }; struct map_data_other_server { char name[24]; - char *gat; // NULL固定にして判断 + unsigned char *gat; // NULL固定にして判断 unsigned long ip; unsigned int port; }; diff --git a/src/map/script.c b/src/map/script.c index 35645eaab..083f3cfd1 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1148,7 +1148,7 @@ static void read_constdb(void) * スクリプトの解析 *------------------------------------------ */ -unsigned char* parse_script(unsigned char *src,int line) +char* parse_script(unsigned char *src,int line) { unsigned char *p,*tmpp; int i; @@ -6875,7 +6875,7 @@ int run_func(struct script_state *st) * スクリプトの実行メイン部分 *------------------------------------------ */ -int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_state *st,unsigned char *rootscript) +int run_script_main(char *script,int pos,int rid,int oid,struct script_state *st,char *rootscript) { int c,rerun_pos; int cmdcount=script_config.check_cmdcount; @@ -7009,17 +7009,17 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_ * スクリプトの実行 *------------------------------------------ */ -int run_script(unsigned char *script,int pos,int rid,int oid) +int run_script(char *script,int pos,int rid,int oid) { struct script_stack stack; struct script_state st; struct map_session_data *sd=map_id2sd(rid); - unsigned char *rootscript=script; + char *rootscript=script; if(script==NULL || pos<0) return -1; - if(sd && sd->npc_stackbuf && sd->npc_scriptroot==(char*)rootscript){ + if(sd && sd->npc_stackbuf && sd->npc_scriptroot==rootscript){ // 前回のスタックを復帰 script=sd->npc_script; stack.sp=sd->npc_stack; diff --git a/src/map/script.h b/src/map/script.h index 50aac9dd7..eecc45e8f 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -32,8 +32,8 @@ struct script_state { int defsp,new_pos,new_defsp; }; -unsigned char * parse_script(unsigned char *,int); -int run_script(unsigned char *,int,int,int); +char * parse_script(unsigned char *,int); +int run_script(char *,int,int,int); struct dbt* script_get_label_db(); struct dbt* script_get_userfunc_db(); -- cgit v1.2.3-70-g09d2 From 4431323e09b1ab9875ea8ac67f0ecd1b36420559 Mon Sep 17 00:00:00 2001 From: celest Date: Wed, 16 Feb 2005 08:25:45 +0000 Subject: * Fixed a typo in quests/all_quest.txt * Set 'killerrid' and do PCKillEvent before calling PCDieEvent * Added some new script event related options to script config * Added 10 of the new card effects on the 2/15's patch * Minor rewrites on self and enemy weapon/armor breaking * Added missing code for 'bBreakWeaponRate' and 'bBreakWeaponRate' effects * Added missing code for 'bAddStealRate' effect * Removed redundant 'infinite_autospell' in map_session_data git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@1116 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-SVN.txt | 20 ++++++++ conf-tmpl/script_athena.conf | 25 ++++++++- db/const.txt | 8 ++- doc/item_bonus.txt | 20 ++++++++ npc/Changelog.txt | 1 + npc/quests/all_quest.txt | 2 +- src/map/battle.c | 120 +++++++++++++++++++++++++++++++------------ src/map/map.c | 5 +- src/map/map.h | 12 +++-- src/map/pc.c | 117 ++++++++++++++++++++++++++++++++++------- src/map/script.c | 43 ++++++++++++++-- src/map/script.h | 7 +++ src/map/skill.c | 116 ++++++++++++++++++++++++++--------------- src/map/status.c | 24 +++++++++ 14 files changed, 409 insertions(+), 111 deletions(-) (limited to 'src/map/script.h') diff --git a/Changelog-SVN.txt b/Changelog-SVN.txt index 87da4e190..bbbe894e7 100644 --- a/Changelog-SVN.txt +++ b/Changelog-SVN.txt @@ -1,6 +1,25 @@ Date Added 02/16 + * Set 'killerrid' and do PCKillEvent before calling PCDieEvent, thanks to + mrmagoo for pointing it out [celest] + + * Added some new script event related options to script config [celest] + + - [die/kill/login/logout]_event_name: Name of script to activate when an + event has occured + - event_requires_trigger: whether or not a 'set [EventName],1;' has to be + defined first for the event to be activated + + * Added 10 of the new card effects on the 2/15's patch (still untested and + not yet added to the item_db) + - Refer to doc/item_bonus.txt for description + + * Minor rewrites on self and enemy weapon/armor breaking during battle [celest] + * Added missing code for 'bBreakWeaponRate' and 'bBreakWeaponRate' effects + [celest] + * Added missing code for 'bAddStealRate' effect [celest] + * Removed redundant 'infinite_autospell' in map_session_data [celest] * Fixed Treasure Box spawn bug in all castles. [Lupus] * Fixed wrong PresentLOG (it wasn't showing PRESENT BOX type ID) [Lupus] * Expanded Monsters Drops Slots from 8 to 10. Everywhere in the sources. [Lupus] @@ -10,6 +29,7 @@ Date Added On expanding MOB_DB.TXT we'll remove that plug. We are adding new cards and some monsters have no free slots for them. Current state is tested and works fine. + 02/15 * Allow Potion Pitcher to be able to cast on yourself -- i've almost forgot about this, thanks to Filougarou and Poki#3 for the fix ^^; [celest] diff --git a/conf-tmpl/script_athena.conf b/conf-tmpl/script_athena.conf index 45ee734f7..bc8f1c907 100644 --- a/conf-tmpl/script_athena.conf +++ b/conf-tmpl/script_athena.conf @@ -11,4 +11,27 @@ warn_cmd_mismatch_paramnum: yes check_cmdcount: 8192 -check_gotocount: 512 \ No newline at end of file +check_gotocount: 512 + + +//---- Custom script functions ---- + +// 0 - Event script is defined as an NPC by itself +// 1 - Event script can be called by script label +event_script_type: 0 + +// Name of event when a player has died +die_event_name: PCDieEvent + +// Name of event when a player kills something +kill_event_name: PCKillEvent + +// Name of event when a player logs out +logout_event_name: PCLogoutEvent + +// Name of event when a player logs in +login_event_name: PCLoginEvent + +// For events to be activated do we require +// a 'set [EventName],1;' to be called first? +event_requires_trigger: yes diff --git a/db/const.txt b/db/const.txt index 71082acce..e8cd07893 100644 --- a/db/const.txt +++ b/db/const.txt @@ -110,8 +110,8 @@ MaxHp 6 1 Sp 7 1 MaxSp 8 1 BaseJob 119 1 -Karma 4 -Manner 5 +Karma 4 1 +Manner 5 1 bMaxHP 6 bMaxSP 8 @@ -241,9 +241,7 @@ bAddEffWhenHit 2016 bAutoSpellWhenHit 2017 bSkillAtk 2018 bUnstripable 2019 -bAddMob 2020 -bSubMob 2021 -bAddByMob 2022 +bAddDamageByClass 2020 Eff_Stone 0 diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt index 30202ee2d..818a1980f 100644 --- a/doc/item_bonus.txt +++ b/doc/item_bonus.txt @@ -135,3 +135,23 @@ bonus3 bAutoSpell,n,x,y; Auto Spell casting of spell n at level x with y% chanc // bAddDamageClass, bAddMagicDamageClass and bAddMonsterDropItem it is setting possible up to 10. Those which exceed 10 are ignored. // those which can be used with the arrow are only bCritical, bAtkEle, bHit, bAddEle, bAddRace, bAddSize and bAddEff. The other things are ignored. + + + +//---- 2/15 new card effects ---- + +bonus bCritAtkRate,n; Increase critical damage by +n% +bonus bNoRegen,n; Stops regeneration for n. + n: 1=HP, 2=SP +bonus bUnstripable,n; Armor cannot be taken off via Strip skills + +bonus2 bCriticalAddRace,n,x; Increase critical + n vs. enemies of type x + +bonus2 bAddEffWhenHit,n,x; n% chance to cause x state to the enemy when + being hit by physical close range damage +bonus2 bSkillAtk,n,x; Increase damage of skill n by x% +bonus2 bAddDamageByClass,n,x; When being hit by monster of class n increase + damage taken by x% + +bonus3 bAutoSpellWhenHit,x,y,n; n% chance to cast skill x of level y when + being hit by physical close range damage diff --git a/npc/Changelog.txt b/npc/Changelog.txt index 12a9e1871..afd47834e 100644 --- a/npc/Changelog.txt +++ b/npc/Changelog.txt @@ -35,6 +35,7 @@ Other Ppl Date Added ====== 02/16 + * Fixed a typo in quests/all_quest.txt, thanks to hongmei [celest] * Fixed treasure chests spawn in the castles. (had to simplify some code and unroll some loops) [Lupus] 02/13 diff --git a/npc/quests/all_quest.txt b/npc/quests/all_quest.txt index a6a6e3264..73a47c6e7 100644 --- a/npc/quests/all_quest.txt +++ b/npc/quests/all_quest.txt @@ -501,7 +501,7 @@ LCancel6: Headset: mes "[Quest Assistant]"; mes "These are Articles needed for my Grandfather's masterpiece."; - mes "^3355FF100 Steel^000000"; + mes "^3355FF40 Steel^000000"; mes "^3355FF1 Oridecon^000000"; mes "^3355FF1 Alchol^000000"; mes "^3355FF1 Coal^000000"; diff --git a/src/map/battle.c b/src/map/battle.c index aa94ac9fc..35b1d2737 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1508,6 +1508,12 @@ static struct Damage battle_calc_mob_weapon_attack( break; } } + for(i=0;iadd_damage_class_count2;i++) { + if(tsd->add_damage_classid2[i] == md->class_) { + cardfix=cardfix*(100+tsd->add_damage_classrate2[i])/100; + break; + } + } if(flag&BF_LONG) cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; if(flag&BF_SHORT) @@ -1776,6 +1782,7 @@ static struct Damage battle_calc_pc_weapon_attack( if(da == 0){ //ダブルアタックが発動していない // クリティカル計算 cri = status_get_critical(src); + cri += sd->critaddrace[t_race]; if(sd->state.arrow_atk) cri += sd->arrow_cri; @@ -1798,7 +1805,6 @@ static struct Damage battle_calc_pc_weapon_attack( else cri <<= 1; } - if(skill_num == SN_SHARPSHOOTING) cri += 200; } @@ -1812,13 +1818,16 @@ static struct Damage battle_calc_pc_weapon_attack( damage += atkmax; damage2 += atkmax_; if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) { - if (sd->status.weapon < 16) { - damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; - damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; - } + if (sd->status.weapon < 16) { + damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100; + } } if(sd->state.arrow_atk) damage += sd->arrow_atk; + + damage += damage * sd->crit_atk_rate / 100; + type = 0x0a; /* if(def1 < 1000000) { @@ -2322,6 +2331,8 @@ static struct Damage battle_calc_pc_weapon_attack( damage *= div_; damage2 *= div_; } + if (sd && skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; } if(da == 2) { //三段掌が発動しているか type = 0x08; @@ -2815,37 +2826,45 @@ struct Damage battle_calc_weapon_attack( memset(&wd,0,sizeof(wd)); if(battle_config.equipment_breaking && src->type==BL_PC && (wd.damage > 0 || wd.damage2 > 0)) { - struct map_session_data *sd=(struct map_session_data *)src; - int breakrate = 1; //0.01% weapon breaking chance [DracoRPG] - - if(sd->status.weapon && sd->status.weapon != 11) { - if(sd->sc_data[SC_MELTDOWN].timer!=-1) { - int breakrate_; // separate breaking rates for meltdown [Celest] - breakrate_ = 100*sd->sc_data[SC_MELTDOWN].val1; - if(rand()%10000 < breakrate_*battle_config.equipment_break_rate/100 || breakrate_ >= 10000) { - if (target->type == BL_PC) - pc_breakweapon((struct map_session_data *)target); - else - status_change_start(target,SC_STRIPWEAPON,1,75,0,0,skill_get_time2(WS_MELTDOWN,1),0 ); - } - - breakrate_ = 70*sd->sc_data[SC_MELTDOWN].val1; - if (rand()%10000 < breakrate_*battle_config.equipment_break_rate/100 || breakrate_ >= 10000) { - if (target->type == BL_PC) - pc_breakarmor((struct map_session_data *)target); - else - status_change_start(target,SC_STRIPSHIELD,1,75,0,0,skill_get_time2(WS_MELTDOWN,1),0 ); - } + struct map_session_data *sd = (struct map_session_data *)src; + // weapon = 0, armor = 1 + int breakrate = 1; //0.01% default self weapon breaking chance [DracoRPG] + int breakrate_[2] = {0,0}; //enemy breaking chance [celest] + int breaktime = 5000; + + breakrate_[0] += sd->break_weapon_rate; + breakrate_[1] += sd->break_armor_rate; + + if (sd->sc_count) { + if (sd->sc_data[SC_MELTDOWN].timer!=-1) { + breakrate_[0] += 100*sd->sc_data[SC_MELTDOWN].val1; + breakrate_[1] = 70*sd->sc_data[SC_MELTDOWN].val1; + breaktime = skill_get_time2(WS_MELTDOWN,1); } if(sd->sc_data[SC_OVERTHRUST].timer!=-1) - breakrate += 10; //+ 0.1% whatever skill level you use [DracoRPG] + breakrate += 10; + } - //if(wd.type==0x0a) //removed! because CRITS don't affect on breaking chance [Lupus] - // breakrate*=2; - if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) { - if(pc_breakweapon(sd)==1) + if(sd->status.weapon && sd->status.weapon != 11) { + if(rand() % 10000 < breakrate * battle_config.equipment_break_rate / 100 || breakrate >= 10000) + if (pc_breakweapon(sd) == 1) wd = battle_calc_pc_weapon_attack(src,target,skill_num,skill_lv,wflag); - } + } + if(rand() % 10000 < breakrate_[0] * battle_config.equipment_break_rate / 100 || breakrate_[0] >= 10000) { + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd->status.weapon != 11) + pc_breakweapon(tsd); + } else + status_change_start(target,SC_STRIPWEAPON,1,75,0,0,breaktime,0); + } + if(rand() % 10000 < breakrate_[1] * battle_config.equipment_break_rate/100 || breakrate_[1] >= 10000) { + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd->status.weapon != 11) + pc_breakarmor(tsd); + } else + status_change_start(target,SC_STRIPSHIELD,1,75,0,0,breaktime,0); } } @@ -3084,6 +3103,8 @@ struct Damage battle_calc_magic_attack( } } damage=damage*cardfix/100; + if (skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; } if( tsd ){ @@ -3283,6 +3304,9 @@ struct Damage battle_calc_misc_attack( cardfix=cardfix*(100-tsd->misc_def_rate)/100; damage=damage*cardfix/100; } + if (sd && skill_num > 0 && sd->skillatk[0] == skill_num) + damage += damage*sd->skillatk[1]/100; + if(damage < 0) damage = 0; damage=battle_attr_fix(damage, ele, status_get_element(target) ); // 属性修正 } @@ -3517,7 +3541,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } } if(sd) { - if(sd->autospell_id > 0 && sd->autospell_lv > 0 && rand()%100 < sd->autospell_rate) { + if(sd->autospell_id > 0 && rand()%100 < sd->autospell_rate) { int skilllv=sd->autospell_lv,i,f=0,sp; i = rand()%100; if(i >= 50) skilllv -= 2; @@ -3564,6 +3588,36 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if (hp || sp) pc_heal(sd, hp, sp); } } + if (target->type == BL_PC) { + struct map_session_data *tsd = (struct map_session_data *)target; + if(tsd->autospell2_id > 0 && rand()%100 < tsd->autospell2_rate) { + int skilllv = tsd->autospell_lv,i,f=0,sp; + i = rand()%100; + if(i >= 50) skilllv -= 2; + else if(i >= 15) skilllv--; + if(skilllv < 1) skilllv = 1; + sp = skill_get_sp(tsd->autospell2_id,skilllv)*2/3; + if(tsd->status.sp >= sp) { + if((i=skill_get_inf(tsd->autospell2_id) == 2) || i == 32) + f = skill_castend_pos2(target,src->x,src->y,tsd->autospell2_id,skilllv,tick,flag); + else { + switch( skill_get_nk(tsd->autospell2_id) ) { + case 0: case 2: + f = skill_castend_damage_id(target,src,tsd->autospell2_id,skilllv,tick,flag); + break; + case 1:/* 支援系 */ + if((tsd->autospell2_id==AL_HEAL || (tsd->autospell2_id==ALL_RESURRECTION && src->type != BL_PC)) && + battle_check_undead(status_get_race(src),status_get_elem_type(src))) + f = skill_castend_damage_id(target,src,tsd->autospell2_id,skilllv,tick,flag); + else + f = skill_castend_nodamage_id(target,src,tsd->autospell2_id,skilllv,tick,flag); + break; + } + } + if(!f) pc_heal(tsd,0,-sp); + } + } + } if(rdamage > 0) battle_damage(target,src,rdamage,0); diff --git a/src/map/map.c b/src/map/map.c index f47d705c1..ee597789c 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1426,9 +1426,10 @@ int map_quit(struct map_session_data *sd) { if (sd->state.event_disconnect) { struct npc_data *npc; - if ((npc = npc_name2id("PCLogoutEvent"))) { + if ((npc = npc_name2id(script_config.logout_event_name))) { run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC - ShowStatus("Event '"CL_WHITE"PCLogoutEvent"CL_RESET"' executed.\n"); + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name); + ShowStatus(tmp_output); } } diff --git a/src/map/map.h b/src/map/map.h index ef104680b..4c5dbb15e 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -275,15 +275,17 @@ struct map_session_data { int weapon_coma_ele[10],weapon_coma_race[12]; int break_weapon_rate,break_armor_rate; short add_steal_rate; - //--- 02/15's new card effectds [celest] + //--- 02/15's new card effects [celest] int crit_atk_rate; - int critaddrace[12],critaddrace_[12],arrow_critaddrace[12]; + int critaddrace[12]; int no_regen; - int addeff3[10], arrow_addeff3[10]; + int addeff3[10]; short autospell2_id,autospell2_lv,autospell2_rate; int skillatk[2]; unsigned short unstripable_equip; - int addmob[2],submob[2],addbymob[2]; + short add_damage_classid2[10]; + int add_damage_classrate2[10]; + int add_damage_class_count2; short spiritball, spiritball_old; int spirit_timer[MAX_SKILL_LEVEL]; @@ -625,7 +627,7 @@ enum { SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017 SP_SKILL_ATK, SP_UNSTRIPABLE, // 2018-2019 - SP_ADDMOB, SP_SUBMOB, SP_ADDBYMOB // 2020-2022 + SP_ADD_DAMAGE_BY_CLASS // 2020-2022 }; enum { diff --git a/src/map/pc.c b/src/map/pc.c index 8cfebbaf2..c8ab8fae4 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -808,9 +808,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER"); // Automated script events - sd->state.event_death = pc_readglobalreg(sd,"PCDieEvent"); - sd->state.event_kill = pc_readglobalreg(sd,"PCKillEvent"); - sd->state.event_disconnect = pc_readglobalreg(sd,"PCLogoffEvent"); + if (script_config.event_requires_trigger) { + sd->state.event_death = pc_readglobalreg(sd,"PCDieEvent"); + sd->state.event_kill = pc_readglobalreg(sd,"PCKillEvent"); + sd->state.event_disconnect = pc_readglobalreg(sd,"PCLogoffEvent"); + // if script triggers are not required + } else { + sd->state.event_death = 1; + sd->state.event_kill = 1; + sd->state.event_disconnect = 1; + } if (night_flag == 1 && !map[sd->bl.m].flag.indoors) { char tmpstr[1024]; @@ -835,9 +842,10 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars { struct npc_data *npc; //printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") ); - if ((npc = npc_name2id("PCLoginEvent"))) { + if ((npc = npc_name2id(script_config.login_event_name))) { run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLoginNPC - ShowStatus("Event '"CL_WHITE"PCLoginEvent"CL_RESET"' executed.\n"); + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.login_event_name); + ShowStatus(tmp_output); } } // Send friends list @@ -1539,10 +1547,34 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(sd->status.weapon == 11 && sd->state.lr_flag != 2) sd->atk_rate += val; break; + case SP_BREAK_WEAPON_RATE: + if(sd->state.lr_flag != 2) + sd->break_weapon_rate+=val; + break; + case SP_BREAK_ARMOR_RATE: + if(sd->state.lr_flag != 2) + sd->break_armor_rate+=val; + break; + case SP_ADD_STEAL_RATE: + if(sd->state.lr_flag != 2) + sd->add_steal_rate+=val; + break; case SP_DELAYRATE: if(sd->state.lr_flag != 2) sd->delayrate+=val; break; + case SP_CRIT_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->crit_atk_rate += val; + break; + case SP_NO_REGEN: + if(sd->state.lr_flag != 2) + sd->no_regen = val; + break; + case SP_UNSTRIPABLE: + if(sd->state.lr_flag != 2) + sd->unstripable_equip |= EQP_ARMOR; + break; default: if(battle_config.error_log) printf("pc_bonus: unknown type %d %d !\n",type,val); @@ -1758,6 +1790,39 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) if(sd->state.lr_flag != 2) sd->weapon_atk_rate[type2]+=val; break; + case SP_CRITICAL_ADDRACE: + if(sd->state.lr_flag != 2) + sd->critaddrace[type2]+=val; + break; + case SP_ADDEFF_WHENHIT: + if(sd->state.lr_flag != 2) + sd->addeff3[type2]+=val; + break; + case SP_SKILL_ATK: + if(sd->state.lr_flag != 2) { + if (sd->skillatk[0] == type2) + sd->skillatk[1] += val; + else { + sd->skillatk[0] = type2; + sd->skillatk[1] = val; + } + } + break; + case SP_ADD_DAMAGE_BY_CLASS: + if(sd->state.lr_flag != 2) { + for(i=0;iadd_damage_class_count2;i++) { + if(sd->add_damage_classid2[i] == type2) { + sd->add_damage_classrate2[i] += val; + break; + } + } + if(i >= sd->add_damage_class_count2 && sd->add_damage_class_count2 < 10) { + sd->add_damage_classid2[sd->add_damage_class_count2] = type2; + sd->add_damage_classrate2[sd->add_damage_class_count2] += val; + sd->add_damage_class_count2++; + } + } + break; default: if(battle_config.error_log) printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); @@ -1795,6 +1860,13 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) sd->autospell_rate = val; } break; + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2){ + sd->autospell2_id = type2; + sd->autospell2_lv = type3; + sd->autospell2_rate = val; + } + break; default: if(battle_config.error_log) printf("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); @@ -2622,6 +2694,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl) if(itemid > 0 && itemdb_type(itemid) != 6) { rate = (mob_db[md->class_].dropitem[i].p / battle_config.item_rate_common * 100 * skill)/100; + rate += sd->add_steal_rate; if(rand()%10000 < rate) { @@ -4467,25 +4540,27 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) clif_updatestatus(sd,SP_HP); status_calc_pc(sd,0); - if (sd->state.event_death) { - struct npc_data *npc; - if ((npc = npc_name2id("PCDeathEvent"))) { - run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC - ShowStatus("Event '"CL_WHITE"PCDeathEvent"CL_RESET"' executed.\n"); - } - } - if (src && src->type == BL_PC) { + if (sd->state.event_death) + pc_setglobalreg(sd,"killerrid",((struct map_session_data *)src)->status.account_id); + if (((struct map_session_data *)src)->state.event_kill) { struct npc_data *npc; - if ((npc = npc_name2id("PCKillEvent"))) { + if ((npc = npc_name2id(script_config.kill_event_name))) { run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCKillNPC - ShowStatus("Event '"CL_WHITE"PCKillEvent"CL_RESET"' executed.\n"); + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.kill_event_name); + ShowStatus(tmp_output); } - } + } + } - if (sd->state.event_death) - pc_setglobalreg(sd,"killerrid",((struct map_session_data *)src)->status.account_id); + if (sd->state.event_death) { + struct npc_data *npc; + if ((npc = npc_name2id(script_config.die_event_name))) { + run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC + sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.die_event_name); + ShowStatus(tmp_output); + } } if(battle_config.bone_drop==2 @@ -6277,6 +6352,9 @@ static int pc_natural_heal_hp(struct map_session_data *sd) if (sd->sc_count && sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT return 0; + if (sd->no_regen & 1) + return 0; + if(pc_checkoverhp(sd)) { sd->hp_sub = sd->inchealhptick = 0; return 0; @@ -6376,6 +6454,9 @@ static int pc_natural_heal_sp(struct map_session_data *sd) sd->sc_data[SC_BERSERK].timer != -1)) return 0; + if (sd->no_regen & 2) + return 0; + if(pc_checkoversp(sd)) { sd->sp_sub = sd->inchealsptick = 0; return 0; diff --git a/src/map/script.c b/src/map/script.c index 6daa1340a..263aba6bc 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7222,6 +7222,14 @@ int script_config_read(char *cfgName) script_config.check_cmdcount=8192; script_config.check_gotocount=512; + script_config.die_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.kill_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.login_event_name = (char *)aCallocA(24,sizeof(char)); + script_config.logout_event_name = (char *)aCallocA(24,sizeof(char)); + + script_config.event_script_type = 0; + script_config.event_requires_trigger = 1; + fp=fopen(cfgName,"r"); if(fp==NULL){ printf("file not found: %s\n",cfgName); @@ -7254,6 +7262,24 @@ int script_config_read(char *cfgName) else if(strcmpi(w1,"check_gotocount")==0) { script_config.check_gotocount = battle_config_switch(w2); } + else if(strcmpi(w1,"event_script_type")==0) { + script_config.event_script_type = battle_config_switch(w2); + } + else if(strcmpi(w1,"die_event_name")==0) { + strcpy(script_config.die_event_name, w2); + } + else if(strcmpi(w1,"kill_event_name")==0) { + strcpy(script_config.kill_event_name, w2); + } + else if(strcmpi(w1,"login_event_name")==0) { + strcpy(script_config.login_event_name, w2); + } + else if(strcmpi(w1,"logout_event_name")==0) { + strcpy(script_config.logout_event_name, w2); + } + else if(strcmpi(w1,"require_set_trigger")==0) { + script_config.event_requires_trigger = battle_config_switch(w2); + } else if(strcmpi(w1,"import")==0){ script_config_read(w2); } @@ -7302,10 +7328,19 @@ int do_final_script() if(userfunc_db) strdb_final(userfunc_db,userfunc_db_final); - if (str_data) - aFree(str_data); - if (str_buf) - aFree(str_buf); + if (str_data) + aFree(str_data); + if (str_buf) + aFree(str_buf); + + if (script_config.die_event_name) + aFree(script_config.die_event_name); + if (script_config.kill_event_name) + aFree(script_config.die_event_name); + if (script_config.login_event_name) + aFree(script_config.die_event_name); + if (script_config.logout_event_name) + aFree(script_config.die_event_name); return 0; } diff --git a/src/map/script.h b/src/map/script.h index eecc45e8f..759013e95 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -9,6 +9,13 @@ extern struct Script_Config { int warn_cmd_mismatch_paramnum; int check_cmdcount; int check_gotocount; + + int event_script_type; + char* die_event_name; + char* kill_event_name; + char* login_event_name; + char* logout_event_name; + int event_requires_trigger; } script_config; struct script_data { diff --git a/src/map/skill.c b/src/map/skill.c index 78849469c..e4b171636 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1050,7 +1050,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s diff = mhp*10/100; if (hp - diff < mhp>>2) diff = hp - (mhp>>2); - pc_heal((struct map_session_data *)bl, -hp, 0); + pc_heal(dstsd, -hp, 0); } else if(bl->type == BL_MOB) { struct mob_data *md = (struct mob_data *)bl; hp -= mhp*15/100; @@ -1287,59 +1287,89 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s break; } - if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */ + if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */ int i; int sc_def_card=100; for(i=SC_STONE;i<=SC_BLIND;i++){ //?象に?態異常 - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk; - - if(!sd->state.arrow_atk) { - if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } + switch (i) { + case SC_STONE: + case SC_FREEZE: + sc_def_card=sc_def_mdef; + break; + case SC_STAN: + case SC_POISON: + case SC_SILENCE: + sc_def_card=sc_def_vit; + break; + case SC_SLEEP: + case SC_CONFUSION: + case SC_BLIND: + sc_def_card=sc_def_int; + break; + case SC_CURSE: + sc_def_card=sc_def_luk; } - else { - if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); - status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + + if (sd) { + if(!sd->state.arrow_atk) { + if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); + status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + } + } + else { + if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]); + status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + } } } //自分に?態異常 - if(i==SC_STONE || i==SC_FREEZE) - sc_def_card=sc_def_mdef2; - else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE) - sc_def_card=sc_def_vit2; - else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND) - sc_def_card=sc_def_int2; - else if(i==SC_CURSE) - sc_def_card=sc_def_luk2; - - if(!sd->state.arrow_atk) { - if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); - } + switch (i) { + case SC_STONE: + case SC_FREEZE: + sc_def_card=sc_def_mdef2; + break; + case SC_STAN: + case SC_POISON: + case SC_SILENCE: + sc_def_card=sc_def_vit2; + break; + case SC_SLEEP: + case SC_CONFUSION: + case SC_BLIND: + sc_def_card=sc_def_int2; + break; + case SC_CURSE: + sc_def_card=sc_def_luk2; } - else { - if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){ - if(battle_config.battle_log) - printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); - status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + + if (sd) { + if(!sd->state.arrow_atk) { + if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + } + } + else { + if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + } } } + if (dstsd && + rand()%10000 < dstsd->addeff3[i-SC_STONE]*sc_def_card/100){ + if(battle_config.battle_log) + printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,dstsd->addeff3[i-SC_STONE]); + status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0); + } } } return 0; @@ -3952,6 +3982,8 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int if (tsc_data && tsc_data[scid].timer != -1) break; + if (dstsd && dstsd->unstripable_equip & equip) + break; strip_fix = status_get_dex(src) - status_get_dex(bl); if(strip_fix < 0) diff --git a/src/map/status.c b/src/map/status.c index a98fd9559..d6a8b1a22 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -252,6 +252,30 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->hp_drain_value = sd->hp_drain_value_ = sd->sp_drain_value = sd->sp_drain_value_ = 0; sd->unbreakable_equip = 0; + sd->break_weapon_rate = sd->break_armor_rate = 0; + sd->add_steal_rate = 0; + sd->crit_atk_rate = 0; + sd->no_regen = 0; + sd->unstripable_equip = 0; + sd->autospell2_id = sd->autospell2_lv = sd->autospell2_rate = 0; + memset(sd->critaddrace,0,sizeof(sd->critaddrace)); + memset(sd->addeff3,0,sizeof(sd->addeff3)); + memset(sd->skillatk,0,sizeof(sd->skillatk)); + sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0; + sd->add_def_class_count = sd->add_mdef_class_count = 0; + sd->add_damage_class_count2 = 0; + memset(sd->add_damage_classid,0,sizeof(sd->add_damage_classid)); + memset(sd->add_damage_classid_,0,sizeof(sd->add_damage_classid_)); + memset(sd->add_magic_damage_classid,0,sizeof(sd->add_magic_damage_classid)); + memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate)); + memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_)); + memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate)); + memset(sd->add_def_classid,0,sizeof(sd->add_def_classid)); + memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate)); + memset(sd->add_mdef_classid,0,sizeof(sd->add_mdef_classid)); + memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate)); + memset(sd->add_damage_classid2,0,sizeof(sd->add_damage_classid2)); + memset(sd->add_damage_classrate2,0,sizeof(sd->add_damage_classrate2)); if(!sd->disguiseflag && sd->disguise) { sd->disguise=0; -- cgit v1.2.3-70-g09d2 From b292e29e093cb3b1cba367e6b4644abe68108ae0 Mon Sep 17 00:00:00 2001 From: amber Date: Tue, 22 Feb 2005 05:01:20 +0000 Subject: PCRE updates git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@1157 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-SVN.txt | 7 +- Makefile | 2 + npc/other/eliza.txt | 702 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/Makefile | 6 +- src/map/clif.c | 4 + src/map/map.h | 2 + src/map/npc.c | 4 + src/map/npc.h | 2 + src/map/npc_chat.c | 502 +++++++++++++++++++++++++++++++++++++ src/map/script.c | 26 +- src/map/script.h | 4 + 11 files changed, 1253 insertions(+), 8 deletions(-) create mode 100644 npc/other/eliza.txt create mode 100644 src/map/npc_chat.c (limited to 'src/map/script.h') diff --git a/Changelog-SVN.txt b/Changelog-SVN.txt index 84b0bb6fb..7e5d7258d 100644 --- a/Changelog-SVN.txt +++ b/Changelog-SVN.txt @@ -1,5 +1,10 @@ Date Added +02/22 + * Added perl regular expression support.. look at src/map/npc_chat.c + for all the dirt on the new features. To build it, you have + to enable the PCRE_SUPPORT #define and you also have to + build/install the pcre library. [SVN 1157: MouseJstr] 02/21 * Added actual item_db.sql into sql-files. [Lupus] * Added actual mob_db.sql into sql-files. If you use SQL Mob DB then update it [Lupus] @@ -2000,4 +2005,4 @@ Date Added router or a firewall since there is no way of determining the external IP address. On the other hand, we should be able to eliminate the lan_conf file since we know our IP addresses as well - as our netmask. \ No newline at end of file + as our netmask. diff --git a/Makefile b/Makefile index 26d07fbcc..cc95d3800 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,13 @@ CC = gcc -pipe +# CC = gcc -pipe -DPCRE_SUPPORT # CC = g++ # CC = gcc -pipe -DGCOLLECT # CC = gcc -pipe -DDMALLOC -DDMALLOC_FUNC_CHECK # CC = /usr/local/bin/gcc -fbounds-checking -pipe -DBCHECK # GCLIB = -lgc +# GCLIB = -L/usr/local/lib -lpcre GCLIB = # GCLIB = -ldmalloc diff --git a/npc/other/eliza.txt b/npc/other/eliza.txt new file mode 100644 index 000000000..d5c3c0765 --- /dev/null +++ b/npc/other/eliza.txt @@ -0,0 +1,702 @@ +prontera.gat,152,181,5 script MouseJstr 763,{ + +// hello +Lquote0: + npctalk "How do you do. Please state your problem."; + break; +// computer +Lquote1: + set $foo,rand(4); + if($foo == 0) goto Lquote1a; + if($foo == 1) goto Lquote1b; + if($foo == 2) goto Lquote1c; + if($foo == 3) goto Lquote1d; +Lquote1a: + npctalk "Do computers worry you?"; + break; +Lquote1b: + npctalk "What do you think about machines?"; + break; +Lquote1c: + npctalk "Why do you mention computers?"; + break; +Lquote1d: + npctalk "What do you think machines have to do with your problem?"; + break; +// name +Lquote2: + npctalk "I am not interested in names"; + break; +// sorry +Lquote3: + set $foo,rand(3); + if($foo == 0) goto Lquote3a; + if($foo == 1) goto Lquote3b; + if($foo == 2) goto Lquote3c; + +Lquote3a: + npctalk "Please don't apologize"; + break; + +Lquote3b: + npctalk "Apologies are not necessary"; + break; + +Lquote3c: + npctalk "What feelings do you have when you apologize"; + break; + +// I remember $p2$ +Lquote4: + set $foo,rand(6); + if($foo == 0) goto Lquote4a; + if($foo == 1) goto Lquote4b; + if($foo == 2) goto Lquote4c; + if($foo == 3) goto Lquote4d; + if($foo == 4) goto Lquote4e; + if($foo == 5) goto Lquote4f; + +Lquote4a: + npctalk "Do you often think of "+$p2$+"?"; + break; + +Lquote4b: + npctalk "Does thinking of "+$p2$+" bring anything else to mind?"; + break; + +Lquote4c: + npctalk "What else do you remember?"; + break; + +Lquote4d: + npctalk "Why do you recall "+$p2$+" right now?"; + break; + +Lquote4e: + npctalk "What in the present situation reminds you of "+$p2$+"?"; + break; + +Lquote4f: + npctalk "What is the connection between me and "+$p2$+"?"; + break; + +// do you remember +Lquote5: + set $foo,rand(4); + if($foo == 0) goto Lquote5a; + if($foo == 1) goto Lquote5b; + if($foo == 2) goto Lquote5c; + if($foo == 3) goto Lquote5d; +Lquote5a: + npctalk "Did you think I would forget "+$p2$+" ?"; + break; + +Lquote5b: + npctalk "Why do you think I should recall "+$p2$+" now"; + break; + +Lquote5c: + npctalk "What about "+$p2$+""; + break; + +Lquote5d: + npctalk "You mentioned "+$p2$+""; + break; + +// if +Lquote6: + set $foo,rand(4); + if($foo == 0) goto Lquote6a; + if($foo == 1) goto Lquote6b; + if($foo == 2) goto Lquote6c; + if($foo == 3) goto Lquote6d; +Lquote6a: + npctalk "Do you really think its likely that "+$p2$+""; + break; + +Lquote6b: + npctalk "Do you wish that "+$p2$+"?"; + break; + +Lquote6c: + npctalk "What do you think about "+$p2$+"?"; + break; + +Lquote6d: + npctalk "Really-- if "+$p2$+"?"; + break; + +// i dreamt +Lquote7: + set $foo,rand(3); + if($foo == 0) goto Lquote7a; + if($foo == 1) goto Lquote7b; + if($foo == 2) goto Lquote7c; +Lquote7a: + npctalk "Really-- "+$p2$+""; + break; + +Lquote7b: + npctalk "Have you ever fantasized "+$p2$+" while you were awake?"; + break; + +Lquote7c: + npctalk "Have you dreamt "+$p2$+" before?"; + break; + +// dream about + +Lquote8: + npctalk "How do you feel about "+$p2$+" in reality?"; + break; + +// dream +Lquote9: + set $foo,rand(4); + if($foo == 0) goto Lquote9a; + if($foo == 1) goto Lquote9b; + if($foo == 2) goto Lquote9c; + if($foo == 3) goto Lquote9d; +Lquote9a: + npctalk "What does this dream suggest to you?"; + break; + +Lquote9b: + npctalk "Do you dream often?"; + break; + +Lquote9c: + npctalk "What persons appear in your dreams?"; + break; + +Lquote9d: + npctalk "Don't you believe that dream has to do with your problem?"; + break; + +// my mother +Lquote10: + set $foo,rand(2); + if($foo == 0) goto Lquote10a; + if($foo == 1) goto Lquote10b; +Lquote10a: + npctalk "Who else in your family "+$p2$+""; + break; + +Lquote10b: + npctalk "Tell me more about your family"; + break; + +// my father +Lquote11: + set $foo,rand(3); + if($foo == 0) goto Lquote11a; + if($foo == 1) goto Lquote11b; + if($foo == 2) goto Lquote11c; +Lquote11a: + npctalk "Your father"; + break; + +Lquote11b: + npctalk "Does he influence you strongly?"; + break; + +Lquote11c: + npctalk "What else comes to mind when you think of your father?"; + break; + +// I want +Lquote12: + set $foo,rand(3); + if($foo == 0) goto Lquote12a; + if($foo == 1) goto Lquote12b; + if($foo == 2) goto Lquote12c; +Lquote12a: + npctalk "What would it mean if you got "+$p2$+""; + break; + +Lquote12b: + npctalk "Why do you want "+$p2$+""; + break; + +Lquote12c: + npctalk "Suppose you got "+$p2$+" soon"; + break; + +// I am glad +Lquote13: + set $foo,rand(3); + if($foo == 0) goto Lquote13a; + if($foo == 1) goto Lquote13b; + if($foo == 2) goto Lquote13c; +Lquote13a: + npctalk "How have I helped you to be "+$p2$+""; + break; + +Lquote13b: + npctalk "What makes you happy just now"; + break; + +Lquote13c: + npctalk "Can you explain why you are suddenly "+$p2$+""; + break; + +// I am sad +Lquote14: + set $foo,rand(2); + if($foo == 0) goto Lquote14a; + if($foo == 1) goto Lquote14b; +Lquote14a: + npctalk "I am sorry to hear you are depressed"; + break; + +Lquote14b: + npctalk "I'm sure its not pleasant to be sad"; + break; + +// $p2 are like "+$p3$+" +Lquote15: + npctalk "What resemblance do you see between "+$p2$+" and "+$p3$+""; + break; + +// "+$p2$+" is like "+$p3$+" +Lquote16: + set $foo,rand(4); + if($foo == 0) goto Lquote16a; + if($foo == 1) goto Lquote16b; + if($foo == 2) goto Lquote16c; + if($foo == 3) goto Lquote16d; +Lquote16a: + npctalk "In what way is it that "+$p2$+" is like "+$p3$+""; + break; + +Lquote16b: + npctalk "What resemblance do you see?"; + break; + +Lquote16c: + npctalk "Could there really be some connection?"; + break; + +Lquote16d: + npctalk "How?"; + break; +// alike +Lquote17: + set $foo,rand(2); + if($foo == 0) goto Lquote17a; + if($foo == 1) goto Lquote17b; +Lquote17a: + npctalk "In what way?"; + break; + +Lquote17b: + npctalk "What similarities are there?"; + break; +// same +Lquote18: + npctalk "What other connections do you see?"; + break; + +// I was "+$p2$+" +Lquote19: + set $foo,rand(3); + if($foo == 0) goto Lquote19a; + if($foo == 1) goto Lquote19b; + if($foo == 2) goto Lquote19c; +Lquote19a: + npctalk "Were you really?"; + break; + +Lquote19b: + npctalk "Perhaps I already knew you were "+$p2$+""; + break; + +Lquote19c: + npctalk "Why do you tell me you were "+$p2$+" now?"; + break; + +// was I +Lquote20: + set $foo,rand(3); + if($foo == 0) goto Lquote20a; + if($foo == 1) goto Lquote20b; + if($foo == 2) goto Lquote20c; +Lquote20a: + npctalk "What if you were "+$p2$+" ?"; + break; + +Lquote20b: + npctalk "Do you thin you were "+$p2$+""; + break; + +Lquote20c: + npctalk "What would it mean if you were "+$p2$+""; + break; + +// I am +Lquote21: + set $foo,rand(2); + if($foo == 0) goto Lquote21a; + if($foo == 1) goto Lquote21b; +Lquote21a: + npctalk "In what way are you "+$p2$+""; + break; + +Lquote21b: + npctalk "Do you want to be "+$p2$+" ?"; + break; + +// am I +Lquote22: + set $foo,rand(4); + if($foo == 0) goto Lquote22a; + if($foo == 1) goto Lquote22b; + if($foo == 2) goto Lquote22c; + if($foo == 3) goto Lquote22d; +Lquote22a: + npctalk "Do you believe you are "+$p2$+""; + break; + +Lquote22b: + npctalk "Would you want to be "+$p2$+""; + break; + +Lquote22c: + npctalk "You wish I would tell you you are "+$p2$+""; + break; + +Lquote22d: + npctalk "What would it mean if you were "+$p2$+""; + break; + +// am +Lquote23: + set $foo,rand(2); + if($foo == 0) goto Lquote23a; + if($foo == 1) goto Lquote23b; + +Lquote23a: + npctalk "Why do you say AM?"; + break; + +Lquote23b: + npctalk "I don't understand that"; + break; + +// are you +Lquote24: + set $foo,rand(3); + if($foo == 0) goto Lquote24a; + if($foo == 1) goto Lquote24b; + if($foo == 2) goto Lquote24c; +Lquote24a: + npctalk "Why are you interested in whether I am "+$p2$+" or not?"; + break; + +Lquote24b: + npctalk "Would you prefer if I weren't "+$p2$+""; + break; + +Lquote24c: + npctalk "Perhaps I am "+$p2$+" in your fantasies"; + break; + +// you are +Lquote25: + npctalk "What makes you think I am "+$p2$+" ?"; + break; + +// because +Lquote26: + set $foo,rand(3); + if($foo == 0) goto Lquote26a; + if($foo == 1) goto Lquote26b; + if($foo == 2) goto Lquote26c; +Lquote26a: + npctalk "Is that the real reason?"; + break; + +Lquote26b: + npctalk "What other reasons might there be?"; + break; + +Lquote26c: + npctalk "Does that reason seem to explain anything else?"; + break; + +// were you +Lquote27: + set $foo,rand(3); + if($foo == 0) goto Lquote27a; + if($foo == 1) goto Lquote27b; + if($foo == 2) goto Lquote27c; +Lquote27a: + npctalk "Perhaps I was "+$p2$+""; + break; + +Lquote27b: + npctalk "What do you think?"; + break; + +Lquote27c: + npctalk "What if I had been "+$p2$+""; + break; + +// I can't +Lquote28: + set $foo,rand(2); + if($foo == 0) goto Lquote28a; + if($foo == 1) goto Lquote28b; +Lquote28a: + npctalk "Maybe you could "+$p2$+" now"; + break; + +Lquote28b: + npctalk "What if you could "+$p2$+" ?"; + break; + +// I feel +Lquote29: + npctalk "Do you often feel "+$p2$+" ?"; + break; + +// I felt +Lquote30: + npctalk "What other feelings do you have?"; + break; + +// $p1$ I $p2$ you $p3$ +Lquote31: + npctalk "Perhaps in your fantasy we "+$p3$+" each other?"; + break; + +// why don't you +Lquote32: + set $foo,rand(3); + if($foo == 0) goto Lquote32a; + if($foo == 1) goto Lquote32b; + if($foo == 2) goto Lquote32c; +Lquote32a: + npctalk "Should you "+$p2$+" yourself?"; + break; + +Lquote32b: + npctalk "Do you believe I don't "+$p2$+""; + break; + +Lquote32c: + npctalk "Perhaps I will "+$p2$+" in good time"; + break; + +// yes +Lquote33: + set $foo,rand(3); + if($foo == 0) goto Lquote33a; + if($foo == 1) goto Lquote33b; + if($foo == 2) goto Lquote33c; +Lquote33a: + npctalk "You seem quite positive"; + break; + +Lquote33b: + npctalk "You are sure?"; + break; + +Lquote33c: + npctalk "I understand"; + break; + +// no +Lquote34: + set $foo,rand(3); + if($foo == 0) goto Lquote34a; + if($foo == 1) goto Lquote34b; + if($foo == 2) goto Lquote34c; +Lquote34a: + npctalk "Why not?"; + break; + +Lquote34b: + npctalk "You are being a bit negative"; + break; + +Lquote34c: + npctalk "Are you saying NO just to be negative?"; + break; + +// someone +Lquote35: + npctalk "Can you be more specific?"; + break; + +// everyone +Lquote36: + set $foo,rand(4); + if($foo == 0) goto Lquote36a; + if($foo == 1) goto Lquote36b; + if($foo == 2) goto Lquote36c; + if($foo == 3) goto Lquote36d; +Lquote36a: + npctalk "surely not everyone"; + break; + +Lquote36b: + npctalk "Can you think of anyone in particular?"; + break; + +Lquote36c: + npctalk "Who for example?"; + break; + +Lquote36d: + npctalk "You are thinking of a special person?"; + break; + +// always +Lquote37: + set $foo,rand(4); + if($foo == 0) goto Lquote37a; + if($foo == 1) goto Lquote37b; + if($foo == 2) goto Lquote37c; + if($foo == 3) goto Lquote37d; +Lquote37a: + npctalk "Can you think of a specific example?"; + break; + +Lquote37b: + npctalk "When?"; + break; + +Lquote37c: + npctalk "What incident are you thinking of?"; + break; + +Lquote37d: + npctalk "Really-- always?"; + break; + +// what +Lquote38: + set $foo,rand(5); + if($foo == 0) goto Lquote38a; + if($foo == 1) goto Lquote38b; + if($foo == 2) goto Lquote38c; + if($foo == 3) goto Lquote38d; + if($foo == 4) goto Lquote38e; +Lquote38a: + npctalk "Why do you ask?"; + break; + +Lquote38b: + npctalk "Does that question interest you?"; + break; + +Lquote38c: + npctalk "What is it you really want to know?"; + break; + +Lquote38d: + npctalk "What do you think?"; + break; + +Lquote38e: + npctalk "What comes to your mind when you ask that?"; + break; + +// perhaps +Lquote39: + npctalk "You do not seem quite certain"; + break; + +// are +Lquote40: + set $foo,rand(2); + if($foo == 0) goto Lquote40a; + if($foo == 1) goto Lquote40b; +Lquote40a: + npctalk "Did you think they might not be "+$p2$+""; + break; + +Lquote40b: + npctalk "Possibly they are "+$p2$; + break; + +// default +Lquote41: + set $foo,rand(6); + if($foo == 0) goto Lquote41a; + if($foo == 1) goto Lquote41b; + if($foo == 2) goto Lquote41c; + if($foo == 3) goto Lquote41d; + if($foo == 4) goto Lquote41e; + if($foo == 5) goto Lquote41f; +Lquote41a: + npctalk "Very interesting"; + break; + +Lquote41b: + npctalk "I am not sure I understand you fully"; + break; + +Lquote41c: + npctalk "What does that suggest to you?"; + break; + +Lquote41d: + npctalk "Please continue"; + break; + +Lquote41e: + npctalk "Go on"; + break; + +Lquote41f: + npctalk "Do you feel strongly about discussing such things?"; + break; +OnInit: + defpattern 1, "([^:]+):.*\\shello.*", "Lquote0"; + defpattern 1, "([^:]+):.*\\scomputer.*", "Lquote1"; + defpattern 1, "([^:]+):.*\\sname.*", "Lquote2"; + defpattern 1, "([^:]+):.*\\ssorry.*", "Lquote3"; + defpattern 1, "([^:]+):.*\\si\\s+remember\\s+(.*)", "Lquote4"; + defpattern 1, "([^:]+):.*\\sdo\\s+you\\s+remember\\s+(.*)", "Lquote5"; + defpattern 1, "([^:]+):.*\\sif\\s+(.*)", "Lquote6"; + defpattern 1, "([^:]+):.*\\si\\s+dreamt\\s+(.*)", "Lquote7"; + defpattern 1, "([^:]+):.*\\sdream\\s+about\\s+(.*)", "Lquote8"; + defpattern 1, "([^:]+):.*\\sdream\\s+(.*)", "Lquote9"; + defpattern 1, "([^:]+):.*\\smy\\s+mother\\s+(.*)", "Lquote10"; + defpattern 1, "([^:]+):.*\\smy\\s+father\\s+(.*)", "Lquote11"; + defpattern 1, "([^:]+):.*\\si\\s+want\\s+(.*)", "Lquote12"; + defpattern 1, "([^:]+):.*\\si\\s+am\\s+glad\\s+(.*)", "Lquote13"; + defpattern 1, "([^:]+):\\s+(.*)\\s+i\\s+am\\s+sad\\s+(.*)", "Lquote14"; + defpattern 1, "([^:]+):\\s+(.*)\\s+are\\s+like\\s+(.*)", "Lquote15"; + defpattern 1, "([^:]+):\\s+(.*)\\s+is\\s+like\\s+(.*)", "Lquote16"; + defpattern 1, "([^:]+):.*\\salike\\s+(.*)", "Lquote17"; + defpattern 1, "([^:]+):.*\\ssame\\s+(.*)", "Lquote18"; + defpattern 1, "([^:]+):.*\\si\\s+was\\s+(.*)", "Lquote19"; + defpattern 1, "([^:]+):.*\\swas\\s+i\\s+(.*)", "Lquote20"; + defpattern 1, "([^:]+):.*\\si\\s+am\\s+(.*)", "Lquote21"; + defpattern 1, "([^:]+):.*\\sam\\s+i\\s+(.*)", "Lquote22"; + defpattern 1, "([^:]+):.*\\sam\\s+(.*)", "Lquote23"; + defpattern 1, "([^:]+):.*\\sare\\s+you\\s+(.*)", "Lquote24"; + defpattern 1, "([^:]+):.*\\syou\\s+are\\s+(.*)", "Lquote25"; + defpattern 1, "([^:]+):.*\\sbecause\\s+(.*)", "Lquote26"; + defpattern 1, "([^:]+):.*\\swere\\s+you\\s+(.*)", "Lquote27"; + defpattern 1, "([^:]+):.*\\si\\s+(cant|can't|cannot)\\s+(.*)", "Lquote28"; + defpattern 1, "([^:]+):.*\\si\\s+feel\\s+(.*)", "Lquote29"; + defpattern 1, "([^:]+):.*\\si\\s+felt\\s+(.*)", "Lquote30"; + defpattern 1, "([^:]+):.*\\si\\s+(.*)\\s+you\\s+(.*)", "Lquote31"; + defpattern 1, "([^:]+):.*\\swhy\\s+(don't|dont)\\s+you\\s+(.*)", "Lquote32"; + defpattern 1, "([^:]+):.*\\syes\\s+(.*)", "Lquote33"; + defpattern 1, "([^:]+):.*\\sno\\s+(.*)", "Lquote34"; + defpattern 1, "([^:]+):.*\\ssomeone\\s+(.*)", "Lquote35"; + defpattern 1, "([^:]+):.*\\severyone\\s+(.*)", "Lquote36"; + defpattern 1, "([^:]+):.*\\salways\\s+(.*)", "Lquote37"; + defpattern 1, "([^:]+):.*\\swhat\\s+(.*)", "Lquote38"; + defpattern 1, "([^:]+):.*\\sperhaps\\s+(.*)", "Lquote39"; + defpattern 1, "([^:]+):.*\\sare\\s+(.*)", "Lquote40"; + defpattern 1, "([^:]+):(.*)", "Lquote41"; + + activatepset 1; + break; +} diff --git a/src/map/Makefile b/src/map/Makefile index 3a05cd7a8..884e8b902 100644 --- a/src/map/Makefile +++ b/src/map/Makefile @@ -13,10 +13,10 @@ sqlobj: COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o LIBS = -lz -lm -map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) +map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) $(CC) -o ../../$@ $> $(LIBS) $(LIB_S) -map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ) +map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ) $(CC) -o ../../$@ $> $(LIB_S) txtobj/%.o: %.c @@ -31,6 +31,7 @@ txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h cha txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h @@ -55,6 +56,7 @@ sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h cha sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h diff --git a/src/map/clif.c b/src/map/clif.c index 0a0db934a..67c925f75 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -7964,6 +7964,10 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c < WFIFOW(fd,0) = 0x8e; WFIFOSET(fd, WFIFOW(fd,2)); +#ifdef PCRE_SUPPORT + map_foreachinarea(npc_chat_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_NPC, RFIFOP(fd,4), strlen(RFIFOP(fd,4)), &sd->bl); +#endif + // Celest if (pc_calc_base_job2 (sd->status.class_) == 23 ) { int next = pc_nextbaseexp(sd)>0 ? pc_nextbaseexp(sd) : sd->status.base_exp; diff --git a/src/map/map.h b/src/map/map.h index 92c334806..2963a316e 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -411,6 +411,8 @@ struct npc_data { char eventqueue[MAX_EVENTQUEUE][50]; int eventtimer[MAX_EVENTTIMER]; short arenaflag; + + void *chatdb; }; struct mob_data { struct block_list bl; diff --git a/src/map/npc.c b/src/map/npc.c index 1ba55699f..54a35c51c 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -153,6 +153,10 @@ int npc_delete(struct npc_data *nd) if(nd->bl.prev == NULL) return 1; +#ifdef PCRE_SUPPORT + npc_chat_finalize(nd); +#endif + clif_clearchar_area(&nd->bl,1); map_delblock(&nd->bl); return 0; diff --git a/src/map/npc.h b/src/map/npc.h index a68cc8e54..dbb351fa0 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -8,6 +8,8 @@ #define WARP_DEBUG_CLASS 722 #define INVISIBLE_CLASS 32767 +void npc_chat_finalize(struct npc_data *nd); +int npc_chat_sub(struct block_list *bl, va_list ap); int npc_event_dequeue(struct map_session_data *sd); int npc_event_timer(int tid,unsigned int tick,int id,int data); int npc_event(struct map_session_data *sd,const char *npcname,int); diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c new file mode 100644 index 000000000..5ec8540ae --- /dev/null +++ b/src/map/npc_chat.c @@ -0,0 +1,502 @@ +#ifdef PCRE_SUPPORT + +#include +#include +#include +#include +#include +#ifdef __WIN32 +#define __USE_W32_SOCKETS +#include +#else +#include +#include +#include +#include +#include +#endif +#include + +#include "../common/timer.h" +#include "../common/malloc.h" +#include "../common/version.h" +#include "../common/nullpo.h" +#include "../common/showmsg.h" + +#include "map.h" +#include "status.h" +#include "npc.h" +#include "chat.h" +#include "script.h" +#include "battle.h" + +#include "pcre.h" + +/** + * Written by MouseJstr in a vision... (2/21/2005) + * + * This allows you to make npc listen for spoken text (global + * messages) and pattern match against that spoken text using perl + * regular expressions. + * + * Please feel free to copy this code into your own personal ragnarok + * servers or distributions but please leave my name. Also, please + * wait until I've put it into the main eA branch which means I + * believe it is ready for distribution. + * + * So, how do people use this? + * + * The first and most important function is defpattern + * + * defpattern 1, "[^:]+: (.*) loves (.*)", "label"; + * + * this defines a new pattern in set 1 using perl syntax + * (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm) + * and tells it to jump to the supplied label when the pattern + * is matched. + * + * each of the matched Groups will result in a variable being + * set ($p1$ through $p9$ with $p0$ being the entire string) + * before the script gets executed. + * + * activatepset 1; + * + * This activates a set of patterns.. You can have many pattern + * sets defined and many active all at once. This feature allows + * you to set up "conversations" and ever changing expectations of + * the pattern matcher + * + * deactivatepset 1; + * + * turns off a pattern set; + * + * deactivatepset -1; + * + * turns off ALL pattern sets; + * + * deletepset 1; + * + * deletes a pset + */ + +/* Structure containing all info associated with a single pattern + block */ + +struct pcrematch_entry { + struct pcrematch_entry *next_; + char *pattern_; + pcre *pcre_; + pcre_extra *pcre_extra_; + char *label_; +}; + +/* A set of patterns that can be activated and deactived with a single + command */ + +struct pcrematch_set { + struct pcrematch_set *next_, *prev_; + struct pcrematch_entry *head_; + int setid_; +}; + +/* + * Entire data structure hung off a NPC + * + * The reason I have done it this way (a void * in npc_data and then + * this) was to reduce the number of patches that needed to be applied + * to a ragnarok distribution to bring this code online. I + * also wanted people to be able to grab this one file to get updates + * without having to do a large number of changes. + */ + +struct npc_parse { + struct pcrematch_set *active_; + struct pcrematch_set *inactive_; +}; + + +/** + * delete everythign associated with a entry + * + * This does NOT do the list management + */ + +void finalize_pcrematch_entry(struct pcrematch_entry *e) { + free(e->pcre_); + free(e->pcre_extra_); + aFree(e->pattern_); + aFree(e->label_); +} + +/** + * Lookup (and possibly create) a new set of patterns by the set id + */ +static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid) +{ + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + nd->chatdb = npcParse = (struct npc_parse *) + aCalloc(sizeof(struct npc_parse), 1); + + pcreset = npcParse->active_; + + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + pcreset = npcParse->inactive_; + + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + + if (pcreset == NULL) { + pcreset = (struct pcrematch_set *) + aCalloc(sizeof(struct pcrematch_set), 1); + pcreset->next_ = npcParse->inactive_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + pcreset->prev_ = 0; + npcParse->inactive_ = pcreset; + pcreset->setid_ = setid; + } + + return pcreset; +} + +/** + * activate a set of patterns. + * + * if the setid does not exist, this will silently return + */ + +static void activate_pcreset(struct npc_data *nd,int setid) { + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to activate... + pcreset = npcParse->inactive_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + return; // not in inactive list + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else + npcParse->inactive_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = npcParse->active_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + npcParse->active_ = pcreset; +} + +/** + * deactivate a set of patterns. + * + * if the setid does not exist, this will silently return + */ + +static void deactivate_pcreset(struct npc_data *nd,int setid) { + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to deactivate... + if (setid == -1) { + while(npcParse->active_ != NULL) + deactivate_pcreset(nd, npcParse->active_->setid_); + return; + } + pcreset = npcParse->active_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) + return; // not in active list + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else + npcParse->active_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = npcParse->inactive_; + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset; + npcParse->inactive_ = pcreset; +} + +/** + * delete a set of patterns. + */ +static void delete_pcreset(struct npc_data *nd,int setid) { + int active = 1; + struct pcrematch_set *pcreset; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; // Nothing to deactivate... + pcreset = npcParse->active_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + if (pcreset == NULL) { + active = 0; + pcreset = npcParse->inactive_; + while (pcreset != NULL) { + if (pcreset->setid_ == setid) + break; + pcreset = pcreset->next_; + } + } + if (pcreset == NULL) + return; + + if (pcreset->next_ != NULL) + pcreset->next_->prev_ = pcreset->prev_; + if (pcreset->prev_ != NULL) + pcreset->prev_->next_ = pcreset->next_; + else if(active == 1) + npcParse->active_ = pcreset->next_; + else + npcParse->inactive_ = pcreset->next_; + + pcreset->prev_ = NULL; + pcreset->next_ = NULL; + + while (pcreset->head_) { + struct pcrematch_entry *n = pcreset->head_->next_;; + finalize_pcrematch_entry(pcreset->head_); + pcreset->head_ = n; + } + + aFree(pcreset); +} + +/** + * create a new pattern entry + */ +static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set * set) { + struct pcrematch_entry * e = (struct pcrematch_entry *) + aCalloc(sizeof(struct pcrematch_entry), 1); + struct pcrematch_entry * last = set->head_; + + // Normally we would have just stuck it at the end of the list but + // this doesn't sink up with peoples usage pattern. They wanted + // the items defined first to have a higher priority then the + // items defined later.. as a result, we have to do some work up + // front.. + + /* if we are the first pattern, stick us at the end */ + if (last == NULL) { + set->head_ = e; + return e; + } + + /* Look for the last entry */ + while (last->next_ != NULL) + last = last->next_; + + last->next_ = e; + e->next_ = NULL; + + return e; +} + +/** + * define/compile a new pattern + */ + +void npc_chat_def_pattern(struct npc_data *nd, int setid, + const char *pattern, const char *label) +{ + const char *err; + int erroff; + + struct pcrematch_set * s = lookup_pcreset(nd, setid); + struct pcrematch_entry *e = create_pcrematch_entry(s); + e->pattern_ = aStrdup(pattern); + e->label_ = aStrdup(label); + e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL); + e->pcre_extra_ = pcre_study(e->pcre_, 0, &err); +} + +/** + * Delete everything associated with a NPC concerning the pattern + * matching code + * + * this could be more efficent but.. how often do you do this? + */ +void npc_chat_finalize(struct npc_data *nd) +{ + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + if (npcParse == NULL) + return; + + while(npcParse->active_) + delete_pcreset(nd, npcParse->active_->setid_); + + while(npcParse->inactive_) + delete_pcreset(nd, npcParse->inactive_->setid_); +} + +/** + * Handler called whenever a global message is spoken in a NPC's area + */ +int npc_chat_sub(struct block_list *bl, va_list ap) +{ + struct npc_data *nd = (struct npc_data *)bl; + struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; + unsigned char *msg; + int len, pos, i; + struct map_session_data *sd; + struct npc_label_list *lst; + struct pcrematch_set *pcreset; + + // Not interested in anything you might have to say... + if (npcParse == NULL || npcParse->active_ == NULL) + return 0; + + msg = va_arg(ap,unsigned char*); + len = va_arg(ap,int); + sd = va_arg(ap,struct map_session_data *); + + // grab the active list + pcreset = npcParse->active_; + + // interate across all active sets + while (pcreset != NULL) { + struct pcrematch_entry *e = pcreset->head_; + // interate across all patterns in that set + while (e != NULL) { + int offsets[20]; + char buf[255]; + // perform pattern match + int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, + 0, offsets, sizeof(offsets) / sizeof(offsets[0])); + if (r >= 0) { + // save out the matched strings + switch (r) { + case 10: + memcpy(buf, &msg[offsets[18]], offsets[19]); + buf[offsets[19]] = '\0'; + set_var(sd, "$p9$", buf); + case 9: + memcpy(buf, &msg[offsets[16]], offsets[17]); + buf[offsets[17]] = '\0'; + set_var(sd, "$p8$", buf); + case 8: + memcpy(buf, &msg[offsets[14]], offsets[15]); + buf[offsets[15]] = '\0'; + set_var(sd, "$p7$", buf); + case 7: + memcpy(buf, &msg[offsets[12]], offsets[13]); + buf[offsets[13]] = '\0'; + set_var(sd, "$p6$", buf); + case 6: + memcpy(buf, &msg[offsets[10]], offsets[11]); + buf[offsets[11]] = '\0'; + set_var(sd, "$p5$", buf); + case 5: + memcpy(buf, &msg[offsets[8]], offsets[9]); + buf[offsets[9]] = '\0'; + set_var(sd, "$p4$", buf); + case 4: + memcpy(buf, &msg[offsets[6]], offsets[7]); + buf[offsets[7]] = '\0'; + set_var(sd, "$p3$", buf); + case 3: + memcpy(buf, &msg[offsets[4]], offsets[5]); + buf[offsets[5]] = '\0'; + set_var(sd, "$p2$", buf); + case 2: + memcpy(buf, &msg[offsets[2]], offsets[3]); + buf[offsets[3]] = '\0'; + set_var(sd, "$p1$", buf); + case 1: + memcpy(buf, &msg[offsets[0]], offsets[1]); + buf[offsets[1]] = '\0'; + set_var(sd, "$p0$", buf); + } + + // find the target label.. this sucks.. + lst=nd->u.scr.label_list; + pos = -1; + for (i = 0; i < nd->u.scr.label_list_num; i++) { + if (strncmp(lst[i].name, e->label_, sizeof(lst[i].name)) == 0) { + pos = lst[i].pos; + break; + } + } + if (pos == -1) { + printf("Unable to find label: %s", e->label_); + // unable to find label... do something.. + return 0; + } + // run the npc script + run_script(nd->u.scr.script,pos,sd->bl.id,nd->bl.id); + return 0; + } + e = e->next_; + } + pcreset = pcreset->next_; + } + + return 0; +} + +// Various script builtins used to support these functions + +int buildin_defpattern(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + char *pattern=conv_str(st,& (st->stack->stack_data[st->start+3])); + char *label=conv_str(st,& (st->stack->stack_data[st->start+4])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + npc_chat_def_pattern(nd, setid, pattern, label); + + return 0; +} + +int buildin_activatepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + activate_pcreset(nd, setid); + + return 0; +} +int buildin_deactivatepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + deactivate_pcreset(nd, setid); + + return 0; +} +int buildin_deletepset(struct script_state *st) { + int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + + delete_pcreset(nd, setid); + + return 0; +} + + +#endif diff --git a/src/map/script.c b/src/map/script.c index 92ecd8690..24195b698 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -253,9 +253,9 @@ int buildin_failedremovecards(struct script_state *st); int buildin_marriage(struct script_state *st); int buildin_wedding_effect(struct script_state *st); int buildin_divorce(struct script_state *st); -int buildin_ispartneron(struct script_state *st); -int buildin_getpartnerid(struct script_state *st); -int buildin_warppartner(struct script_state *st); +int buildin_ispartneron(struct script_state *st); // MouseJstr +int buildin_getpartnerid(struct script_state *st); // MouseJstr +int buildin_warppartner(struct script_state *st); // MouseJstr int buildin_getitemname(struct script_state *st); int buildin_makepet(struct script_state *st); int buildin_getexp(struct script_state *st); @@ -315,6 +315,13 @@ int run_func(struct script_state *st); int mapreg_setreg(int num,int val); int mapreg_setregstr(int num,const char *str); +#ifdef PCRE_SUPPORT +int buildin_defpattern(struct script_state *st); // MouseJstr +int buildin_activatepset(struct script_state *st); // MouseJstr +int buildin_deactivatepset(struct script_state *st); // MouseJstr +int buildin_deletepset(struct script_state *st); // MouseJstr +#endif + struct { int (*func)(struct script_state *); char *name; @@ -537,10 +544,14 @@ struct { {buildin_isday,"isday",""}, // check whether it is day time [Celest] {buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest] {buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest] +#ifdef PCRE_SUPPORT + {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr] + {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr] + {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr] + {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr] +#endif {NULL,NULL,NULL}, }; -int buildin_message(struct script_state *st); // [MouseJstr] - enum { C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG, @@ -1403,6 +1414,11 @@ static int set_reg(struct map_session_data *sd,int num,char *name,void *v) return 0; } +int set_var(struct map_session_data *sd, char *name, void *val) +{ + return set_reg(sd, add_str(name), name, val); +} + /*========================================== * 文字列への変換 *------------------------------------------ diff --git a/src/map/script.h b/src/map/script.h index 759013e95..b30201a67 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -42,6 +42,10 @@ struct script_state { char * parse_script(unsigned char *,int); int run_script(char *,int,int,int); +int set_var(struct map_session_data *sd, char *name, void *val); +int conv_num(struct script_state *st,struct script_data *data); +char* conv_str(struct script_state *st,struct script_data *data); + struct dbt* script_get_label_db(); struct dbt* script_get_userfunc_db(); -- cgit v1.2.3-70-g09d2