Jump to content

[NEW_CUBE]Unknown Server Command cube_npc_id


Recommended Posts

WEll my problem is that i get the crafting window but empty.Even if i have server side quest and cupe .txt as attched you can see.

Problem:

Spoiler

bbc16b2bdd8f7214068cdf3e5cca8f6a.gif

QUEST:

Spoiler

quest cube begin
    state start begin
        function cube_open(vnum)
            local cube_results = {
                [20018] = "50801,1/50802,1/50803,100/50804,100"}
            local cube_needs = {
                [20018] = "50721,1@50722,1@50723,1@50724,1"}
            cmdchat("cube_npc_id "..vnum)
            cmdchat("cs_result "..cube_results[vnum])
            cmdchat("cs_need "..cube_needs[vnum])
            command("cube open")
        end
        
        when 20018.chat."iarba"begin

            setskin(NOWINDOW)
            cube.cube_open(npc.get_race())
        end
    end
end

 

Game.py

Spoiler

This is the hidden content, please

CUBE.txt from server side

Spoiler

#??????		
section		
npc	20018	
item	50721	1
reward	50801	1
percent	100	
end		
		
#?????		
section		
npc	20018	
item	50722	1
reward	50802	1
percent	100	
end		
		
#????		
section		
npc	20018	
item	50723	1
reward	50803	100
percent	100	
end		
		
#???????		
section		
npc	20018	
item	50724	1
reward	50804	100
percent	100	
end	

 

Syserr from client

Spoiler

0807 23:01:24386 :: Unknown Server Command cube_npc_id 20018 | cube_npc_id
0807 23:01:24386 :: Unknown Server Command cs_result 50801,1/50802,1/50803,100/50804,100 | cs_result
0807 23:01:24386 :: Unknown Server Command cs_need 50721,1@50722,1@50723,1@50724,1 | cs_need

 

If you need any other files just ask ill post with EDIT.

ToT

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 4
  • Confused 1
  • Good 3
  • Love 3
Link to comment
Share on other sites

6 hours ago, sananemk said:

Check in the file named cube.cpp

Cube.cpp

Spoiler

/*********************************************************************
 * date        : 2006.11.20
 * file        : cube.cpp
 * author      : mhh
 * description : 
 */

#define _cube_cpp_

#include "stdafx.h"
#include "constants.h"
#include "utils.h"
#include "log.h"
#include "char.h"
#include "dev_log.h"
#include "locale_service.h"
#include "item.h"
#include "item_manager.h"

#include <sstream>
#include "config.h"

extern bool bigger_inventory;

extern int test_server;


#define RETURN_IF_CUBE_IS_NOT_OPENED(ch) if (!(ch)->IsCubeOpen()) return


/*--------------------------------------------------------*/
/*                   GLOBAL VARIABLES                     */
/*--------------------------------------------------------*/
static std::vector<CUBE_DATA*>	s_cube_proto;
static bool s_isInitializedCubeMaterialInformation = false;



/*--------------------------------------------------------*/
/*               Cube Material Information                */ 
/*--------------------------------------------------------*/
enum ECubeResultCategory
{
	CUBE_CATEGORY_POTION,				// 약초, 진액 등등..  (포션으로 특정할 수 없으니 사용 안 함. 약초같은건 다 걍 기타)
	CUBE_CATEGORY_WEAPON,				// 무기
	CUBE_CATEGORY_ARMOR,				// 방어구
	CUBE_CATEGORY_ACCESSORY,			// 장신구
	CUBE_CATEGORY_ETC,				// 기타 등등...
};

typedef std::vector<CUBE_VALUE>	TCubeValueVector;

struct SCubeMaterialInfo
{
	SCubeMaterialInfo()
	{
		bHaveComplicateMaterial = false;
	};

	CUBE_VALUE			reward;							// 보상이 뭐냐
	TCubeValueVector	material;						// 재료들은 뭐냐
	DWORD				gold;							// 돈은 얼마드냐
	TCubeValueVector	complicateMaterial;				// 복잡한-_- 재료들

	// .. 클라이언트에서 재료를 보여주기 위하여 약속한 포맷
	// 72723,1&72724,2&72730,1
	// 52001,1|52002,1|52003,1&72723,1&72724,5
	//	=> ( 52001,1 or 52002,1 or 52003,1 ) and 72723,1 and 72724,5
	std::string			infoText;		
	bool				bHaveComplicateMaterial;		//
};

struct SItemNameAndLevel
{
	SItemNameAndLevel() { level = 0; }

	std::string		name;
	int				level;
};


// 자료구조나 이런거 병신인건 이해좀... 누구땜에 영혼이 없는 상태에서 만들었씀
typedef std::vector<SCubeMaterialInfo>								TCubeResultList;
typedef boost::unordered_map<DWORD, TCubeResultList>				TCubeMapByNPC;				// 각각의 NPC별로 어떤 걸 만들 수 있고 재료가 뭔지...
typedef boost::unordered_map<DWORD, std::string>					TCubeResultInfoTextByNPC;	// 각각의 NPC별로 만들 수 있는 목록을 정해진 포맷으로 정리한 정보

TCubeMapByNPC cube_info_map;
TCubeResultInfoTextByNPC cube_result_info_map_by_npc;				// 네이밍 존나 병신같다 ㅋㅋㅋ

class CCubeMaterialInfoHelper
{
public:
public:
};

/*--------------------------------------------------------*/
/*                  STATIC FUNCTIONS                      */ 
/*--------------------------------------------------------*/
 // 필요한 아이템 개수를 가지고있는가?
static bool FN_check_item_count (LPITEM *items, DWORD item_vnum, int need_count)
{
	int	count = 0;

	// for all cube
	for (int i=0; i<CUBE_MAX_NUM; ++i)
	{
		if (NULL==items[i])	continue;

		if (item_vnum==items[i]->GetVnum())
		{
			count += items[i]->GetCount();
		}
	}

	return (count>=need_count);
}

// 큐브내의 재료를 지운다.
static void FN_remove_material (LPITEM *items, DWORD item_vnum, int need_count)
{
	int		count	= 0;
	LPITEM	item	= NULL;

	// for all cube
	for (int i=0; i<CUBE_MAX_NUM; ++i)
	{
		if (NULL==items[i])	continue;

		item = items[i];
		if (item_vnum==item->GetVnum())
		{
			count += item->GetCount();

			if (count>need_count)
			{
				item->SetCount(count-need_count);
				return;
			}
			else
			{
				item->SetCount(0);
				items[i] = NULL;
			}
		}
	}
}


static CUBE_DATA* FN_find_cube (LPITEM *items, WORD npc_vnum)
{
	DWORD	i, end_index;

	if (0==npc_vnum)	return NULL;

	// FOR ALL CUBE_PROTO
	end_index = s_cube_proto.size();
	for (i=0; i<end_index; ++i)
	{
		if ( s_cube_proto[i]->can_make_item(items, npc_vnum) )
			return s_cube_proto[i];
	}

	return NULL;
}

static bool FN_check_valid_npc( WORD vnum )
{
	for ( std::vector<CUBE_DATA*>::iterator iter = s_cube_proto.begin(); iter != s_cube_proto.end(); iter++ )
	{
		if ( std::find((*iter)->npc_vnum.begin(), (*iter)->npc_vnum.end(), vnum) != (*iter)->npc_vnum.end() )
			return true;
	}

	return false;
}

// 큐브데이타가 올바르게 초기화 되었는지 체크한다.
static bool FN_check_cube_data (CUBE_DATA *cube_data)
{
	DWORD	i = 0;
	DWORD	end_index = 0;

	end_index = cube_data->npc_vnum.size();
	for (i=0; i<end_index; ++i)
	{
		if ( cube_data->npc_vnum[i] == 0 )	return false;
	}

	end_index = cube_data->item.size();
	for (i=0; i<end_index; ++i)
	{
		if ( cube_data->item[i].vnum == 0 )		return false;
		if ( cube_data->item[i].count == 0 )	return false;
	}

	end_index = cube_data->reward.size();
	for (i=0; i<end_index; ++i)
	{
		if ( cube_data->reward[i].vnum == 0 )	return false;
		if ( cube_data->reward[i].count == 0 )	return false;
	}
	return true;
}

CUBE_DATA::CUBE_DATA()
{
	this->percent = 0;
	this->gold = 0;
}

// 필요한 재료의 수량을 만족하는지 체크한다.
bool CUBE_DATA::can_make_item (LPITEM *items, WORD npc_vnum)
{
	// 필요한 재료, 수량을 만족하는지 체크한다.
	DWORD	i, end_index;
	DWORD	need_vnum;
	int		need_count;
	int		found_npc = false;

	// check npc_vnum
	end_index = this->npc_vnum.size();
	for (i=0; i<end_index; ++i)
	{
		if (npc_vnum == this->npc_vnum[i])
			found_npc = true;
	}
	if (false==found_npc)	return false;

	end_index = this->item.size();
	for (i=0; i<end_index; ++i)
	{
		need_vnum	= this->item[i].vnum;
		need_count	= this->item[i].count;

		if ( false==FN_check_item_count(items, need_vnum, need_count) )
			return false;
	}

	return true;
}

// 큐브를 돌렸을때 나오는 아이템의 종류를 결정함
CUBE_VALUE* CUBE_DATA::reward_value ()
{
	int		end_index		= 0;
	DWORD	reward_index	= 0;

	end_index = this->reward.size();
	reward_index = number(0, end_index);
	reward_index = number(0, end_index-1);

	return &this->reward[reward_index];
}

// 큐브에 들어있는 재료를 지운다
void CUBE_DATA::remove_material (LPCHARACTER ch)
{
	DWORD	i, end_index;
	DWORD	need_vnum;
	int		need_count;
	LPITEM	*items = ch->GetCubeItem();

	end_index = this->item.size();
	for (i=0; i<end_index; ++i)
	{
		need_vnum	= this->item[i].vnum;
		need_count	= this->item[i].count;

		FN_remove_material (items, need_vnum, need_count);
	}
}

void Cube_clean_item (LPCHARACTER ch)
{
	LPITEM	*cube_item;

	cube_item = ch->GetCubeItem();

	for (int i=0; i<CUBE_MAX_NUM; ++i)
	{
		if (NULL == cube_item[i])
			continue;

		cube_item[i] = NULL;
	}
}

// 큐브창 열기
void Cube_open (LPCHARACTER ch)
{
	if (false == s_isInitializedCubeMaterialInformation)
	{
		Cube_InformationInitialize();
	}

	if (NULL == ch)
		return;

	LPCHARACTER	npc;
	npc = ch->GetQuestNPC();
	if (NULL==npc)
	{
		if (test_server)
			dev_log(LOG_DEB0, "cube_npc is NULL");
		return;
	}

	if ( FN_check_valid_npc(npc->GetRaceNum()) == false )
	{
		if ( test_server == true )
		{
			dev_log(LOG_DEB0, "cube not valid NPC");
		}
		return;
	}

	if (ch->IsCubeOpen())
	{
		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이미 제조창이 열려있습니다."));
		return;
	}
	if ( ch->GetExchange() || ch->GetMyShop() || ch->GetShopOwner() || ch->IsOpenSafebox() || ch->IsCubeOpen() )
	{
		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 사용할 수 없습니다."));
		return;
	}

	long distance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY());

	if (distance >= CUBE_MAX_DISTANCE)
	{
		sys_log(1, "CUBE: TOO_FAR: %s distance %d", ch->GetName(), distance);
		return;
	}


	Cube_clean_item(ch);
	ch->SetCubeNpc(npc);
	ch->ChatPacket(CHAT_TYPE_COMMAND, "cube open %d", npc->GetRaceNum());
}

// 큐브 캔슬
void Cube_close (LPCHARACTER ch)
{
	RETURN_IF_CUBE_IS_NOT_OPENED(ch);
	Cube_clean_item(ch);
	ch->SetCubeNpc(NULL);
	ch->ChatPacket(CHAT_TYPE_COMMAND, "cube close");
	dev_log(LOG_DEB0, "<CUBE> close (%s)", ch->GetName());
}

void Cube_init()
{
	CUBE_DATA * p_cube = NULL;
	std::vector<CUBE_DATA*>::iterator iter;

	char file_name[256+1];
	snprintf(file_name, sizeof(file_name), "%s/cube.txt", LocaleService_GetBasePath().c_str());

	sys_log(0, "Cube_Init %s", file_name);

	for (iter = s_cube_proto.begin(); iter!=s_cube_proto.end(); iter++)
	{
		p_cube = *iter;
		M2_DELETE(p_cube);
	}

	s_cube_proto.clear();

	if (false == Cube_load(file_name))
		sys_err("Cube_Init failed");
}

bool Cube_load (const char *file)
{
	FILE	*fp;
	char	one_line[256];
	int		value1, value2;
	const char	*delim = " \t\r\n";
	char	*v, *token_string;
	CUBE_DATA	*cube_data = NULL;
	CUBE_VALUE	cube_value = {0,0};

	if (0 == file || 0 == file[0])
		return false;

	if ((fp = fopen(file, "r")) == 0)
		return false;

	while (fgets(one_line, 256, fp))
	{
		value1 = value2 = 0;

		if (one_line[0] == '#')
			continue;

		token_string = strtok(one_line, delim);

		if (NULL == token_string)
			continue;

		// set value1, value2
		if ((v = strtok(NULL, delim)))
			str_to_number(value1, v);

		if ((v = strtok(NULL, delim)))
			str_to_number(value2, v);

		TOKEN("section")
		{
			cube_data = M2_NEW CUBE_DATA;
		}
		else TOKEN("npc")
		{
			cube_data->npc_vnum.push_back((WORD)value1);
		}
		else TOKEN("item")
		{
			cube_value.vnum		= value1;
			cube_value.count	= value2;

			cube_data->item.push_back(cube_value);
		}
		else TOKEN("reward")
		{
			cube_value.vnum		= value1;
			cube_value.count	= value2;

			cube_data->reward.push_back(cube_value);
		}
		else TOKEN("percent")
		{
			cube_data->percent = value1;
		}
		else TOKEN("gold")
		{
			// 제조에 필요한 금액
			cube_data->gold = value1;
		}
		else TOKEN("end")
		{
			// TODO : check cube data
			if (false == FN_check_cube_data(cube_data))
			{
				dev_log(LOG_DEB0, "something wrong");
				M2_DELETE(cube_data);
				continue;
			}
			s_cube_proto.push_back(cube_data);
		}
	}

	fclose(fp);
	return true;
}

static void FN_cube_print (CUBE_DATA *data, DWORD index)
{
	DWORD	i;
	dev_log(LOG_DEB0, "--------------------------------");
	dev_log(LOG_DEB0, "CUBE_DATA[%d]", index);

	for (i=0; i<data->npc_vnum.size(); ++i)
	{
		dev_log(LOG_DEB0, "\tNPC_VNUM[%d] = %d", i, data->npc_vnum[i]);
	}
	for (i=0; i<data->item.size(); ++i)
	{
		dev_log(LOG_DEB0, "\tITEM[%d]   = (%d, %d)", i, data->item[i].vnum, data->item[i].count);
	}
	for (i=0; i<data->reward.size(); ++i)
	{
		dev_log(LOG_DEB0, "\tREWARD[%d] = (%d, %d)", i, data->reward[i].vnum, data->reward[i].count);
	}
	dev_log(LOG_DEB0, "\tPERCENT = %d", data->percent);
	dev_log(LOG_DEB0, "--------------------------------");
}

void Cube_print ()
{
	for (DWORD i=0; i<s_cube_proto.size(); ++i)
	{
		FN_cube_print(s_cube_proto[i], i);
	}
}


static bool FN_update_cube_status(LPCHARACTER ch)
{
	if (NULL == ch)
		return false;

	if (!ch->IsCubeOpen())
		return false;

	LPCHARACTER	npc = ch->GetQuestNPC();
	if (NULL == npc)
		return false;

	CUBE_DATA* cube = FN_find_cube(ch->GetCubeItem(), npc->GetRaceNum());

	if (NULL == cube)
	{
		ch->ChatPacket(CHAT_TYPE_COMMAND, "cube info 0 0 0");
		return false;
	}

	ch->ChatPacket(CHAT_TYPE_COMMAND, "cube info %d %d %d", cube->gold, 0, 0);
	return true;
}

// return new item
bool Cube_make (LPCHARACTER ch)
{
	// 주어진 아이템을 필요로하는 조합을 찾는다. (큐브데이타로 칭함)
	// 큐브 데이타가 있다면 아이템의 재료를 체크한다.
	// 새로운 아이템을 만든다.
	// 새로운 아이템 지급

	LPCHARACTER	npc;
	int			percent_number = 0;
	CUBE_DATA	*cube_proto;
	LPITEM	*items;
	LPITEM	new_item;

	if (!(ch)->IsCubeOpen())
	{
		(ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("제조창이 열려있지 않습니다"));
		return false;
	}

	npc = ch->GetQuestNPC();
	if (NULL == npc)
	{
		return false;
	}

	items = ch->GetCubeItem();
	cube_proto = FN_find_cube(items, npc->GetRaceNum());

	if (NULL == cube_proto)
	{
		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("제조 재료가 부족합니다"));
		return false;
	}

	if (ch->GetGold() < (long long)cube_proto->gold)
	{
		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("돈이 부족하거나 아이템이 제자리에 없습니다."));	// 이 텍스트는 이미 널리 쓰이는거라 추가번역 필요 없음
		return false;
	}

	CUBE_VALUE	*reward_value = cube_proto->reward_value();

	// 사용되었던 재료아이템 삭제
	cube_proto->remove_material (ch);
	
	// 제조시 필요한 골드 차감
	if (0 < cube_proto->gold)
		ch->PointChange(POINT_GOLD, -(cube_proto->gold), false);

	percent_number = number(1,100);
	if ( percent_number<=cube_proto->percent)
	{
		// 성공
		ch->ChatPacket(CHAT_TYPE_COMMAND, "cube success %d %d", reward_value->vnum, reward_value->count);
		new_item = ch->AutoGiveItem(reward_value->vnum, reward_value->count);

		LogManager::instance().CubeLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(),
				reward_value->vnum, new_item->GetID(), reward_value->count, 1);
		return true;
	}
	else
	{
		// 실패
		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("제조에 실패하였습니다."));	// 2012.11.12 새로 추가된 메세지 (locale_string.txt 에 추가해야 함)
		ch->ChatPacket(CHAT_TYPE_COMMAND, "cube fail");
		LogManager::instance().CubeLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(),
				reward_value->vnum, 0, 0, 0);
		return false;
	}

	return false;
}


// 큐브에 있는 아이템들을 표시
void Cube_show_list (LPCHARACTER ch)
{
	LPITEM	*cube_item;
	LPITEM	item;

	RETURN_IF_CUBE_IS_NOT_OPENED(ch);

	cube_item = ch->GetCubeItem();

	for (int i=0; i<CUBE_MAX_NUM; ++i)
	{
		item = cube_item[i];
		if (NULL==item)	continue;

		ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: inventory[%d]: %s",
				i, item->GetCell(), item->GetName());
	}
}


// 인벤토리에 있는 아이템을 큐브에 등록
void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index)
{
	// 아이템이 있는가?
	// 큐브내의 빈자리 찾기
	// 큐브세팅
	// 메시지 전송
	LPITEM	item;
	LPITEM	*cube_item;

	RETURN_IF_CUBE_IS_NOT_OPENED(ch);

	int inventorysize = INVENTORY_MAX_NUM;
	if(!bigger_inventory) inventorysize = 90;

	if (inven_index<0 || inventorysize<=inven_index)
		return;
	if (cube_index<0 || CUBE_MAX_NUM<=cube_index)
		return;

	item = ch->GetInventoryItem(inven_index);

	if (NULL==item)	return;

	cube_item = ch->GetCubeItem();

	// 이미 다른위치에 등록되었던 아이템이면 기존 indext삭제
	for (int i=0; i<CUBE_MAX_NUM; ++i)
	{
		if (item==cube_item[i])
		{
			cube_item[i] = NULL;
			break;
		}
	}

	cube_item[cube_index] = item;

	if (test_server)
		ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: inventory[%d]: %s added",
									cube_index, inven_index, item->GetName());

	// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
	// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
	FN_update_cube_status(ch);

	return;
}

// 큐브에있는 아이템을 제거
void Cube_delete_item (LPCHARACTER ch, int cube_index)
{
	LPITEM	item;
	LPITEM	*cube_item;

	RETURN_IF_CUBE_IS_NOT_OPENED(ch);

	if (cube_index<0 || CUBE_MAX_NUM<=cube_index)	return;

	cube_item = ch->GetCubeItem();

	if ( NULL== cube_item[cube_index] )	return;

	item = cube_item[cube_index];
	cube_item[cube_index] = NULL;

	if (test_server)
		ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: cube[%d]: %s deleted",
				cube_index, item->GetCell(), item->GetName());

	// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
	// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
	FN_update_cube_status(ch);

	return;
}

// 아이템 이름을 통해서 순수 이름과 강화레벨을 분리하는 함수 (무쌍검+5 -> 무쌍검, 5)
SItemNameAndLevel SplitItemNameAndLevelFromName(const std::string& name)
{
	int level = 0;
	SItemNameAndLevel info;
	info.name = name;

	size_t pos = name.find("+");
	
	if (std::string::npos != pos)
	{
		const std::string levelStr = name.substr(pos + 1, name.size() - pos - 1);
		str_to_number(level, levelStr.c_str());

		info.name = name.substr(0, pos);
	}

	info.level = level;

	return info;
};

bool FIsEqualCubeValue(const CUBE_VALUE& a, const CUBE_VALUE& b)
{
	return (a.vnum == b.vnum) && (a.count == b.count);
}

bool FIsLessCubeValue(const CUBE_VALUE& a, const CUBE_VALUE& b)
{
	return a.vnum < b.vnum;
}

void Cube_MakeCubeInformationText()
{
	// 이제 정리된 큐브 결과 및 재료들의 정보로 클라이언트에 보내 줄 정보로 변환함.
	for (TCubeMapByNPC::iterator iter = cube_info_map.begin(); cube_info_map.end() != iter; ++iter)
	{
//		const DWORD& npcVNUM = iter->first;
		TCubeResultList& resultList = iter->second;

		for (TCubeResultList::iterator resultIter = resultList.begin(); resultList.end() != resultIter; ++resultIter)
		{
			SCubeMaterialInfo& materialInfo = *resultIter;
			std::string& infoText = materialInfo.infoText;

			
			// 이놈이 나쁜놈이야
			if (0 < materialInfo.complicateMaterial.size())
			{
				std::sort(materialInfo.complicateMaterial.begin(), materialInfo.complicateMaterial.end(), FIsLessCubeValue);
				std::sort(materialInfo.material.begin(), materialInfo.material.end(), FIsLessCubeValue);

				//// 중복되는 재료들을 지움
				for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
				{
					for (TCubeValueVector::iterator targetIter = materialInfo.material.begin(); materialInfo.material.end() != targetIter; ++targetIter)
					{
						if (*targetIter == *iter)
						{
							targetIter = materialInfo.material.erase(targetIter);
						}
					}
				}

				// 72723,1 or 72725,1 or ... 이런 식의 약속된 포맷을 지키는 텍스트를 생성
				for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
				{
					char tempBuffer[128];
					sprintf(tempBuffer, "%d,%d|", iter->vnum, iter->count);
					
					infoText += std::string(tempBuffer);
				}

				infoText.erase(infoText.size() - 1);

				if (0 < materialInfo.material.size())
					infoText.push_back('&');
			}

			// 중복되지 않는 일반 재료들도 포맷 생성
			for (TCubeValueVector::iterator iter = materialInfo.material.begin(); materialInfo.material.end() != iter; ++iter)
			{
				char tempBuffer[128];
				sprintf(tempBuffer, "%d,%d&", iter->vnum, iter->count);
				infoText += std::string(tempBuffer);
			}

			infoText.erase(infoText.size() - 1);

			// 만들 때 골드가 필요하다면 골드정보 추가
			if (0 < materialInfo.gold)
			{
				char temp[128];
				sprintf(temp, "%d", materialInfo.gold);
				infoText += std::string("/") + temp;
			}

			//sys_err("\t\tNPC: %d, Reward: %d(%s)\n\t\t\tInfo: %s", npcVNUM, materialInfo.reward.vnum, ITEM_MANAGER::Instance().GetTable(materialInfo.reward.vnum)->szName, materialInfo.infoText.c_str());
		} // for resultList
	} // for npc
}

bool Cube_InformationInitialize()
{
	for (unsigned int i = 0; i < s_cube_proto.size(); ++i)
	{
		CUBE_DATA* cubeData = s_cube_proto[i];

		const std::vector<CUBE_VALUE>& rewards = cubeData->reward;

		// 하드코딩 ㅈㅅ
		if (1 != rewards.size())
		{
			sys_err("[CubeInfo] WARNING! Does not support multiple rewards (count: %d)", rewards.size());			
			continue;
		}
		//if (1 != cubeData->npc_vnum.size())
		//{
		//	sys_err("[CubeInfo] WARNING! Does not support multiple NPC (count: %d)", cubeData->npc_vnum.size());			
		//	continue;
		//}

		const CUBE_VALUE& reward = rewards.at(0);
		const WORD& npcVNUM = cubeData->npc_vnum.at(0);
		bool bComplicate = false;
		
		TCubeMapByNPC& cubeMap = cube_info_map;
		TCubeResultList& resultList = cubeMap[npcVNUM];
		SCubeMaterialInfo materialInfo;

		materialInfo.reward = reward;
		materialInfo.gold = cubeData->gold;
		materialInfo.material = cubeData->item;

		for (TCubeResultList::iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
		{
			SCubeMaterialInfo& existInfo = *iter;

			// 이미 중복되는 보상이 등록되어 있다면 아예 다른 조합으로 만드는 것인지, 
			// 거의 같은 조합인데 특정 부분만 틀린 것인지 구분함.
			// 예를들면 특정 부분만 틀린 아이템들은 아래처럼 하나로 묶어서 하나의 결과로 보여주기 위함임:
			// 용신지검:
			//		무쌍검+5 ~ +9 x 1
			//		붉은 칼자루 조각 x1
			//		녹색 검장식 조각 x1
			if (reward.vnum == existInfo.reward.vnum)
			{
				for (TCubeValueVector::iterator existMaterialIter = existInfo.material.begin(); existInfo.material.end() != existMaterialIter; ++existMaterialIter)
				{
					TItemTable* existMaterialProto = ITEM_MANAGER::Instance().GetTable(existMaterialIter->vnum);
					if (NULL == existMaterialProto)
					{
						sys_err("There is no item(%u)", existMaterialIter->vnum);
						return false;
					}
					SItemNameAndLevel existItemInfo = SplitItemNameAndLevelFromName(existMaterialProto->szName);

					if (0 < existItemInfo.level)
					{
						// 지금 추가하는 큐브 결과물의 재료와, 기존에 등록되어있던 큐브 결과물의 재료 중 
						// 중복되는 부분이 있는지 검색한다
						for (TCubeValueVector::iterator currentMaterialIter = materialInfo.material.begin(); materialInfo.material.end() != currentMaterialIter; ++currentMaterialIter)
						{
							TItemTable* currentMaterialProto = ITEM_MANAGER::Instance().GetTable(currentMaterialIter->vnum);
							SItemNameAndLevel currentItemInfo = SplitItemNameAndLevelFromName(currentMaterialProto->szName);

							if (currentItemInfo.name == existItemInfo.name)
							{
								bComplicate = true;
								existInfo.complicateMaterial.push_back(*currentMaterialIter);

								if (std::find(existInfo.complicateMaterial.begin(), existInfo.complicateMaterial.end(), *existMaterialIter) == existInfo.complicateMaterial.end())
									existInfo.complicateMaterial.push_back(*existMaterialIter);

								//currentMaterialIter = materialInfo.material.erase(currentMaterialIter);

								// TODO: 중복되는 아이템 두 개 이상 검출해야 될 수도 있음
								break;
							}
						} // for currentMaterialIter
					}	// if level
				}	// for existMaterialInfo
			}	// if (reward.vnum == existInfo.reward.vnum)

		}	// for resultList

		if (false == bComplicate)
			resultList.push_back(materialInfo);
	}

	Cube_MakeCubeInformationText();

	s_isInitializedCubeMaterialInformation = true;
	return true;
}

// 클라이언트에서 서버로 : 현재 NPC가 만들 수 있는 아이템들의 정보(목록)를 요청
void Cube_request_result_list(LPCHARACTER ch)
{
	RETURN_IF_CUBE_IS_NOT_OPENED(ch);

	LPCHARACTER	npc = ch->GetQuestNPC();
	if (NULL == npc)
		return;

	DWORD npcVNUM = npc->GetRaceNum();
	size_t resultCount = 0;

	std::string& resultText = cube_result_info_map_by_npc[npcVNUM];

	// 해당 NPC가 만들 수 있는 목록이 정리된 게 없다면 캐시를 생성
	if (resultText.length() == 0)
	{
		resultText.clear();

		const TCubeResultList& resultList = cube_info_map[npcVNUM];
		for (TCubeResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
		{
			const SCubeMaterialInfo& materialInfo = *iter;
			char temp[128];
			sprintf(temp, "%d,%d", materialInfo.reward.vnum, materialInfo.reward.count);

			resultText += std::string(temp) + "/";
		}

		if (resultCount == 0) 
		{    
		return;
		}

		resultText.erase(resultText.size() - 1);

		// 채팅 패킷의 한계를 넘어가면 에러 남김... 기획자 분들 께 조정해달라고 요청하거나, 나중에 다른 방식으로 바꾸거나...
		if (resultText.size() - 20 >= CHAT_MAX_LEN)
		{
			sys_err("[CubeInfo] Too long cube result list text. (NPC: %d, length: %d)", npcVNUM, resultText.size());
			resultText.clear();
			resultCount = 0;
		}

	}

	// 현재 NPC가 만들 수 있는 아이템들의 목록을 아래 포맷으로 전송한다.
	// (Server -> Client) /cube r_list npcVNUM resultCount vnum1,count1/vnum2,count2,/vnum3,count3/...
	// (Server -> Client) /cube r_list 20383 4 123,1/125,1/128,1/130,5
	
	ch->ChatPacket(CHAT_TYPE_COMMAND, "cube r_list %d %d %s", npcVNUM, resultCount, resultText.c_str());
}

// 
void Cube_request_material_info(LPCHARACTER ch, int requestStartIndex, int requestCount)
{
	RETURN_IF_CUBE_IS_NOT_OPENED(ch);

	LPCHARACTER	npc = ch->GetQuestNPC();
	if (NULL == npc)
		return;

	DWORD npcVNUM = npc->GetRaceNum();
	std::string materialInfoText = "";

	int index = 0;
	bool bCatchInfo = false;

	const TCubeResultList& resultList = cube_info_map[npcVNUM];
	for (TCubeResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter)
	{
		const SCubeMaterialInfo& materialInfo = *iter;

		if (index++ == requestStartIndex)
		{
			bCatchInfo = true;
		}
		
		if (bCatchInfo)
		{
			materialInfoText += materialInfo.infoText + "@";
		}

		if (index >= requestStartIndex + requestCount)
			break;
	}

	if (!bCatchInfo || materialInfoText.size() == 0)
	{
		sys_err("[CubeInfo] Can't find matched material info (NPC: %d, index: %d, request count: %d)", npcVNUM, requestStartIndex, requestCount);
		return;
	}

	materialInfoText.erase(materialInfoText.size() - 1);

	// 
	// (Server -> Client) /cube m_info start_index count 125,1|126,2|127,2|123,5&555,5&555,4/120000
	if (materialInfoText.size() - 20 >= CHAT_MAX_LEN)
	{
		sys_err("[CubeInfo] Too long material info. (NPC: %d, requestStart: %d, requestCount: %d, length: %d)", npcVNUM, requestStartIndex, requestCount, materialInfoText.size());
	}

	ch->ChatPacket(CHAT_TYPE_COMMAND, "cube m_info %d %d %s", requestStartIndex, requestCount, materialInfoText.c_str());

	
}

 

 

Link to comment
Share on other sites

  • Bronze

Why you are using it like that? It´s old version.. that is why you are getting error.. When you have added new cube system that your quest doesn´t work anymore :) 

Easier way

quest

quest cube begin
	state start begin
		when 20018.chat."Cube Window" begin
			setskin(NOWINDOW)
			command("cube open")
		end
	end
end

cube.txt

section        
npc    20018    
item    item needed    count
item    item needed    count
reward    item what did you get    count
gold    gold needed    
percent    % chance to succes    
end    

example of cube

section		
npc	20018	
item	11290	1
item	11290	1
reward	11299	1
gold	1000000	
percent	100	
end	

 

Link to comment
Share on other sites

Spoiler
13 hours ago, enzi said:

Why you are using it like that? It´s old version.. that is why you are getting error.. When you have added new cube system that your quest doesn´t work anymore :) 

Easier way

quest



quest cube begin
	state start begin
		when 20018.chat."Cube Window" begin
			setskin(NOWINDOW)
			command("cube open")
		end
	end
end

cube.txt



section        
npc    20018    
item    item needed    count
item    item needed    count
reward    item what did you get    count
gold    gold needed    
percent    % chance to succes    
end    

example of cube



section		
npc	20018	
item	11290	1
item	11290	1
reward	11299	1
gold	1000000	
percent	100	
end	

 

 

I get this in syserr after  :

Spoiler

0809 13:04:16059 :: Traceback (most recent call last):

0809 13:04:16060 ::   File "game.py", line 833, in BINARY_NEW_AddAffect

0809 13:04:16060 ::   File "uiAffectShower.py", line 528, in BINARY_NEW_AddAffect

0809 13:04:16060 ::   File "localeInfo.py", line 137, in f

0809 13:04:16060 :: TypeError
0809 13:04:16060 :: : 
0809 13:04:16060 :: not all arguments converted during string formatting
0809 13:04:16060 :: 

0809 13:04:18290 :: Traceback (most recent call last):

0809 13:04:18290 ::   File "game.py", line 1922, in BINARY_Cube_ResultList

0809 13:04:18290 :: ValueError
0809 13:04:18290 :: : 
0809 13:04:18290 :: invalid literal for int() with base 10: ''
0809 13:04:18290 :: 

 

and when i open now cube if i do like this materials needed dont show just reward.

Spoiler

eb8bc9b11149d4e13dea160089cbee89.gif

My cube from game.py

Spoiler

	# CUBE
	def BINARY_Cube_Open(self, npcVNUM):
		self.currentCubeNPC = npcVNUM
		
		self.interface.OpenCubeWindow()

		
		if npcVNUM not in self.cubeInformation:
			net.SendChatPacket("/cube r_info")
		else:
			cubeInfoList = self.cubeInformation[npcVNUM]
			
			i = 0
			for cubeInfo in cubeInfoList:								
				self.interface.wndCube.AddCubeResultItem(cubeInfo["vnum"], cubeInfo["count"])
				
				j = 0				
				for materialList in cubeInfo["materialList"]:
					for materialInfo in materialList:
						itemVnum, itemCount = materialInfo
						self.interface.wndCube.AddMaterialInfo(i, j, itemVnum, itemCount)
					j = j + 1						
						
				i = i + 1
				
			self.interface.wndCube.Refresh()

	def BINARY_Cube_Close(self):
		self.interface.CloseCubeWindow()

	# Á¦ÀÛ¿¡ ÇÊ¿äÇÑ °ñµå, ¿¹»óµÇ´Â ¿Ï¼ºÇ°ÀÇ VNUM°ú °³¼ö Á¤º¸ update
	def BINARY_Cube_UpdateInfo(self, gold, itemVnum, count):
		self.interface.UpdateCubeInfo(gold, itemVnum, count)
		
	def BINARY_Cube_Succeed(self, itemVnum, count):
		print "Å¥ºê Á¦ÀÛ ¼º°ø"
		self.interface.SucceedCubeWork(itemVnum, count)
		pass

	def BINARY_Cube_Failed(self):
		print "Å¥ºê Á¦ÀÛ ½ÇÆÐ"
		self.interface.FailedCubeWork()
		pass

	def BINARY_Cube_ResultList(self, npcVNUM, listText):
		# ResultList Text Format : 72723,1/72725,1/72730.1/50001,5  ÀÌ·±½ÄÀ¸·Î "/" ¹®ÀÚ·Î ±¸ºÐµÈ ¸®½ºÆ®¸¦ ÁÜ
		#print listText
		
		if npcVNUM == 0:
			npcVNUM = self.currentCubeNPC
		
		self.cubeInformation[npcVNUM] = []
		
		try:
			for eachInfoText in listText.split("/"):
				eachInfo = eachInfoText.split(",")
				itemVnum	= int(eachInfo[0])
				itemCount	= int(eachInfo[1])

				self.cubeInformation[npcVNUM].append({"vnum": itemVnum, "count": itemCount})
				self.interface.wndCube.AddCubeResultItem(itemVnum, itemCount)
			
			resultCount = len(self.cubeInformation[npcVNUM])
			requestCount = 7
			modCount = resultCount % requestCount
			splitCount = resultCount / requestCount
			for i in xrange(splitCount):
				#print("/cube r_info %d %d" % (i * requestCount, requestCount))
				net.SendChatPacket("/cube r_info %d %d" % (i * requestCount, requestCount))
				
			if 0 < modCount:
				#print("/cube r_info %d %d" % (splitCount * requestCount, modCount))				
				net.SendChatPacket("/cube r_info %d %d" % (splitCount * requestCount, modCount))

		except RuntimeError, msg:
			dbg.TraceError(msg)
			return 0
			
		pass
		
	def BINARY_Cube_MaterialInfo(self, startIndex, listCount, listText):
		# Material Text Format : 125,1|126,2|127,2|123,5&555,5&555,4/120000
		try:
			#print listText
			
			if 3 > len(listText):
				dbg.TraceError("Wrong Cube Material Infomation")
				return 0

			
			
			eachResultList = listText.split("@")

			cubeInfo = self.cubeInformation[self.currentCubeNPC]			
			
			itemIndex = 0
			for eachResultText in eachResultList:
				cubeInfo[startIndex + itemIndex]["materialList"] = [[], [], [], [], []]
				materialList = cubeInfo[startIndex + itemIndex]["materialList"]
				
				gold = 0
				splitResult = eachResultText.split("/")
				if 1 < len(splitResult):
					gold = int(splitResult[1])
					
				#print "splitResult : ", splitResult
				eachMaterialList = splitResult[0].split("&")
				
				i = 0
				for eachMaterialText in eachMaterialList:
					complicatedList = eachMaterialText.split("|")
					
					if 0 < len(complicatedList):
						for complicatedText in complicatedList:
							(itemVnum, itemCount) = complicatedText.split(",")
							itemVnum = int(itemVnum)
							itemCount = int(itemCount)
							self.interface.wndCube.AddMaterialInfo(itemIndex + startIndex, i, itemVnum, itemCount)
							
							materialList[i].append((itemVnum, itemCount))
							
					else:
						itemVnum, itemCount = eachMaterialText.split(",")
						itemVnum = int(itemVnum)
						itemCount = int(itemCount)
						self.interface.wndCube.AddMaterialInfo(itemIndex + startIndex, i, itemVnum, itemCount)
						
						materialList[i].append((itemVnum, itemCount))
						
					i = i + 1
					
					
					
				itemIndex = itemIndex + 1
				
			self.interface.wndCube.Refresh()
			
				
		except RuntimeError, msg:
			dbg.TraceError(msg)
			return 0
			
		pass
	
	# END_OF_CUBE

 

My localeinfo.py

Spoiler

import app
import constInfo

MAP_TRENT02 = "MAP_TRENT02" # ÀÓ½Ã
MAP_WL = "MAP_WL" # ÀÓ½Ã
MAP_NUSLUCK = "MAP_NUSLUCK" # Àӽà 
MAP_TREE2 = "MAP_TREE2"

BLEND_POTION_NO_TIME = "BLEND_POTION_NO_TIME"
BLEND_POTION_NO_INFO = "BLEND_POTION_NO_INFO"

APP_TITLE = "---"

GUILD_HEADQUARTER = "Main Building"
GUILD_FACILITY = "Facility"
GUILD_OBJECT = "Object"
GUILD_MEMBER_COUNT_INFINITY = "INFINITY"

LOGIN_FAILURE_WEB_BLOCK = "BLOCK_LOGIN(WEB)"
LOGIN_FAILURE_BLOCK_LOGIN = "BLOCK_LOGIN"
CHANNEL_NOTIFY_FULL = "CHANNEL_NOTIFY_FULL"

GUILD_BUILDING_LIST_TXT = app.GetLocalePath() + "/GuildBuildingList.txt"

GUILD_MARK_MIN_LEVEL = "3"
GUILD_MARK_NOT_ENOUGH_LEVEL = "±æµå·¹º§ 3ÀÌ»ó ºÎÅÍ °¡´ÉÇÕ´Ï´Ù."

ERROR_MARK_UPLOAD_NEED_RECONNECT = "UploadMark: Reconnect to game"
ERROR_MARK_CHECK_NEED_RECONNECT = "CheckMark: Reconnect to game"

VIRTUAL_KEY_ALPHABET_LOWERS  = r"[1234567890]/qwertyuiop\=asdfghjkl;`'zxcvbnm.,"
VIRTUAL_KEY_ALPHABET_UPPERS  = r'{1234567890}?QWERTYUIOP|+ASDFGHJKL:~"ZXCVBNM<>'
VIRTUAL_KEY_SYMBOLS    = '!@#$%^&*()_+|{}:"<>?~'
VIRTUAL_KEY_NUMBERS    = "1234567890-=\[];',./`"
VIRTUAL_KEY_SYMBOLS_BR    = '!@#$%^&*()_+|{}:"<>?~áàãâéèêíìóòôõúùç'

__IS_ENGLISH	= "ENGLISH" == app.GetLocaleServiceName()	
__IS_HONGKONG	= "HONGKONG" == app.GetLocaleServiceName()
__IS_NEWCIBN	= "locale/newcibn" == app.GetLocalePath()
__IS_EUROPE		= "EUROPE" == app.GetLocaleServiceName()		
__IS_CANADA		= "locale/ca" == app.GetLocalePath()
__IS_BRAZIL		= "locale/br" == app.GetLocalePath()
__IS_SINGAPORE	= "locale/sg" == app.GetLocalePath()
__IS_VIETNAM	= "locale/vn" == app.GetLocalePath()
__IS_ARABIC		= "locale/ae" == app.GetLocalePath()
__IS_CIBN10		= "locale/cibn10" == app.GetLocalePath()
__IS_WE_KOREA	= "locale/we_korea" == app.GetLocalePath()
__IS_TAIWAN		= "locale/taiwan" == app.GetLocalePath()
__IS_JAPAN		= "locale/japan" == app.GetLocalePath()	
LOGIN_FAILURE_WRONG_SOCIALID = "ASDF"
LOGIN_FAILURE_SHUTDOWN_TIME = "ASDF"

if __IS_CANADA:
	__IS_EUROPE = True

def IsYMIR():
	return "locale/ymir" == app.GetLocalePath()

def IsJAPAN():
	return "locale/japan" == app.GetLocalePath()

def IsENGLISH():
	global __IS_ENGLISH
	return __IS_ENGLISH

def IsHONGKONG():
	global __IS_HONGKONG
	return __IS_HONGKONG

def IsTAIWAN():
	return "locale/taiwan" == app.GetLocalePath()

def IsNEWCIBN():
	return "locale/newcibn" == app.GetLocalePath()

def IsCIBN10():
	global __IS_CIBN10
	return __IS_CIBN10
	
def IsEUROPE():
	global __IS_EUROPE
	return __IS_EUROPE

def IsCANADA():
	global __IS_CANADA
	return __IS_CANADA

def IsBRAZIL():
	global __IS_BRAZIL
	return __IS_BRAZIL

def IsVIETNAM():
	global __IS_VIETNAM
	return __IS_VIETNAM

def IsSINGAPORE():
	global __IS_SINGAPORE
	return __IS_SINGAPORE
	
def IsARABIC():
	global __IS_ARABIC
	return __IS_ARABIC

def IsWE_KOREA():
	return "locale/we_korea" == app.GetLocalePath()
	
# SUPPORT_NEW_KOREA_SERVER
def LoadLocaleData():
	if IsYMIR():
		import net
		SERVER = "Äèµµ ¼­¹ö"
		if SERVER == net.GetServerInfo()[:len(SERVER)]:
			app.SetCHEONMA(0)
			app.LoadLocaleData("locale/we_korea")
			constInfo.ADD_DEF_BONUS_ENABLE = 0
		else:
			app.SetCHEONMA(1)
			app.LoadLocaleData("locale/ymir")
			constInfo.ADD_DEF_BONUS_ENABLE = 1
	else:
		app.LoadLocaleData(app.GetLocalePath())

def IsCHEONMA():
	return IsYMIR()		# ÀÌÁ¦ YMIR ·ÎÄÉÀÏÀº ¹«Á¶°Ç õ¸¶¼­¹öÀÓ. õ¸¶¼­¹ö°¡ ¹®À» ´Ý±â Àü±îÁö º¯ÇÒ ÀÏ ¾øÀ½.

# END_OF_SUPPORT_NEW_KOREA_SERVER

def mapping(**kwargs): return kwargs

def SNA(text):	
	def f(x):
		return text
	return f

def SA(text):
	def f(x):
		return text % x
	return f

def LoadLocaleFile(srcFileName, localeDict):

	funcDict = {"SA":SA, "SNA":SNA}

	lineIndex = 1

	try:
		lines = pack_open(srcFileName, "r").readlines()
	except IOError:
		import dbg
		dbg.LogBox("LoadLocaleError(%(srcFileName)s)" % locals())
		app.Abort()

	for line in lines:
		try:		
			tokens = line[:-1].split("\t")
			if len(tokens) == 2:
				localeDict[tokens[0]] = tokens[1]
			elif len(tokens) >= 3:
				type = tokens[2].strip()
				if type:
					localeDict[tokens[0]] = funcDict[type](tokens[1])
				else:
					localeDict[tokens[0]] = tokens[1]
			else:
				raise RuntimeError, "Unknown TokenSize"

			lineIndex += 1
		except:
			import dbg
			dbg.LogBox("%s: line(%d): %s" % (srcFileName, lineIndex, line), "Error")
			raise


	
all = ["locale","error"]

if IsEUROPE()  and  IsBRAZIL()  :
	FN_GM_MARK = "%s/effect/gm.mse"	% app.GetLocalePath()
	LOCALE_FILE_NAME = "%s/locale_game.txt" % app.GetLocalePath()
	constInfo.IN_GAME_SHOP_ENABLE = 0
elif IsSINGAPORE() :
	FN_GM_MARK = "%s/effect/gm.mse"	% app.GetLocalePath()
	LOCALE_FILE_NAME = "%s/locale_game.txt" % app.GetLocalePath()
	constInfo.IN_GAME_SHOP_ENABLE = 0
elif IsNEWCIBN() :
	##°ÔÀÓ¸íÀ̱úÁø´Ù.
	APP_TITLE = "ÐÂÒÐÌì2"
	FN_GM_MARK = "%s/effect/gm.mse"	% app.GetLocalePath()
	LOCALE_FILE_NAME = "%s/locale_game.txt" % app.GetLocalePath()
	constInfo.IN_GAME_SHOP_ENABLE = 1
elif IsTAIWAN():
	APP_TITLE = "°«III°ê"
	FN_GM_MARK = "%s/effect/gm.mse"	% app.GetLocalePath()
	LOCALE_FILE_NAME = "%s/locale_game.txt" % app.GetLocalePath()

	constInfo.IN_GAME_SHOP_ENABLE = 1
	
else:
	FN_GM_MARK = "%s/effect/gm.mse"	% app.GetLocalePath()
	LOCALE_FILE_NAME = "%s/locale_game.txt" % app.GetLocalePath()

	constInfo.IN_GAME_SHOP_ENABLE = 1

LoadLocaleFile(LOCALE_FILE_NAME, locals())

########################################################################################################
## NOTE : ¾ÆÀÌÅÛÀ» ¹ö¸±¶§ "¹«¾ùÀ»/¸¦ ¹ö¸®½Ã°Ú½À´Ï±î?" ¹®ÀÚ¿­ÀÇ Á¶»ç ¼±ÅÃÀ» À§ÇÑ ÄÚµå
dictSingleWord = {
	"m":1, "n":1, "r":1, "M":1, "N":1, "R":1, "l":1, "L":1, "1":1, "3":1, "6":1, "7":1, "8":1, "0":1,
}

dictDoubleWord = {
	"°¡":1, "°¼":1, "°Å":1, "°Ü":1, "°í":1, "±³":1, "±¸":1, "±Ô":1, "±×":1, "±â":1, "°³":1, "°Â":1, "°Ô":1, "°è":1, "°ú":1, "±¥":1, "±Å":1, "±Ë":1, "±«":1, "±Í":1, "±á":1,
	"±î":1, "²¥":1, "²¨":1, "²¸":1, "²¿":1, "²Ø":1, "²Ù":1, "²ó":1, "²ô":1, "³¢":1, "±ú":1, "ƒÆ":1, "²²":1, "²¾":1, "²Ê":1, "²Ï":1, "²ã":1, "²ç":1, "²Ò":1, "²î":1, "…Ê":1,
	"³ª":1, "³Ä":1, "³Ê":1, "³à":1, "³ë":1, "´¢":1, "´©":1, "´º":1, "´À":1, "´Ï":1, "³»":1, "†v":1, "³×":1, "³é":1, "³ö":1, "‡R":1, "´²":1, "´´":1, "³ú":1, "´µ":1, "´Ì":1,
	"´Ù":1, "´ô":1, "´õ":1, "µ®":1, "µµ":1, "µÍ":1, "µÎ":1, "µà":1, "µå":1, "µð":1, "´ë":1, "ˆÛ":1, "µ¥":1, "µ³":1, "µÂ":1, "µÅ":1, "µÖ":1, "µØ":1, "µÇ":1, "µÚ":1, "µï":1,
	"µû":1, "‹x":1, "¶°":1, "¶Å":1, "¶Ç":1, "ŒÃ":1, "¶Ñ":1, "":1, "¶ß":1, "¶ì":1, "¶§":1, "‹š":1, "¶¼":1, "‹ó":1, "¶Ì":1, "¶Î":1, "Œô":1, "¶Ø":1, "¶Ï":1, "¶Ù":1, "¶ç":1,
	"¶ó":1, "·ª":1, "·¯":1, "·Á":1, "·Î":1, "·á":1, "·ç":1, "·ù":1, "¸£":1, "¸®":1, "·¡":1, "Žm":1, "·¹":1, "·Ê":1, "·Ö":1, "O":1, "·ï":1, "·ñ":1, "·Ú":1, "·ò":1, "l":1,
	"¸¶":1, "¸Ï":1, "¸Ó":1, "¸ç":1, "¸ð":1, "¹¦":1, "¹«":1, "¹Â":1, "¹Ç":1, "¹Ì":1, "¸Å":1, "Ù":1, "¸Þ":1, "¸ï":1, "¸ú":1, "‘À":1, "¹¹":1, "¹¾":1, "¸þ":1, "¹¿":1, "’Þ":1,
	"¹Ù":1, "¹ò":1, "¹ö":1, "º­":1, "º¸":1, "ºÌ":1, "ºÎ":1, "ºä":1, "ºê":1, "ºñ":1, "¹è":1, "“Ž":1, "º£":1, "º¶":1, "ºÁ":1, "ºÄ":1, "ºÛ":1, "ºÞ":1, "ºÆ":1, "ºß":1, "•‘":1,
	"ºü":1, "»²":1, "»µ":1, "»À":1, "»Ç":1, "»Ï":1, "»Ñ":1, "»Ø":1, "»Ú":1, "»ß":1, "»©":1, "•û":1, "»¾":1, "–§":1, "–Ø":1, "–ô":1, "—¨":1, "—Ä":1, "»Î":1, "—à":1, "˜u":1,
	"»ç":1, "»þ":1, "¼­":1, "¼Å":1, "¼Ò":1, "¼î":1, "¼ö":1, "½´":1, "½º":1, "½Ã":1, "»õ":1, "¼¨":1, "¼¼":1, "¼Î":1, "¼Ý":1, "¼â":1, "½¤":1, "½¦":1, "¼è":1, "½¬":1, "šÃ":1,
	"½Î":1, "›X":1, "½á":1, "›Ç":1, "½î":1, "¾¤":1, "¾¥":1, "o":1, "¾²":1, "¾¾":1, "½Ø":1, "›y":1, "½ê":1, "›ã":1, "½÷":1, "½û":1, "¾¬":1, "¾®":1, "½ý":1, "¾¯":1, "¾º":1,
	"¾Æ":1, "¾ß":1, "¾î":1, "¿©":1, "¿À":1, "¿ä":1, "¿ì":1, "À¯":1, "À¸":1, "ÀÌ":1, "¾Ö":1, "¾ê":1, "¿¡":1, "¿¹":1, "¿Í":1, "¿Ö":1, "¿ö":1, "¿þ":1, "¿Ü":1, "À§":1, "ÀÇ":1,
	"ÀÚ":1, "Àð":1, "Àú":1, "Á®":1, "Á¶":1, "ÁÒ":1, "ÁÖ":1, "Áê":1, "Áî":1, "Áö":1, "Àç":1, "À÷":1, "Á¦":1, "Áµ":1, "ÁÂ":1, "ÁÈ":1, "Áà":1, "Áâ":1, "ÁË":1, "Áã":1, "£p":1,
	"Â¥":1, "¹":1, "¼":1, "ÂÇ":1, "ÂÉ":1, "§c":1, "ÂÞ":1, "Âé":1, "Âê":1, "Âî":1, "°":1, "¤Š":1, "ÂÅ":1, "¥™":1, "ÂÒ":1, "ÂÖ":1, "Âå":1, "¨R":1, "ÂØ":1, "Âè":1, "©n":1,
	"Â÷":1, "í":1, "ó":1, "ÃÄ":1, "ÃÊ":1, "ÃÝ":1, "Ãß":1, "Ãò":1, "Ã÷":1, "Ä¡":1, "ä":1, "ª‰":1, "ü":1, "ÃÇ":1, "ÃÒ":1, "¬‚":1, "Ãç":1, "Ãé":1, "ÃÖ":1, "Ãë":1, "¯M":1,
	"Ä«":1, "ļ":1, "Ä¿":1, "ÄÑ":1, "ÄÚ":1, "Äì":1, "Äí":1, "Å¥":1, "Å©":1, "Å°":1, "ij":1, "°m":1, "ÄÉ":1, "ÄÙ":1, "Äâ":1, "Äè":1, "Äõ":1, "Äù":1, "Äê":1, "Äû":1, "´”":1,
	"Ÿ":1, "ÅË":1, "ÅÍ":1, "Åß":1, "Åä":1, "Åô":1, "Åõ":1, "Æ©":1, "Æ®":1, "Ƽ":1, "ÅÂ":1, "¶O":1, "Å×":1, "Åâ":1, "Åí":1, "Åï":1, "Åý":1, "Æ¡":1, "Åð":1, "Æ¢":1, "Æ·":1,
	"ÆÄ":1, "ÆÙ":1, "ÆÛ":1, "Æì":1, "Æ÷":1, "Ç¥":1, "Ǫ":1, "Ç»":1, "ÇÁ":1, "ÇÇ":1, "ÆÐ":1, "»—":1, "Æä":1, "Æó":1, "Ç¡":1, "½":1, "Ç´":1, "¿R":1, "Ç£":1, "Ƕ":1, "Àc":1,
	"ÇÏ":1, "Çá":1, "Çã":1, "Çô":1, "È£":1, "È¿":1, "ÈÄ":1, "ÈÞ":1, "Èå":1, "È÷":1, "ÇØ":1, "Á…":1, "Çì":1, "Çý":1, "È­":1, "ȳ":1, "ÈÌ":1, "ÈÑ":1, "ȸ":1, "ÈÖ":1, "Èñ":1,
}

locale = mapping(
)


def GetAuxiliaryWordType(text):

	textLength = len(text)

	if textLength > 1:

		singleWord = text[-1]

		if (singleWord >= '0' and singleWord <= '9') or\
			(singleWord >= 'a' and singleWord <= 'z') or\
			(singleWord >= 'A' and singleWord <= 'Z'):
			if not dictSingleWord.has_key(singleWord):
				return 1

		elif dictDoubleWord.has_key(text[-2:]):
			return 1

	return 0



def CutMoneyString(sourceText, startIndex, endIndex, insertingText, backText):

	sourceLength = len(sourceText)

	if sourceLength < startIndex:
		return backText

	text = sourceText[max(0, sourceLength-endIndex):sourceLength-startIndex]

	if not text:
		return backText

	if int(text) <= 0:
		return backText

	text = str(int(text))

	if backText:
		backText = " " + backText

	return text + insertingText + backText

def SecondToDHM(time):
	if time < 60:
		if IsARABIC():
			return "%.2f %s" % (time, SECOND)
		else:
			return "0" + MINUTE
		
	second = int(time % 60)
	minute = int((time / 60) % 60)
	hour = int((time / 60) / 60) % 24
	day = int(int((time / 60) / 60) / 24)

	text = ""

	if day > 0:
		text += str(day) + DAY
		text += " "

	if hour > 0:
		text += str(hour) + HOUR
		text += " "

	if minute > 0:
		text += str(minute) + MINUTE

	return text

def SecondToHM(time):

	if time < 60:
		if IsARABIC():
			return "%.2f %s" % (time, SECOND)
		else:
			return "0" + MINUTE

	second = int(time % 60)
	minute = int((time / 60) % 60)
	hour = int((time / 60) / 60)

	text = ""

	if hour > 0:
		text += str(hour) + HOUR
		if hour > 0:
			text += " "

	if minute > 0:
		text += str(minute) + MINUTE

	return text


def GetAlignmentTitleName(alignment):
	if alignment >= 12000:
		return TITLE_NAME_LIST[0]
	elif alignment >= 8000:
		return TITLE_NAME_LIST[1]
	elif alignment >= 4000:
		return TITLE_NAME_LIST[2]
	elif alignment >= 1000:
		return TITLE_NAME_LIST[3]
	elif alignment >= 0:
		return TITLE_NAME_LIST[4]
	elif alignment > -4000:
		return TITLE_NAME_LIST[5]
	elif alignment > -8000:
		return TITLE_NAME_LIST[6]
	elif alignment > -12000:
		return TITLE_NAME_LIST[7]

	return TITLE_NAME_LIST[8]


if app.ENABLE_TITLE_SYSTEM:
	TITLEPRESTIGE_NAME_LIST = (TITLE_1,TITLE_2,TITLE_3,TITLE_4,TITLE_5,TITLE_6,TITLE_7,TITLE_8,TITLE_9,TITLE_10,TITLE_11,TITLE_12,TITLE_13,TITLE_14,TITLE_15,TITLE_16,TITLE_17,TITLE_18,TITLE_19,TITLE_0)

	
if app.ENABLE_TITLE_SYSTEM:	
	def GetPrestigeTitleName(prestige):
		if prestige == 1:
			return TITLEPRESTIGE_NAME_LIST[0]
		elif prestige == 2:
			return TITLEPRESTIGE_NAME_LIST[1]
		elif prestige == 3:
			return TITLEPRESTIGE_NAME_LIST[2]
		elif prestige == 4:
			return TITLEPRESTIGE_NAME_LIST[3]
		elif prestige == 5:
			return TITLEPRESTIGE_NAME_LIST[4]
		elif prestige == 6:
			return TITLEPRESTIGE_NAME_LIST[5]
		elif prestige == 7:
			return TITLEPRESTIGE_NAME_LIST[6]
		elif prestige == 8:
			return TITLEPRESTIGE_NAME_LIST[7]
		elif prestige == 9:
			return TITLEPRESTIGE_NAME_LIST[8]
		elif prestige == 10:
			return TITLEPRESTIGE_NAME_LIST[9]
		elif prestige == 11:
			return TITLEPRESTIGE_NAME_LIST[10]
		elif prestige == 12:
			return TITLEPRESTIGE_NAME_LIST[11]
		elif prestige == 13:
			return TITLEPRESTIGE_NAME_LIST[12]
		elif prestige == 14:
			return TITLEPRESTIGE_NAME_LIST[13]
		elif prestige == 15:
			return TITLEPRESTIGE_NAME_LIST[14]
		elif prestige == 16:
			return TITLEPRESTIGE_NAME_LIST[15]
		elif prestige == 17:
			return TITLEPRESTIGE_NAME_LIST[16]
		elif prestige == 18:
			return TITLEPRESTIGE_NAME_LIST[17]
		elif prestige == 19:
			return TITLEPRESTIGE_NAME_LIST[18]
		elif prestige == 0:
			return TITLEPRESTIGE_NAME_LIST[19]

OPTION_PVPMODE_MESSAGE_DICT = {
	0 : PVP_MODE_NORMAL,
	1 : PVP_MODE_REVENGE,
	2 : PVP_MODE_KILL,
	3 : PVP_MODE_PROTECT,
	4 : PVP_MODE_GUILD,
}

error = mapping(
	CREATE_WINDOW = GAME_INIT_ERROR_MAIN_WINDOW,
	CREATE_CURSOR = GAME_INIT_ERROR_CURSOR,
	CREATE_NETWORK = GAME_INIT_ERROR_NETWORK,
	CREATE_ITEM_PROTO = GAME_INIT_ERROR_ITEM_PROTO,
	CREATE_MOB_PROTO = GAME_INIT_ERROR_MOB_PROTO,
	CREATE_NO_DIRECTX = GAME_INIT_ERROR_DIRECTX,
	CREATE_DEVICE = GAME_INIT_ERROR_GRAPHICS_NOT_EXIST,
	CREATE_NO_APPROPRIATE_DEVICE = GAME_INIT_ERROR_GRAPHICS_BAD_PERFORMANCE,
	CREATE_FORMAT = GAME_INIT_ERROR_GRAPHICS_NOT_SUPPORT_32BIT,
	NO_ERROR = ""
)


GUILDWAR_NORMAL_DESCLIST = [GUILD_WAR_USE_NORMAL_MAP, GUILD_WAR_LIMIT_30MIN, GUILD_WAR_WIN_CHECK_SCORE]
GUILDWAR_WARP_DESCLIST = [GUILD_WAR_USE_BATTLE_MAP, GUILD_WAR_WIN_WIPE_OUT_GUILD, GUILD_WAR_REWARD_POTION]
GUILDWAR_CTF_DESCLIST = [GUILD_WAR_USE_BATTLE_MAP, GUILD_WAR_WIN_TAKE_AWAY_FLAG1, GUILD_WAR_WIN_TAKE_AWAY_FLAG2, GUILD_WAR_REWARD_POTION]

MINIMAP_ZONE_NAME_DICT = {
	"metin2_map_a1"  : MAP_A1,
	"map_a2"         : MAP_A2,
	"metin2_map_a3"  : MAP_A3,
	"metin2_map_b1"  : MAP_B1,
	"map_b2"         : MAP_B2,
	"metin2_map_b3"  : MAP_B3,
	"metin2_map_c1"  : MAP_C1,
	"map_c2"         : MAP_C2,
	"metin2_map_c3"  : MAP_C3,
	"map_n_snowm_01" : MAP_SNOW,
	"metin2_map_n_flame_01" : MAP_FLAME,
	"metin2_map_n_desert_01" : MAP_DESERT,
	"metin2_map_milgyo" : MAP_TEMPLE,
	"metin2_map_spiderdungeon" : MAP_SPIDER,
	"metin2_map_deviltower1" : MAP_SKELTOWER,
	"metin2_map_guild_01" : MAP_AG,
	"metin2_map_guild_02" : MAP_BG,
	"metin2_map_guild_03" : MAP_CG,
	"metin2_map_trent" : MAP_TREE,
	"metin2_map_trent02" : MAP_TREE2,
	"season1/metin2_map_WL_01" : MAP_WL,
	"season1/metin2_map_nusluck01" : MAP_NUSLUCK,
    "Metin2_map_CapeDragonHead" : MAP_CAPE,
    "metin2_map_Mt_Thunder" : MAP_THUNDER,
    "metin2_map_dawnmistwood" : MAP_DAWN,
    "metin2_map_BayBlackSand" : MAP_BAY,
}



JOBINFO_TITLE = [
	[JOB_WARRIOR0, JOB_WARRIOR1, JOB_WARRIOR2,],
	[JOB_ASSASSIN0, JOB_ASSASSIN1, JOB_ASSASSIN2,],
	[JOB_SURA0, JOB_SURA1, JOB_SURA2,],
	[JOB_SHAMAN0, JOB_SHAMAN1, JOB_SHAMAN2,],
]

JOBINFO_DATA_LIST = [
	[
		["Ÿ°í³­ ¿ë¸Í°ú ±ÁÈ÷Áö ¾Ê´Â ¹«»çÀÇ",
		"±â°³¸¦ »ç¶÷µéÀº ÀÏÄþî [¿ëÀÚ]¶ó°í",
		"ºÎ¸¥´Ù. ¾î¶°ÇÑ À§±â¿¡¼­µµ ±×µéÀº ",
		"µÚ·Î ¹°·¯¼­Áö ¾ÊÀ¸¸ç, ´ÙÄ¡°í ¿òÁ÷",
		"À̱â Èûµç µ¿·á¸¦ À§ÇØ ´Ü½ÅÀ¸·Î",
		"Àûµé°ú ¸¶ÁÖ ½Î¿ì±âµµ ÇÑ´Ù. À̵éÀº",
		"Àß ´Ü·ÃµÈ ±ÙÀ°°ú Èû, °­·ÂÇÑ °ø°Ý·Â",
		"À¸·Î ÀüÀå ÃÖ¼±µÎ¿¡¼­ °ø°ÝÁøÀ¸·Î",
		"È°¾àÇÑ´Ù.                      ",],
		["°¡Àå ÀϹÝÀûÀÎ °ø°ÝÇü ¹«»ç·Î, ",
		"ÀûÁ¢Àü¿¡ µû¸¥ Á÷Á¢ °ø°ÝÀ¸·Î ÀüÀå",
		"¿¡¼­ È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó ±Ù·ÂÀ»",
		"¸ÞÀÎÀ¸·Î ½ºÅÝ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ, ",
		"ÀûÁ¢Àü¿¡ µû¸¥ »ý¸í·Â / ¹æ¾î·Â",
		"È®º¸¸¦ À§ÇØ Ã¼·ÂÀ» ¿Ã¸°´Ù. ¶ÇÇÑ",
		"°ø°ÝÀÇ Á¤È®¼ºÀ» ³ôÀ̱â À§ÇØ ¹Îø",
		"¿¡µµ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.",],
		["»ó´ç ¼öÁØÀÇ Á¤½Å·ÂÀ» ÀÌ¿ëÇÏ´Â",
		"Áß/±Ù°Å¸® Á¢ÀüÇü ¹«»ç·Î, °¢ ±â¼ú",
		"ÇϳªÇϳªÀÇ ³ôÀº °ø°Ý·ÂÀ¸·Î ÀüÀå¿¡¼­",
		"È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó ±Ù·ÂÀ» ¸ÞÀÎ",
		"À¸·Î ½ºÅÈ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ, ",
		"Áß/±Ù°Å¸® °ø°ÝÀÇ Á¤È®¼º°ú ¸íÁß·üÀ»",
		"À§ÇØ ¹ÎøÀ» ¿Ã¸°´Ù. ¶ÇÇÑ Á¢Àü ½Ã ",
		"Àû °ø°Ý¿¡ µû¸¥ »ý¸í·Â / ¹æ¾î·Â",
		"È®º¸¸¦ À§ÇØ Ã¼·Â¿¡µµ Æ÷ÀÎÆ®¸¦",
		"ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.        ",],		
	],
	[
		["ÀÚ°´Àº ¾î¶°ÇÑ »óȲ¿¡¼­µµ ÀÚ½ÅÀÇ",
		"¸öÀ» ¼û±â°í Àº¹ÐÇÑ ¾îµÒÀÇ ÀÓ¹«¸¦",
		"¼öÇàÇϸ鼭 ÀüÀåÀÇ ÈÄÀ§¸¦ Áö¿øÇÏ´Â", 
		"ÀÚµéÀÌ´Ù. À̵éÀº ¾ÆÁÖ ºü¸£°í ½Å¼Ó",
		"Çϸç, ºñÇÒ µ¥ ¾øÀÌ °ú°¨ÇÏ°í ÀýÁ¦µÈ",
		"ÇൿÀ¸·Î ÀûÀÇ ±Þ¼Ò¿¡ Ä¡¸íŸ¸¦ ³¯¸®",
		"µÇ, ÀüÀå¿¡¼± ÀûÁøÀ» ÇâÇØ ¹«¼öÇÑ",
		"È­»ìÀ» ³»»ÕÀ¸¸ç ÀÚ½ÅÀÇ ¿ë¸ÍÀ»",
		"¼±º¸ÀδÙ.                   "],
		["µÎ¼Õ ´Ü°ËÀ» ÁÖ¹«±â·Î ´Ù·ç¸ç, ½Å¼Ó",
		"ÇÏ°Ô Ä¡°í ºüÁö´Â ÀÚ°´ ƯÀ¯ÀÇ ¿òÁ÷ÀÓ",
		"À¸·Î ÀüÀå¿¡¼­ È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó",
		"¹ÎøÀ» ¸ÞÀÎÀ¸·Î ½ºÅÝ Æ÷ÀÎÆ®¸¦ ÅõÀÚ",
		"ÇϵÇ, ±Ù·ÂÀ» ¿Ã·Á °ø°Ý·ÂÀ» ³ôÀδÙ.",
		"¶ÇÇÑ ±ÙÁ¢Àü¿¡ µû¸¥ »ý¸í·Â/¹æ¾î·Â ",
		"»ó½ÂÀ» À§ÇØ Ã¼·Â¿¡µµ Æ÷ÀÎÆ®¸¦",
		"ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.          ",],
		["È°À» ÁÖ¹«±â·Î ´Ù·ç¸ç, ±ä ½Ã¾ß¿Í",
		"»çÁ¤°Å¸®¿¡ µû¸¥ ¿ø°Å¸® °ø°ÝÀ¸·Î",
		"ÀüÀå¿¡¼­ È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó",
		"°ø°Ý ¼º°ø·üÀÇ Áõ°¡¸¦ À§ÇØ ¹ÎøÀ»",
		"¸ÞÀÎÀ¸·Î ¿Ã·Á¾ß Çϸç, ¿ø°Å¸®",
		"°ø°ÝÀÇ µ¥¹ÌÁö Áõ°¡¸¦ À§ÇØ ±Ù·ÂÀ»",
		"¿Ã¸± ÇÊ¿ä°¡ ÀÖ´Ù. ¶ÇÇÑ Àûµé¿¡°Ô",
		"Æ÷À§µÇ¾úÀ» ½Ã, Àû °ø°Ý¿¡ ¹öƼ±â",
		"À§ÇÑ »ý¸í·Â/¹æ¾î·Â »ó½ÂÀ» À§ÇØ",
		"ü·Â¿¡µµ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇÒ ÇÊ¿ä°¡",
		"ÀÖ´Ù.                        ", ],
	],
	[
		["¼ö¶ó´Â [µ¶Àº µ¶À¸·Î]ÀÇ ¼Ó¼ºÀ¸·Î",
		"â¼³µÈ Ư¼ö ¼Ó¼ºÀÇ ±ºÁ÷ÀÌ´Ù. ",
		"±×µéÀº ÀüÀå¿¡¼­ ÀûµéÀÇ »ç±â¸¦ ÀúÇÏ",
		"½ÃÅ°°í, ¾Ç¸¶ÀÇ ÈûÀ» ½ÇÀº ¸¶ÅºÀ¸·Î",
		"ÀûÀÇ ¿µÈ¥°ú À°½ÅÀ» Áþ¹¶°µ´Ù. ¶§·Î",
		"À̵éÀº ÀÚ½ÅÀÇ °Ë°ú °©¿Ê¿¡ ¾îµÒÀÇ",
		"ÈûÀ» ½Ç¾î, ÀüÀå¿¡¼­ ¹«»ç ¸øÁö ¾ÊÀº",
		"°ø°Ý·ÂÀ» ¹ßÈÖÇϱ⵵ Çϴµ¥, ÀûµéÀ»",
		"Á׿©´ë´Â±× ¸ð½ÀÀÌ ¿ö³«¿¡ ²ûÂïÇØ",
		"»ç¶÷µéÀº ¼ö¶ó¸¦ ÀÏÄþî [¸¶½Å]À̶ó",
		"ºÎ¸£±â¸¦ ÁÖÀú ¾É´Â´Ù."],
		["ȯ¹«±ºÀÇ ¼ö¶ó´Â ¾Ç¸¶ÀÇ ¾¾¿¡¼­",
		"¾ò¾îÁö´Â ¸¶·ÂÀ» ¹«±â³ª ¹æ¾î±¸¿¡",
		"½Ç¾î ¹«»ç ¸øÁö ¾ÊÀº ÀüÅõ·ÂÀ¸·Î",
		"ÀüÀå¿¡¼­ È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó",
		"Áö´ÉÀÌ ³ô¾ÆÁú¼ö·Ï Âø¿ë Àåºñ¿¡", 
		"½Ç¸®´Â ¸¶·ÂÀÇ À§·ÂÀÌ Áõ´ëµÇ¹Ç·Î,",
		"Áö´É°ú ±Ù·ÂÀ» ¸ÞÀÎÀ¸·Î ½ºÅÈ",
		"Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ, Á¢Àü¿¡ µû¸¥",
		"»ý¸í·Â/¹æ¾î·Â È®º¸¸¦ À§ÇØ Ã¼·ÂÀ»",
		"¿Ã¸°´Ù. ¶ÇÇÑ °ø°ÝÀÇ Á¤È®¼º°ú",
		"ȸÇǸ¦ À§Çؼ­ ¹Îø¿¡µµ Æ÷ÀÎÆ®¸¦",
		"ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.           ",],
		["È渶±ºÀÇ ¼ö¶óµéÀº °¢Á¾ ¾îµÒÀÇ",
		"ÁÖ¹®°ú ¾Ç¸¶ÀÇ ¸¶¹ýÀ¸·Î ÀüÀå¿¡¼­",
		"È°¾àÇÑ´Ù. ±ºÁ÷ Ư¼º»ó ¸¶¹ý °ø°ÝÀÌ",
		"ÁÖÀ̹ǷΠÁö´ÉÀ» ¸ÞÀÎÀ¸·Î ½ºÅÝ",
		"Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ, ¿ø°Å¸® ¸¶¹ý",
		"°ø°ÝÀÇ Á¤È®¼ºÀ» À§ÇØ ¹ÎøÀ» ¿Ã¸°´Ù.",
		"¶ÇÇÑ Æ÷À§ µÇ¾úÀ»½Ã, Àû °ø°Ý¿¡ µû¸¥",
		"»ý¸í·Â / ¹æ¾î·Â È®º¸¸¦ À§ÇØ Ã¼·Â¿¡µµ",
		"Æ÷ÀÎÆ®¸¦ ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.    ",],
	],
	[
		["¹«´çÀº ¿ë½Å°ú ÀÚ¿¬, µÎ °í´ëÀÇ",
		"ÈûÀ» ´Ù·ê ¼ö ÀÖ´Â À¯ÀÏÇÑ Á÷Á¾ÀÌ´Ù.",
		"±×µéÀº ÈĹ濡¼­ ¾Æ±ºÀ» º¸Á¶ÇÏ°í",
		"´ÙÄ£ µ¿·áÀÇ ºÎ»óÀ» ȸº¹ ½ÃÅ°¸ç",
		"¶³¾îÁø »ç±â¸¦ »ó½Â½ÃŲ´Ù. ±×µéÀº",
		"¾Æ±ºÀÇ ¼ö¸é°ú ÈÞ½ÄÀ» ¹æÇØÇÏ´Â ÀÚ¸¦ ",
		"Àý´ë ¿ë¼­ÇÏÁö ¾ÊÀ¸¸ç, ±×·± ÀÚµé",
		"¿¡°Ô´Â ÇÑ Á¡ ÁÖÀú ¾øÀÌ ÁÖ¹®À»",
		"ÅÍÆ®·Á ±× ºñ°ÌÇÔÀ» ¾öÈ÷ ¡°èÇÑ´Ù.",],
		["õ·æ±ºÀÇ ¹«´çµéÀº °¢Á¾ ºÎÀû¼ú°ú",
		"º¸Á¶ÁÖ¹®¿¡ ´ÉÇϸç, ÀûÀÇ Á÷ / °£Á¢",
		"°ø°ÝÀ¸·ÎºÎÅÍ ¾Æ±ºÀ» ÁöŲ´Ù. ±ºÁ÷",
		"Ư¼º»ó ¸¶¹ý ´É·ÂÀÌ ÁÖÀ̹ǷΠÁö´ÉÀ»",
		"¸ÞÀÎÀ¸·Î ½ºÅÝ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ,",
		"Æ÷À§µÇ¾úÀ» ½Ã, Àû °ø°Ý¿¡ µû¸¥",
		"»ý¸í·Â / ¹æ¾î·Â È®º¸¸¦ À§ÇØ Ã¼·ÂÀ»",
		"¿Ã¸°´Ù. ¶ÇÇÑ ¿ø°Å¸® ¸¶¹ý °ø°ÝÀÇ",
		"Á¤È®¼ºÀ» À§¿¡ ¹Îø¿¡µµ Æ÷ÀÎÆ®¸¦",
		"ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.           ",],
		["±¤·Ú±ºÀÇ ¹«´çµéÀº ÀÚ¿¬ÀÇ ÈûÀ»",
		"ºô·Á ¾Æ±ºÀ» ȸº¹ÇÏ°í, ³ú½ÅÀÇ ",
		"ÈûÀ¸·Î ¹ÐÁýÇÑ Àûµé¿¡°Ô Å« Ãæ°ÝÀ»",
		"ÀÔÈú ¼ö ÀÖ´Â À̵éÀÌ´Ù. ±ºÁ÷ÀÇ",
		"Ư¼º»ó ¸¶¹ý ´É·ÂÀÌ ÁÖÀ̹ǷΠÁö´ÉÀ»",
		"¸ÞÀÎÀ¸·Î ½ºÅÝ Æ÷ÀÎÆ®¸¦ ÅõÀÚÇϵÇ,",
		"Æ÷À§µÇ¾úÀ»½Ã, Àû °ø°Ý¿¡ µû¸¥",
		"»ý¸í·Â / ¹æ¾î·Â È®º¸¸¦ À§ÇØ Ã¼·ÂÀ»",
		"¿Ã¸°´Ù. ¶ÇÇÑ ¿ø°Å¸® ¸¶¹ý °ø°ÝÀÇ",
		"Á¤È®¼ºÀ» À§¿¡ ¹Îø¿¡µµ Æ÷ÀÎÆ®¸¦",
		"ÅõÀÚÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.             "],
	],
]


WHISPER_ERROR = {
	1 : CANNOT_WHISPER_NOT_LOGON,
	2 : CANNOT_WHISPER_DEST_REFUSE,
	3 : CANNOT_WHISPER_SELF_REFUSE,
}

NOTIFY_MESSAGE = {
	"CANNOT_EQUIP_SHOP" : CANNOT_EQUIP_IN_SHOP,
	"CANNOT_EQUIP_EXCHANGE" : CANNOT_EQUIP_IN_EXCHANGE,
}


ATTACK_ERROR_TAIL_DICT = {
	"IN_SAFE" : CANNOT_ATTACK_SELF_IN_SAFE,
	"DEST_IN_SAFE" : CANNOT_ATTACK_DEST_IN_SAFE,
}

SHOT_ERROR_TAIL_DICT = {
	"EMPTY_ARROW" : CANNOT_SHOOT_EMPTY_ARROW,
	"IN_SAFE" : CANNOT_SHOOT_SELF_IN_SAFE,
	"DEST_IN_SAFE" : CANNOT_SHOOT_DEST_IN_SAFE,
}
	
USE_SKILL_ERROR_TAIL_DICT = {	
	"IN_SAFE" : CANNOT_SKILL_SELF_IN_SAFE,
	"NEED_TARGET" : CANNOT_SKILL_NEED_TARGET,
	"NEED_EMPTY_BOTTLE" : CANNOT_SKILL_NEED_EMPTY_BOTTLE,
	"NEED_POISON_BOTTLE" : CANNOT_SKILL_NEED_POISON_BOTTLE,
	"REMOVE_FISHING_ROD" : CANNOT_SKILL_REMOVE_FISHING_ROD,
	"NOT_YET_LEARN" : CANNOT_SKILL_NOT_YET_LEARN,
	"NOT_MATCHABLE_WEAPON" : CANNOT_SKILL_NOT_MATCHABLE_WEAPON,
	"WAIT_COOLTIME" : CANNOT_SKILL_WAIT_COOLTIME,
	"NOT_ENOUGH_HP" : CANNOT_SKILL_NOT_ENOUGH_HP,
	"NOT_ENOUGH_SP" : CANNOT_SKILL_NOT_ENOUGH_SP,
	"CANNOT_USE_SELF" : CANNOT_SKILL_USE_SELF,
	"ONLY_FOR_ALLIANCE" : CANNOT_SKILL_ONLY_FOR_ALLIANCE,
	"CANNOT_ATTACK_ENEMY_IN_SAFE_AREA" : CANNOT_SKILL_DEST_IN_SAFE,
	"CANNOT_APPROACH" : CANNOT_SKILL_APPROACH,
	"CANNOT_ATTACK" : CANNOT_SKILL_ATTACK,
	"ONLY_FOR_CORPSE" : CANNOT_SKILL_ONLY_FOR_CORPSE,
	"EQUIP_FISHING_ROD" : CANNOT_SKILL_EQUIP_FISHING_ROD, 
	"NOT_HORSE_SKILL" : CANNOT_SKILL_NOT_HORSE_SKILL,
	"HAVE_TO_RIDE" : CANNOT_SKILL_HAVE_TO_RIDE,
}

LEVEL_LIST=["", HORSE_LEVEL1, HORSE_LEVEL2, HORSE_LEVEL3]

HEALTH_LIST=[
	HORSE_HEALTH0,
	HORSE_HEALTH1, 
	HORSE_HEALTH2,
	HORSE_HEALTH3,
]


USE_SKILL_ERROR_CHAT_DICT = {	
	"NEED_EMPTY_BOTTLE" : SKILL_NEED_EMPTY_BOTTLE,
	"NEED_POISON_BOTTLE" : SKILL_NEED_POISON_BOTTLE, 
	"ONLY_FOR_GUILD_WAR" : SKILL_ONLY_FOR_GUILD_WAR,
}

SHOP_ERROR_DICT = {
	"NOT_ENOUGH_MONEY" : SHOP_NOT_ENOUGH_MONEY,
	"SOLDOUT" : SHOP_SOLDOUT,
	"INVENTORY_FULL" : SHOP_INVENTORY_FULL,
	"INVALID_POS" : SHOP_INVALID_POS,
	"NOT_ENOUGH_MONEY_EX" : SHOP_NOT_ENOUGH_MONEY_EX,
}

STAT_MINUS_DESCRIPTION = {
	"HTH-" : STAT_MINUS_CON,
	"INT-" : STAT_MINUS_INT,
	"STR-" : STAT_MINUS_STR,
	"DEX-" : STAT_MINUS_DEX,
}

MODE_NAME_LIST = ( PVP_OPTION_NORMAL, PVP_OPTION_REVENGE, PVP_OPTION_KILL, PVP_OPTION_PROTECT, )
TITLE_NAME_LIST = ( PVP_LEVEL0, PVP_LEVEL1, PVP_LEVEL2, PVP_LEVEL3, PVP_LEVEL4, PVP_LEVEL5, PVP_LEVEL6, PVP_LEVEL7, PVP_LEVEL8, )

def GetLetterImageName():
	return "season1/icon/scroll_close.tga"
def GetLetterOpenImageName():
	return "season1/icon/scroll_open.tga"
def GetLetterCloseImageName():
	return "season1/icon/scroll_close.tga"

if 949 == app.GetDefaultCodePage():
	def EUL(name):
		if GetAuxiliaryWordType(name):
			return "¸¦ "
		else:
			return "À» "

	def I(name):
		if GetAuxiliaryWordType(name):
			return "°¡ "
		else:
			return "ÀÌ "

	def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice):
		name = sellItemName
		if sellItemCount > 1:
			name += " "
			name += str(sellItemCount)
			name += "°³"

		return name + EUL(name) + str(sellItemPrice) + "³É¿¡ ÆĽðڽÀ´Ï±î?"

	def DO_YOU_BUY_ITEM(sellItemName, sellItemCount, sellItemPrice):
		name = sellItemName
		if sellItemCount > 1:
			name += " "
			name += str(sellItemCount)
			name += "°³"

		return name + EUL(name) + str(sellItemPrice) + "¿¡ »ç½Ã°Ú½À´Ï±î?"

	def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName):
		return attachedItemName+EUL(attachedItemName)+"ºÎÂøÇÒ ¼ö ¾ø´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù"

	def REFINE_FAILURE_NO_SOCKET(attachedItemName):
		return attachedItemName+EUL(attachedItemName)+"ºÎÂøÇÒ ¼ö ÀÖ´Â ¼ÒÄÏÀÌ ¾ø½À´Ï´Ù"	

	def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName):
		return attachedItemName+EUL(attachedItemName)+"ºÎÂøÇÒ ¼ö Àִ Ȳ±Ý ¼ÒÄÏÀÌ ¾ø½À´Ï´Ù"	

	def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount):
		name = dropItemName
		if dropItemCount > 1:
			name += " "
			name += str(dropItemCount)
			name += "°³"

		return name+EUL(name)+"¹ö¸®½Ã°Ú½À´Ï±î?"

	def NumberToMoneyString(number):
		if number <= 0:
			return "0³É"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "¸¸", result)
		result = CutMoneyString(number, 8, 12, "¾ï", result)
		result = result + "³É"

		return result

	def NumberToSecondaryCoinString(number):
		if number <= 0:
			return "0Àü"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "¸¸", result)
		result = CutMoneyString(number, 8, 12, "¾ï", result)
		result = result + "Àü"

		return result

	def FISHING_NOTIFY(isFish, fishName):
		if isFish:
			return fishName + I(fishName) + "¹® µí ÇÕ´Ï´Ù."
		else:
			return fishName + I(fishName) + "°É¸°µí ÇÕ´Ï´Ù."

	def FISHING_SUCCESS(isFish, fishName):
		if isFish:
			return fishName + EUL(fishName) + "Àâ¾Ò½À´Ï´Ù!"
		else:
			return fishName + EUL(fishName) + "¾ò¾ú½À´Ï´Ù!"

elif 932 == app.GetDefaultCodePage():
	def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice):
		if sellItemCount > 1 :
			return "%s %s ŒÂ‚ð %s‚É”„‚è‚Ü‚·‚©H" % ( sellItemName, sellItemCount, NumberToMoneyString(sellItemPrice) )
		else:
			return "%s ‚ð %s‚Å”„‚è‚Ü‚·‚©H" % (sellItemName, NumberToMoneyString(sellItemPrice) )

	def DO_YOU_BUY_ITEM(buyItemName, buyItemCount, buyItemPrice) :
		if buyItemCount > 1 :
			return "%s %sŒÂ‚ð %s‚Å”ƒ‚¢‚Ü‚·‚©H" % ( buyItemName, buyItemCount, buyItemPrice )
		else:
			return "%s‚ð %s‚Å”ƒ‚¢‚Ü‚·‚©H" % ( buyItemName, buyItemPrice )
			
	def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName) :
		return "%s‚ð‘•’…‚Å‚«‚È‚¢ƒAƒCƒe?‚Å‚·B" % (attachedItemName)

	def REFINE_FAILURE_NO_SOCKET(attachedItemName) :
		return "%s‚ð‘•’…‚·‚é?ƒPƒbƒg‚ª‚ ‚è‚Ü‚¹‚ñB" % (attachedItemName)

	def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName) :
		return "%s‚ð‘•’…‚Å‚«‚鉩‹à?ƒPƒbƒg‚ª‚ ‚è‚Ü‚¹‚ñB" % (attachedItemName)
		
	def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount) :
		if dropItemCount > 1 :
			return "%s %d ŒÂ‚ðŽÌ‚Ä‚Ü‚·‚©H" % (dropItemName, dropItemCount)
		else :	
			return "%s‚ðŽÌ‚Ä‚Ü‚·‚©H" % (dropItemName)

	def FISHING_NOTIFY(isFish, fishName) :
		if isFish :
			return "%s ‚ªH‚¢‚‚¢‚½‚悤‚Å‚·" % ( fishName )
		else :
			return "%s ‚ª‚©‚©‚Á‚½‚悤‚Å‚·" % ( fishName )

	def FISHING_SUCCESS(isFish, fishName) :
		if isFish :
			return "%s ‚ð•ß‚Ü‚¦‚Ü‚µ‚½I" % (fishName)
		else :
			return "%s ‚ðŽè‚É“ü‚ê‚Ü‚µ‚½I" % (fishName)
			
	def NumberToMoneyString(number) :
		if number <= 0 :
			return "0—¼"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "–œ", result)
		result = CutMoneyString(number, 8, 12, "‰­", result)
		result = result + "—¼"

		return result
	def NumberToSecondaryCoinString(number) :
		if number <= 0 :
			return "0jun"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "–œ", result)
		result = CutMoneyString(number, 8, 12, "‰­", result)
		result = result + "jun"

		return result
elif IsHONGKONG():
	def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice):
		if sellItemCount > 1 :
			return DO_YOU_SELL_ITEM2 % (sellItemName, sellItemCount, NumberToMoneyString(sellItemPrice) )
		else:
			return DO_YOU_SELL_ITEM1 % (sellItemName, NumberToMoneyString(sellItemPrice) )

	def DO_YOU_BUY_ITEM(buyItemName, buyItemCount, buyItemPrice) :
		if buyItemCount > 1 :
			return DO_YOU_BUY_ITEM2 % ( buyItemName, buyItemCount, buyItemPrice )
		else:
			return DO_YOU_BUY_ITEM1 % ( buyItemName, buyItemPrice )
			
	def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName) :
		return REFINE_FAILURE_CAN_NOT_ATTACH0 % (attachedItemName)

	def REFINE_FAILURE_NO_SOCKET(attachedItemName) :
		return REFINE_FAILURE_NO_SOCKET0 % (attachedItemName)

	def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName) :
		return REFINE_FAILURE_NO_GOLD_SOCKET0 % (attachedItemName)
		
	def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount) :
		if dropItemCount > 1 :
			return HOW_MANY_ITEM_DO_YOU_DROP2 % (dropItemName, dropItemCount)
		else :	
			return HOW_MANY_ITEM_DO_YOU_DROP1 % (dropItemName)

	def FISHING_NOTIFY(isFish, fishName) :
		if isFish :
			return FISHING_NOTIFY1 % ( fishName )
		else :
			return FISHING_NOTIFY2 % ( fishName )

	def FISHING_SUCCESS(isFish, fishName) :
		if isFish :
			return FISHING_SUCCESS1 % (fishName)
		else :
			return FISHING_SUCCESS2 % (fishName)
			
	def NumberToMoneyString(number) :
		if number <= 0 :
			return "0 %s" % (MONETARY_UNIT0)

		number = str(number)
		result = CutMoneyString(number, 0, 4, 	"", "")
		result = CutMoneyString(number, 4, 8, 	MONETARY_UNIT1, result)
		result = CutMoneyString(number, 8, 12, 	MONETARY_UNIT2, result)
		result = result + MONETARY_UNIT0

		return result

	def NumberToSecondaryCoinString(number) :
		if number <= 0 :
			return "0 %s" % (MONETARY_UNIT_JUN)

		number = str(number)
		result = CutMoneyString(number, 0, 4, 	"", "")
		result = CutMoneyString(number, 4, 8, 	MONETARY_UNIT1, result)
		result = CutMoneyString(number, 8, 12, 	MONETARY_UNIT2, result)
		result = result + MONETARY_UNIT_JUN

		return result

elif IsNEWCIBN() or IsCIBN10():
	def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice):
		if sellItemCount>1:
			return "È·¶¨Òª°Ñ%s¸ö%sÒÔ%s½ð±ÒÂôµôÂð£¿" % (str(sellItemCount), sellItemName, str(sellItemPrice))
		else:
			return "È·¶¨Òª°Ñ%sÒÔ%s½ð±ÒÂôµôÂð£¿" % (sellItemName, str(sellItemPrice))

	def DO_YOU_BUY_ITEM(sellItemName, sellItemCount, sellItemPrice):
		if sellItemCount>1:
			return "È·¶¨Òª°Ñ%s¸ö%sÒÔ%s½ð±ÒÂò½øÂð£¿" % (str(sellItemCount), sellItemName, str(sellItemPrice))
		else:
			return "È·¶¨Òª°Ñ%sÒÔ%s½ð±ÒÂò½øÂð£¿" % (sellItemName, str(sellItemPrice))

	def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName):
		return "ÎÞ·¨ÏâǶ%s µÄ×°±¸" % (attachedItemName)

	def REFINE_FAILURE_NO_SOCKET(attachedItemName):
		return "ûÓпÉÒÔÏâǶ%s µÄ¿×" % (attachedItemName)

	def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName):
		return "ûÓпÉÒÔÏâǶ%s µÄ»Æ½ð¿×" % (attachedItemName)

	def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount):
		if dropItemCount>1:
			return "È·¶¨ÒªÈÓµô%d¸ö%sÂð?" % (dropItemCount, dropItemName)
		else:
			return "È·¶¨ÒªÈÓµô%sÂð?" % (dropItemName)

	def FISHING_NOTIFY(isFish, fishName):
		if isFish:
			return fishName # º»·¡ ¿©±â¿¡ ¾î¶² ¸»ÀÌ ºÙ¾îÀִµ¥, ÀÎÄÚµùÀÌ ±úÁ®À־ º¹¿øÇÒ ¼ö°¡ ¾ø´Ù ¤Ð¤Ð... cython¿¡¼­ ÀÎÄÚµù ¿¡·¯ ³ª¼­ Áö¿ö¹ö¸²...
		else:
			return "µö×Å" + fishName + "ÁË¡£"

	def FISHING_SUCCESS(isFish, fishName):
		if isFish:
			return "µö×Å" + fishName + "ÁË¡£"
		else:
			return "»ñµÃ" + fishName + "ÁË¡£"

	def NumberToMoneyString(number):

		if number <= 0:
			return "0Á½"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "Íò", result)
		result = CutMoneyString(number, 8, 12, "ÒÚ", result)
		result = result + "Á½"

		return result

	def NumberToSecondaryCoinString(number):

		if number <= 0:
			return "0JUN"

		number = str(number)
		result = CutMoneyString(number, 0, 4, "", "")
		result = CutMoneyString(number, 4, 8, "Íò", result)
		result = CutMoneyString(number, 8, 12, "ÒÚ", result)
		result = result + "JUN"

		return result		
elif IsEUROPE() and not IsWE_KOREA() and not IsYMIR():
	def DO_YOU_SELL_ITEM(sellItemName, sellItemCount, sellItemPrice):
		if sellItemCount > 1 :
			return DO_YOU_SELL_ITEM2 % (sellItemName, sellItemCount, NumberToMoneyString(sellItemPrice) )
		else:
			return DO_YOU_SELL_ITEM1 % (sellItemName, NumberToMoneyString(sellItemPrice) )

	def DO_YOU_BUY_ITEM(buyItemName, buyItemCount, buyItemPrice) :
		if buyItemCount > 1 :
			return DO_YOU_BUY_ITEM2 % ( buyItemName, buyItemCount, buyItemPrice )
		else:
			return DO_YOU_BUY_ITEM1 % ( buyItemName, buyItemPrice )
			
	def REFINE_FAILURE_CAN_NOT_ATTACH(attachedItemName) :
		return REFINE_FAILURE_CAN_NOT_ATTACH0 % (attachedItemName)

	def REFINE_FAILURE_NO_SOCKET(attachedItemName) :
		return REFINE_FAILURE_NO_SOCKET0 % (attachedItemName)

	def REFINE_FAILURE_NO_GOLD_SOCKET(attachedItemName) :
		return REFINE_FAILURE_NO_GOLD_SOCKET0 % (attachedItemName)
		
	def HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, dropItemCount) :
		if dropItemCount > 1 :
			return HOW_MANY_ITEM_DO_YOU_DROP2 % (dropItemName, dropItemCount)
		else :	
			return HOW_MANY_ITEM_DO_YOU_DROP1 % (dropItemName)

	def FISHING_NOTIFY(isFish, fishName) :
		if isFish :
			return FISHING_NOTIFY1 % ( fishName )
		else :
			return FISHING_NOTIFY2 % ( fishName )

	def FISHING_SUCCESS(isFish, fishName) :
		if isFish :
			return FISHING_SUCCESS1 % (fishName)
		else :
			return FISHING_SUCCESS2 % (fishName)
			
	def NumberToMoneyString(n) :
		if n <= 0 :
			return "0 %s" % (MONETARY_UNIT0)

		return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT0) 

	def NumberToSecondaryCoinString(n) :
		if n <= 0 :
			return "0 %s" % (MONETARY_UNIT_JUN)

		return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT_JUN) 

 

My uiaffectshower.py

Spoiler

import ui
import localeInfo
import chr
import item
import app
import skill
import player
import uiToolTip
import math

# WEDDING
class LovePointImage(ui.ExpandedImageBox):

	FILE_PATH = "d:/ymir work/ui/pattern/LovePoint/"
	FILE_DICT = {
		0 : FILE_PATH + "01.dds",
		1 : FILE_PATH + "02.dds",
		2 : FILE_PATH + "02.dds",
		3 : FILE_PATH + "03.dds",
		4 : FILE_PATH + "04.dds",
		5 : FILE_PATH + "05.dds",
	}

	def __init__(self):
		ui.ExpandedImageBox.__init__(self)

		self.loverName = ""
		self.lovePoint = 0

		self.toolTip = uiToolTip.ToolTip(100)
		self.toolTip.HideToolTip()

	def __del__(self):
		ui.ExpandedImageBox.__del__(self)

	def SetLoverInfo(self, name, lovePoint):
		self.loverName = name
		self.lovePoint = lovePoint
		self.__Refresh()

	def OnUpdateLovePoint(self, lovePoint):
		self.lovePoint = lovePoint
		self.__Refresh()

	def __Refresh(self):
		self.lovePoint = max(0, self.lovePoint)
		self.lovePoint = min(100, self.lovePoint)

		if 0 == self.lovePoint:
			loveGrade = 0
		else:
			loveGrade = self.lovePoint / 25 + 1
		fileName = self.FILE_DICT.get(loveGrade, self.FILE_PATH+"00.dds")

		try:
			self.LoadImage(fileName)
		except:
			import dbg
			dbg.TraceError("LovePointImage.SetLoverInfo(lovePoint=%d) - LoadError %s" % (self.lovePoint, fileName))

		self.SetScale(0.7, 0.7)

		self.toolTip.ClearToolTip()
		self.toolTip.SetTitle(self.loverName)
		self.toolTip.AppendTextLine(localeInfo.AFF_LOVE_POINT % (self.lovePoint))
		self.toolTip.ResizeToolTip()

	def OnMouseOverIn(self):
		self.toolTip.ShowToolTip()

	def OnMouseOverOut(self):
		self.toolTip.HideToolTip()
# END_OF_WEDDING


class HorseImage(ui.ExpandedImageBox):

	FILE_PATH = "d:/ymir work/ui/pattern/HorseState/"

	FILE_DICT = {
		00 : FILE_PATH+"00.dds",
		01 : FILE_PATH+"00.dds",
		02 : FILE_PATH+"00.dds",
		03 : FILE_PATH+"00.dds",
		10 : FILE_PATH+"10.dds",
		11 : FILE_PATH+"11.dds",
		12 : FILE_PATH+"12.dds",
		13 : FILE_PATH+"13.dds",
		20 : FILE_PATH+"20.dds",
		21 : FILE_PATH+"21.dds",
		22 : FILE_PATH+"22.dds",
		23 : FILE_PATH+"23.dds",
		30 : FILE_PATH+"30.dds",
		31 : FILE_PATH+"31.dds",
		32 : FILE_PATH+"32.dds",
		33 : FILE_PATH+"33.dds",
	}

	def __init__(self):
		ui.ExpandedImageBox.__init__(self)

		#self.textLineList = []
		self.toolTip = uiToolTip.ToolTip(100)
		self.toolTip.HideToolTip()

	def __GetHorseGrade(self, level):
		if 0 == level:
			return 0

		return (level-1)/10 + 1

	def SetState(self, level, health, battery):
		#self.textLineList=[]
		self.toolTip.ClearToolTip()

		if level>0:

			try:
				grade = self.__GetHorseGrade(level)
				self.__AppendText(localeInfo.LEVEL_LIST[grade])
			except IndexError:
				print "HorseImage.SetState(level=%d, health=%d, battery=%d) - Unknown Index" % (level, health, battery)
				return

			try:
				healthName=localeInfo.HEALTH_LIST[health]
				if len(healthName)>0:
					self.__AppendText(healthName)
			except IndexError:
				print "HorseImage.SetState(level=%d, health=%d, battery=%d) - Unknown Index" % (level, health, battery)
				return

			if health>0:
				if battery==0:
					self.__AppendText(localeInfo.NEEFD_REST)

			try:
				fileName=self.FILE_DICT[health*10+battery]
			except KeyError:
				print "HorseImage.SetState(level=%d, health=%d, battery=%d) - KeyError" % (level, health, battery)

			try:
				self.LoadImage(fileName)
			except:
				print "HorseImage.SetState(level=%d, health=%d, battery=%d) - LoadError %s" % (level, health, battery, fileName)

		self.SetScale(0.7, 0.7)

	def __AppendText(self, text):

		self.toolTip.AppendTextLine(text)
		self.toolTip.ResizeToolTip()

		#x=self.GetWidth()/2
		#textLine = ui.TextLine()
		#textLine.SetParent(self)
		#textLine.SetSize(0, 0)
		#textLine.SetOutline()
		#textLine.Hide()
		#textLine.SetPosition(x, 40+len(self.textLineList)*16)
		#textLine.SetText(text)
		#self.textLineList.append(textLine)

	def OnMouseOverIn(self):
		#for textLine in self.textLineList:
		#	textLine.Show()

		self.toolTip.ShowToolTip()

	def OnMouseOverOut(self):
		#for textLine in self.textLineList:
		#	textLine.Hide()

		self.toolTip.HideToolTip()


# AUTO_POTION
class AutoPotionImage(ui.ExpandedImageBox):

	FILE_PATH_HP = "d:/ymir work/ui/pattern/auto_hpgauge/"
	FILE_PATH_SP = "d:/ymir work/ui/pattern/auto_spgauge/"

	def __init__(self):
		ui.ExpandedImageBox.__init__(self)

		self.loverName = ""
		self.lovePoint = 0
		self.potionType = player.AUTO_POTION_TYPE_HP
		self.filePath = ""

		self.toolTip = uiToolTip.ToolTip(100)
		self.toolTip.HideToolTip()

	def __del__(self):
		ui.ExpandedImageBox.__del__(self)

	def SetPotionType(self, type):
		self.potionType = type
		
		if player.AUTO_POTION_TYPE_HP == type:
			self.filePath = self.FILE_PATH_HP
		elif player.AUTO_POTION_TYPE_SP == type:
			self.filePath = self.FILE_PATH_SP
			

	def OnUpdateAutoPotionImage(self):
		self.__Refresh()

	def __Refresh(self):
		print "__Refresh"
	
		isActivated, currentAmount, totalAmount, slotIndex = player.GetAutoPotionInfo(self.potionType)
		
		amountPercent = (float(currentAmount) / totalAmount) * 100.0
		grade = math.ceil(amountPercent / 20)
		
		if 5.0 > amountPercent:
			grade = 0
			
		if 80.0 < amountPercent:
			grade = 4
			if 90.0 < amountPercent:
				grade = 5			

		fmt = self.filePath + "%.2d.dds"
		fileName = fmt % grade
		
		print self.potionType, amountPercent, fileName

		try:
			self.LoadImage(fileName)
		except:
			import dbg
			dbg.TraceError("AutoPotionImage.__Refresh(potionType=%d) - LoadError %s" % (self.potionType, fileName))

		self.SetScale(0.7, 0.7)

		self.toolTip.ClearToolTip()
		
		if player.AUTO_POTION_TYPE_HP == type:
			self.toolTip.SetTitle(localeInfo.TOOLTIP_AUTO_POTION_HP)
		else:
			self.toolTip.SetTitle(localeInfo.TOOLTIP_AUTO_POTION_SP)
			
		self.toolTip.AppendTextLine(localeInfo.TOOLTIP_AUTO_POTION_REST	% (amountPercent))
		self.toolTip.ResizeToolTip()

	def OnMouseOverIn(self):
		self.toolTip.ShowToolTip()

	def OnMouseOverOut(self):
		self.toolTip.HideToolTip()
# END_OF_AUTO_POTION


class AffectImage(ui.ExpandedImageBox):

	def __init__(self):
		ui.ExpandedImageBox.__init__(self)

		self.toolTipText = None
		self.isSkillAffect = TRUE
		self.description = None
		self.endTime = 0
		self.affect = None
		self.isClocked = TRUE

	def SetAffect(self, affect):
		self.affect = affect

	def GetAffect(self):
		return self.affect

	def SetToolTipText(self, text, x = 0, y = -19):

		if not self.toolTipText:
			textLine = ui.TextLine()
			textLine.SetParent(self)
			textLine.SetSize(0, 0)
			textLine.SetOutline()
			textLine.Hide()
			self.toolTipText = textLine
			
		self.toolTipText.SetText(text)
		w, h = self.toolTipText.GetTextSize()
		self.toolTipText.SetPosition(max(0, x + self.GetWidth()/2 - w/2), y)

	def SetDescription(self, description):
		self.description = description

	def SetDuration(self, duration):
		self.endTime = 0
		if duration > 0:
			self.endTime = app.GetGlobalTimeStamp() + duration

	def UpdateAutoPotionDescription(self):		
		
		potionType = 0
		if self.affect == chr.NEW_AFFECT_AUTO_HP_RECOVERY:
			potionType = player.AUTO_POTION_TYPE_HP
		else:
			potionType = player.AUTO_POTION_TYPE_SP	
		
		isActivated, currentAmount, totalAmount, slotIndex = player.GetAutoPotionInfo(potionType)
		
		#print "UpdateAutoPotionDescription ", isActivated, currentAmount, totalAmount, slotIndex
		
		amountPercent = 0.0
		
		try:
			amountPercent = (float(currentAmount) / totalAmount) * 100.0		
		except:
			amountPercent = 100.0
		
		self.SetToolTipText(self.description % amountPercent, 0, 40)
		
	def SetClock(self, isClocked):
		self.isClocked = isClocked
		
	def UpdateDescription(self):
		if not self.isClocked:
			self.__UpdateDescription2()
			return
	
		if not self.description:
			return
			
		toolTip = self.description
		if self.endTime > 0:
			leftTime = localeInfo.SecondToDHM(self.endTime - app.GetGlobalTimeStamp())
			toolTip += " (%s : %s)" % (localeInfo.LEFT_TIME, leftTime)
		self.SetToolTipText(toolTip, 0, 40)
		
	#µ¶ÀϹöÀü¿¡¼­ ½Ã°£À» Á¦°ÅÇϱâ À§Çؼ­ »ç¿ë 
	def __UpdateDescription2(self):
		if not self.description:
			return

		toolTip = self.description
		self.SetToolTipText(toolTip, 0, 40)

	def SetSkillAffectFlag(self, flag):
		self.isSkillAffect = flag

	def IsSkillAffect(self):
		return self.isSkillAffect

	def OnMouseOverIn(self):
		if self.toolTipText:
			self.toolTipText.Show()

	def OnMouseOverOut(self):
		if self.toolTipText:
			self.toolTipText.Hide()

class AffectShower(ui.Window):

	MALL_DESC_IDX_START = 1000
	IMAGE_STEP = 25
	AFFECT_MAX_NUM = 32

	INFINITE_AFFECT_DURATION = 0x1FFFFFFF 
	
	AFFECT_DATA_DICT =	{
			chr.AFFECT_ANTI_EXP : (localeInfo.ANTI_EXP, "d:/ymir work/effect/xp.dds"),
			chr.AFFECT_DUEL : (localeInfo.AFFECT_DUEL, "d:/ymir work/effect/pvp.dds"),
			chr.AFFECT_POTION_1 : (localeInfo.TOOLTIP_AFFECT_POTION_1, "d:/ymir work/effect/50821.dds"),
			chr.AFFECT_POTION_2 : (localeInfo.TOOLTIP_AFFECT_POTION_2, "d:/ymir work/effect/50822.dds"),
			chr.AFFECT_POTION_3 : (localeInfo.TOOLTIP_AFFECT_POTION_3, "d:/ymir work/effect/50823.dds"),
			chr.AFFECT_POTION_4 : (localeInfo.TOOLTIP_AFFECT_POTION_4, "d:/ymir work/effect/50824.dds"),
			chr.AFFECT_POTION_5 : (localeInfo.TOOLTIP_AFFECT_POTION_5, "d:/ymir work/effect/50825.dds"),
			chr.AFFECT_POTION_6 : (localeInfo.TOOLTIP_AFFECT_POTION_6, "d:/ymir work/effect/50826.dds"),
			chr.AFFECT_POISON : (localeInfo.SKILL_TOXICDIE, "d:/ymir work/ui/skill/common/affect/poison.sub"),
			chr.AFFECT_SLOW : (localeInfo.SKILL_SLOW, "d:/ymir work/ui/skill/common/affect/slow.sub"),
			chr.AFFECT_STUN : (localeInfo.SKILL_STUN, "d:/ymir work/ui/skill/common/affect/stun.sub"),

			chr.AFFECT_ATT_SPEED_POTION : (localeInfo.SKILL_INC_ATKSPD, "d:/ymir work/ui/skill/common/affect/Increase_Attack_Speed.sub"),
			chr.AFFECT_MOV_SPEED_POTION : (localeInfo.SKILL_INC_MOVSPD, "d:/ymir work/ui/skill/common/affect/Increase_Move_Speed.sub"),
			chr.AFFECT_FISH_MIND : (localeInfo.SKILL_FISHMIND, "d:/ymir work/ui/skill/common/affect/fishmind.sub"),

			chr.AFFECT_JEONGWI : (localeInfo.SKILL_JEONGWI, "d:/ymir work/ui/skill/warrior/jeongwi_03.sub",),
			chr.AFFECT_GEOMGYEONG : (localeInfo.SKILL_GEOMGYEONG, "d:/ymir work/ui/skill/warrior/geomgyeong_03.sub",),
			chr.AFFECT_CHEONGEUN : (localeInfo.SKILL_CHEONGEUN, "d:/ymir work/ui/skill/warrior/cheongeun_03.sub",),
			chr.AFFECT_GYEONGGONG : (localeInfo.SKILL_GYEONGGONG, "d:/ymir work/ui/skill/assassin/gyeonggong_03.sub",),
			chr.AFFECT_EUNHYEONG : (localeInfo.SKILL_EUNHYEONG, "d:/ymir work/ui/skill/assassin/eunhyeong_03.sub",),
			chr.AFFECT_GWIGEOM : (localeInfo.SKILL_GWIGEOM, "d:/ymir work/ui/skill/sura/gwigeom_03.sub",),
			chr.AFFECT_GONGPO : (localeInfo.SKILL_GONGPO, "d:/ymir work/ui/skill/sura/gongpo_03.sub",),
			chr.AFFECT_JUMAGAP : (localeInfo.SKILL_JUMAGAP, "d:/ymir work/ui/skill/sura/jumagap_03.sub"),
			chr.AFFECT_HOSIN : (localeInfo.SKILL_HOSIN, "d:/ymir work/ui/skill/shaman/hosin_03.sub",),
			chr.AFFECT_BOHO : (localeInfo.SKILL_BOHO, "d:/ymir work/ui/skill/shaman/boho_03.sub",),
			chr.AFFECT_KWAESOK : (localeInfo.SKILL_KWAESOK, "d:/ymir work/ui/skill/shaman/kwaesok_03.sub",),
			chr.AFFECT_HEUKSIN : (localeInfo.SKILL_HEUKSIN, "d:/ymir work/ui/skill/sura/heuksin_03.sub",),
			chr.AFFECT_MUYEONG : (localeInfo.SKILL_MUYEONG, "d:/ymir work/ui/skill/sura/muyeong_03.sub",),
			chr.AFFECT_GICHEON : (localeInfo.SKILL_GICHEON, "d:/ymir work/ui/skill/shaman/gicheon_03.sub",),
			chr.AFFECT_JEUNGRYEOK : (localeInfo.SKILL_JEUNGRYEOK, "d:/ymir work/ui/skill/shaman/jeungryeok_03.sub",),
			chr.AFFECT_PABEOP : (localeInfo.SKILL_PABEOP, "d:/ymir work/ui/skill/sura/pabeop_03.sub",),
			chr.AFFECT_FALLEN_CHEONGEUN : (localeInfo.SKILL_CHEONGEUN, "d:/ymir work/ui/skill/warrior/cheongeun_03.sub",),
			28 : (localeInfo.SKILL_FIRE, "d:/ymir work/ui/skill/sura/hwayeom_03.sub",),
			chr.AFFECT_CHINA_FIREWORK : (localeInfo.SKILL_POWERFUL_STRIKE, "d:/ymir work/ui/skill/common/affect/powerfulstrike.sub",),

			#64 - END
			chr.NEW_AFFECT_EXP_BONUS : (localeInfo.TOOLTIP_MALL_EXPBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/exp_bonus.sub",),

			chr.NEW_AFFECT_ITEM_BONUS : (localeInfo.TOOLTIP_MALL_ITEMBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/item_bonus.sub",),
			chr.NEW_AFFECT_SAFEBOX : (localeInfo.TOOLTIP_MALL_SAFEBOX, "d:/ymir work/ui/skill/common/affect/safebox.sub",),
			chr.NEW_AFFECT_AUTOLOOT : (localeInfo.TOOLTIP_MALL_AUTOLOOT, "d:/ymir work/ui/skill/common/affect/autoloot.sub",),
			chr.NEW_AFFECT_FISH_MIND : (localeInfo.TOOLTIP_MALL_FISH_MIND, "d:/ymir work/ui/skill/common/affect/fishmind.sub",),
			chr.NEW_AFFECT_MARRIAGE_FAST : (localeInfo.TOOLTIP_MALL_MARRIAGE_FAST, "d:/ymir work/ui/skill/common/affect/marriage_fast.sub",),
			chr.NEW_AFFECT_GOLD_BONUS : (localeInfo.TOOLTIP_MALL_GOLDBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/gold_bonus.sub",),

			chr.NEW_AFFECT_NO_DEATH_PENALTY : (localeInfo.TOOLTIP_APPLY_NO_DEATH_PENALTY, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),
			chr.NEW_AFFECT_SKILL_BOOK_BONUS : (localeInfo.TOOLTIP_APPLY_SKILL_BOOK_BONUS, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),
			chr.NEW_AFFECT_SKILL_BOOK_NO_DELAY : (localeInfo.TOOLTIP_APPLY_SKILL_BOOK_NO_DELAY, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),
			
			# ÀÚµ¿¹°¾à hp, sp
			chr.NEW_AFFECT_AUTO_HP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/pattern/auto_hpgauge/05.dds"),			
			chr.NEW_AFFECT_AUTO_SP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/pattern/auto_spgauge/05.dds"),
			#chr.NEW_AFFECT_AUTO_HP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),			
			#chr.NEW_AFFECT_AUTO_SP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/skill/common/affect/gold_bonus.sub"),			

			MALL_DESC_IDX_START+player.POINT_MALL_ATTBONUS : (localeInfo.TOOLTIP_MALL_ATTBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/att_bonus.sub",),
			MALL_DESC_IDX_START+player.POINT_MALL_DEFBONUS : (localeInfo.TOOLTIP_MALL_DEFBONUS_STATIC, "d:/ymir work/ui/skill/common/affect/def_bonus.sub",),
			MALL_DESC_IDX_START+player.POINT_MALL_EXPBONUS : (localeInfo.TOOLTIP_MALL_EXPBONUS, "d:/ymir work/ui/skill/common/affect/exp_bonus.sub",),
			MALL_DESC_IDX_START+player.POINT_MALL_ITEMBONUS : (localeInfo.TOOLTIP_MALL_ITEMBONUS, "d:/ymir work/ui/skill/common/affect/item_bonus.sub",),
			MALL_DESC_IDX_START+player.POINT_MALL_GOLDBONUS : (localeInfo.TOOLTIP_MALL_GOLDBONUS, "d:/ymir work/ui/skill/common/affect/gold_bonus.sub",),
			MALL_DESC_IDX_START+player.POINT_CRITICAL_PCT : (localeInfo.TOOLTIP_APPLY_CRITICAL_PCT,"d:/ymir work/ui/skill/common/affect/critical.sub"),
			MALL_DESC_IDX_START+player.POINT_PENETRATE_PCT : (localeInfo.TOOLTIP_APPLY_PENETRATE_PCT, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),
			MALL_DESC_IDX_START+player.POINT_MAX_HP_PCT : (localeInfo.TOOLTIP_MAX_HP_PCT, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),
			MALL_DESC_IDX_START+player.POINT_MAX_SP_PCT : (localeInfo.TOOLTIP_MAX_SP_PCT, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"),	

			MALL_DESC_IDX_START+player.POINT_PC_BANG_EXP_BONUS : (localeInfo.TOOLTIP_MALL_EXPBONUS_P_STATIC, "d:/ymir work/ui/skill/common/affect/EXP_Bonus_p_on.sub",),
			MALL_DESC_IDX_START+player.POINT_PC_BANG_DROP_BONUS: (localeInfo.TOOLTIP_MALL_ITEMBONUS_P_STATIC, "d:/ymir work/ui/skill/common/affect/Item_Bonus_p_on.sub",),
	}

	def __init__(self):
		ui.Window.__init__(self)

		self.serverPlayTime=0
		self.clientPlayTime=0
		
		self.lastUpdateTime=0
		self.affectImageDict={}
		self.horseImage=None
		self.lovePointImage=None
		self.autoPotionImageHP = AutoPotionImage()
		self.autoPotionImageSP = AutoPotionImage()
		self.SetPosition(10, 10)
		self.Show()

	def ClearAllAffects(self):
		self.horseImage=None
		self.lovePointImage=None
		self.affectImageDict={}
		self.__ArrangeImageList()

	def ClearAffects(self): ## ½ºÅ³ ÀÌÆåÆ®¸¸ ¾ø¾Û´Ï´Ù.
		self.living_affectImageDict={}
		for key, image in self.affectImageDict.items():
			if not image.IsSkillAffect():
				self.living_affectImageDict[key] = image
		self.affectImageDict = self.living_affectImageDict
		self.__ArrangeImageList()

	def BINARY_NEW_AddAffect(self, type, pointIdx, value, duration):

		print "BINARY_NEW_AddAffect", type, pointIdx, value, duration

		if type < 500:
			return

		if type == chr.NEW_AFFECT_MALL:
			affect = self.MALL_DESC_IDX_START + pointIdx
		else:
			affect = type

		if self.affectImageDict.has_key(affect):
			return

		if not self.AFFECT_DATA_DICT.has_key(affect):
			return

		## ¿ë½ÅÀÇ °¡È£, ¼±ÀÎÀÇ ±³ÈÆÀº Duration À» 0 À¸·Î ¼³Á¤ÇÑ´Ù.
		if affect == chr.NEW_AFFECT_NO_DEATH_PENALTY or\
		   affect == chr.NEW_AFFECT_SKILL_BOOK_BONUS or\
		   affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY or\
		   affect == chr.NEW_AFFECT_AUTO_HP_RECOVERY or\
		   affect == chr.NEW_AFFECT_SKILL_BOOK_NO_DELAY:
			duration = 0

		affectData = self.AFFECT_DATA_DICT[affect]
		description = affectData[0]
		filename = affectData[1]

		if pointIdx == player.POINT_MALL_ITEMBONUS or\
		   pointIdx == player.POINT_MALL_GOLDBONUS:
			value = 1 + float(value) / 100.0

		trashValue = 123
		#if affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY or affect == chr.NEW_AFFECT_AUTO_HP_RECOVERY:
		if trashValue == 1:
			try:
				#image = AutoPotionImage()
				#image.SetParent(self)
				image = None
				
				if affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY:
					image.SetPotionType(player.AUTO_POTION_TYPE_SP)
					image = self.autoPotionImageSP
					#self.autoPotionImageSP = image;
				else:
					image.SetPotionType(player.AUTO_POTION_TYPE_HP)
					image = self.autoPotionImageHP
					#self.autoPotionImageHP = image;
					
				image.SetParent(self)
				image.Show()
				image.OnUpdateAutoPotionImage()
				
				self.affectImageDict[affect] = image
				self.__ArrangeImageList()
				
			except Exception, e:
				print "except Aff auto potion affect ", e
				pass				
			
		else:
			if affect != chr.NEW_AFFECT_AUTO_SP_RECOVERY and affect != chr.NEW_AFFECT_AUTO_HP_RECOVERY:
				description = description(float(value))

			try:
				print "Add affect %s" % affect
				image = AffectImage()
				image.SetParent(self)
				image.LoadImage(filename)
				image.SetDescription(description)
				image.SetDuration(duration)
				image.SetAffect(affect)
				if affect == chr.NEW_AFFECT_EXP_BONUS_EURO_FREE or\
					affect == chr.NEW_AFFECT_EXP_BONUS_EURO_FREE_UNDER_15 or\
					self.INFINITE_AFFECT_DURATION < duration:
					image.SetClock(FALSE)
					image.UpdateDescription()
				elif affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY or affect == chr.NEW_AFFECT_AUTO_HP_RECOVERY:
					image.UpdateAutoPotionDescription()
				else:
					image.UpdateDescription()
					
				if affect == chr.NEW_AFFECT_DRAGON_SOUL_DECK1 or affect == chr.NEW_AFFECT_DRAGON_SOUL_DECK2:
					image.SetScale(1, 1)
				else:
					image.SetScale(0.7, 0.7)
				image.SetSkillAffectFlag(FALSE)
				image.Show()
				self.affectImageDict[affect] = image
				self.__ArrangeImageList()
			except Exception, e:
				print "except Aff affect ", e
				pass

	def BINARY_NEW_RemoveAffect(self, type, pointIdx):
		if type == chr.NEW_AFFECT_MALL:
			affect = self.MALL_DESC_IDX_START + pointIdx
		else:
			affect = type
	
		print "Remove Affect %s %s" % ( type , pointIdx )
		self.__RemoveAffect(affect)
		self.__ArrangeImageList()

	def SetAffect(self, affect):
		self.__AppendAffect(affect)
		self.__ArrangeImageList()

	def ResetAffect(self, affect):
		self.__RemoveAffect(affect)
		self.__ArrangeImageList()

	def SetLoverInfo(self, name, lovePoint):
		image = LovePointImage()
		image.SetParent(self)
		image.SetLoverInfo(name, lovePoint)
		self.lovePointImage = image
		self.__ArrangeImageList()

	def ShowLoverState(self):
		if self.lovePointImage:
			self.lovePointImage.Show()
			self.__ArrangeImageList()

	def HideLoverState(self):
		if self.lovePointImage:
			self.lovePointImage.Hide()
			self.__ArrangeImageList()

	def ClearLoverState(self):
		self.lovePointImage = None
		self.__ArrangeImageList()

	def OnUpdateLovePoint(self, lovePoint):
		if self.lovePointImage:
			self.lovePointImage.OnUpdateLovePoint(lovePoint)

	def SetHorseState(self, level, health, battery):
		if level==0:
			self.horseImage=None
		else:
			image = HorseImage()
			image.SetParent(self)
			image.SetState(level, health, battery)
			image.Show()

			self.horseImage=image
			self.__ArrangeImageList()

	def SetPlayTime(self, playTime):
		self.serverPlayTime = playTime
		self.clientPlayTime = app.GetTime()
		
		if localeInfo.IsVIETNAM():		
			image = PlayTimeImage()
			image.SetParent(self)
			image.SetPlayTime(playTime)
			image.Show()

			self.playTimeImage=image
			self.__ArrangeImageList()

	def __AppendAffect(self, affect):

		if self.affectImageDict.has_key(affect):
			return

		try:
			affectData = self.AFFECT_DATA_DICT[affect]
		except KeyError:
			return

		name = affectData[0]
		filename = affectData[1]

		skillIndex = player.AffectIndexToSkillIndex(affect)
		if 0 != skillIndex:
			name = skill.GetSkillName(skillIndex)

		image = AffectImage()
		image.SetParent(self)
		image.SetSkillAffectFlag(TRUE)

		try:
			image.LoadImage(filename)
		except:
			pass

		image.SetToolTipText(name, 0, 40)
		image.SetScale(0.7, 0.7)
		image.Show()
		self.affectImageDict[affect] = image

	def __RemoveAffect(self, affect):
		"""
		if affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY:
			self.autoPotionImageSP.Hide()

		if affect == chr.NEW_AFFECT_AUTO_HP_RECOVERY:
			self.autoPotionImageHP.Hide()
		"""
			
		if not self.affectImageDict.has_key(affect):
			print "__RemoveAffect %s ( No Affect )" % affect
			return

		print "__RemoveAffect %s ( Affect )" % affect
		del self.affectImageDict[affect]
		
		self.__ArrangeImageList()

	def __ArrangeImageList(self):

		width = len(self.affectImageDict) * self.IMAGE_STEP
		if self.lovePointImage:
			width+=self.IMAGE_STEP
		if self.horseImage:
			width+=self.IMAGE_STEP

		self.SetSize(width, 26)

		xPos = 0

		if self.lovePointImage:
			if self.lovePointImage.IsShow():
				self.lovePointImage.SetPosition(xPos, 0)
				xPos += self.IMAGE_STEP

		if self.horseImage:
			self.horseImage.SetPosition(xPos, 0)
			xPos += self.IMAGE_STEP

		for image in self.affectImageDict.values():
			image.SetPosition(xPos, 0)
			xPos += self.IMAGE_STEP

	def OnUpdate(self):		
		try:
			if app.GetGlobalTime() - self.lastUpdateTime > 500:
			#if 0 < app.GetGlobalTime():
				self.lastUpdateTime = app.GetGlobalTime()

				for image in self.affectImageDict.values():
					if image.GetAffect() == chr.NEW_AFFECT_AUTO_HP_RECOVERY or image.GetAffect() == chr.NEW_AFFECT_AUTO_SP_RECOVERY:
						image.UpdateAutoPotionDescription()
						continue
						
					if not image.IsSkillAffect():
						image.UpdateDescription()
		except Exception, e:
			print "AffectShower::OnUpdate error : ", e

 

Im 1 step close to fix it but i dont get the error -.-

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

2 hours ago, zeimpekis9 said:

Hi thanks for trying to help me but i get this error:

0813 12:43:12550 :: Traceback (most recent call last):

0813 12:43:12550 ::   File "game.py", line 1826, in BINARY_Cube_ResultList

0813 12:43:12552 :: ValueError
0813 12:43:12552 :: : 
0813 12:43:12552 :: invalid literal for int() with base 10: ''
0813 12:43:12553 :: 

And in game.py line 1826 is this

Spoiler

c90f08c0285e97c4536a344b0a6457d0.png

Hope we can fix this together cheers mate <3.

My game.py full

https://pastebin.com/cV9KGYpf

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

  • 5 months later...
  • 2 months later...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.