/*********************************************** * アイテム合成! **********************************************/ #include "version.h" #include #include #include #include #include #include #include #include "configfile.h" #include "util.h" #include "buf.h" #include "char.h" #include "item.h" #include "item_gen.h" #include "enemy.h" #include "log.h" #include "saacproto_cli.h" #include "family.h" #include "magic_base.h" #define DEBUGPRINT 0 #define DEBUGPRINT_DETAIL 0 // shan begin #define FOOD_HP_RATE 200 #define FOOD_MP_RATE 200 #define FOOD_SUCCESS_RATE 150 #define FOOD_TURN_ADDPOINT 1 // shan end static int ITEM_getTableNum( int num); /* 素材の値のMAX値 */ #define ITEM_ATOMIND_MAX 1000 // shan add #define ITEM_ATOMIND_FM_MAX 4000 #define ITEM_RANDRANGEDOM 1000 #define ITEM_RANDRANGEDOM_BASE 0 // shan add #define ITEM_FM_RANDRANGEDOM 4000 /*********************************************** * (ITEM_GEN_RAND_MIN/1000) * ITEN_GEN_SEARCH_MIN * - (ITEM_GEN_RAND_MAX/1000) * ITEN_GEN_SEARCH_MAX * これだけの幅の素材の範囲を取りうる事になる。 **********************************************/ /* 素材の値変動のランダム幅の最少と最大(1000分率) */ #define ITEM_GEN_RAND_MIN 700 #define ITEM_GEN_RAND_MAX 1200 /* アイテムを検索する素材の値の幅の最少と最大の倍率(double) */ #define ITEN_GEN_SEARCH_MIN (0.7) #define ITEN_GEN_SEARCH_MAX (1.10) static struct tagItemSearchRangeTable { double searchmin; double searchmax; }ItemSearchTable[2] = { // { 0.7, 1.1}, // shan add // { 0.7, 1.3}, // { 0.5, 1.5} { 0.8, 1.2}, { 0.7, 1.3} }; static struct tagItemRandRangeTable { int randmin; int randmax; }ItemRandTable[2] = { // { 700, 1200}, { 700, 1300}, { 900, 1100} }; #define ITEM_GEN_RATE 0.7 static struct _tagItemRandRangeTableForItem { int num; /* 素材の各ランクの基本値 */ int minnum; /* ランク中取りうる値のMin */ int maxnum; /* ランク中取りうる値のMAX(num +次のランクの差*ITEM_GEN_RATE) */ double rate; /* 倍率 maxnum / num*/ }ItemRandTableForItem[] = { { 10, 0,0,0 }, { 30, 0,0,0 }, { 65, 0,0,0 }, { 125, 0,0,0 }, { 205, 0,0,0 }, { 305, 0,0,0 }, { 425, 0,0,0 }, { 565, 0,0,0 }, { 725, 0,0,0 }, { 905, 0,0,0 }, { 1125, 0,0,0 }, // shan add { 1354, 0,0,0 }, { 1594, 0,0,0 }, { 1825, 0,0,0 }, { 2105, 0,0,0 }, { 2405, 0,0,0 }, { 2725, 0,0,0 }, { 3065, 0,0,0 }, { 3425, 0,0,0 }, { 3805, 0,0,0 } }; #define ATOM_LEVEL_MAX 16 struct item_atom { char name[32]; unsigned int name_hash; int magicflg; }; struct item_atom *item_atoms; int item_atoms_size; #define MAX_ITEM_ATOMS_SIZE 256 struct item_ingindtable { double data[MAX_ITEM_ATOMS_SIZE]; int index; int num; }; static int ITEM_getAtomIndexByName( char *nm ) // 从素材名称取得素材index { int i; unsigned int h = hashpjw( nm ); for( i = 0; i < item_atoms_size; i ++ ){ if( item_atoms[i].name_hash == h && strcmp( item_atoms[i].name, nm) == 0 ){ return i; } } return -1; } #ifdef _ITEMTBL_STAIC extern ITEM_table ITEM_tbl[24000]; #else extern ITEM_table *ITEM_tbl; #endif struct ingcache { int use; #define MAXING_ONE 5 int inguse; int canmergefrom; int canmergeto; int hitnum; int ingind[MAXING_ONE]; int ingval[MAXING_ONE]; }; int ITEM_initRandTable( void) { int i; for( i = 0; i < arraysizeof( ItemRandTableForItem); i ++) { if( i == 0 ) ItemRandTableForItem[i].minnum = 0; else { ItemRandTableForItem[i].minnum = ItemRandTableForItem[i-1].maxnum+1; } if( i + 1 != arraysizeof( ItemRandTableForItem)) { ItemRandTableForItem[i].maxnum = ItemRandTableForItem[i].num + (ItemRandTableForItem[i+1].num - ItemRandTableForItem[i].num) *ITEM_GEN_RATE; } else { // shan add ItemRandTableForItem[i].maxnum = 4000; //ItemRandTableForItem[i].maxnum = 1000; } ItemRandTableForItem[i].rate = ItemRandTableForItem[i].maxnum / (double)ItemRandTableForItem[i].num; } /*for( i = 0; i < arraysizeof( ItemRandTableForItem); i ++) { print( "\ntable num:[%d] min:[%d] max:[%d] rate:[%3.3f] ", ItemRandTableForItem[i].num, ItemRandTableForItem[i].minnum, ItemRandTableForItem[i].maxnum, ItemRandTableForItem[i].rate); }*/ return TRUE; } static struct ingcache *icache; int icache_num; int ITEM_initItemIngCache( void ) { int i; // print ( "\n初始化物品缓冲: 物品最大数:%d ", ITEM_getItemMaxIdNum() ); icache_num = ITEM_getItemMaxIdNum( ); print(" 缓冲数:%d ", icache_num); icache = calloc(1, sizeof( struct ingcache ) * icache_num ); if( icache == NULL ){ print( "初始化物品缓冲: 没有物品\n" ); return FALSE; } print("分配 %4.2f MB 空间...", sizeof( struct ingcache ) * icache_num /1024.0/1024.0); remove( "old_icache.txt"); memset( icache, 0, icache_num * sizeof( struct ingcache) ); for( i=0; i= MAX_ITEM_ATOMS_SIZE ){ print( "初始化物品成份: 物品成份太多了\n" ); return FALSE; } item_atoms_size = count; print( "初始化物品成份: 读取 %d 物品成份...", count ); return TRUE; } /* 乱数のレート base が 100 で min が 0.7 で max が 1.3 だったら、 70 ~ 130 に均一に分布する。とりあえず均一。 均一じゃなくしたりするかもしれないので、 アイテム専用ルーチンとしてここに定義する by ringo 1999Oct1 1000分のmin_rate,max_rateで扱う。 double やfloat は,ややこしいので使わない。 */ static int ITEM_randRange( int base, int min_rate , int max_rate ) { int minnum; int maxnum; int range; if( min_rate > max_rate) { int tmp; tmp = min_rate; min_rate = max_rate; max_rate = tmp; } minnum = rint((double)base / ITEM_RANDRANGEDOM * min_rate); maxnum = rint((double)base / ITEM_RANDRANGEDOM * max_rate); range = ( maxnum - minnum ); if( min_rate == max_rate && min_rate == 0 ) return 0; if( range == 0 ) return base; if( range < 0 ) return 0; return minnum + RAND( 0, range); } typedef int (*FUNC)( const void *, const void * ); static int cmprutine( double *p1, double *p2) { if( *p1 < *p2 ) return -1; if( *p1 > *p2 ) return 1; return 0; } /* * 高いのにあわせる * 返り値は配列がいくつになったか。 * 合わせる前に,ソートして並べて, * tableに沿った倍率分,足していく。 */ static void ITEM_simplify_atoms( struct item_ingindtable *inds, int num, int *retinds, int *retvals, int petindex, int alchemist) { //int newinds[MAX_ITEM_ATOMS_SIZE]; //int newvals[MAX_ITEM_ATOMS_SIZE]; int i; double oddstable[] = { 0.1, 0.25, 0.35, 0.4, 0.42, 0.44, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53 }; for( i = 0; i < num; i ++ ) { int datacnt = (inds + i)->num; if( datacnt > 1 ) { int j; qsort( (inds + i)->data, datacnt, sizeof( double ), (FUNC)cmprutine); for( j = 1; j < datacnt; j ++ ) { int tablenum; double rate; tablenum = ITEM_getTableNum( (inds + i)->data[j-1]); rate = ItemRandTableForItem[tablenum].rate / ItemRandTableForItem[0].rate; (inds + i)->data[j] += (inds + i)->data[j-1] * oddstable[j-1] * rate; } } *(retinds + i) = ( inds + i)->index; *(retvals + i) = (int)( inds + i)->data[ datacnt-1]; // shan add begin if( petindex != -1 ){ if (CHAR_getInt(petindex, CHAR_PETFAMILY) == 1){ if( *( retvals + i) > ITEM_ATOMIND_FM_MAX ){ *( retvals + i) = ITEM_ATOMIND_FM_MAX; } }else{ if( *( retvals + i) > ITEM_ATOMIND_MAX ){ *( retvals + i) = ITEM_ATOMIND_MAX; } } } // shan end } } /* PET_ADD_INGRED( nm,vl1,vl2,vl3) { if( strlen( ENEMYTEMP_getChar( petarray, nm)) != 0 ) { fixatom[ingnum] =ITEM_getAtomIndexByName( ENEMYTEMP_getChar( petarray, nm) ); if( fixatom[ingnum] < 0 ) { print( "\nfucking atom:[%s] for pet id %d", ENEMYTEMP_getChar( petarray, nm), petid ); continue; } baseup[ingnum] = ENEMYTEMP_getInt( petarray, vl1); minadd[ingnum] = ENEMYTEMP_getInt( petarray, vl2); maxadd[ingnum] = ENEMYTEMP_getInt( petarray, vl3); if( petindex != -1) { if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ) { int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if (!CHAR_CHECKINDEX(ownerindex)) { print("ownerindex err!\n"); return; } if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER) { print("\n Pet Ownerindex Error"); return; } baseup[ingnum] = PetLv[getFmLv(ownerindex)]; } } if( minadd[ingnum] > maxadd[ingnum] ) { int tmp = minadd[ingnum]; minadd[ingnum] = maxadd[ingnum];maxadd[ingnum] = tmp; } if( CHAR_getInt(petid, CHAR_PETFAMILY) == 1 ) { if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_FM_RANDRANGEDOM; if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_FM_RANDRANGEDOM; } else { if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_RANDRANGEDOM; if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_RANDRANGEDOM; } ingnum++; } } */ /* ペットのIDから、乱数の修正設定を取りだす。 int *fixuse : 値結果引数。配列の最大数をとり、定義数をいれてかえす int *fixatom : どの素材に対する修正なのか int *baseup : 基本値にたいする加算 int *minadd : かけ算の最小にたいする加算 int *maxadd : かけ算の最大にたいする加算 */ static void ITEM_merge_getPetFix( int petid, int *fixuse, int *fixatom, int *baseup, int *minadd, int *maxadd, int petindex, int *fm_fix) { int i; int ingnum = 0; int petarray; // shan begin #define FamilyLv 11 //int PetLv[FamilyLv]; //for(i=0; i maxadd[ingnum] ) { int tmp = minadd[ingnum];minadd[ingnum] = maxadd[ingnum];maxadd[ingnum] = tmp;}if( CHAR_getInt(petid, CHAR_PETFAMILY) == 1 ){if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_FM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_FM_RANDRANGEDOM;}else{if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_RANDRANGEDOM;}ingnum++;} #define PET_ADD_INGRED( nm,vl1,vl2,vl3) if( strlen( ENEMYTEMP_getChar( petarray, nm)) != 0 ) { fixatom[ingnum] =ITEM_getAtomIndexByName( ENEMYTEMP_getChar( petarray, nm) ); if( fixatom[ingnum] < 0 ){ print( "\nfucking atom:[%s] for pet id %d", ENEMYTEMP_getChar( petarray, nm), petid ); continue;} baseup[ingnum] = ENEMYTEMP_getInt( petarray, vl1); minadd[ingnum] = ITEM_RANDRANGEDOM_BASE + ENEMYTEMP_getInt( petarray, vl2); maxadd[ingnum] = ITEM_RANDRANGEDOM_BASE + ENEMYTEMP_getInt( petarray, vl3); if( petindex != -1){ if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ){ int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if (!CHAR_CHECKINDEX(ownerindex)){print("ownerindex err!\n");return;}if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER){print("\n Pet Ownerindex Error");return;}baseup[ingnum] = PetLv[getFmLv(ownerindex)];}}if( minadd[ingnum] > maxadd[ingnum] ) { int tmp = minadd[ingnum];minadd[ingnum] = maxadd[ingnum];maxadd[ingnum] = tmp;}if( CHAR_getInt(petid, CHAR_PETFAMILY) == 1 ){if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_FM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_FM_RANDRANGEDOM;}else{if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_RANDRANGEDOM;}ingnum++;} #else #define PET_ADD_INGRED( nm,vl1,vl2,vl3) if( strlen( ENEMYTEMP_getChar( petarray, nm)) != 0 ) { fixatom[ingnum] =ITEM_getAtomIndexByName( ENEMYTEMP_getChar( petarray, nm) ); if( fixatom[ingnum] < 0 ){ print( "\nfucking atom:[%s] for pet id %d", ENEMYTEMP_getChar( petarray, nm), petid ); continue;} baseup[ingnum] = ENEMYTEMP_getInt( petarray, vl1); minadd[ingnum] = ENEMYTEMP_getInt( petarray, vl2); maxadd[ingnum] = ENEMYTEMP_getInt( petarray, vl3); if( petindex != -1){ if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ){ int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if (!CHAR_CHECKINDEX(ownerindex)){print("ownerindex err!\n");return;}if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != 1){print("\n Pet Ownerindex Error");return;}baseup[ingnum] = PetLv[getFmLv(ownerindex)];}}if( minadd[ingnum] > maxadd[ingnum] ) {int tmp = minadd[ingnum];minadd[ingnum] = maxadd[ingnum];maxadd[ingnum] = tmp;}if( CHAR_getInt(petid, CHAR_PETFAMILY) == 1 ){if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_FM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_FM_RANDRANGEDOM;}else{if( minadd[ingnum]<0 ) minadd[ingnum] = ITEM_RANDRANGEDOM;if( maxadd[ingnum]<0 ) maxadd[ingnum] = ITEM_RANDRANGEDOM;}ingnum++;} #endif PET_ADD_INGRED( E_T_ATOMFIXNAME1, E_T_ATOMBASEADD1, E_T_ATOMFIXMIN1, E_T_ATOMFIXMAX1); PET_ADD_INGRED( E_T_ATOMFIXNAME2, E_T_ATOMBASEADD2, E_T_ATOMFIXMIN2, E_T_ATOMFIXMAX2); PET_ADD_INGRED( E_T_ATOMFIXNAME3, E_T_ATOMBASEADD3, E_T_ATOMFIXMIN3, E_T_ATOMFIXMAX3); PET_ADD_INGRED( E_T_ATOMFIXNAME4, E_T_ATOMBASEADD4, E_T_ATOMFIXMIN4, E_T_ATOMFIXMAX4); PET_ADD_INGRED( E_T_ATOMFIXNAME5, E_T_ATOMBASEADD5, E_T_ATOMFIXMIN5, E_T_ATOMFIXMAX5); } if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ) { int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if( CHAR_CHECKINDEX(ownerindex) ) { *fm_fix = PetLv[getFmLv(ownerindex)]; } } *fixuse = ingnum; return; } /* * そのIDが,合成元アイテムにあったらFALSEを返す */ static BOOL ITEM_merge_checkitem( ITEM_Item *items, int itemsnum, int id) { int loop; for( loop = 0; loop < itemsnum; loop ++ ) { if( items[loop].data[ITEM_ID] == id ) break; } if( loop == itemsnum ) return TRUE; return FALSE; } static int ITEM_merge_with_retry( ITEM_Item *items,int itemsnum, int *ingindtable, int ingnum, int *ingtable, int searchtable, int petindex ) { int ideal; int idel_num[5][5] = { { 0}, { 250,0 }, { 400,150,0}, { 700,260,70,0}, { 740,500,200,40,0} }; int endflg[5]; BOOL first = TRUE; int extractcnt = 0; #define MAXMATCH 2048 int matchid[MAXMATCH]; int i,j,k; if( ingnum > 5 ) ideal = 5; else ideal = ingnum; memset( endflg, 0, sizeof( endflg)); while( 1 ) { int r = RAND( 0, 999); int extractnum; int match = 0; if( extractcnt >= ideal ) break; // 计算合成道具的必须材料数 for( extractnum = 0; extractnum < ideal; extractnum ++ ) { if( r >= idel_num[ideal-1][extractnum] ) { break; } } if( endflg[extractnum] == TRUE ) continue; endflg[extractnum] = TRUE; extractcnt++; extractnum = ideal - ( extractnum ); if( first ) { for( i = 0; i < icache_num; i++ ){ // 搜寻全部ITEM if( icache[i].use && icache[i].canmergeto) { // 如果是可合成的ITEM icache[i].hitnum = 0; for( j = 0; j < icache[i].inguse; j ++ ) { // 这个ITEM的材料数 for( k = 0; k < ingnum ; k ++){ // 合成的材料数 if( icache[i].ingind[j] == ingindtable[k] ) { // 材料符合 if( searchtable == 0 ) { // 道具合成的话 int tablenum = ITEM_getTableNum( ingtable[k]); // 材料等级 // shan begin if( petindex != -1){ if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ){ // 如果是守护兽的话 int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); int familyLevel = getFmLv(ownerindex); if (!CHAR_CHECKINDEX(ownerindex)){ print("主人索引错误!\n"); return -1; } #ifdef _FMVER21 if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER){ #else if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != 1){ #endif print("\n 宠物主人索引错误"); return -1; } // 需符合上下限 if( icache[i].ingval[j] <= ingtable[k]*ItemRandTableForItem[tablenum].rate && icache[i].ingval[j] >= ingtable[k]*(1/ItemRandTableForItem[tablenum].rate) && icache[i].ingval[j] <= ItemRandTableForItem[familyLevel+9].maxnum) { icache[i].hitnum++; break; } }else{ // 非守护兽的话 float toplimit = ingtable[k]*ItemRandTableForItem[tablenum].rate; if( toplimit > 1000) toplimit = 1000; // 需符合上下限 if( icache[i].ingval[j] <= toplimit && icache[i].ingval[j] >= ingtable[k]*(1/ItemRandTableForItem[tablenum].rate)){ icache[i].hitnum++; break; } } } // shan end }else { // 食物合成的话 // shan begin if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ){ int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); int familyLevel = getFmLv(ownerindex); if (!CHAR_CHECKINDEX(ownerindex)){ print("主人索引错误!\n"); return -1; } #ifdef _FMVER21 if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER){ #else if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != 1){ #endif print("\n 宠物主人索引错误"); return -1; } if( ingtable[k] > ItemRandTableForItem[familyLevel+9].maxnum / ItemSearchTable[searchtable].searchmax ){ ingtable[k] = ItemRandTableForItem[familyLevel+9].maxnum / ItemSearchTable[searchtable].searchmax; } }else{ if( ingtable[k] > ItemRandTableForItem[9].maxnum / ItemSearchTable[searchtable].searchmax ){ ingtable[k] = ItemRandTableForItem[9].maxnum / ItemSearchTable[searchtable].searchmax; } } // shan end if( icache[i].ingval[j] <= ingtable[k]*ItemSearchTable[searchtable].searchmax && icache[i].ingval[j] >= ingtable[k]*ItemSearchTable[searchtable].searchmin){ icache[i].hitnum++; break; } } } } } // 符合的材料数必须相同 if( icache[i].hitnum == icache[i].inguse && icache[i].hitnum == extractnum ){ if( ITEM_merge_checkitem(items,itemsnum,i)) { matchid[match++] = i; } } } } first = FALSE; }else { for( i = 0; i < icache_num; i++ ){ if( icache[i].use && icache[i].canmergeto) { if( icache[i].hitnum == icache[i].inguse && icache[i].hitnum == extractnum ){ if( ITEM_merge_checkitem(items,itemsnum,i)) { matchid[match++] = i; } } } } } if( match > 0 ) { return matchid[ random() % match ]; }else { } } return -1; } #ifdef _NEW_MANOR_LAW extern struct FM_POINTLIST fmpointlist; #endif int ITEM_mergeItem( int charaindex, ITEM_Item *items, int num , int money, int petid, int searchtable, int petindex, int alchemist) { int i; // shan add int item_type = -1; int ingnum =0; struct item_ingindtable ingindtable[MAX_ITEM_ATOMS_SIZE]; int sortedingindtable[MAX_ITEM_ATOMS_SIZE]; int sortedingtable[MAX_ITEM_ATOMS_SIZE]; /* ペットによる修正用 */ int pet_fixatom[MAX_ITEM_ATOMS_SIZE]; int pet_baseup[MAX_ITEM_ATOMS_SIZE]; int pet_minadd[MAX_ITEM_ATOMS_SIZE]; int pet_maxadd[MAX_ITEM_ATOMS_SIZE]; int pet_fixuse = MAX_ITEM_ATOMS_SIZE; int fm_fix; int nowtime; nowtime = time( NULL); // 如果合成封包过於频繁... if( nowtime - CHAR_getWorkInt( charaindex, CHAR_WORKLASTMERGETIME) < #ifdef _MERGE_TIME getMergeTime() #else 5 #endif +(num-2) ) { CHAR_setWorkInt( charaindex, CHAR_WORKLASTMERGETIME, nowtime); CHAR_talkToCli( charaindex, -1 ,"合成料理过於频繁,休息一下比较好哟。", CHAR_COLORRED); //print(" 合成频繁 "); return items[RAND( 0, (num-1))].data[ITEM_ID]; } CHAR_setWorkInt( charaindex, CHAR_WORKLASTMERGETIME, nowtime); for( i = 0; i < arraysizeof( ingindtable); i ++ ) { int j; for( j = 0; j < MAX_ITEM_ATOMS_SIZE; j ++ ) { ingindtable[i].data[j] = 0.0; } ingindtable[i].num = 0; ingindtable[i].index = -1; } for(i=0; i ItemRandTableForItem[familyLevel+9].maxnum ){ sortedingtable[i] = RAND(ItemRandTableForItem[familyLevel+9].minnum, ItemRandTableForItem[familyLevel+9].maxnum); } }else{ sortedingtable[i] = ITEM_randRange( sortedingtable[i], ItemRandTable[searchtable].randmin , ItemRandTable[searchtable].randmax); } } else{ if( searchtable == 0 ) { sortedingtable[i] = ITEM_randRange( sortedingtable[i], ((1/ItemRandTableForItem[tablenum].rate)*ITEM_MERGE_RANGEWIDTH_FORMIN) * ITEM_RANDRANGEDOM, ItemRandTableForItem[tablenum].rate * ITEM_MERGE_RANGEWIDTH_FORMAX * ITEM_RANDRANGEDOM); if(sortedingtable[i] > 905) sortedingtable[i] = 905; } else { sortedingtable[i] = ITEM_randRange( sortedingtable[i], ItemRandTable[searchtable].randmin , ItemRandTable[searchtable].randmax); } } } // shan end } } if( ingnum == 0 ) return -1; { int created; for( i = 0 ; i < 5; i++ ) { created = ITEM_merge_with_retry( items, num, sortedingindtable,ingnum, sortedingtable, searchtable, petindex); if( created >= 0 ) { // shan begin if( petindex != -1){ #ifdef _FMVER21 #else if( CHAR_getInt( CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX), CHAR_FMLEADERFLAG ) > 0 ){ #endif int kind_num = 0; int syndp = 0; int fooddp = 0; int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if (!CHAR_CHECKINDEX(ownerindex)){ print("ownerindex err!\n"); return -1; } if( searchtable == 1 ){ if( ITEMTBL_getInt( created, ITEM_INGVALUE0) != 0 ) kind_num++; if( ITEMTBL_getInt( created, ITEM_INGVALUE1) != 0 ) kind_num++; if( ITEMTBL_getInt( created, ITEM_INGVALUE2) != 0 ) kind_num++; if( ITEMTBL_getInt( created, ITEM_INGVALUE3) != 0 ) kind_num++; if( ITEMTBL_getInt( created, ITEM_INGVALUE4) != 0 ) kind_num++; fooddp = ITEMTBL_getInt( created, ITEM_INGVALUE0) + ITEMTBL_getInt( created, ITEM_INGVALUE1) + ITEMTBL_getInt( created, ITEM_INGVALUE2) + ITEMTBL_getInt( created, ITEM_INGVALUE3) + ITEMTBL_getInt( created, ITEM_INGVALUE4); #ifndef _NEW_MANOR_LAW #ifdef _PERSONAL_FAME // Arminius: 家族个人声望 fooddp = sqrt(fooddp) * pow(2,kind_num-2) * RAND(0,6) / 200; #else fooddp = sqrt(fooddp) * pow(2,kind_num-2) * RAND(0,6) / 100; #endif print("FoodDP: num->%d sumdp->%d", kind_num, fooddp); sprintf(buf, "%d", fooddp); #ifdef _PERSONAL_FAME // Arminius 8.30: 家族个人声望 CHAR_earnFame(ownerindex, fooddp); #endif #ifdef _FMVER21 if( CHAR_getInt( CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX), CHAR_FMLEADERFLAG ) > 0 && CHAR_getInt( CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX), CHAR_FMLEADERFLAG ) != FMMEMBER_APPLY ) { // CoolFish: 2001/10/03 int fd = getfdFromCharaIndex(ownerindex); saacproto_ACFixFMData_send(acfd, CHAR_getChar(ownerindex, CHAR_FMNAME), CHAR_getInt(ownerindex, CHAR_FMINDEX), CHAR_getWorkInt(ownerindex, CHAR_WORKFMINDEXI), FM_FIX_FMDEALFOOD, buf, "", // CoolFish: 2001/10/03 CHAR_getWorkInt(ownerindex, CHAR_WORKFMCHARINDEX), CONNECT_getFdid(fd)); // CHAR_getWorkInt(ownerindex, CHAR_WORKFMCHARINDEX), 0); } #else saacproto_ACFixFMData_send(acfd, CHAR_getChar(ownerindex, CHAR_FMNAME), CHAR_getInt(ownerindex, CHAR_FMINDEX), CHAR_getWorkInt(ownerindex, CHAR_WORKFMINDEXI), FM_FIX_FMDEALFOOD, buf, "", CHAR_getWorkInt(ownerindex, CHAR_WORKFMCHARINDEX), 0); #endif #endif }else{ syndp = ITEMTBL_getInt( created, ITEM_INGVALUE0) + ITEMTBL_getInt( created, ITEM_INGVALUE1) + ITEMTBL_getInt( created, ITEM_INGVALUE2) + ITEMTBL_getInt( created, ITEM_INGVALUE3) + ITEMTBL_getInt( created, ITEM_INGVALUE4); #ifndef _NEW_MANOR_LAW #ifdef _PERSONAL_FAME // Arminius: 家族个人声望 syndp = syndp / 200; #else syndp = syndp / 100; #endif sprintf(buf, "%d", syndp); #ifdef _PERSONAL_FAME // Arminius 8.30: 家族个人声望 CHAR_earnFame(ownerindex, syndp); #endif #ifdef _FMVER21 if( CHAR_getInt( CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX), CHAR_FMLEADERFLAG ) > 0 && CHAR_getInt( CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX), CHAR_FMLEADERFLAG ) != FMMEMBER_APPLY ) { // CoolFish: 2001/10/03 int fd = getfdFromCharaIndex(ownerindex); saacproto_ACFixFMData_send(acfd, CHAR_getChar(ownerindex, CHAR_FMNAME), CHAR_getInt(ownerindex, CHAR_FMINDEX), CHAR_getWorkInt(ownerindex, CHAR_WORKFMINDEXI), FM_FIX_FMSYNTHESIZE, buf, "", // CoolFish: 2001/10/03 CHAR_getWorkInt(ownerindex, CHAR_WORKFMCHARINDEX), CONNECT_getFdid(fd)); } #else saacproto_ACFixFMData_send(acfd, CHAR_getChar(ownerindex, CHAR_FMNAME), CHAR_getInt(ownerindex, CHAR_FMINDEX), CHAR_getWorkInt(ownerindex, CHAR_WORKFMINDEXI), FM_FIX_FMSYNTHESIZE, buf, "", CHAR_getWorkInt(ownerindex, CHAR_WORKFMCHARINDEX), 0); #endif #endif } #ifdef _FMVER21 #else } #endif } return created; } } return items[RAND( 0, (num-1))].data[ITEM_ID]; } return -3; } int ITEM_canDigest( ITEM_Item *itm ) { /* 1個目の材料の名前が設定されていたら1、 そうでないなら0 */ if( itm->string[ITEM_INGNAME0].string[0] ) return 1; else return 0; } int ITEM_merge_test(void) { int iid,i,k; ITEM_Item itm[1]; for( k = 0 ; k < 10 ; k ++ ){ iid = 1; for( i = 0 ; i < 20 ; i ++ ){ ITEM_makeItem( &itm[0] , iid ); print( "%d RETURN: %d\n", i, // shan iid = ITEM_mergeItem( -1, itm, 1 , 0, -1,0,-1,0) ); } print( "------\n" ); } return 0; } int ITEM_mergeItem_merge( int charaindex, int petid, char *data, int petindex, int alchemist) { BOOL result = FALSE; int i; int ret; int cnt = 0; int itemindexs[CHAR_MAXITEMHAVE - CHAR_STARTITEMARRAY]; int haveitemindexs[CHAR_MAXITEMHAVE - CHAR_STARTITEMARRAY]; // Nuke +2 1026: Avoid merge cheat int itemflag[CHAR_MAXITEMHAVE - CHAR_STARTITEMARRAY]; int j,collision=0; char buff[64]; ITEM_Item items[CHAR_MAXITEMHAVE - CHAR_STARTITEMARRAY]; // Nuke +1 1026 memset(itemflag,0,sizeof(itemflag)); { int emptyindex = CHAR_findEmptyItemBox( charaindex ); if( emptyindex == -1 ){ CHAR_talkToCli( charaindex, -1, "合成时,最少需空一格物品栏位!", CHAR_COLORYELLOW); return -1; } } for( i = CHAR_STARTITEMARRAY; i < CHAR_MAXITEMHAVE; i ++ ) { int haveitemindex; ret = getStringFromIndexWithDelim( data , "|", i - CHAR_STARTITEMARRAY+1, buff, sizeof( buff ) ); if( ret == FALSE ) break; haveitemindex = atoi( buff); if( CHAR_CHECKITEMINDEX( charaindex, haveitemindex) ) { int itemindex = CHAR_getItemIndex( charaindex, haveitemindex); if( ITEM_CHECKINDEX( itemindex)) { if(ITEM_getInt(itemindex,ITEM_TIME)>0){ CHAR_talkToCli( charaindex, -1, "限时道具无法合成或料理!", CHAR_COLORYELLOW); return FALSE; } #ifdef _ITEM_INSLAY char *code; if( (code = ITEM_getChar( itemindex, ITEM_TYPECODE)) == "\0" ) { if( strcmp( code, "\0") ) { char token[256]; snprintf( token, sizeof( token), "似乎对%s没有兴趣。", ITEM_getChar( itemindex, ITEM_NAME)); CHAR_talkToCli( charaindex, -1, token, CHAR_COLORYELLOW); return FALSE; } } #endif if( ITEM_getmergeItemFromFromITEMtabl( ITEM_getInt( itemindex, ITEM_ID)) == TRUE ){ //检查是否可合成 ITEM_Item *itm; itm = ITEM_getItemPointer(itemindex); if( itm != NULL ) { ITEM_makeItem( &items[cnt], ITEM_getInt( itemindex, ITEM_ID)); itemindexs[cnt] = itemindex; haveitemindexs[cnt] = haveitemindex; // Nuke start 1026 for (j=0;j 1 ) { int randtable = 0; if( items[0].data[ITEM_TYPE] == ITEM_DISH ) { randtable = 1; } ret = ITEM_mergeItem( charaindex, items, cnt, 0, petid, randtable, petindex, alchemist); if( ret == -10) CHAR_talkToCli( charaindex, -1, "非法的合成方法", CHAR_COLORWHITE); CHAR_setInt( charaindex, CHAR_MERGEITEMCOUNT, CHAR_getInt( charaindex, CHAR_MERGEITEMCOUNT)+1); for( i = 0; i < cnt; i ++ ) { #ifdef _ITEM_PILENUMS int pilenum=0; int itemindex = CHAR_getItemIndex( charaindex, haveitemindexs[i]); if( !ITEM_CHECKINDEX( itemindex) ) continue; pilenum = ITEM_getInt( itemindex, ITEM_USEPILENUMS); pilenum -= 1; ITEM_setInt( itemindex, ITEM_USEPILENUMS, pilenum); if( pilenum <= 0 ){ #endif CHAR_setItemIndex( charaindex, haveitemindexs[i], -1); CHAR_sendItemDataOne( charaindex, haveitemindexs[i]); LogItem( CHAR_getChar( charaindex, CHAR_NAME ), /* キャラ名 */ CHAR_getChar( charaindex, CHAR_CDKEY ), #ifdef _add_item_log_name // WON ADD 在item的log中增加item名称 itemindexs[i], #else ITEM_getInt( itemindexs[i], ITEM_ID), /* アイテム番号 */ #endif "mergedel(合成所删除的道具)", CHAR_getInt( charaindex,CHAR_FLOOR), CHAR_getInt( charaindex,CHAR_X ), CHAR_getInt( charaindex,CHAR_Y ), ITEM_getChar( itemindexs[i], ITEM_UNIQUECODE), ITEM_getChar( itemindexs[i], ITEM_NAME), ITEM_getInt( itemindexs[i], ITEM_ID) ); ITEM_endExistItemsOne( itemindexs[i]); #ifdef _ITEM_PILENUMS } #endif } CHAR_sendItemData( charaindex, haveitemindexs, cnt); if( ret >= 0 ) { int rc; int createitemindex = ITEM_makeItemAndRegist( ret); // shan begin if( createitemindex != -1 ){ if( petindex != -1){ #ifdef _FM_LIAOLI if(getFmLiaoLiType()==1 || CHAR_getInt(petindex, CHAR_PETFAMILY) == 1){ #else if( CHAR_getInt(petindex, CHAR_PETFAMILY) == 1 ){ #endif int ownerindex = CHAR_getWorkInt(petindex, CHAR_WORKPLAYERINDEX); if (!CHAR_CHECKINDEX(ownerindex)){ print("ownerindex err!\n"); return -1; } #ifdef _FM_LIAOLI if(getFmLiaoLiType()!=1 && CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER){ #else #ifdef _FMVER21 if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != FMMEMBER_LEADER){ #else if( CHAR_getInt( ownerindex, CHAR_FMLEADERFLAG) != 1){ #endif #endif print("\n Pet Ownerindex Error"); return -1; } if( randtable == 1){ char *p; char charbuf1[512]="",charbuf2[1024]="",charbuf[128]=""; char argbuf[256]; int arg1 = 0, arg2 = 0; if( ITEM_getInt( createitemindex, ITEM_TYPE) == 20){ if( (p = strstr( ITEM_getChar(createitemindex, ITEM_ARGUMENT), "气")) ){ strcpy( argbuf, (p+2)); arg1 = atoi(argbuf); arg1 = arg1 * FOOD_MP_RATE / 100; } if( (p = strstr( ITEM_getChar(createitemindex, ITEM_ARGUMENT), "体")) ){ strcpy( argbuf, (p+2)); arg2 = atoi(argbuf); arg2 = arg2 * FOOD_HP_RATE / 100; } if( arg1 != 0 && arg2 != 0 ){ sprintf( charbuf1, "气%d体%d", arg1, arg2); } else if( arg1 != 0){ sprintf( charbuf1, "气%d", arg1); } else if( arg2 != 0){ sprintf( charbuf1, "体%d", arg2); } if(arg1!=0 || arg2!=0){ #ifdef _FM_LIAOLI sprintf( charbuf, "(功效翻倍)"); #else sprintf( charbuf, "(家族料理)"); #endif strcpy( charbuf2, ITEM_getChar( createitemindex, ITEM_EFFECTSTRING)); strncat( charbuf2, charbuf, 10); ITEM_setChar( createitemindex, ITEM_ARGUMENT, charbuf1); ITEM_setChar( createitemindex, ITEM_EFFECTSTRING, charbuf2); } } } } } } // shan end ITEM_setInt( createitemindex, ITEM_MERGEFLG, TRUE); if( createitemindex != -1 ) { rc = CHAR_addItemSpecificItemIndex( charaindex, createitemindex); if( rc >= 0 && rc < CHAR_MAXITEMHAVE) { CHAR_sendItemDataOne( charaindex, rc); LogItem( CHAR_getChar( charaindex, CHAR_NAME ), CHAR_getChar( charaindex, CHAR_CDKEY ), #ifdef _add_item_log_name // WON ADD 在item的log中增加item名称 createitemindex, #else ITEM_getInt( createitemindex, ITEM_ID), #endif "mergeadd(合成出来的道具)", CHAR_getInt( charaindex,CHAR_FLOOR), CHAR_getInt( charaindex,CHAR_X ), CHAR_getInt( charaindex,CHAR_Y ), ITEM_getChar( createitemindex, ITEM_UNIQUECODE), ITEM_getChar( createitemindex, ITEM_NAME), ITEM_getInt( createitemindex, ITEM_ID) ); result = TRUE; } else { ITEM_endExistItemsOne( createitemindex); } } } } return result; } static int ITEM_getTableNum( int num) { int i; for( i = 0; i < arraysizeof( ItemRandTableForItem); i ++) { if( num <= ItemRandTableForItem[i].maxnum ) { break; } } if( i == arraysizeof( ItemRandTableForItem)) i--; return i; } #ifdef _ITEM_INSLAY int PETSKILL_ITEM_inslay( int charindex, int inslayindex, int itemindex) { char *inslaystr , *code=NULL; char codeTemp[][32]={ "NULL", "NULL", "NULL"}; char codeTemp1[][32]={ "NULL", "NULL", "NULL", "NULL"}; char codeTemp2[][32]={ "NULL", "NULL", "NULL", "NULL", "NULL"}; char buf1[256], buf2[256]; char TypeName[][256]={ "攻", "防", "敏", "HP", "MP", "幸运", "伤", "吸", "魔法ID" }; int worktyp[] = { ITEM_MODIFYATTACK, ITEM_MODIFYDEFENCE, ITEM_MODIFYQUICK, ITEM_MODIFYHP, ITEM_MODIFYMP, ITEM_MODIFYLUCK, ITEM_OTHERDAMAGE, ITEM_OTHERDEFC, ITEM_MAGICID }; int worknum[ arraysizeof(worktyp)]; int i; #ifdef _DIY_INSLAY int MAXCANINSLAY=getInslayNum(); #else int MAXCANINSLAY=3; #endif memset( worknum, 0, sizeof( worknum)); if( !CHAR_CHECKINDEX( charindex) ) return FALSE; if( !ITEM_CHECKINDEX( inslayindex) ) return FALSE; if( !ITEM_CHECKINDEX( itemindex) ) return FALSE; if( itemindex == inslayindex ) return FALSE; if( ITEM_getInt(itemindex,ITEM_TIME)>0 || ITEM_getInt(inslayindex,ITEM_TIME)>0){ CHAR_talkToCli( charindex, -1, "限时道具无法合成或料理!", CHAR_COLORYELLOW); return FALSE; } if( (code = ITEM_getChar( itemindex, ITEM_TYPECODE)) == "\0" ) { print(" ITEM_TYPECODE == NULL error !!\n"); return FALSE; } if( !strcmp( code, "NULL" ) ) return FALSE; if( (inslaystr = ITEM_getChar( inslayindex, ITEM_INLAYCODE)) == "\0" ) { print(" ITEM_INLAYCODE == NULL error !!\n"); return FALSE; } for( i = 0; i < MAXCANINSLAY; i ++ ) { if( getStringFromIndexWithDelim( inslaystr , "|", i+1, buf1, sizeof( buf1 ) ) == TRUE ){ if( strcmp( buf1, "\0")){ if(MAXCANINSLAY == 4){ sprintf( codeTemp1[i], "%s", buf1); }else if(MAXCANINSLAY == 5){ sprintf( codeTemp2[i], "%s", buf1); }else{ sprintf( codeTemp[i], "%s", buf1); } } continue; } break; } for( i = 0; i < MAXCANINSLAY; i ++ ) { if(MAXCANINSLAY == 4){ if( strcmp( codeTemp1[i], "NULL") ) continue; sprintf( codeTemp1[i], "%s", code); break; }else if(MAXCANINSLAY == 5){ if( strcmp( codeTemp2[i], "NULL") ) continue; sprintf( codeTemp2[i], "%s", code); break; }else{ if( strcmp( codeTemp[i], "NULL") ) continue; sprintf( codeTemp[i], "%s", code); break; } } if( i == MAXCANINSLAY ) { CHAR_talkToCli( charindex, -1, "武器或防具已经镶满了。", CHAR_COLORYELLOW); return FALSE; } memset( buf2, 0, sizeof( buf2)); if(MAXCANINSLAY==4){ sprintf( buf2, "%s|%s|%s|%s", codeTemp1[0], codeTemp1[1], codeTemp1[2], codeTemp1[3]); }else if(MAXCANINSLAY==5){ sprintf( buf2, "%s|%s|%s|%s|%s", codeTemp2[0], codeTemp2[1], codeTemp2[2], codeTemp2[3], codeTemp2[4]); }else{ sprintf( buf2, "%s|%s|%s", codeTemp[0], codeTemp[1], codeTemp[2]); } // sprintf( buf2, "%s|%s|%s", codeTemp[0], codeTemp[1], codeTemp[2]); // print("buf2:%s\n", buf2); ITEM_setChar( inslayindex, ITEM_INLAYCODE, buf2); for( i=0; i 0 ) { //魔法 ID int magicid,mp; magicid = ITEM_getInt( itemindex, ITEM_MAGICID); ITEM_setInt( inslayindex, ITEM_MAGICID, magicid); mp = ITEM_getInt( itemindex, ITEM_MAGICUSEMP ); ITEM_setInt( inslayindex, ITEM_MAGICUSEMP, mp); } for( i=ITEM_FIRSTFUNCTION; i 0 ) { //取得魔法名称 int marray = MAGIC_getMagicArray( ITEM_getInt( inslayindex, ITEM_MAGICID)); if( marray != -1 ){ if( (magicname = MAGIC_getChar( marray, MAGIC_NAME)) != NULL ){ sprintf( Mname, "%s", magicname); } } ITEM_setInt( inslayindex, ITEM_MAGICID, ITEM_getInt( inslayindex, ITEM_MAGICID)); } sprintf( secretname, "%s%s%d %s%s%d %s%s%d %s%s%d %s%s%d %s%s%d %s%s%d %s", TypeName[0],(worknum[0]>=0)?"+":"",worknum[0], TypeName[1],(worknum[1]>=0)?"+":"",worknum[1], TypeName[2],(worknum[2]>=0)?"+":"",worknum[2], TypeName[3],(worknum[3]>=0)?"+":"",worknum[3], TypeName[4],(worknum[4]>=0)?"+":"",worknum[4], TypeName[6],(worknum[6]>=0)?"+":"",worknum[6], TypeName[7],(worknum[7]>=0)?"+":"",worknum[7], Mname); ITEM_setChar( inslayindex, ITEM_EFFECTSTRING, secretname); } return TRUE; } #endif #ifdef _PETSKILL_FIXITEM int PETSKILL_ITEM_FixItem( int charindex, int fixindex, int *itemindex) { int index, i; char *buf2; int crushes, maxcrushes; #define MAXFIXNUM 2 index = 0; for( i=0; i= 5 ){ #ifdef _ITEM_FIXALLBASE char *ITEM_ARG = ITEM_getChar( index, ITEM_ARGUMENT); if( ITEM_ARG != "\0" && !strcmp( ITEM_ARG, "FIXITEMALL") ){ }else{ #endif CHAR_talkToCli( charindex, -1, "材料不符", CHAR_COLORYELLOW); return FALSE; #ifdef _ITEM_FIXALLBASE } #endif } crushes = ITEM_getInt( fixindex, ITEM_DAMAGECRUSHE); maxcrushes = ITEM_getInt( fixindex, ITEM_MAXDAMAGECRUSHE); if( crushes >= (maxcrushes*0.80) ) { char buff[256]; sprintf( buff, "%s并没有损坏到需要修复。", ITEM_getChar( fixindex, ITEM_NAME)); CHAR_talkToCli( charindex, -1, buff, CHAR_COLORYELLOW); return FALSE; }else { char *buf1; if( maxcrushes < 500 ){ CHAR_talkToCli( charindex, -1, "此物品已不能修复", CHAR_COLORYELLOW); return FALSE; } if( crushes <= 0 ) return FALSE; maxcrushes = maxcrushes*0.85; crushes = maxcrushes; ITEM_setInt( fixindex, ITEM_DAMAGECRUSHE, crushes); ITEM_setInt( fixindex, ITEM_MAXDAMAGECRUSHE, maxcrushes); //修正名称 buf1 = ITEM_getChar( fixindex, ITEM_SECRETNAME); if( strstr( buf1, "(") != 0 ) { char buf5[256]; if( getStringFromIndexWithDelim( buf1,"(",1, buf5, sizeof( buf5)) != FALSE ) { sprintf( buf1, buf5); } } ITEM_setChar( fixindex, ITEM_SECRETNAME, buf1); ITEM_setInt( fixindex, ITEM_CRUSHLEVEL, 0); } return TRUE; } #endif