forked from metin2/server
935 lines
29 KiB
C++
935 lines
29 KiB
C++
//#define __FISHING_MAIN__
|
|
#include "stdafx.h"
|
|
#include "constants.h"
|
|
#include "fishing.h"
|
|
#include "locale_service.h"
|
|
|
|
#ifndef __FISHING_MAIN__
|
|
#include "item_manager.h"
|
|
|
|
#include "config.h"
|
|
#include "packet.h"
|
|
|
|
#include "sectree_manager.h"
|
|
#include "char.h"
|
|
#include "char_manager.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "questmanager.h"
|
|
#include "buffer_manager.h"
|
|
#include "desc_client.h"
|
|
#include "locale_service.h"
|
|
|
|
#include "affect.h"
|
|
#include "unique_item.h"
|
|
#endif
|
|
|
|
namespace fishing
|
|
{
|
|
enum
|
|
{
|
|
MAX_FISH = 37,
|
|
NUM_USE_RESULT_COUNT = 10, // 1 : DEAD 2 : BONE 3 ~ 12 : rest
|
|
FISH_BONE_VNUM = 27799,
|
|
SHELLFISH_VNUM = 27987,
|
|
EARTHWORM_VNUM = 27801,
|
|
WATER_STONE_VNUM_BEGIN = 28030,
|
|
WATER_STONE_VNUM_END = 28043,
|
|
FISH_NAME_MAX_LEN = 64,
|
|
MAX_PROB = 4,
|
|
};
|
|
|
|
enum
|
|
{
|
|
USED_NONE,
|
|
USED_SHELLFISH,
|
|
USED_WATER_STONE,
|
|
USED_TREASURE_MAP,
|
|
USED_EARTHWARM,
|
|
MAX_USED_FISH
|
|
};
|
|
|
|
enum
|
|
{
|
|
FISHING_TIME_NORMAL,
|
|
FISHING_TIME_SLOW,
|
|
FISHING_TIME_QUICK,
|
|
FISHING_TIME_ALL,
|
|
FISHING_TIME_EASY,
|
|
|
|
FISHING_TIME_COUNT,
|
|
|
|
MAX_FISHING_TIME_COUNT = 31,
|
|
};
|
|
|
|
enum
|
|
{
|
|
FISHING_LIMIT_NONE,
|
|
FISHING_LIMIT_APPEAR,
|
|
};
|
|
|
|
int aFishingTime[FISHING_TIME_COUNT][MAX_FISHING_TIME_COUNT] =
|
|
{
|
|
{ 0, 0, 0, 0, 0, 2, 4, 8, 12, 16, 20, 22, 25, 30, 50, 80, 50, 30, 25, 22, 20, 16, 12, 8, 4, 2, 0, 0, 0, 0, 0 },
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 22, 25, 30, 50, 80, 50, 30, 25, 22, 20 },
|
|
{ 20, 22, 25, 30, 50, 80, 50, 30, 25, 22, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
|
|
{ 20, 20, 20, 20, 20, 22, 24, 28, 32, 36, 40, 42, 45, 50, 70, 100, 70, 50, 45, 42, 40, 36, 32, 28, 24, 22, 20, 20, 20, 20, 20 },
|
|
};
|
|
|
|
struct SFishInfo
|
|
{
|
|
char name[FISH_NAME_MAX_LEN];
|
|
|
|
DWORD vnum;
|
|
DWORD dead_vnum;
|
|
DWORD grill_vnum;
|
|
|
|
int prob[MAX_PROB];
|
|
int difficulty;
|
|
|
|
int time_type;
|
|
int length_range[3]; // MIN MAX EXTRA_MAX : 99% MIN~MAX, 1% MAX~EXTRA_MAX
|
|
|
|
int used_table[NUM_USE_RESULT_COUNT];
|
|
// 6000 2000 1000 500 300 100 50 30 10 5 4 1
|
|
};
|
|
|
|
bool operator < ( const SFishInfo& lhs, const SFishInfo& rhs )
|
|
{
|
|
return lhs.vnum < rhs.vnum;
|
|
}
|
|
|
|
int g_prob_sum[MAX_PROB];
|
|
int g_prob_accumulate[MAX_PROB][MAX_FISH];
|
|
|
|
SFishInfo fish_info[MAX_FISH] = { { "\0", }, };
|
|
/*
|
|
{
|
|
{ "\xB2\xCE", 00000, 00000, 00000, { 750, 1750, 2750 }, 10, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, { 0, },
|
|
{0, } },
|
|
{ "\xB1\xDD\xB9\xDD\xC1\xF6", 50002, 00000, 00000, { 50, 50, 0 }, 200, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, { 0, },
|
|
{0, } },
|
|
{ "\xC7\xC7\xB6\xF3\xB9\xCC", 27802, 00000, 00000, { 2100, 1500, 50 }, 10, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_EASY, {500, 550, 600},
|
|
{0, } },
|
|
{ "\xBA\xD8\xBE\xEE", 27803, 27833, 27863, { 2100, 1500, 100 }, 13, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_EASY, {1000,2500,2800},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBD\xEE\xB0\xA1\xB8\xAE", 27804, 27834, 27864, { 1100, 1300, 150 }, 16, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {2000,3500,3800},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBF\xF9\xC3\xB4\xBA\xD8\xBE\xEE", 27805, 27835, 27865, { 1100, 1100, 200 }, 20, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_SLOW, {3030,3500,4300},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC0\xD7\xBE\xEE", 27806, 27836, 27866, { 1100, 500, 300 }, 26, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {4000,6000,10000},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBF\xAC\xBE\xEE", 27807, 27837, 27867, { 1100, 450, 400 }, 33, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{6000,8000,10000},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC7\xE2\xBE\xEE", 27808, 27838, 27868, { 200, 400, 500 }, 42, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{1500,3000,3800},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBC\xDB\xBE\xEE", 27809, 27839, 27869, { 200, 300, 700 }, 54, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{5000,7000,8000},
|
|
{USED_NONE, USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB9\xCE\xB9\xB0\xC0\xE5\xBE\xEE", 27810, 27840, 27870, { 0, 270, 1000 }, 70, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{4000,5000,6000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB9\xAB\xC1\xF6\xB0\xB3\xBC\xDB\xBE\xEE", 27811, 27841, 27871, { 0, 200, 1000 }, 91, FISHING_LIMIT_APPEAR, { 0, 0, 0}, FISHING_TIME_NORMAL,{5000,7000,8000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB0\xAD\xBC\xDB\xBE\xEE", 27812, 27842, 27872, { 0, 160, 1000 }, 118, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_QUICK,{4000,6000,7000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB7\xAF\xB5\xE5", 27813, 27843, 27873, { 0, 130, 700 }, 153, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{4000,6000,10000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC6\xDB\xC4\xA1", 27814, 27844, 27874, { 0, 100, 400 }, 198, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{3000,4000,5000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC5\xD9\xC4\xA1", 27815, 27845, 27875, { 0, 50, 300 }, 257, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{3500,5500,8000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB8\xDE\xB1\xE2", 27816, 27846, 27876, { 0, 30, 100 }, 334, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{3000,5000,10000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB9\xCC\xB2\xD9\xB6\xF3\xC1\xF6", 27817, 27847, 27877, { 0, 10, 64 }, 434, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_QUICK,{1800,2200,3000},
|
|
{USED_SHELLFISH, USED_NONE, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xB9\xE9\xB7\xC3", 27818, 27848, 27878, { 0, 0, 15 }, 564, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{5000,8000,10000},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC0\xBA\xBE\xEE", 27819, 27849, 27879, { 0, 0, 9 }, 733, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{1500,3000,3800},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBA\xF9\xBE\xEE", 27820, 27850, 27880, { 0, 0, 6 }, 952, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_QUICK,{1500,3000,3800},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBD\xAC\xB8\xAE", 27821, 27851, 27881, { 0, 0, 3 }, 1237, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL,{1000,1500,2000},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xBA\xF1\xB4\xC3\xC0\xD7\xBE\xEE", 27822, 27852, 27882, { 0, 0, 2 }, 1608, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_SLOW,{4000,6000,10000},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC8\xB2\xB1\xDD\xBA\xD8\xBE\xEE", 27823, 27853, 27883, { 0, 0, 1 }, 2090, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_SLOW,{1000,3000,3500},
|
|
{USED_SHELLFISH, USED_NONE, USED_WATER_STONE, USED_TREASURE_MAP, USED_NONE, USED_NONE, USED_EARTHWARM, USED_NONE,USED_NONE, USED_NONE } },
|
|
{ "\xC5\xBB\xBB\xF6\xBE\xE0", 70201, 00000, 00000, { 5, 5, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBF\xB0\xBB\xF6\xBE\xE0(\xC8\xF2\xBB\xF6)", 70202, 00000, 00000, { 15, 15, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBF\xB0\xBB\xF6\xBE\xE0(\xB1\xDD\xBB\xF6)", 70203, 00000, 00000, { 15, 15, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBF\xB0\xBB\xF6\xBE\xE0(\xBB\xA1\xB0\xA3\xBB\xF6)",70204, 00000, 00000, { 15, 15, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBF\xB0\xBB\xF6\xBE\xE0(\xB0\xA5\xBB\xF6)", 70205, 00000, 00000, { 15, 15, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBF\xB0\xBB\xF6\xBE\xE0(\xB0\xCB\xC0\xBA\xBB\xF6)",70206, 00000, 00000, { 15, 15, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xC0\xBA\xB5\xD0\xC0\xDA\xC0\xC7 \xB8\xC1\xC5\xE4", 70048, 00000, 00000, { 8, 8, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xC7\xE0\xBF\xEE\xC0\xC7 \xB9\xDD\xC1\xF6", 70049, 00000, 00000, { 8, 8, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBC\xB1\xBF\xD5\xC0\xC7 \xC1\xF5\xC7\xA5", 70050, 00000, 00000, { 8, 8, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xBC\xB1\xBF\xD5\xC0\xC7 \xC0\xE5\xB0\xA9", 70051, 00000, 00000, { 8, 8, 0 }, 60, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, },
|
|
{0, }},
|
|
{ "\xB1\xDD\xB5\xA2\xBE\xEE\xB8\xAE", 80008, 00000, 00000, { 20, 20, 0 }, 250, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_SLOW, {0, },
|
|
{0, } },
|
|
{ "\xC0\xBA\xBF\xAD\xBC\xE8", 50009, 00000, 00000, {300, 300, 0, }, 70, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, }, {0, } },
|
|
|
|
{ "\xB1\xDD\xBF\xAD\xBC\xE8", 50008, 00000, 00000, {110, 110, 0, }, 100, FISHING_LIMIT_NONE, { 0, 0, 0}, FISHING_TIME_NORMAL, {0, }, {0, } },
|
|
};
|
|
*/
|
|
void Initialize()
|
|
{
|
|
SFishInfo fish_info_bak[MAX_FISH];
|
|
memcpy(fish_info_bak, fish_info, sizeof(fish_info));
|
|
|
|
memset(fish_info, 0, sizeof(fish_info));
|
|
|
|
|
|
// LOCALE_SERVICE
|
|
const int FILE_NAME_LEN = 256;
|
|
char szFishingFileName[FILE_NAME_LEN+1];
|
|
snprintf(szFishingFileName, sizeof(szFishingFileName),
|
|
"%s/fishing.txt", LocaleService_GetBasePath().c_str());
|
|
FILE * fp = fopen(szFishingFileName, "r");
|
|
// END_OF_LOCALE_SERVICE
|
|
|
|
if (*fish_info_bak[0].name)
|
|
SendLog("Reloading fish table.");
|
|
|
|
if (!fp)
|
|
{
|
|
SendLog("error! cannot open fishing.txt");
|
|
|
|
// 백업에 이름이 있으면 리스토어 한다.
|
|
if (*fish_info_bak[0].name)
|
|
{
|
|
memcpy(fish_info, fish_info_bak, sizeof(fish_info));
|
|
SendLog(" restoring to backup");
|
|
}
|
|
return;
|
|
}
|
|
|
|
memset(fish_info, 0, sizeof(fish_info));
|
|
|
|
char buf[512];
|
|
int idx = 0;
|
|
|
|
while (fgets(buf, 512, fp))
|
|
{
|
|
if (*buf == '#')
|
|
continue;
|
|
|
|
char * p = strrchr(buf, '\n');
|
|
*p = '\0';
|
|
|
|
const char * start = buf;
|
|
const char * tab = strchr(start, '\t');
|
|
|
|
if (!tab)
|
|
{
|
|
printf("Tab error on line: %s\n", buf);
|
|
SendLog("error! parsing fishing.txt");
|
|
|
|
if (*fish_info_bak[0].name)
|
|
{
|
|
memcpy(fish_info, fish_info_bak, sizeof(fish_info));
|
|
SendLog(" restoring to backup");
|
|
}
|
|
break;
|
|
}
|
|
|
|
char szCol[256], szCol2[256];
|
|
int iColCount = 0;
|
|
|
|
do
|
|
{
|
|
strlcpy(szCol2, start, std::min<size_t>(sizeof(szCol2), (tab - start) + 1));
|
|
szCol2[tab-start] = '\0';
|
|
|
|
trim_and_lower(szCol2, szCol, sizeof(szCol));
|
|
|
|
if (!*szCol || *szCol == '\t')
|
|
iColCount++;
|
|
else
|
|
{
|
|
switch (iColCount++)
|
|
{
|
|
case 0: strlcpy(fish_info[idx].name, szCol, sizeof(fish_info[idx].name)); break;
|
|
case 1: str_to_number(fish_info[idx].vnum, szCol); break;
|
|
case 2: str_to_number(fish_info[idx].dead_vnum, szCol); break;
|
|
case 3: str_to_number(fish_info[idx].grill_vnum, szCol); break;
|
|
case 4: str_to_number(fish_info[idx].prob[0], szCol); break;
|
|
case 5: str_to_number(fish_info[idx].prob[1], szCol); break;
|
|
case 6: str_to_number(fish_info[idx].prob[2], szCol); break;
|
|
case 7: str_to_number(fish_info[idx].prob[3], szCol); break;
|
|
case 8: str_to_number(fish_info[idx].difficulty, szCol); break;
|
|
case 9: str_to_number(fish_info[idx].time_type, szCol); break;
|
|
case 10: str_to_number(fish_info[idx].length_range[0], szCol); break;
|
|
case 11: str_to_number(fish_info[idx].length_range[1], szCol); break;
|
|
case 12: str_to_number(fish_info[idx].length_range[2], szCol); break;
|
|
case 13: // 0
|
|
case 14: // 1
|
|
case 15: // 2
|
|
case 16: // 3
|
|
case 17: // 4
|
|
case 18: // 5
|
|
case 19: // 6
|
|
case 20: // 7
|
|
case 21: // 8
|
|
case 22: // 9
|
|
str_to_number(fish_info[idx].used_table[iColCount-1-12], szCol);
|
|
break;
|
|
}
|
|
}
|
|
|
|
start = tab + 1;
|
|
tab = strchr(start, '\t');
|
|
} while (tab);
|
|
|
|
idx++;
|
|
|
|
if (idx == MAX_FISH)
|
|
break;
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
for (int i = 0; i < MAX_FISH; ++i)
|
|
{
|
|
SPDLOG_TRACE("FISH: {:24} vnum {:5} prob {:4} {:4} {:4} {:4} len {} {} {}",
|
|
fish_info[i].name,
|
|
fish_info[i].vnum,
|
|
fish_info[i].prob[0],
|
|
fish_info[i].prob[1],
|
|
fish_info[i].prob[2],
|
|
fish_info[i].prob[3],
|
|
fish_info[i].length_range[0],
|
|
fish_info[i].length_range[1],
|
|
fish_info[i].length_range[2]);
|
|
}
|
|
|
|
// 확률 계산
|
|
for (int j = 0; j < MAX_PROB; ++j)
|
|
{
|
|
g_prob_accumulate[j][0] = fish_info[0].prob[j];
|
|
|
|
for (int i = 1; i < MAX_FISH; ++i)
|
|
g_prob_accumulate[j][i] = fish_info[i].prob[j] + g_prob_accumulate[j][i - 1];
|
|
|
|
g_prob_sum[j] = g_prob_accumulate[j][MAX_FISH - 1];
|
|
SPDLOG_DEBUG("FISH: prob table {} {}", j, g_prob_sum[j]);
|
|
}
|
|
}
|
|
|
|
int DetermineFishByProbIndex(int prob_idx)
|
|
{
|
|
int rv = Random::get(1, g_prob_sum[prob_idx]);
|
|
int * p = std::lower_bound(g_prob_accumulate[prob_idx], g_prob_accumulate[prob_idx]+ MAX_FISH, rv);
|
|
int fish_idx = p - g_prob_accumulate[prob_idx];
|
|
return fish_idx;
|
|
}
|
|
|
|
int GetProbIndexByMapIndex(int index)
|
|
{
|
|
if (index > 60)
|
|
return -1;
|
|
|
|
switch (index)
|
|
{
|
|
case 1:
|
|
case 21:
|
|
case 41:
|
|
return 0;
|
|
|
|
case 3:
|
|
case 23:
|
|
case 43:
|
|
return 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
#ifndef __FISHING_MAIN__
|
|
int DetermineFish(LPCHARACTER ch)
|
|
{
|
|
int map_idx = ch->GetMapIndex();
|
|
int prob_idx = GetProbIndexByMapIndex(map_idx);
|
|
|
|
if (prob_idx < 0)
|
|
return 0;
|
|
|
|
// ADD_PREMIUM
|
|
if (ch->GetPremiumRemainSeconds(PREMIUM_FISH_MIND) > 0 ||
|
|
ch->IsEquipUniqueGroup(UNIQUE_GROUP_FISH_MIND)) // 월간어심 착용시 고급 물고기 확률 상승
|
|
{
|
|
if (quest::CQuestManager::instance().GetEventFlag("manwoo") != 0)
|
|
prob_idx = 3;
|
|
else
|
|
prob_idx = 2;
|
|
}
|
|
// END_OF_ADD_PREMIUM
|
|
|
|
int adjust = 0;
|
|
if (quest::CQuestManager::instance().GetEventFlag("fish_miss_pct") != 0)
|
|
{
|
|
int fish_pct_value = std::clamp(quest::CQuestManager::instance().GetEventFlag("fish_miss_pct"), 0, 200);
|
|
adjust = (100-fish_pct_value) * fish_info[0].prob[prob_idx] / 100;
|
|
}
|
|
|
|
int rv = Random::get(adjust + 1, g_prob_sum[prob_idx]);
|
|
|
|
int * p = std::lower_bound(g_prob_accumulate[prob_idx], g_prob_accumulate[prob_idx] + MAX_FISH, rv);
|
|
int fish_idx = p - g_prob_accumulate[prob_idx];
|
|
|
|
DWORD vnum = fish_info[fish_idx].vnum;
|
|
|
|
if (vnum == 50008 || vnum == 50009 || vnum == 80008)
|
|
return 0;
|
|
|
|
return (fish_idx);
|
|
}
|
|
|
|
void FishingReact(LPCHARACTER ch)
|
|
{
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_REACT;
|
|
p.info = ch->GetVID();
|
|
ch->PacketAround(&p, sizeof(p));
|
|
}
|
|
|
|
void FishingSuccess(LPCHARACTER ch)
|
|
{
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_SUCCESS;
|
|
p.info = ch->GetVID();
|
|
ch->PacketAround(&p, sizeof(p));
|
|
}
|
|
|
|
void FishingFail(LPCHARACTER ch)
|
|
{
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_FAIL;
|
|
p.info = ch->GetVID();
|
|
ch->PacketAround(&p, sizeof(p));
|
|
}
|
|
|
|
void FishingPractice(LPCHARACTER ch)
|
|
{
|
|
LPITEM rod = ch->GetWear(WEAR_WEAPON);
|
|
if (rod && rod->GetType() == ITEM_ROD)
|
|
{
|
|
// 최대 수련도가 아닌 경우 낚시대 수련
|
|
if ( rod->GetRefinedVnum()>0 && rod->GetSocket(0) < rod->GetValue(2) && Random::get(1,rod->GetValue(1))==1 )
|
|
{
|
|
rod->SetSocket(0, rod->GetSocket(0) + 1);
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Your fishing points have increased! (%d/%d)"),rod->GetSocket(0), rod->GetValue(2));
|
|
if (rod->GetSocket(0) == rod->GetValue(2))
|
|
{
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You have reached the maximum number of fishing points."));
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Go to the Fisherman and get your Fishing Pole upgraded!"));
|
|
}
|
|
}
|
|
}
|
|
// 미끼를 뺀다
|
|
rod->SetSocket(2, 0);
|
|
}
|
|
|
|
bool PredictFish(LPCHARACTER ch)
|
|
{
|
|
// ADD_PREMIUM
|
|
// 어심환
|
|
if (ch->FindAffect(AFFECT_FISH_MIND_PILL) ||
|
|
ch->GetPremiumRemainSeconds(PREMIUM_FISH_MIND) > 0 ||
|
|
ch->IsEquipUniqueGroup(UNIQUE_GROUP_FISH_MIND))
|
|
return true;
|
|
// END_OF_ADD_PREMIUM
|
|
|
|
return false;
|
|
}
|
|
|
|
EVENTFUNC(fishing_event)
|
|
{
|
|
fishing_event_info * info = dynamic_cast<fishing_event_info *>( event->info );
|
|
|
|
if ( info == NULL )
|
|
{
|
|
SPDLOG_ERROR("fishing_event> <Factor> Null pointer" );
|
|
return 0;
|
|
}
|
|
|
|
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(info->pid);
|
|
|
|
if (!ch)
|
|
return 0;
|
|
|
|
LPITEM rod = ch->GetWear(WEAR_WEAPON);
|
|
|
|
if (!(rod && rod->GetType() == ITEM_ROD))
|
|
{
|
|
ch->m_pkFishingEvent = NULL;
|
|
return 0;
|
|
}
|
|
|
|
switch (info->step)
|
|
{
|
|
case 0: // 흔들리기 또는 떡밥만 날아감
|
|
++info->step;
|
|
|
|
//info->ch->Motion(MOTION_FISHING_SIGN);
|
|
info->hang_time = get_dword_time();
|
|
info->fish_id = DetermineFish(ch);
|
|
FishingReact(ch);
|
|
|
|
if (PredictFish(ch))
|
|
{
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_FISH;
|
|
p.info = fish_info[info->fish_id].vnum;
|
|
ch->GetDesc()->Packet(&p, sizeof(TPacketGCFishing));
|
|
}
|
|
return (PASSES_PER_SEC(6));
|
|
|
|
default:
|
|
++info->step;
|
|
|
|
if (info->step > 5)
|
|
info->step = 5;
|
|
|
|
ch->m_pkFishingEvent = NULL;
|
|
FishingFail(ch);
|
|
rod->SetSocket(2, 0);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
LPEVENT CreateFishingEvent(LPCHARACTER ch)
|
|
{
|
|
fishing_event_info* info = AllocEventInfo<fishing_event_info>();
|
|
info->pid = ch->GetPlayerID();
|
|
info->step = 0;
|
|
info->hang_time = 0;
|
|
|
|
int time = Random::get(10, 40);
|
|
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_START;
|
|
p.info = ch->GetVID();
|
|
p.dir = (BYTE)(ch->GetRotation()/5);
|
|
ch->PacketAround(&p, sizeof(TPacketGCFishing));
|
|
|
|
return event_create(fishing_event, info, PASSES_PER_SEC(time));
|
|
}
|
|
|
|
int GetFishingLevel(LPCHARACTER ch)
|
|
{
|
|
LPITEM rod = ch->GetWear(WEAR_WEAPON);
|
|
|
|
if (!rod || rod->GetType()!= ITEM_ROD)
|
|
return 0;
|
|
|
|
return rod->GetSocket(2) + rod->GetValue(0);
|
|
}
|
|
|
|
int Compute(DWORD fish_id, DWORD ms, DWORD* item, int level)
|
|
{
|
|
if (fish_id == 0)
|
|
return -2;
|
|
|
|
if (fish_id >= MAX_FISH)
|
|
{
|
|
SPDLOG_ERROR("Wrong FISH ID : {}", fish_id);
|
|
return -2;
|
|
}
|
|
|
|
if (ms > 6000)
|
|
return -1;
|
|
|
|
int time_step = std::clamp<int>(((ms + 99) / 200), 0, MAX_FISHING_TIME_COUNT - 1);
|
|
|
|
if (Random::get(1, 100) <= aFishingTime[fish_info[fish_id].time_type][time_step])
|
|
{
|
|
if (Random::get(1, fish_info[fish_id].difficulty) <= level)
|
|
{
|
|
*item = fish_info[fish_id].vnum;
|
|
return 0;
|
|
}
|
|
return -3;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int GetFishLength(int fish_id)
|
|
{
|
|
if (Random::get(0,99))
|
|
{
|
|
// 99% : normal size
|
|
return (int)(fish_info[fish_id].length_range[0] +
|
|
(fish_info[fish_id].length_range[1] - fish_info[fish_id].length_range[0])
|
|
* (Random::get(0,2000)+Random::get(0,2000)+Random::get(0,2000)+Random::get(0,2000)+Random::get(0,2000))/10000);
|
|
}
|
|
else
|
|
{
|
|
// 1% : extra LARGE size
|
|
return (int)(fish_info[fish_id].length_range[1] +
|
|
(fish_info[fish_id].length_range[2] - fish_info[fish_id].length_range[1])
|
|
* 2 * asin(Random::get(0,10000)/10000.) / M_PI);
|
|
}
|
|
}
|
|
|
|
void Take(fishing_event_info* info, LPCHARACTER ch)
|
|
{
|
|
if (info->step == 1) // 고기가 걸린 상태면..
|
|
{
|
|
int ms = (int) ((get_dword_time() - info->hang_time));
|
|
DWORD item_vnum = 0;
|
|
int ret = Compute(info->fish_id, ms, &item_vnum, GetFishingLevel(ch));
|
|
|
|
//if (test_server)
|
|
//ch->ChatPacket(CHAT_TYPE_INFO, "%d ms", ms);
|
|
|
|
switch (ret)
|
|
{
|
|
case -2: // 잡히지 않은 경우
|
|
case -3: // 난이도 때문에 실패
|
|
case -1: // 시간 확률 때문에 실패
|
|
//ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You lost your bait to the fish."));
|
|
{
|
|
int map_idx = ch->GetMapIndex();
|
|
int prob_idx = GetProbIndexByMapIndex(map_idx);
|
|
|
|
LogManager::instance().FishLog(
|
|
ch->GetPlayerID(),
|
|
prob_idx,
|
|
info->fish_id,
|
|
GetFishingLevel(ch),
|
|
ms);
|
|
}
|
|
FishingFail(ch);
|
|
break;
|
|
|
|
case 0:
|
|
//ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You have caught a fish! (%s)"), fish_info[info->fish_id].name);
|
|
if (item_vnum)
|
|
{
|
|
FishingSuccess(ch);
|
|
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_FISH;
|
|
p.info = item_vnum;
|
|
ch->GetDesc()->Packet(&p, sizeof(TPacketGCFishing));
|
|
|
|
LPITEM item = ch->AutoGiveItem(item_vnum, 1, -1, false);
|
|
if (item)
|
|
{
|
|
item->SetSocket(0,GetFishLength(info->fish_id));
|
|
if (test_server)
|
|
{
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("The length of the captured fish is %.2fcm."), item->GetSocket(0)/100.f);
|
|
}
|
|
}
|
|
|
|
int map_idx = ch->GetMapIndex();
|
|
int prob_idx = GetProbIndexByMapIndex(map_idx);
|
|
|
|
LogManager::instance().FishLog(
|
|
ch->GetPlayerID(),
|
|
prob_idx,
|
|
info->fish_id,
|
|
GetFishingLevel(ch),
|
|
ms,
|
|
true,
|
|
item ? item->GetSocket(0) : 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
int map_idx = ch->GetMapIndex();
|
|
int prob_idx = GetProbIndexByMapIndex(map_idx);
|
|
|
|
LogManager::instance().FishLog(
|
|
ch->GetPlayerID(),
|
|
prob_idx,
|
|
info->fish_id,
|
|
GetFishingLevel(ch),
|
|
ms);
|
|
FishingFail(ch);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (info->step > 1)
|
|
{
|
|
int map_idx = ch->GetMapIndex();
|
|
int prob_idx = GetProbIndexByMapIndex(map_idx);
|
|
|
|
LogManager::instance().FishLog(
|
|
ch->GetPlayerID(),
|
|
prob_idx,
|
|
info->fish_id,
|
|
GetFishingLevel(ch),
|
|
7000);
|
|
//ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You lost your bait to the fish."));
|
|
FishingFail(ch);
|
|
}
|
|
else
|
|
{
|
|
TPacketGCFishing p;
|
|
p.header = HEADER_GC_FISHING;
|
|
p.subheader = FISHING_SUBHEADER_GC_STOP;
|
|
p.info = ch->GetVID();
|
|
ch->PacketAround(&p, sizeof(p));
|
|
}
|
|
|
|
if (info->step)
|
|
{
|
|
FishingPractice(ch);
|
|
}
|
|
//Motion(MOTION_FISHING_PULL);
|
|
}
|
|
|
|
void Simulation(int level, int count, int prob_idx, LPCHARACTER ch)
|
|
{
|
|
std::map<std::string, int> fished;
|
|
int total_count = 0;
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
int fish_id = DetermineFishByProbIndex(prob_idx);
|
|
DWORD item = 0;
|
|
Compute(fish_id, (Random::get(2000, 4000) + Random::get(2000,4000)) / 2, &item, level);
|
|
|
|
if (item)
|
|
{
|
|
fished[fish_info[fish_id].name]++;
|
|
total_count ++;
|
|
}
|
|
}
|
|
|
|
for (std::map<std::string,int>::iterator it = fished.begin(); it != fished.end(); ++it)
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s: %d"), it->first.c_str(), it->second);
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You have caught %d of %d ."), fished.size(), total_count);
|
|
}
|
|
|
|
void UseFish(LPCHARACTER ch, LPITEM item)
|
|
{
|
|
int idx = item->GetVnum() - fish_info[2].vnum+2;
|
|
|
|
// 피라미 사용불가, 살아있는게 아닌건 사용불가
|
|
|
|
if (idx<=1 || idx >= MAX_FISH)
|
|
return;
|
|
|
|
int r = Random::get(1, 10000);
|
|
|
|
item->SetCount(item->GetCount()-1);
|
|
|
|
if (r >= 4001)
|
|
{
|
|
// 죽은 물고기
|
|
ch->AutoGiveItem(fish_info[idx].dead_vnum);
|
|
}
|
|
else if (r >= 2001)
|
|
{
|
|
// 생선뼈
|
|
ch->AutoGiveItem(FISH_BONE_VNUM);
|
|
}
|
|
else
|
|
{
|
|
// 1000 500 300 100 50 30 10 5 4 1
|
|
static int s_acc_prob[NUM_USE_RESULT_COUNT] = { 1000, 1500, 1800, 1900, 1950, 1980, 1990, 1995, 1999, 2000 };
|
|
int u_index = std::lower_bound(s_acc_prob, s_acc_prob + NUM_USE_RESULT_COUNT, r) - s_acc_prob;
|
|
|
|
switch (fish_info[idx].used_table[u_index])
|
|
{
|
|
case USED_TREASURE_MAP: // 3
|
|
case USED_NONE: // 0
|
|
case USED_WATER_STONE: // 2
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("The fish vanished in the depths of the water."));
|
|
break;
|
|
|
|
case USED_SHELLFISH: // 1
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("There is a Clam inside the Fish."));
|
|
ch->AutoGiveItem(SHELLFISH_VNUM);
|
|
break;
|
|
|
|
case USED_EARTHWARM: // 4
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("There is a Worm inside the Fish."));
|
|
ch->AutoGiveItem(EARTHWORM_VNUM);
|
|
break;
|
|
|
|
default:
|
|
ch->AutoGiveItem(fish_info[idx].used_table[u_index]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Grill(LPCHARACTER ch, LPITEM item)
|
|
{
|
|
/*if (item->GetVnum() < fish_info[3].vnum)
|
|
return;
|
|
int idx = item->GetVnum()-fish_info[3].vnum+3;
|
|
if (idx>=MAX_FISH)
|
|
idx = item->GetVnum()-fish_info[3].dead_vnum+3;
|
|
if (idx>=MAX_FISH)
|
|
return;*/
|
|
int idx = -1;
|
|
DWORD vnum = item->GetVnum();
|
|
if (vnum >= 27803 && vnum <= 27830)
|
|
idx = vnum - 27800;
|
|
if (vnum >= 27833 && vnum <= 27860)
|
|
idx = vnum - 27830;
|
|
if (idx == -1)
|
|
return;
|
|
|
|
int count = item->GetCount();
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You are roasting %s over the fire."), item->GetName());
|
|
item->SetCount(0);
|
|
ch->AutoGiveItem(fish_info[idx].grill_vnum, count);
|
|
}
|
|
|
|
bool RefinableRod(LPITEM rod)
|
|
{
|
|
if (rod->GetType() != ITEM_ROD)
|
|
return false;
|
|
|
|
if (rod->IsEquipped())
|
|
return false;
|
|
|
|
return (rod->GetSocket(0) == rod->GetValue(2));
|
|
}
|
|
|
|
int RealRefineRod(LPCHARACTER ch, LPITEM item)
|
|
{
|
|
if (!ch || !item)
|
|
return 2;
|
|
|
|
// REFINE_ROD_HACK_BUG_FIX
|
|
if (!RefinableRod(item))
|
|
{
|
|
SPDLOG_ERROR("REFINE_ROD_HACK pid({}) item({}:{})", ch->GetPlayerID(), item->GetName(), item->GetID());
|
|
|
|
LogManager::instance().RefineLog(ch->GetPlayerID(), item->GetName(), item->GetID(), -1, 1, "ROD_HACK");
|
|
|
|
return 2;
|
|
}
|
|
// END_OF_REFINE_ROD_HACK_BUG_FIX
|
|
|
|
LPITEM rod = item;
|
|
|
|
int iAdv = rod->GetValue(0) / 10;
|
|
|
|
if (Random::get(1,100) <= rod->GetValue(3))
|
|
{
|
|
LogManager::instance().RefineLog(ch->GetPlayerID(), rod->GetName(), rod->GetID(), iAdv, 1, "ROD");
|
|
|
|
LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(rod->GetRefinedVnum(), 1);
|
|
|
|
if (pkNewItem)
|
|
{
|
|
BYTE bCell = rod->GetCell();
|
|
// 낚시대 개량 성공
|
|
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
|
|
pkNewItem->AddToCharacter(ch, TItemPos (INVENTORY, bCell));
|
|
LogManager::instance().ItemLog(ch, pkNewItem, "REFINE FISH_ROD SUCCESS", pkNewItem->GetName());
|
|
return 1;
|
|
}
|
|
|
|
// 낚시대 개량 실패
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
LogManager::instance().RefineLog(ch->GetPlayerID(), rod->GetName(), rod->GetID(), iAdv, 0, "ROD");
|
|
|
|
LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(rod->GetValue(4), 1);
|
|
if (pkNewItem)
|
|
{
|
|
BYTE bCell = rod->GetCell();
|
|
// 낚시대 개량에 성공
|
|
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
|
|
pkNewItem->AddToCharacter(ch, TItemPos(INVENTORY, bCell));
|
|
LogManager::instance().ItemLog(ch, pkNewItem, "REFINE FISH_ROD FAIL", pkNewItem->GetName());
|
|
return 0;
|
|
}
|
|
|
|
// 낚시대 개량 실패
|
|
return 2;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef __FISHING_MAIN__
|
|
int main(int argc, char **argv)
|
|
{
|
|
//srandom(time(0) + getpid());
|
|
srandomdev();
|
|
/*
|
|
struct SFishInfo
|
|
{
|
|
const char* name;
|
|
|
|
DWORD vnum;
|
|
DWORD dead_vnum;
|
|
DWORD grill_vnum;
|
|
|
|
int prob[3];
|
|
int difficulty;
|
|
|
|
int limit_type;
|
|
int limits[3];
|
|
|
|
int time_type;
|
|
int length_range[3]; // MIN MAX EXTRA_MAX : 99% MIN~MAX, 1% MAX~EXTRA_MAX
|
|
|
|
int used_table[NUM_USE_RESULT_COUNT];
|
|
// 6000 2000 1000 500 300 100 50 30 10 5 4 1
|
|
};
|
|
*/
|
|
using namespace fishing;
|
|
|
|
Initialize();
|
|
|
|
for (int i = 0; i < MAX_FISH; ++i)
|
|
{
|
|
printf("%s\t%u\t%u\t%u\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d",
|
|
fish_info[i].name,
|
|
fish_info[i].vnum,
|
|
fish_info[i].dead_vnum,
|
|
fish_info[i].grill_vnum,
|
|
fish_info[i].prob[0],
|
|
fish_info[i].prob[1],
|
|
fish_info[i].prob[2],
|
|
fish_info[i].difficulty,
|
|
fish_info[i].time_type,
|
|
fish_info[i].length_range[0],
|
|
fish_info[i].length_range[1],
|
|
fish_info[i].length_range[2]);
|
|
|
|
for (int j = 0; j < NUM_USE_RESULT_COUNT; ++j)
|
|
printf("\t%d", fish_info[i].used_table[j]);
|
|
|
|
puts("");
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#endif
|