text encoding fixed
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
#ifndef __HEADER_VNUM_HELPER__
|
||||
#ifndef __HEADER_VNUM_HELPER__
|
||||
#define __HEADER_VNUM_HELPER__
|
||||
|
||||
/**
|
||||
이미 존재하거나 앞으로 추가될 아이템, 몹 등을 소스에서 식별할 때 현재는 모두
|
||||
식별자(숫자=VNum)를 하드코딩하는 방식으로 되어있어서 가독성이 매우 떨어지는데
|
||||
이미 존재하거나 앞으로 추가될 아이템, 몹 등을 소스에서 식별할 때 현재는 모두
|
||||
식별자(숫자=VNum)를 하드코딩하는 방식으로 되어있어서 가독성이 매우 떨어지는데
|
||||
|
||||
앞으로는 소스만 봐도 어떤 아이템(혹은 몹)인지 알 수 있게 하자는 승철님의 제안으로 추가.
|
||||
앞으로는 소스만 봐도 어떤 아이템(혹은 몹)인지 알 수 있게 하자는 승철님의 제안으로 추가.
|
||||
|
||||
* 이 파일은 변경이 잦을것으로 예상되는데 PCH에 넣으면 바뀔 때마다 전체 컴파일 해야하니
|
||||
일단은 필요한 cpp파일에서 include 해서 쓰도록 했음.
|
||||
* 이 파일은 변경이 잦을것으로 예상되는데 PCH에 넣으면 바뀔 때마다 전체 컴파일 해야하니
|
||||
일단은 필요한 cpp파일에서 include 해서 쓰도록 했음.
|
||||
|
||||
* cpp에서 구현하면 컴파일 ~ 링크해야하니 그냥 common에 헤더만 넣었음. (game, db프로젝트 둘 다 사용 예정)
|
||||
* cpp에서 구현하면 컴파일 ~ 링크해야하니 그냥 common에 헤더만 넣었음. (game, db프로젝트 둘 다 사용 예정)
|
||||
|
||||
@date 2011. 8. 29.
|
||||
*/
|
||||
@@ -19,35 +19,35 @@
|
||||
class CItemVnumHelper
|
||||
{
|
||||
public:
|
||||
/// 독일 DVD용 불사조 소환권
|
||||
static const bool IsPhoenix(DWORD vnum) { return 53001 == vnum; } // NOTE: 불사조 소환 아이템은 53001 이지만 mob-vnum은 34001 입니다.
|
||||
/// 독일 DVD용 불사조 소환권
|
||||
static const bool IsPhoenix(DWORD vnum) { return 53001 == vnum; } // NOTE: 불사조 소환 아이템은 53001 이지만 mob-vnum은 34001 입니다.
|
||||
|
||||
/// 라마단 이벤트 초승달의 반지 (원래는 라마단 이벤트용 특수 아이템이었으나 앞으로 여러 방향으로 재활용해서 계속 쓴다고 함)
|
||||
/// 라마단 이벤트 초승달의 반지 (원래는 라마단 이벤트용 특수 아이템이었으나 앞으로 여러 방향으로 재활용해서 계속 쓴다고 함)
|
||||
static const bool IsRamadanMoonRing(DWORD vnum) { return 71135 == vnum; }
|
||||
|
||||
/// 할로윈 사탕 (스펙은 초승달의 반지와 동일)
|
||||
/// 할로윈 사탕 (스펙은 초승달의 반지와 동일)
|
||||
static const bool IsHalloweenCandy(DWORD vnum) { return 71136 == vnum; }
|
||||
|
||||
/// 크리스마스 행복의 반지
|
||||
/// 크리스마스 행복의 반지
|
||||
static const bool IsHappinessRing(DWORD vnum) { return 71143 == vnum; }
|
||||
|
||||
/// 발렌타인 사랑의 팬던트
|
||||
/// 발렌타인 사랑의 팬던트
|
||||
static const bool IsLovePendant(DWORD vnum) { return 71145 == vnum; }
|
||||
};
|
||||
|
||||
class CMobVnumHelper
|
||||
{
|
||||
public:
|
||||
/// 독일 DVD용 불사조 몹 번호
|
||||
/// 독일 DVD용 불사조 몹 번호
|
||||
static bool IsPhoenix(DWORD vnum) { return 34001 == vnum; }
|
||||
static bool IsIcePhoenix(DWORD vnum) { return 34003 == vnum; }
|
||||
/// PetSystem이 관리하는 펫인가?
|
||||
/// PetSystem이 관리하는 펫인가?
|
||||
static bool IsPetUsingPetSystem(DWORD vnum) { return (IsPhoenix(vnum) || IsReindeerYoung(vnum)) || IsIcePhoenix(vnum); }
|
||||
|
||||
/// 2011년 크리스마스 이벤트용 펫 (아기 순록)
|
||||
/// 2011년 크리스마스 이벤트용 펫 (아기 순록)
|
||||
static bool IsReindeerYoung(DWORD vnum) { return 34002 == vnum; }
|
||||
|
||||
/// 라마단 이벤트 보상용 흑마(20119) .. 할로윈 이벤트용 라마단 흑마 클론(스펙은 같음, 20219)
|
||||
/// 라마단 이벤트 보상용 흑마(20119) .. 할로윈 이벤트용 라마단 흑마 클론(스펙은 같음, 20219)
|
||||
static bool IsRamadanBlackHorse(DWORD vnum) { return 20119 == vnum || 20219 == vnum || 22022 == vnum; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_AUCTION_TABLES_H__
|
||||
#ifndef __INC_AUCTION_TABLES_H__
|
||||
#define __INC_AUCTION_TABLES_H__
|
||||
|
||||
#include "tables.h"
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
int get_price () { return offer_price; }
|
||||
} TAuctionSimpleItemInfo;
|
||||
|
||||
// 각 auction 정보들.
|
||||
// 각 auction 정보들.
|
||||
// primary key (item_id)
|
||||
typedef struct _auction : public _base_auction
|
||||
{
|
||||
@@ -49,8 +49,8 @@ public:
|
||||
empire = _empire;
|
||||
}
|
||||
|
||||
// 이 메소드들은 어떤 변수가 auction에서 어떤 역할을 하는지 까먹을 까봐
|
||||
// 만들어놓았다.
|
||||
// 이 메소드들은 어떤 변수가 auction에서 어떤 역할을 하는지 까먹을 까봐
|
||||
// 만들어놓았다.
|
||||
// by rtsummit
|
||||
DWORD get_item_id () { return item_id; }
|
||||
DWORD get_bidder_id () { return bidder_id; }
|
||||
@@ -89,7 +89,7 @@ typedef struct _sale : public _base_auction
|
||||
|
||||
} TSaleItemInfo;
|
||||
|
||||
// wish는 실제하는 아이템은 없다.
|
||||
// wish는 실제하는 아이템은 없다.
|
||||
// primary key (item_num, wisher_id)
|
||||
typedef struct _wish : public _base_auction
|
||||
{
|
||||
@@ -118,9 +118,9 @@ enum AuctionCmd {OPEN_AUCTION, OPEN_WISH_AUCTION, OPEN_MY_AUCTION, OPEN_MY_WISH_
|
||||
AUCTION_REBID, AUCTION_BID_CANCEL,
|
||||
};
|
||||
|
||||
// 반드시 FAIL 앞에, 실패 류 들이 와야한다.
|
||||
// 왜냐, <= AUCTION_FAIL 이런 CHECK을 할 거거든
|
||||
// 반대로 SUCCESS 뒤에, 성공 류 들이 와야한다. 근데 성공류가 있긴 하려나...
|
||||
// 반드시 FAIL 앞에, 실패 류 들이 와야한다.
|
||||
// 왜냐, <= AUCTION_FAIL 이런 CHECK을 할 거거든
|
||||
// 반대로 SUCCESS 뒤에, 성공 류 들이 와야한다. 근데 성공류가 있긴 하려나...
|
||||
|
||||
enum AuctionResult { AUCTION_EXPIRED, AUCTION_NOT_EXPIRED, AUCTION_NOT_ENOUGH_MONEY,
|
||||
AUCTION_SOLD, AUCTION_CANCEL, AUCTION_ALREADY_IN, AUCTION_NOT_IN, AUCTION_FAIL, AUCTION_SUCCESS };
|
||||
@@ -218,7 +218,7 @@ typedef struct command_auction
|
||||
cmd = AUCTION_CHANGING_MONEY;
|
||||
price1 = _money;
|
||||
}
|
||||
// bid랑 cmd만 다르다.
|
||||
// bid랑 cmd만 다르다.
|
||||
void rebid (DWORD _item_id, int _bidPrice)
|
||||
{
|
||||
cmd = AUCTION_REBID;
|
||||
@@ -322,7 +322,7 @@ typedef struct auction_impur : public command_auction
|
||||
// auction_type;
|
||||
// start_idx;
|
||||
// size;
|
||||
// conditions; 정렬은 승철님께 조언을 구해보자.ㅇㅇ
|
||||
// conditions; 정렬은 승철님께 조언을 구해보자.ㅇㅇ
|
||||
//}
|
||||
//
|
||||
//get_auction_detail_item_info
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_COMMON_BILLING_H__
|
||||
#ifndef __INC_METIN_II_COMMON_BILLING_H__
|
||||
#define __INC_METIN_II_COMMON_BILLING_H__
|
||||
|
||||
enum EBillingTypes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __METIN_II_COMMON_BUILDING_H__
|
||||
#ifndef __METIN_II_COMMON_BUILDING_H__
|
||||
#define __METIN_II_COMMON_BUILDING_H__
|
||||
|
||||
namespace building
|
||||
@@ -41,8 +41,8 @@ namespace building
|
||||
long lNPCX;
|
||||
long lNPCY;
|
||||
|
||||
DWORD dwGroupVnum; // 같은 그룹은 하나만 건설가능
|
||||
DWORD dwDependOnGroupVnum; // 지어져 있어야하는 그룹
|
||||
DWORD dwGroupVnum; // 같은 그룹은 하나만 건설가능
|
||||
DWORD dwDependOnGroupVnum; // 지어져 있어야하는 그룹
|
||||
} TObjectProto;
|
||||
|
||||
typedef struct SObject
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_COMMON_CACHE_H__
|
||||
#ifndef __INC_COMMON_CACHE_H__
|
||||
#define __INC_COMMON_CACHE_H__
|
||||
|
||||
template <typename T> class cache
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_D3DTYPE_H__
|
||||
#ifndef __INC_METIN_II_D3DTYPE_H__
|
||||
#define __INC_METIN_II_D3DTYPE_H__
|
||||
|
||||
typedef struct D3DXVECTOR2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN2_ITEM_LENGTH_H__
|
||||
#ifndef __INC_METIN2_ITEM_LENGTH_H__
|
||||
#define __INC_METIN2_ITEM_LENGTH_H__
|
||||
|
||||
enum EItemMisc
|
||||
@@ -31,8 +31,8 @@ enum EItemDragonSoulSockets
|
||||
ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX = 2,
|
||||
ITEM_SOCKET_CHARGING_AMOUNT_IDX = 2,
|
||||
};
|
||||
// 헐 이거 미친거 아니야?
|
||||
// 나중에 소켓 확장하면 어쩌려고 이지랄 -_-;;;
|
||||
// 헐 이거 미친거 아니야?
|
||||
// 나중에 소켓 확장하면 어쩌려고 이지랄 -_-;;;
|
||||
enum EItemUniqueSockets
|
||||
{
|
||||
ITEM_SOCKET_UNIQUE_SAVE_TIME = ITEM_SOCKET_MAX_NUM - 2,
|
||||
@@ -42,18 +42,18 @@ enum EItemUniqueSockets
|
||||
enum EItemTypes
|
||||
{
|
||||
ITEM_NONE, //0
|
||||
ITEM_WEAPON, //1//무기
|
||||
ITEM_ARMOR, //2//갑옷
|
||||
ITEM_USE, //3//아이템 사용
|
||||
ITEM_WEAPON, //1//무기
|
||||
ITEM_ARMOR, //2//갑옷
|
||||
ITEM_USE, //3//아이템 사용
|
||||
ITEM_AUTOUSE, //4
|
||||
ITEM_MATERIAL, //5
|
||||
ITEM_SPECIAL, //6 //스페셜 아이템
|
||||
ITEM_SPECIAL, //6 //스페셜 아이템
|
||||
ITEM_TOOL, //7
|
||||
ITEM_LOTTERY, //8//복권
|
||||
ITEM_ELK, //9//돈
|
||||
ITEM_LOTTERY, //8//복권
|
||||
ITEM_ELK, //9//돈
|
||||
ITEM_METIN, //10
|
||||
ITEM_CONTAINER, //11
|
||||
ITEM_FISH, //12//낚시
|
||||
ITEM_FISH, //12//낚시
|
||||
ITEM_ROD, //13
|
||||
ITEM_RESOURCE, //14
|
||||
ITEM_CAMPFIRE, //15
|
||||
@@ -61,21 +61,21 @@ enum EItemTypes
|
||||
ITEM_SKILLBOOK, //17
|
||||
ITEM_QUEST, //18
|
||||
ITEM_POLYMORPH, //19
|
||||
ITEM_TREASURE_BOX, //20//보물상자
|
||||
ITEM_TREASURE_KEY, //21//보물상자 열쇠
|
||||
ITEM_TREASURE_BOX, //20//보물상자
|
||||
ITEM_TREASURE_KEY, //21//보물상자 열쇠
|
||||
ITEM_SKILLFORGET, //22
|
||||
ITEM_GIFTBOX, //23
|
||||
ITEM_PICK, //24
|
||||
ITEM_HAIR, //25//머리
|
||||
ITEM_TOTEM, //26//토템
|
||||
ITEM_BLEND, //27//생성될때 랜덤하게 속성이 붙는 약물
|
||||
ITEM_COSTUME, //28//코스츔 아이템 (2011년 8월 추가된 코스츔 시스템용 아이템)
|
||||
ITEM_DS, //29 //용혼석
|
||||
ITEM_SPECIAL_DS, //30 // 특수한 용혼석 (DS_SLOT에 착용하는 UNIQUE 아이템이라 생각하면 됨)
|
||||
ITEM_EXTRACT, //31 추출도구.
|
||||
ITEM_SECONDARY_COIN, //32 ?? 명도전??
|
||||
ITEM_RING, //33 반지
|
||||
ITEM_BELT, //34 벨트
|
||||
ITEM_HAIR, //25//머리
|
||||
ITEM_TOTEM, //26//토템
|
||||
ITEM_BLEND, //27//생성될때 랜덤하게 속성이 붙는 약물
|
||||
ITEM_COSTUME, //28//코스츔 아이템 (2011년 8월 추가된 코스츔 시스템용 아이템)
|
||||
ITEM_DS, //29 //용혼석
|
||||
ITEM_SPECIAL_DS, //30 // 특수한 용혼석 (DS_SLOT에 착용하는 UNIQUE 아이템이라 생각하면 됨)
|
||||
ITEM_EXTRACT, //31 추출도구.
|
||||
ITEM_SECONDARY_COIN, //32 ?? 명도전??
|
||||
ITEM_RING, //33 반지
|
||||
ITEM_BELT, //34 벨트
|
||||
};
|
||||
|
||||
enum EMetinSubTypes
|
||||
@@ -111,8 +111,8 @@ enum EArmorSubTypes
|
||||
|
||||
enum ECostumeSubTypes
|
||||
{
|
||||
COSTUME_BODY = ARMOR_BODY, // [중요!!] ECostumeSubTypes enum value는 종류별로 EArmorSubTypes의 그것과 같아야 함.
|
||||
COSTUME_HAIR = ARMOR_HEAD, // 이는 코스츔 아이템에 추가 속성을 붙이겠다는 사업부의 요청에 따라서 기존 로직을 활용하기 위함임.
|
||||
COSTUME_BODY = ARMOR_BODY, // [중요!!] ECostumeSubTypes enum value는 종류별로 EArmorSubTypes의 그것과 같아야 함.
|
||||
COSTUME_HAIR = ARMOR_HEAD, // 이는 코스츔 아이템에 추가 속성을 붙이겠다는 사업부의 요청에 따라서 기존 로직을 활용하기 위함임.
|
||||
COSTUME_NUM_TYPES,
|
||||
};
|
||||
|
||||
@@ -215,8 +215,8 @@ enum EUseSubTypes
|
||||
USE_UNBIND,
|
||||
USE_TIME_CHARGE_PER,
|
||||
USE_TIME_CHARGE_FIX, // 28
|
||||
USE_PUT_INTO_BELT_SOCKET, // 29 벨트 소켓에 사용할 수 있는 아이템
|
||||
USE_PUT_INTO_RING_SOCKET, // 30 반지 소켓에 사용할 수 있는 아이템 (유니크 반지 말고, 새로 추가된 반지 슬롯)
|
||||
USE_PUT_INTO_BELT_SOCKET, // 29 벨트 소켓에 사용할 수 있는 아이템
|
||||
USE_PUT_INTO_RING_SOCKET, // 30 반지 소켓에 사용할 수 있는 아이템 (유니크 반지 말고, 새로 추가된 반지 슬롯)
|
||||
};
|
||||
|
||||
enum EExtractSubTypes
|
||||
@@ -270,7 +270,7 @@ enum EItemFlag
|
||||
{
|
||||
ITEM_FLAG_REFINEABLE = (1 << 0),
|
||||
ITEM_FLAG_SAVE = (1 << 1),
|
||||
ITEM_FLAG_STACKABLE = (1 << 2), // 여러개 합칠 수 있음
|
||||
ITEM_FLAG_STACKABLE = (1 << 2), // 여러개 합칠 수 있음
|
||||
ITEM_FLAG_COUNT_PER_1GOLD = (1 << 3),
|
||||
ITEM_FLAG_SLOW_QUERY = (1 << 4),
|
||||
ITEM_FLAG_UNUSED01 = (1 << 5), // UNUSED
|
||||
@@ -287,24 +287,24 @@ enum EItemFlag
|
||||
|
||||
enum EItemAntiFlag
|
||||
{
|
||||
ITEM_ANTIFLAG_FEMALE = (1 << 0), // 여성 사용 불가
|
||||
ITEM_ANTIFLAG_MALE = (1 << 1), // 남성 사용 불가
|
||||
ITEM_ANTIFLAG_WARRIOR = (1 << 2), // 무사 사용 불가
|
||||
ITEM_ANTIFLAG_ASSASSIN = (1 << 3), // 자객 사용 불가
|
||||
ITEM_ANTIFLAG_SURA = (1 << 4), // 수라 사용 불가
|
||||
ITEM_ANTIFLAG_SHAMAN = (1 << 5), // 무당 사용 불가
|
||||
ITEM_ANTIFLAG_GET = (1 << 6), // 집을 수 없음
|
||||
ITEM_ANTIFLAG_DROP = (1 << 7), // 버릴 수 없음
|
||||
ITEM_ANTIFLAG_SELL = (1 << 8), // 팔 수 없음
|
||||
ITEM_ANTIFLAG_EMPIRE_A = (1 << 9), // A 제국 사용 불가
|
||||
ITEM_ANTIFLAG_EMPIRE_B = (1 << 10), // B 제국 사용 불가
|
||||
ITEM_ANTIFLAG_EMPIRE_C = (1 << 11), // C 제국 사용 불가
|
||||
ITEM_ANTIFLAG_SAVE = (1 << 12), // 저장되지 않음
|
||||
ITEM_ANTIFLAG_GIVE = (1 << 13), // 거래 불가
|
||||
ITEM_ANTIFLAG_PKDROP = (1 << 14), // PK시 떨어지지 않음
|
||||
ITEM_ANTIFLAG_STACK = (1 << 15), // 합칠 수 없음
|
||||
ITEM_ANTIFLAG_MYSHOP = (1 << 16), // 개인 상점에 올릴 수 없음
|
||||
ITEM_ANTIFLAG_SAFEBOX = (1 << 17), // 창고에 넣을 수 없음
|
||||
ITEM_ANTIFLAG_FEMALE = (1 << 0), // 여성 사용 불가
|
||||
ITEM_ANTIFLAG_MALE = (1 << 1), // 남성 사용 불가
|
||||
ITEM_ANTIFLAG_WARRIOR = (1 << 2), // 무사 사용 불가
|
||||
ITEM_ANTIFLAG_ASSASSIN = (1 << 3), // 자객 사용 불가
|
||||
ITEM_ANTIFLAG_SURA = (1 << 4), // 수라 사용 불가
|
||||
ITEM_ANTIFLAG_SHAMAN = (1 << 5), // 무당 사용 불가
|
||||
ITEM_ANTIFLAG_GET = (1 << 6), // 집을 수 없음
|
||||
ITEM_ANTIFLAG_DROP = (1 << 7), // 버릴 수 없음
|
||||
ITEM_ANTIFLAG_SELL = (1 << 8), // 팔 수 없음
|
||||
ITEM_ANTIFLAG_EMPIRE_A = (1 << 9), // A 제국 사용 불가
|
||||
ITEM_ANTIFLAG_EMPIRE_B = (1 << 10), // B 제국 사용 불가
|
||||
ITEM_ANTIFLAG_EMPIRE_C = (1 << 11), // C 제국 사용 불가
|
||||
ITEM_ANTIFLAG_SAVE = (1 << 12), // 저장되지 않음
|
||||
ITEM_ANTIFLAG_GIVE = (1 << 13), // 거래 불가
|
||||
ITEM_ANTIFLAG_PKDROP = (1 << 14), // PK시 떨어지지 않음
|
||||
ITEM_ANTIFLAG_STACK = (1 << 15), // 합칠 수 없음
|
||||
ITEM_ANTIFLAG_MYSHOP = (1 << 16), // 개인 상점에 올릴 수 없음
|
||||
ITEM_ANTIFLAG_SAFEBOX = (1 << 17), // 창고에 넣을 수 없음
|
||||
};
|
||||
|
||||
enum EItemWearableFlag
|
||||
@@ -335,16 +335,16 @@ enum ELimitTypes
|
||||
LIMIT_CON,
|
||||
LIMIT_PCBANG,
|
||||
|
||||
/// 착용 여부와 상관 없이 실시간으로 시간 차감 (socket0에 소멸 시간이 박힘: unix_timestamp 타입)
|
||||
/// 착용 여부와 상관 없이 실시간으로 시간 차감 (socket0에 소멸 시간이 박힘: unix_timestamp 타입)
|
||||
LIMIT_REAL_TIME,
|
||||
|
||||
/// 아이템을 맨 처음 사용(혹은 착용) 한 순간부터 리얼타임 타이머 시작
|
||||
/// 최초 사용 전에는 socket0에 사용가능시간(초단위, 0이면 프로토의 limit value값 사용) 값이 쓰여있다가
|
||||
/// 아이템 사용시 socket1에 사용 횟수가 박히고 socket0에 unix_timestamp 타입의 소멸시간이 박힘.
|
||||
/// 아이템을 맨 처음 사용(혹은 착용) 한 순간부터 리얼타임 타이머 시작
|
||||
/// 최초 사용 전에는 socket0에 사용가능시간(초단위, 0이면 프로토의 limit value값 사용) 값이 쓰여있다가
|
||||
/// 아이템 사용시 socket1에 사용 횟수가 박히고 socket0에 unix_timestamp 타입의 소멸시간이 박힘.
|
||||
LIMIT_REAL_TIME_START_FIRST_USE,
|
||||
|
||||
/// 아이템을 착용 중일 때만 사용 시간이 차감되는 아이템
|
||||
/// socket0에 남은 시간이 초단위로 박힘. (아이템 최초 사용시 해당 값이 0이면 프로토의 limit value값을 socket0에 복사)
|
||||
/// 아이템을 착용 중일 때만 사용 시간이 차감되는 아이템
|
||||
/// socket0에 남은 시간이 초단위로 박힘. (아이템 최초 사용시 해당 값이 0이면 프로토의 limit value값을 socket0에 복사)
|
||||
LIMIT_TIMER_BASED_ON_WEAR,
|
||||
|
||||
LIMIT_MAX_NUM
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_LENGTH_H__
|
||||
#ifndef __INC_METIN_II_LENGTH_H__
|
||||
#define __INC_METIN_II_LENGTH_H__
|
||||
|
||||
#define WORD_MAX 0xffff
|
||||
@@ -22,10 +22,10 @@ enum EMisc
|
||||
|
||||
GUILD_NAME_MAX_LEN = 12,
|
||||
|
||||
SHOP_HOST_ITEM_MAX_NUM = 40, /* 호스트의 최대 아이템 개수 */
|
||||
SHOP_GUEST_ITEM_MAX_NUM = 18, /* 게스트의 최대 아이템 개수 */
|
||||
SHOP_HOST_ITEM_MAX_NUM = 40, /* 호스트의 최대 아이템 개수 */
|
||||
SHOP_GUEST_ITEM_MAX_NUM = 18, /* 게스트의 최대 아이템 개수 */
|
||||
|
||||
SHOP_PRICELIST_MAX_NUM = 40, ///< 개인상점 가격정보 리스트에서 유지할 가격정보의 최대 갯수
|
||||
SHOP_PRICELIST_MAX_NUM = 40, ///< 개인상점 가격정보 리스트에서 유지할 가격정보의 최대 갯수
|
||||
|
||||
CHAT_MAX_LEN = 512,
|
||||
|
||||
@@ -84,19 +84,19 @@ enum EMisc
|
||||
|
||||
|
||||
/**
|
||||
**** 현재까지 할당 된 아이템 영역 정리 (DB상 Item Position) ****
|
||||
**** 현재까지 할당 된 아이템 영역 정리 (DB상 Item Position) ****
|
||||
+------------------------------------------------------+ 0
|
||||
| 캐릭터 기본 인벤토리 (45칸 * 2페이지) 90칸 |
|
||||
| 캐릭터 기본 인벤토리 (45칸 * 2페이지) 90칸 |
|
||||
+------------------------------------------------------+ 90 = INVENTORY_MAX_NUM(90)
|
||||
| 캐릭터 장비 창 (착용중인 아이템) 32칸 |
|
||||
| 캐릭터 장비 창 (착용중인 아이템) 32칸 |
|
||||
+------------------------------------------------------+ 122 = INVENTORY_MAX_NUM(90) + WEAR_MAX_NUM(32)
|
||||
| 용혼석 장비 창 (착용중인 용혼석) 12칸 |
|
||||
| 용혼석 장비 창 (착용중인 용혼석) 12칸 |
|
||||
+------------------------------------------------------+ 134 = 122 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_MAX_NUM(2)
|
||||
| 용혼석 장비 창 예약 (아직 미사용) 18칸 |
|
||||
| 용혼석 장비 창 예약 (아직 미사용) 18칸 |
|
||||
+------------------------------------------------------+ 152 = 134 + DS_SLOT_MAX(6) * DRAGON_SOUL_DECK_RESERVED_MAX_NUM(3)
|
||||
| 벨트 인벤토리 (벨트 착용시에만 벨트 레벨에 따라 활성)|
|
||||
| 벨트 인벤토리 (벨트 착용시에만 벨트 레벨에 따라 활성)|
|
||||
+------------------------------------------------------+ 168 = 152 + BELT_INVENTORY_SLOT_COUNT(16) = INVENTORY_AND_EQUIP_CELL_MAX
|
||||
| 미사용 |
|
||||
| 미사용 |
|
||||
+------------------------------------------------------+ ??
|
||||
*/
|
||||
};
|
||||
@@ -131,10 +131,10 @@ enum EWearPositions
|
||||
WEAR_COSTUME_BODY, // 19
|
||||
WEAR_COSTUME_HAIR, // 20
|
||||
|
||||
WEAR_RING1, // 21 : 신규 반지슬롯1 (왼쪽)
|
||||
WEAR_RING2, // 22 : 신규 반지슬롯2 (오른쪽)
|
||||
WEAR_RING1, // 21 : 신규 반지슬롯1 (왼쪽)
|
||||
WEAR_RING2, // 22 : 신규 반지슬롯2 (오른쪽)
|
||||
|
||||
WEAR_BELT, // 23 : 신규 벨트슬롯
|
||||
WEAR_BELT, // 23 : 신규 벨트슬롯
|
||||
|
||||
WEAR_MAX = 32 //
|
||||
};
|
||||
@@ -145,7 +145,7 @@ enum EDragonSoulDeckType
|
||||
DRAGON_SOUL_DECK_1,
|
||||
DRAGON_SOUL_DECK_MAX_NUM = 2,
|
||||
|
||||
DRAGON_SOUL_DECK_RESERVED_MAX_NUM = 3, // NOTE: 중요! 아직 사용중이진 않지만, 3페이지 분량을 예약 해 둠. DS DECK을 늘릴 경우 반드시 그 수만큼 RESERVED에서 차감해야 함!
|
||||
DRAGON_SOUL_DECK_RESERVED_MAX_NUM = 3, // NOTE: 중요! 아직 사용중이진 않지만, 3페이지 분량을 예약 해 둠. DS DECK을 늘릴 경우 반드시 그 수만큼 RESERVED에서 차감해야 함!
|
||||
};
|
||||
|
||||
enum ESex
|
||||
@@ -167,7 +167,7 @@ enum EDirection
|
||||
DIR_MAX_NUM
|
||||
};
|
||||
|
||||
#define ABILITY_MAX_LEVEL 10 /* 기술 최대 레벨 */
|
||||
#define ABILITY_MAX_LEVEL 10 /* 기술 최대 레벨 */
|
||||
|
||||
enum EAbilityDifficulty
|
||||
{
|
||||
@@ -180,9 +180,9 @@ enum EAbilityDifficulty
|
||||
|
||||
enum EAbilityCategory
|
||||
{
|
||||
CATEGORY_PHYSICAL, /* 신체적 어빌리티 */
|
||||
CATEGORY_MENTAL, /* 정신적 어빌리티 */
|
||||
CATEGORY_ATTRIBUTE, /* 능력 어빌리티 */
|
||||
CATEGORY_PHYSICAL, /* 신체적 어빌리티 */
|
||||
CATEGORY_MENTAL, /* 정신적 어빌리티 */
|
||||
CATEGORY_ATTRIBUTE, /* 능력 어빌리티 */
|
||||
CATEGORY_NUM_TYPES
|
||||
};
|
||||
|
||||
@@ -252,13 +252,13 @@ enum EParts
|
||||
|
||||
enum EChatType
|
||||
{
|
||||
CHAT_TYPE_TALKING, /* 그냥 채팅 */
|
||||
CHAT_TYPE_INFO, /* 정보 (아이템을 집었다, 경험치를 얻었다. 등) */
|
||||
CHAT_TYPE_NOTICE, /* 공지사항 */
|
||||
CHAT_TYPE_PARTY, /* 파티말 */
|
||||
CHAT_TYPE_GUILD, /* 길드말 */
|
||||
CHAT_TYPE_COMMAND, /* 일반 명령 */
|
||||
CHAT_TYPE_SHOUT, /* 외치기 */
|
||||
CHAT_TYPE_TALKING, /* 그냥 채팅 */
|
||||
CHAT_TYPE_INFO, /* 정보 (아이템을 집었다, 경험치를 얻었다. 등) */
|
||||
CHAT_TYPE_NOTICE, /* 공지사항 */
|
||||
CHAT_TYPE_PARTY, /* 파티말 */
|
||||
CHAT_TYPE_GUILD, /* 길드말 */
|
||||
CHAT_TYPE_COMMAND, /* 일반 명령 */
|
||||
CHAT_TYPE_SHOUT, /* 외치기 */
|
||||
CHAT_TYPE_WHISPER,
|
||||
CHAT_TYPE_BIG_NOTICE,
|
||||
CHAT_TYPE_MONARCH_NOTICE,
|
||||
@@ -401,38 +401,38 @@ enum EApplyTypes
|
||||
APPLY_ATTBONUS_SURA, // 61
|
||||
APPLY_ATTBONUS_SHAMAN, // 62
|
||||
APPLY_ATTBONUS_MONSTER, // 63
|
||||
APPLY_MALL_ATTBONUS, // 64 공격력 +x%
|
||||
APPLY_MALL_DEFBONUS, // 65 방어력 +x%
|
||||
APPLY_MALL_EXPBONUS, // 66 경험치 +x%
|
||||
APPLY_MALL_ITEMBONUS, // 67 아이템 드롭율 x/10배
|
||||
APPLY_MALL_GOLDBONUS, // 68 돈 드롭율 x/10배
|
||||
APPLY_MAX_HP_PCT, // 69 최대 생명력 +x%
|
||||
APPLY_MAX_SP_PCT, // 70 최대 정신력 +x%
|
||||
APPLY_SKILL_DAMAGE_BONUS, // 71 스킬 데미지 * (100+x)%
|
||||
APPLY_NORMAL_HIT_DAMAGE_BONUS, // 72 평타 데미지 * (100+x)%
|
||||
APPLY_SKILL_DEFEND_BONUS, // 73 스킬 데미지 방어 * (100-x)%
|
||||
APPLY_NORMAL_HIT_DEFEND_BONUS, // 74 평타 데미지 방어 * (100-x)%
|
||||
APPLY_PC_BANG_EXP_BONUS, // 75 PC방 아이템 EXP 보너스
|
||||
APPLY_PC_BANG_DROP_BONUS, // 76 PC방 아이템 드롭율 보너스
|
||||
APPLY_MALL_ATTBONUS, // 64 공격력 +x%
|
||||
APPLY_MALL_DEFBONUS, // 65 방어력 +x%
|
||||
APPLY_MALL_EXPBONUS, // 66 경험치 +x%
|
||||
APPLY_MALL_ITEMBONUS, // 67 아이템 드롭율 x/10배
|
||||
APPLY_MALL_GOLDBONUS, // 68 돈 드롭율 x/10배
|
||||
APPLY_MAX_HP_PCT, // 69 최대 생명력 +x%
|
||||
APPLY_MAX_SP_PCT, // 70 최대 정신력 +x%
|
||||
APPLY_SKILL_DAMAGE_BONUS, // 71 스킬 데미지 * (100+x)%
|
||||
APPLY_NORMAL_HIT_DAMAGE_BONUS, // 72 평타 데미지 * (100+x)%
|
||||
APPLY_SKILL_DEFEND_BONUS, // 73 스킬 데미지 방어 * (100-x)%
|
||||
APPLY_NORMAL_HIT_DEFEND_BONUS, // 74 평타 데미지 방어 * (100-x)%
|
||||
APPLY_PC_BANG_EXP_BONUS, // 75 PC방 아이템 EXP 보너스
|
||||
APPLY_PC_BANG_DROP_BONUS, // 76 PC방 아이템 드롭율 보너스
|
||||
|
||||
APPLY_EXTRACT_HP_PCT, // 77 사용시 HP 소모
|
||||
APPLY_EXTRACT_HP_PCT, // 77 사용시 HP 소모
|
||||
|
||||
APPLY_RESIST_WARRIOR, // 78 무사에게 저항
|
||||
APPLY_RESIST_ASSASSIN, // 79 자객에게 저항
|
||||
APPLY_RESIST_SURA, // 80 수라에게 저항
|
||||
APPLY_RESIST_SHAMAN, // 81 무당에게 저항
|
||||
APPLY_ENERGY, // 82 기력
|
||||
APPLY_DEF_GRADE, // 83 방어력. DEF_GRADE_BONUS는 클라에서 두배로 보여지는 의도된 버그(...)가 있다.
|
||||
APPLY_COSTUME_ATTR_BONUS, // 84 코스튬 아이템에 붙은 속성치 보너스
|
||||
APPLY_MAGIC_ATTBONUS_PER, // 85 마법 공격력 +x%
|
||||
APPLY_MELEE_MAGIC_ATTBONUS_PER, // 86 마법 + 밀리 공격력 +x%
|
||||
APPLY_RESIST_WARRIOR, // 78 무사에게 저항
|
||||
APPLY_RESIST_ASSASSIN, // 79 자객에게 저항
|
||||
APPLY_RESIST_SURA, // 80 수라에게 저항
|
||||
APPLY_RESIST_SHAMAN, // 81 무당에게 저항
|
||||
APPLY_ENERGY, // 82 기력
|
||||
APPLY_DEF_GRADE, // 83 방어력. DEF_GRADE_BONUS는 클라에서 두배로 보여지는 의도된 버그(...)가 있다.
|
||||
APPLY_COSTUME_ATTR_BONUS, // 84 코스튬 아이템에 붙은 속성치 보너스
|
||||
APPLY_MAGIC_ATTBONUS_PER, // 85 마법 공격력 +x%
|
||||
APPLY_MELEE_MAGIC_ATTBONUS_PER, // 86 마법 + 밀리 공격력 +x%
|
||||
|
||||
APPLY_RESIST_ICE, // 87 냉기 저항
|
||||
APPLY_RESIST_EARTH, // 88 대지 저항
|
||||
APPLY_RESIST_DARK, // 89 어둠 저항
|
||||
APPLY_RESIST_ICE, // 87 냉기 저항
|
||||
APPLY_RESIST_EARTH, // 88 대지 저항
|
||||
APPLY_RESIST_DARK, // 89 어둠 저항
|
||||
|
||||
APPLY_ANTI_CRITICAL_PCT, //90 크리티컬 저항
|
||||
APPLY_ANTI_PENETRATE_PCT, //91 관통타격 저항
|
||||
APPLY_ANTI_CRITICAL_PCT, //90 크리티컬 저항
|
||||
APPLY_ANTI_PENETRATE_PCT, //91 관통타격 저항
|
||||
|
||||
|
||||
MAX_APPLY_NUM, //
|
||||
@@ -584,7 +584,7 @@ enum EGuildWarState
|
||||
GUILD_WAR_OVER,
|
||||
GUILD_WAR_RESERVE,
|
||||
|
||||
GUILD_WAR_DURATION = 30*60, // 1시간
|
||||
GUILD_WAR_DURATION = 30*60, // 1시간
|
||||
GUILD_WAR_WIN_POINT = 1000,
|
||||
GUILD_WAR_LADDER_HALF_PENALTY_TIME = 12*60*60,
|
||||
};
|
||||
@@ -628,13 +628,13 @@ enum EMoneyLogType
|
||||
|
||||
enum EPremiumTypes
|
||||
{
|
||||
PREMIUM_EXP, // 경험치가 1.2배
|
||||
PREMIUM_ITEM, // 아이템 드롭율이 2배
|
||||
PREMIUM_SAFEBOX, // 창고가 1칸에서 3칸
|
||||
PREMIUM_AUTOLOOT, // 돈 자동 줍기
|
||||
PREMIUM_FISH_MIND, // 고급 물고기 낚일 확률 상승
|
||||
PREMIUM_MARRIAGE_FAST, // 금실 증가 양을 빠르게합니다.
|
||||
PREMIUM_GOLD, // 돈 드롭율이 1.5배
|
||||
PREMIUM_EXP, // 경험치가 1.2배
|
||||
PREMIUM_ITEM, // 아이템 드롭율이 2배
|
||||
PREMIUM_SAFEBOX, // 창고가 1칸에서 3칸
|
||||
PREMIUM_AUTOLOOT, // 돈 자동 줍기
|
||||
PREMIUM_FISH_MIND, // 고급 물고기 낚일 확률 상승
|
||||
PREMIUM_MARRIAGE_FAST, // 금실 증가 양을 빠르게합니다.
|
||||
PREMIUM_GOLD, // 돈 드롭율이 1.5배
|
||||
PREMIUM_MAX_NUM = 9
|
||||
};
|
||||
|
||||
@@ -664,10 +664,10 @@ enum SPECIAL_EFFECT
|
||||
SE_AUTO_HPUP,
|
||||
SE_AUTO_SPUP,
|
||||
|
||||
SE_EQUIP_RAMADAN_RING, // 라마단 초승달의 반지(71135) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
SE_EQUIP_HALLOWEEN_CANDY, // 할로윈 사탕을 착용(-_-;)한 순간에 발동하는 이펙트
|
||||
SE_EQUIP_HAPPINESS_RING, // 크리스마스 행복의 반지(71143) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
SE_EQUIP_LOVE_PENDANT, // 발렌타인 사랑의 팬던트(71145) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
SE_EQUIP_RAMADAN_RING, // 라마단 초승달의 반지(71135) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
SE_EQUIP_HALLOWEEN_CANDY, // 할로윈 사탕을 착용(-_-;)한 순간에 발동하는 이펙트
|
||||
SE_EQUIP_HAPPINESS_RING, // 크리스마스 행복의 반지(71143) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
SE_EQUIP_LOVE_PENDANT, // 발렌타인 사랑의 팬던트(71145) 착용할 때 이펙트 (발동이펙트임, 지속이펙트 아님)
|
||||
} ;
|
||||
|
||||
enum ETeenFlags
|
||||
@@ -682,10 +682,10 @@ enum ETeenFlags
|
||||
|
||||
#include "item_length.h"
|
||||
|
||||
// inventory의 position을 나타내는 구조체
|
||||
// int와의 암시적 형변환이 있는 이유는,
|
||||
// 인벤 관련된 모든 함수가 window_type은 받지 않고, cell 하나만 받았기 때문에,(기존에는 인벤이 하나 뿐이어서 inventory type이란게 필요없었기 때문에,)
|
||||
// 인벤 관련 모든 함수 호출부분을 수정하는 것이 난감하기 떄문이다.
|
||||
// inventory의 position을 나타내는 구조체
|
||||
// int와의 암시적 형변환이 있는 이유는,
|
||||
// 인벤 관련된 모든 함수가 window_type은 받지 않고, cell 하나만 받았기 때문에,(기존에는 인벤이 하나 뿐이어서 inventory type이란게 필요없었기 때문에,)
|
||||
// 인벤 관련 모든 함수 호출부분을 수정하는 것이 난감하기 떄문이다.
|
||||
|
||||
enum EDragonSoulRefineWindowSize
|
||||
{
|
||||
@@ -734,7 +734,7 @@ typedef struct SItemPos
|
||||
return cell < INVENTORY_AND_EQUIP_SLOT_MAX;
|
||||
case DRAGON_SOUL_INVENTORY:
|
||||
return cell < (DRAGON_SOUL_INVENTORY_MAX_NUM);
|
||||
// 동적으로 크기가 정해지는 window는 valid 체크를 할 수가 없다.
|
||||
// 동적으로 크기가 정해지는 window는 valid 체크를 할 수가 없다.
|
||||
case SAFEBOX:
|
||||
case MALL:
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef INC_METIN_II_COMMON_NONCOPYABLE_TEMPLATE
|
||||
#ifndef INC_METIN_II_COMMON_NONCOPYABLE_TEMPLATE
|
||||
#define INC_METIN_II_COMMON_NONCOPYABLE_TEMPLATE
|
||||
|
||||
class noncopyable
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_COMMON_POOL_H__
|
||||
#ifndef __INC_METIN_II_COMMON_POOL_H__
|
||||
#define __INC_METIN_II_COMMON_POOL_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef __INC_SERVICE_H__
|
||||
#ifndef __INC_SERVICE_H__
|
||||
#define __INC_SERVICE_H__
|
||||
|
||||
#define ENABLE_AUTODETECT_INTERNAL_IP
|
||||
#define ENABLE_PROXY_IP
|
||||
#define ENABLE_PORT_SECURITY
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_ // 패킷 암호화 개선
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_ // 패킷 암호화 개선
|
||||
//#define __AUCTION__
|
||||
#define __PET_SYSTEM__
|
||||
#define __UDP_BLOCK__
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_SINGLETON_H__
|
||||
#ifndef __INC_SINGLETON_H__
|
||||
#define __INC_SINGLETON_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_STL_H__
|
||||
#ifndef __INC_METIN_II_STL_H__
|
||||
#define __INC_METIN_II_STL_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_TABLES_H__
|
||||
#ifndef __INC_TABLES_H__
|
||||
#define __INC_TABLES_H__
|
||||
|
||||
#include "length.h"
|
||||
@@ -6,7 +6,7 @@
|
||||
typedef DWORD IDENT;
|
||||
|
||||
/**
|
||||
* @version 05/06/10 Bang2ni - Myshop Pricelist 관련 패킷 HEADER_XX_MYSHOP_PRICELIST_XXX 추가
|
||||
* @version 05/06/10 Bang2ni - Myshop Pricelist 관련 패킷 HEADER_XX_MYSHOP_PRICELIST_XXX 추가
|
||||
*/
|
||||
enum
|
||||
{
|
||||
@@ -104,8 +104,8 @@ enum
|
||||
HEADER_GD_BILLING_CHECK = 106,
|
||||
HEADER_GD_MALL_LOAD = 107,
|
||||
|
||||
HEADER_GD_MYSHOP_PRICELIST_UPDATE = 108, ///< 가격정보 갱신 요청
|
||||
HEADER_GD_MYSHOP_PRICELIST_REQ = 109, ///< 가격정보 리스트 요청
|
||||
HEADER_GD_MYSHOP_PRICELIST_UPDATE = 108, ///< 가격정보 갱신 요청
|
||||
HEADER_GD_MYSHOP_PRICELIST_REQ = 109, ///< 가격정보 리스트 요청
|
||||
|
||||
HEADER_GD_BLOCK_CHAT = 110,
|
||||
|
||||
@@ -116,21 +116,21 @@ enum
|
||||
// END_OF_PCBANG_IP_LIST_BY_AUTH
|
||||
|
||||
HEADER_GD_HAMMER_OF_TOR = 114,
|
||||
HEADER_GD_RELOAD_ADMIN = 115, ///<운영자 정보 요청
|
||||
HEADER_GD_BREAK_MARRIAGE = 116, ///< 결혼 파기
|
||||
HEADER_GD_ELECT_MONARCH = 117, ///< 군주 투표
|
||||
HEADER_GD_CANDIDACY = 118, ///< 군주 등록
|
||||
HEADER_GD_ADD_MONARCH_MONEY = 119, ///< 군주 돈 증가
|
||||
HEADER_GD_TAKE_MONARCH_MONEY = 120, ///< 군주 돈 감소
|
||||
HEADER_GD_COME_TO_VOTE = 121, ///< 표결
|
||||
HEADER_GD_RMCANDIDACY = 122, ///< 후보 제거 (운영자)
|
||||
HEADER_GD_SETMONARCH = 123, ///<군주설정 (운영자)
|
||||
HEADER_GD_RMMONARCH = 124, ///<군주삭제
|
||||
HEADER_GD_RELOAD_ADMIN = 115, ///<운영자 정보 요청
|
||||
HEADER_GD_BREAK_MARRIAGE = 116, ///< 결혼 파기
|
||||
HEADER_GD_ELECT_MONARCH = 117, ///< 군주 투표
|
||||
HEADER_GD_CANDIDACY = 118, ///< 군주 등록
|
||||
HEADER_GD_ADD_MONARCH_MONEY = 119, ///< 군주 돈 증가
|
||||
HEADER_GD_TAKE_MONARCH_MONEY = 120, ///< 군주 돈 감소
|
||||
HEADER_GD_COME_TO_VOTE = 121, ///< 표결
|
||||
HEADER_GD_RMCANDIDACY = 122, ///< 후보 제거 (운영자)
|
||||
HEADER_GD_SETMONARCH = 123, ///<군주설정 (운영자)
|
||||
HEADER_GD_RMMONARCH = 124, ///<군주삭제
|
||||
HEADER_GD_DEC_MONARCH_MONEY = 125,
|
||||
|
||||
HEADER_GD_CHANGE_MONARCH_LORD = 126,
|
||||
HEADER_GD_BLOCK_COUNTRY_IP = 127, // 광대역 IP-Block
|
||||
HEADER_GD_BLOCK_EXCEPTION = 128, // 광대역 IP-Block 예외
|
||||
HEADER_GD_BLOCK_COUNTRY_IP = 127, // 광대역 IP-Block
|
||||
HEADER_GD_BLOCK_EXCEPTION = 128, // 광대역 IP-Block 예외
|
||||
|
||||
HEADER_GD_REQ_CHANGE_GUILD_MASTER = 129,
|
||||
|
||||
@@ -139,7 +139,7 @@ enum
|
||||
HEADER_GD_UPDATE_HORSE_NAME = 131,
|
||||
HEADER_GD_REQ_HORSE_NAME = 132,
|
||||
|
||||
HEADER_GD_DC = 133, // Login Key를 지움
|
||||
HEADER_GD_DC = 133, // Login Key를 지움
|
||||
|
||||
HEADER_GD_VALID_LOGOUT = 134,
|
||||
|
||||
@@ -257,23 +257,23 @@ enum
|
||||
HEADER_DG_WEDDING_START = 155,
|
||||
HEADER_DG_WEDDING_END = 156,
|
||||
|
||||
HEADER_DG_MYSHOP_PRICELIST_RES = 157, ///< 가격정보 리스트 응답
|
||||
HEADER_DG_RELOAD_ADMIN = 158, ///< 운영자 정보 리로드
|
||||
HEADER_DG_BREAK_MARRIAGE = 159, ///< 결혼 파기
|
||||
HEADER_DG_ELECT_MONARCH = 160, ///< 군주 투표
|
||||
HEADER_DG_CANDIDACY = 161, ///< 군주 등록
|
||||
HEADER_DG_ADD_MONARCH_MONEY = 162, ///< 군주 돈 증가
|
||||
HEADER_DG_TAKE_MONARCH_MONEY = 163, ///< 군주 돈 감소
|
||||
HEADER_DG_COME_TO_VOTE = 164, ///< 표결
|
||||
HEADER_DG_RMCANDIDACY = 165, ///< 후보 제거 (운영자)
|
||||
HEADER_DG_SETMONARCH = 166, ///<군주설정 (운영자)
|
||||
HEADER_DG_RMMONARCH = 167, ///<군주삭제
|
||||
HEADER_DG_MYSHOP_PRICELIST_RES = 157, ///< 가격정보 리스트 응답
|
||||
HEADER_DG_RELOAD_ADMIN = 158, ///< 운영자 정보 리로드
|
||||
HEADER_DG_BREAK_MARRIAGE = 159, ///< 결혼 파기
|
||||
HEADER_DG_ELECT_MONARCH = 160, ///< 군주 투표
|
||||
HEADER_DG_CANDIDACY = 161, ///< 군주 등록
|
||||
HEADER_DG_ADD_MONARCH_MONEY = 162, ///< 군주 돈 증가
|
||||
HEADER_DG_TAKE_MONARCH_MONEY = 163, ///< 군주 돈 감소
|
||||
HEADER_DG_COME_TO_VOTE = 164, ///< 표결
|
||||
HEADER_DG_RMCANDIDACY = 165, ///< 후보 제거 (운영자)
|
||||
HEADER_DG_SETMONARCH = 166, ///<군주설정 (운영자)
|
||||
HEADER_DG_RMMONARCH = 167, ///<군주삭제
|
||||
HEADER_DG_DEC_MONARCH_MONEY = 168,
|
||||
|
||||
HEADER_DG_CHANGE_MONARCH_LORD_ACK = 169,
|
||||
HEADER_DG_UPDATE_MONARCH_INFO = 170,
|
||||
HEADER_DG_BLOCK_COUNTRY_IP = 171, // 광대역 IP-Block
|
||||
HEADER_DG_BLOCK_EXCEPTION = 172, // 광대역 IP-Block 예외 account
|
||||
HEADER_DG_BLOCK_COUNTRY_IP = 171, // 광대역 IP-Block
|
||||
HEADER_DG_BLOCK_EXCEPTION = 172, // 광대역 IP-Block 예외 account
|
||||
|
||||
HEADER_DG_ACK_CHANGE_GUILD_MASTER = 173,
|
||||
|
||||
@@ -393,7 +393,7 @@ typedef struct SPlayerItem
|
||||
DWORD count;
|
||||
|
||||
DWORD vnum;
|
||||
long alSockets[ITEM_SOCKET_MAX_NUM]; // 소켓번호
|
||||
long alSockets[ITEM_SOCKET_MAX_NUM]; // 소켓번호
|
||||
|
||||
TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
|
||||
|
||||
@@ -608,9 +608,9 @@ typedef struct SShopItemTable
|
||||
DWORD vnum;
|
||||
BYTE count;
|
||||
|
||||
TItemPos pos; // PC 상점에만 이용
|
||||
DWORD price; // PC, shop_table_ex.txt 상점에만 이용
|
||||
BYTE display_pos; // PC, shop_table_ex.txt 상점에만 이용, 보일 위치.
|
||||
TItemPos pos; // PC 상점에만 이용
|
||||
DWORD price; // PC, shop_table_ex.txt 상점에만 이용
|
||||
BYTE display_pos; // PC, shop_table_ex.txt 상점에만 이용, 보일 위치.
|
||||
} TShopItemTable;
|
||||
|
||||
typedef struct SShopTable
|
||||
@@ -674,12 +674,12 @@ typedef struct SItemTable : public SEntityTable
|
||||
BYTE bSpecular;
|
||||
BYTE bGainSocketPct;
|
||||
|
||||
short int sAddonType; // 기본 속성
|
||||
short int sAddonType; // 기본 속성
|
||||
|
||||
// 아래 limit flag들은 realtime에 체크 할 일이 많고, 아이템 VNUM당 고정된 값인데,
|
||||
// 현재 구조대로 매번 아이템마다 필요한 경우에 LIMIT_MAX_NUM까지 루프돌면서 체크하는 부하가 커서 미리 저장 해 둠.
|
||||
char cLimitRealTimeFirstUseIndex; // 아이템 limit 필드값 중에서 LIMIT_REAL_TIME_FIRST_USE 플래그의 위치 (없으면 -1)
|
||||
char cLimitTimerBasedOnWearIndex; // 아이템 limit 필드값 중에서 LIMIT_TIMER_BASED_ON_WEAR 플래그의 위치 (없으면 -1)
|
||||
// 아래 limit flag들은 realtime에 체크 할 일이 많고, 아이템 VNUM당 고정된 값인데,
|
||||
// 현재 구조대로 매번 아이템마다 필요한 경우에 LIMIT_MAX_NUM까지 루프돌면서 체크하는 부하가 커서 미리 저장 해 둠.
|
||||
char cLimitRealTimeFirstUseIndex; // 아이템 limit 필드값 중에서 LIMIT_REAL_TIME_FIRST_USE 플래그의 위치 (없으면 -1)
|
||||
char cLimitTimerBasedOnWearIndex; // 아이템 limit 필드값 중에서 LIMIT_TIMER_BASED_ON_WEAR 플래그의 위치 (없으면 -1)
|
||||
|
||||
} TItemTable;
|
||||
|
||||
@@ -717,7 +717,7 @@ typedef struct SPlayerLoadPacket
|
||||
{
|
||||
DWORD account_id;
|
||||
DWORD player_id;
|
||||
BYTE account_index; /* account 에서의 위치 */
|
||||
BYTE account_index; /* account 에서의 위치 */
|
||||
} TPlayerLoadPacket;
|
||||
|
||||
typedef struct SPlayerCreatePacket
|
||||
@@ -794,9 +794,9 @@ typedef struct SEmpireSelectPacket
|
||||
typedef struct SPacketGDSetup
|
||||
{
|
||||
char szPublicIP[16]; // Public IP which listen to users
|
||||
BYTE bChannel; // 채널
|
||||
WORD wListenPort; // 클라이언트가 접속하는 포트 번호
|
||||
WORD wP2PPort; // 서버끼리 연결 시키는 P2P 포트 번호
|
||||
BYTE bChannel; // 채널
|
||||
WORD wListenPort; // 클라이언트가 접속하는 포트 번호
|
||||
WORD wP2PPort; // 서버끼리 연결 시키는 P2P 포트 번호
|
||||
long alMaps[32];
|
||||
DWORD dwLoginCount;
|
||||
BYTE bAuthServer;
|
||||
@@ -974,8 +974,8 @@ typedef struct SPacketGuildWar
|
||||
long lInitialScore;
|
||||
} TPacketGuildWar;
|
||||
|
||||
// Game -> DB : 상대적 변화값
|
||||
// DB -> Game : 토탈된 최종값
|
||||
// Game -> DB : 상대적 변화값
|
||||
// DB -> Game : 토탈된 최종값
|
||||
typedef struct SPacketGuildWarScore
|
||||
{
|
||||
DWORD dwGuildGainPoint;
|
||||
@@ -996,8 +996,8 @@ typedef struct SRefineTable
|
||||
//DWORD result_vnum;
|
||||
DWORD id;
|
||||
BYTE material_count;
|
||||
int cost; // 소요 비용
|
||||
int prob; // 확률
|
||||
int cost; // 소요 비용
|
||||
int prob; // 확률
|
||||
TRefineMaterial materials[REFINE_MATERIAL_MAX_NUM];
|
||||
} TRefineTable;
|
||||
|
||||
@@ -1082,14 +1082,14 @@ typedef struct SPacketGDLoginByKey
|
||||
} TPacketGDLoginByKey;
|
||||
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
*/
|
||||
typedef struct SPacketGiveGuildPriv
|
||||
{
|
||||
BYTE type;
|
||||
int value;
|
||||
DWORD guild_id;
|
||||
time_t duration_sec; ///< 지속시간
|
||||
time_t duration_sec; ///< 지속시간
|
||||
} TPacketGiveGuildPriv;
|
||||
typedef struct SPacketGiveEmpirePriv
|
||||
{
|
||||
@@ -1124,7 +1124,7 @@ typedef struct SPacketDGChangeCharacterPriv
|
||||
} TPacketDGChangeCharacterPriv;
|
||||
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
*/
|
||||
typedef struct SPacketDGChangeGuildPriv
|
||||
{
|
||||
@@ -1132,7 +1132,7 @@ typedef struct SPacketDGChangeGuildPriv
|
||||
int value;
|
||||
DWORD guild_id;
|
||||
BYTE bLog;
|
||||
time_t end_time_sec; ///< 지속시간
|
||||
time_t end_time_sec; ///< 지속시간
|
||||
} TPacketDGChangeGuildPriv;
|
||||
|
||||
typedef struct SPacketDGChangeEmpirePriv
|
||||
@@ -1313,27 +1313,27 @@ typedef struct
|
||||
DWORD dwPID2;
|
||||
} TPacketWeddingEnd;
|
||||
|
||||
/// 개인상점 가격정보의 헤더. 가변 패킷으로 이 뒤에 byCount 만큼의 TItemPriceInfo 가 온다.
|
||||
/// 개인상점 가격정보의 헤더. 가변 패킷으로 이 뒤에 byCount 만큼의 TItemPriceInfo 가 온다.
|
||||
typedef struct SPacketMyshopPricelistHeader
|
||||
{
|
||||
DWORD dwOwnerID; ///< 가격정보를 가진 플레이어 ID
|
||||
BYTE byCount; ///< 가격정보 갯수
|
||||
DWORD dwOwnerID; ///< 가격정보를 가진 플레이어 ID
|
||||
BYTE byCount; ///< 가격정보 갯수
|
||||
} TPacketMyshopPricelistHeader;
|
||||
|
||||
/// 개인상점의 단일 아이템에 대한 가격정보
|
||||
/// 개인상점의 단일 아이템에 대한 가격정보
|
||||
typedef struct SItemPriceInfo
|
||||
{
|
||||
DWORD dwVnum; ///< 아이템 vnum
|
||||
DWORD dwPrice; ///< 가격
|
||||
DWORD dwVnum; ///< 아이템 vnum
|
||||
DWORD dwPrice; ///< 가격
|
||||
} TItemPriceInfo;
|
||||
|
||||
/// 개인상점 아이템 가격정보 리스트 테이블
|
||||
/// 개인상점 아이템 가격정보 리스트 테이블
|
||||
typedef struct SItemPriceListTable
|
||||
{
|
||||
DWORD dwOwnerID; ///< 가격정보를 가진 플레이어 ID
|
||||
BYTE byCount; ///< 가격정보 리스트의 갯수
|
||||
DWORD dwOwnerID; ///< 가격정보를 가진 플레이어 ID
|
||||
BYTE byCount; ///< 가격정보 리스트의 갯수
|
||||
|
||||
TItemPriceInfo aPriceInfo[SHOP_PRICELIST_MAX_NUM]; ///< 가격정보 리스트
|
||||
TItemPriceInfo aPriceInfo[SHOP_PRICELIST_MAX_NUM]; ///< 가격정보 리스트
|
||||
} TItemPriceListTable;
|
||||
|
||||
typedef struct
|
||||
@@ -1354,12 +1354,12 @@ typedef struct SPacketPCBangIP
|
||||
//ADMIN_MANAGER
|
||||
typedef struct TAdminInfo
|
||||
{
|
||||
int m_ID; //고유ID
|
||||
char m_szAccount[32]; //계정
|
||||
char m_szName[32]; //캐릭터이름
|
||||
char m_szContactIP[16]; //접근아이피
|
||||
char m_szServerIP[16]; //서버아이피
|
||||
int m_Authority; //권한
|
||||
int m_ID; //고유ID
|
||||
char m_szAccount[32]; //계정
|
||||
char m_szName[32]; //캐릭터이름
|
||||
char m_szContactIP[16]; //접근아이피
|
||||
char m_szServerIP[16]; //서버아이피
|
||||
int m_Authority; //권한
|
||||
} tAdminInfo;
|
||||
//END_ADMIN_MANAGER
|
||||
|
||||
@@ -1380,20 +1380,20 @@ typedef struct SPacketReloadAdmin
|
||||
|
||||
typedef struct TMonarchInfo
|
||||
{
|
||||
DWORD pid[4]; // 군주의 PID
|
||||
int64_t money[4]; // 군주의 별개 돈
|
||||
char name[4][32]; // 군주의 이름
|
||||
char date[4][32]; // 군주 등록 날짜
|
||||
DWORD pid[4]; // 군주의 PID
|
||||
int64_t money[4]; // 군주의 별개 돈
|
||||
char name[4][32]; // 군주의 이름
|
||||
char date[4][32]; // 군주 등록 날짜
|
||||
} MonarchInfo;
|
||||
|
||||
typedef struct TMonarchElectionInfo
|
||||
{
|
||||
DWORD pid; // 투표 한사람 PID
|
||||
DWORD selectedpid; // 투표 당한 PID ( 군주 참가자 )
|
||||
char date[32]; // 투표 날짜
|
||||
DWORD pid; // 투표 한사람 PID
|
||||
DWORD selectedpid; // 투표 당한 PID ( 군주 참가자 )
|
||||
char date[32]; // 투표 날짜
|
||||
} MonarchElectionInfo;
|
||||
|
||||
// 군주 출마자
|
||||
// 군주 출마자
|
||||
typedef struct tMonarchCandidacy
|
||||
{
|
||||
DWORD pid;
|
||||
@@ -1465,14 +1465,14 @@ typedef struct tNeedLoginLogInfo
|
||||
DWORD dwPlayerID;
|
||||
} TPacketNeedLoginLogInfo;
|
||||
|
||||
//독일 선물 알림 기능 테스트용 패킷 정보
|
||||
//독일 선물 알림 기능 테스트용 패킷 정보
|
||||
typedef struct tItemAwardInformer
|
||||
{
|
||||
char login[LOGIN_MAX_LEN + 1];
|
||||
char command[20]; //명령어
|
||||
unsigned int vnum; //아이템
|
||||
char command[20]; //명령어
|
||||
unsigned int vnum; //아이템
|
||||
} TPacketItemAwardInfromer;
|
||||
// 선물 알림 기능 삭제용 패킷 정보
|
||||
// 선물 알림 기능 삭제용 패킷 정보
|
||||
typedef struct tDeleteAwardID
|
||||
{
|
||||
DWORD dwID;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*********************************************************************
|
||||
/*********************************************************************
|
||||
* date : 2007.06.07
|
||||
* file : teen_packet.h
|
||||
* author : mhh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*----- atoi function -----*/
|
||||
/*----- atoi function -----*/
|
||||
inline bool str_to_number (bool& out, const char *in)
|
||||
{
|
||||
if (0==in || 0==in[0]) return false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#ifdef __AUCTION__
|
||||
|
||||
#include "DBManager.h"
|
||||
@@ -135,7 +135,7 @@ void AuctionManager::LoadAuctionItem()
|
||||
}
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ void AuctionManager::LoadAuctionInfo()
|
||||
}
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -226,7 +226,7 @@ void AuctionManager::LoadSaleInfo()
|
||||
}
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -269,7 +269,7 @@ void AuctionManager::LoadWishInfo()
|
||||
}
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -311,7 +311,7 @@ void AuctionManager::LoadMyBidInfo ()
|
||||
}
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -518,7 +518,7 @@ AuctionResult AuctionManager::Impur(DWORD purchaser_id, const char* purchaser_na
|
||||
return AUCTION_EXPIRED;
|
||||
}
|
||||
|
||||
// 즉구 해버렸으므로, 경매는 끝났다.
|
||||
// 즉구 해버렸으므로, 경매는 끝났다.
|
||||
item_info->expired_time = 0;
|
||||
item_info->bidder_id = purchaser_id;
|
||||
item_info->set_bidder_name (purchaser_name);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifdef __AUCTION__
|
||||
#ifdef __AUCTION__
|
||||
|
||||
#ifndef __INC_AUCTION_MANAGER_H__
|
||||
#define __INC_AUCTION_MANAGER_H__
|
||||
@@ -243,7 +243,7 @@ private:
|
||||
TItemInfoCacheMap item_cache_map;
|
||||
};
|
||||
|
||||
// pc가 입찰에 참여했던 경매를 관리.
|
||||
// pc가 입찰에 참여했던 경매를 관리.
|
||||
class MyBidBoard
|
||||
{
|
||||
public:
|
||||
@@ -255,7 +255,7 @@ public:
|
||||
|
||||
int GetMoney (DWORD player_id, DWORD item_id);
|
||||
bool Delete (DWORD player_id, DWORD item_id);
|
||||
// 이미 있으면 덮어 씌운다.
|
||||
// 이미 있으면 덮어 씌운다.
|
||||
void Insert (DWORD player_id, DWORD item_id, int money);
|
||||
|
||||
private:
|
||||
@@ -267,11 +267,11 @@ private:
|
||||
class AuctionManager : public singleton <AuctionManager>
|
||||
{
|
||||
private:
|
||||
// auction에 등록된 아이템들.
|
||||
// auction에 등록된 아이템들.
|
||||
typedef std::unordered_map<DWORD, CItemCache *> TItemCacheMap;
|
||||
TItemCacheMap auction_item_cache_map;
|
||||
|
||||
// auction에 등록된 정보 중 가격, 등등 아이템 테이블에 포함되지 않는 정보들을 관리하는 것들
|
||||
// auction에 등록된 정보 중 가격, 등등 아이템 테이블에 포함되지 않는 정보들을 관리하는 것들
|
||||
AuctionBoard Auction;
|
||||
SaleBoard Sale;
|
||||
WishBoard Wish;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
/*********************************************************************
|
||||
* date : 2007.05.31
|
||||
* file : BlockCountry.cpp
|
||||
@@ -114,7 +114,7 @@ bool CBlockCountry::IsBlockedCountryIp(const char *user_ip)
|
||||
st_addr.s_addr = in_address;
|
||||
if (INADDR_NONE == in_address)
|
||||
#endif
|
||||
return true; // 아이피가 괴상하니 일단 블럭처리
|
||||
return true; // 아이피가 괴상하니 일단 블럭처리
|
||||
|
||||
DO_ALL_BLOCK_IP(iter)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=4 sw=4
|
||||
// vim: ts=4 sw=4
|
||||
// Date : 2007.05.31
|
||||
// File : BlockCountry.h
|
||||
// Author : mhh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Cache.h"
|
||||
|
||||
@@ -29,12 +29,12 @@ CItemCache::~CItemCache()
|
||||
{
|
||||
}
|
||||
|
||||
// 이거 이상한데...
|
||||
// Delete를 했으면, Cache도 해제해야 하는것 아닌가???
|
||||
// 근데 Cache를 해제하는 부분이 없어.
|
||||
// 못 찾은 건가?
|
||||
// 이렇게 해놓으면, 계속 시간이 될 때마다 아이템을 계속 지워...
|
||||
// 이미 사라진 아이템인데... 확인사살??????
|
||||
// 이거 이상한데...
|
||||
// Delete를 했으면, Cache도 해제해야 하는것 아닌가???
|
||||
// 근데 Cache를 해제하는 부분이 없어.
|
||||
// 못 찾은 건가?
|
||||
// 이렇게 해놓으면, 계속 시간이 될 때마다 아이템을 계속 지워...
|
||||
// 이미 사라진 아이템인데... 확인사살??????
|
||||
// fixme
|
||||
// by rtsummit
|
||||
void CItemCache::Delete()
|
||||
@@ -53,12 +53,12 @@ void CItemCache::Delete()
|
||||
OnFlush();
|
||||
|
||||
//m_bNeedQuery = false;
|
||||
//m_lastUpdateTime = time(0) - m_expireTime; // 바로 타임아웃 되도록 하자.
|
||||
//m_lastUpdateTime = time(0) - m_expireTime; // 바로 타임아웃 되도록 하자.
|
||||
}
|
||||
|
||||
void CItemCache::OnFlush()
|
||||
{
|
||||
if (m_data.vnum == 0) // vnum이 0이면 삭제하라고 표시된 것이다.
|
||||
if (m_data.vnum == 0) // vnum이 0이면 삭제하라고 표시된 것이다.
|
||||
{
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM item%s WHERE id=%u", GetTablePostfix(), m_data.id);
|
||||
@@ -190,7 +190,7 @@ CItemPriceListTableCache::CItemPriceListTableCache()
|
||||
void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList)
|
||||
{
|
||||
//
|
||||
// 이미 캐싱된 아이템과 중복된 아이템을 찾고 중복되지 않는 이전 정보는 tmpvec 에 넣는다.
|
||||
// 이미 캐싱된 아이템과 중복된 아이템을 찾고 중복되지 않는 이전 정보는 tmpvec 에 넣는다.
|
||||
//
|
||||
|
||||
std::vector<TItemPriceInfo> tmpvec;
|
||||
@@ -206,7 +206,7 @@ void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList
|
||||
}
|
||||
|
||||
//
|
||||
// pUpdateList 를 m_data 에 복사하고 남은 공간을 tmpvec 의 앞에서 부터 남은 만큼 복사한다.
|
||||
// pUpdateList 를 m_data 에 복사하고 남은 공간을 tmpvec 의 앞에서 부터 남은 만큼 복사한다.
|
||||
//
|
||||
|
||||
if (pUpdateList->byCount > SHOP_PRICELIST_MAX_NUM)
|
||||
@@ -219,7 +219,7 @@ void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList
|
||||
|
||||
thecore_memcpy(m_data.aPriceInfo, pUpdateList->aPriceInfo, sizeof(TItemPriceInfo) * pUpdateList->byCount);
|
||||
|
||||
int nDeletedNum; // 삭제된 가격정보의 갯수
|
||||
int nDeletedNum; // 삭제된 가격정보의 갯수
|
||||
|
||||
if (pUpdateList->byCount < SHOP_PRICELIST_MAX_NUM)
|
||||
{
|
||||
@@ -248,14 +248,14 @@ void CItemPriceListTableCache::OnFlush()
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
|
||||
//
|
||||
// 이 캐시의 소유자에 대한 기존에 DB 에 저장된 아이템 가격정보를 모두 삭제한다.
|
||||
// 이 캐시의 소유자에 대한 기존에 DB 에 저장된 아이템 가격정보를 모두 삭제한다.
|
||||
//
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery), "DELETE FROM myshop_pricelist%s WHERE owner_id = %u", GetTablePostfix(), m_data.dwOwnerID);
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_DESTROY, 0, NULL);
|
||||
|
||||
//
|
||||
// 캐시의 내용을 모두 DB 에 쓴다.
|
||||
// 캐시의 내용을 모두 DB 에 쓴다.
|
||||
//
|
||||
|
||||
for (int idx = 0; idx < m_data.byCount; ++idx)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_DB_CACHE_H__
|
||||
#define __INC_DB_CACHE_H__
|
||||
|
||||
@@ -29,7 +29,7 @@ class CPlayerTableCache : public cache<TPlayerTable>
|
||||
// MYSHOP_PRICE_LIST
|
||||
/**
|
||||
* @class CItemPriceListTableCache
|
||||
* @brief 개인상점의 아이템 가격정보 리스트에 대한 캐시 class
|
||||
* @brief 개인상점의 아이템 가격정보 리스트에 대한 캐시 class
|
||||
* @version 05/06/10 Bang2ni - First release.
|
||||
*/
|
||||
class CItemPriceListTableCache : public cache< TItemPriceListTable >
|
||||
@@ -38,20 +38,20 @@ class CItemPriceListTableCache : public cache< TItemPriceListTable >
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* 캐시 만료 시간을 설정한다.
|
||||
* 캐시 만료 시간을 설정한다.
|
||||
*/
|
||||
CItemPriceListTableCache(void);
|
||||
|
||||
/// 리스트 갱신
|
||||
/// 리스트 갱신
|
||||
/**
|
||||
* @param [in] pUpdateList 갱신할 리스트
|
||||
* @param [in] pUpdateList 갱신할 리스트
|
||||
*
|
||||
* 캐시된 가격정보를 갱신한다.
|
||||
* 가격정보 리스트가 가득 찼을 경우 기존에 캐싱된 정보들을 뒤에서 부터 삭제한다.
|
||||
* 캐시된 가격정보를 갱신한다.
|
||||
* 가격정보 리스트가 가득 찼을 경우 기존에 캐싱된 정보들을 뒤에서 부터 삭제한다.
|
||||
*/
|
||||
void UpdateList(const TItemPriceListTable* pUpdateList);
|
||||
|
||||
/// 가격정보를 DB 에 기록한다.
|
||||
/// 가격정보를 DB 에 기록한다.
|
||||
virtual void OnFlush(void);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "../../common/billing.h"
|
||||
@@ -167,7 +167,7 @@ bool CClientManager::Initialize()
|
||||
|
||||
LoadEventFlag();
|
||||
|
||||
// database character-set을 강제로 맞춤
|
||||
// database character-set을 강제로 맞춤
|
||||
if (g_stLocale == "big5" || g_stLocale == "sjis")
|
||||
CDBManager::instance().QueryLocaleSet();
|
||||
|
||||
@@ -180,7 +180,7 @@ void CClientManager::MainLoop()
|
||||
|
||||
sys_log(0, "ClientManager pointer is %p", this);
|
||||
|
||||
// 메인루프
|
||||
// 메인루프
|
||||
while (!m_bShutdowned)
|
||||
{
|
||||
while ((tmp = CDBManager::instance().PopResult()))
|
||||
@@ -196,7 +196,7 @@ void CClientManager::MainLoop()
|
||||
}
|
||||
|
||||
//
|
||||
// 메인루프 종료처리
|
||||
// 메인루프 종료처리
|
||||
//
|
||||
sys_log(0, "MainLoop exited, Starting cache flushing");
|
||||
|
||||
@@ -204,7 +204,7 @@ void CClientManager::MainLoop()
|
||||
|
||||
itertype(m_map_playerCache) it = m_map_playerCache.begin();
|
||||
|
||||
//플레이어 테이블 캐쉬 플러쉬
|
||||
//플레이어 테이블 캐쉬 플러쉬
|
||||
while (it != m_map_playerCache.end())
|
||||
{
|
||||
CPlayerTableCache * c = (it++)->second;
|
||||
@@ -216,7 +216,7 @@ void CClientManager::MainLoop()
|
||||
|
||||
|
||||
itertype(m_map_itemCache) it2 = m_map_itemCache.begin();
|
||||
//아이템 플러쉬
|
||||
//아이템 플러쉬
|
||||
while (it2 != m_map_itemCache.end())
|
||||
{
|
||||
CItemCache * c = (it2++)->second;
|
||||
@@ -228,7 +228,7 @@ void CClientManager::MainLoop()
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
//
|
||||
// 개인상점 아이템 가격 리스트 Flush
|
||||
// 개인상점 아이템 가격 리스트 Flush
|
||||
//
|
||||
for (itertype(m_mapItemPriceListCache) itPriceList = m_mapItemPriceListCache.begin(); itPriceList != m_mapItemPriceListCache.end(); ++itPriceList)
|
||||
{
|
||||
@@ -248,7 +248,7 @@ void CClientManager::Quit()
|
||||
|
||||
void CClientManager::QUERY_BOOT(CPeer* peer, TPacketGDBoot * p)
|
||||
{
|
||||
const BYTE bPacketVersion = 6; // BOOT 패킷이 바뀔때마다 번호를 올리도록 한다.
|
||||
const BYTE bPacketVersion = 6; // BOOT 패킷이 바뀔때마다 번호를 올리도록 한다.
|
||||
|
||||
std::vector<tAdminInfo> vAdmin;
|
||||
std::vector<std::string> vHost;
|
||||
@@ -507,9 +507,9 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
|
||||
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
|
||||
DWORD dwHandle = pi->dwHandle;
|
||||
|
||||
// 여기에서 사용하는 account_index는 쿼리 순서를 말한다.
|
||||
// 첫번째 패스워드 알아내기 위해 하는 쿼리가 0
|
||||
// 두번째 실제 데이터를 얻어놓는 쿼리가 1
|
||||
// 여기에서 사용하는 account_index는 쿼리 순서를 말한다.
|
||||
// 첫번째 패스워드 알아내기 위해 하는 쿼리가 0
|
||||
// 두번째 실제 데이터를 얻어놓는 쿼리가 1
|
||||
|
||||
if (pi->account_index == 0)
|
||||
{
|
||||
@@ -534,7 +534,7 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
|
||||
|
||||
// 비밀번호가 틀리면..
|
||||
// 비밀번호가 틀리면..
|
||||
if (((!row[2] || !*row[2]) && strcmp("000000", szSafeboxPassword)) ||
|
||||
((row[2] && *row[2]) && strcmp(row[2], szSafeboxPassword)))
|
||||
{
|
||||
@@ -600,8 +600,8 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
|
||||
}
|
||||
|
||||
|
||||
// 쿼리에 에러가 있었으므로 응답할 경우 창고가 비어있는 것 처럼
|
||||
// 보이기 때문에 창고가 아얘 안열리는게 나음
|
||||
// 쿼리에 에러가 있었으므로 응답할 경우 창고가 비어있는 것 처럼
|
||||
// 보이기 때문에 창고가 아얘 안열리는게 나음
|
||||
if (!msg->Get()->pSQLResult)
|
||||
{
|
||||
sys_err("null safebox result");
|
||||
@@ -711,8 +711,8 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
|
||||
{
|
||||
case 72723: case 72724: case 72725: case 72726:
|
||||
case 72727: case 72728: case 72729: case 72730:
|
||||
// 무시무시하지만 이전에 하던 걸 고치기는 무섭고...
|
||||
// 그래서 그냥 하드 코딩. 선물 상자용 자동물약 아이템들.
|
||||
// 무시무시하지만 이전에 하던 걸 고치기는 무섭고...
|
||||
// 그래서 그냥 하드 코딩. 선물 상자용 자동물약 아이템들.
|
||||
case 76004: case 76005: case 76021: case 76022:
|
||||
case 79012: case 79013:
|
||||
if (pItemAward->dwSocket2 == 0)
|
||||
@@ -824,7 +824,7 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
|
||||
void CClientManager::QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p)
|
||||
{
|
||||
ClientHandleInfo * pi = new ClientHandleInfo(dwHandle);
|
||||
pi->account_index = p->bSize; // account_index를 사이즈로 임시로 사용
|
||||
pi->account_index = p->bSize; // account_index를 사이즈로 임시로 사용
|
||||
|
||||
char szQuery[QUERY_MAX_LEN];
|
||||
|
||||
@@ -912,7 +912,7 @@ void CClientManager::RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg)
|
||||
TItemPricelistReqInfo* pReqInfo = (TItemPricelistReqInfo*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData;
|
||||
|
||||
//
|
||||
// DB 에서 로드한 정보를 Cache 에 저장
|
||||
// DB 에서 로드한 정보를 Cache 에 저장
|
||||
//
|
||||
|
||||
TItemPriceListTable table;
|
||||
@@ -931,7 +931,7 @@ void CClientManager::RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg)
|
||||
PutItemPriceListCache(&table);
|
||||
|
||||
//
|
||||
// 로드한 데이터를 Game server 에 전송
|
||||
// 로드한 데이터를 Game server 에 전송
|
||||
//
|
||||
|
||||
TPacketMyshopPricelistHeader header;
|
||||
@@ -955,7 +955,7 @@ void CClientManager::RESULT_PRICELIST_LOAD_FOR_UPDATE(SQLMsg* pMsg)
|
||||
TItemPriceListTable* pUpdateTable = (TItemPriceListTable*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData;
|
||||
|
||||
//
|
||||
// DB 에서 로드한 정보를 Cache 에 저장
|
||||
// DB 에서 로드한 정보를 Cache 에 저장
|
||||
//
|
||||
|
||||
TItemPriceListTable table;
|
||||
@@ -1017,18 +1017,18 @@ void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpire
|
||||
UINT g_start_map[4] =
|
||||
{
|
||||
0, // reserved
|
||||
1, // 신수국
|
||||
21, // 천조국
|
||||
41 // 진노국
|
||||
1, // 신수국
|
||||
21, // 천조국
|
||||
41 // 진노국
|
||||
};
|
||||
|
||||
// FIXME share with game
|
||||
DWORD g_start_position[4][2]=
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 469300, 964200 }, // 신수국
|
||||
{ 55700, 157900 }, // 천조국
|
||||
{ 969600, 278400 } // 진노국
|
||||
{ 469300, 964200 }, // 신수국
|
||||
{ 55700, 157900 }, // 천조국
|
||||
{ 969600, 278400 } // 진노국
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
@@ -1079,7 +1079,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
|
||||
peer->SetMaps(p->alMaps);
|
||||
|
||||
//
|
||||
// 어떤 맵이 어떤 서버에 있는지 보내기
|
||||
// 어떤 맵이 어떤 서버에 있는지 보내기
|
||||
//
|
||||
TMapLocation kMapLocations;
|
||||
|
||||
@@ -1186,7 +1186,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
|
||||
peer->Encode(&vec_kMapLocations[0], sizeof(TMapLocation) * vec_kMapLocations.size());
|
||||
|
||||
//
|
||||
// 셋업 : 접속한 피어에 다른 피어들이 접속하게 만든다. (P2P 컨넥션 생성)
|
||||
// 셋업 : 접속한 피어에 다른 피어들이 접속하게 만든다. (P2P 컨넥션 생성)
|
||||
//
|
||||
sys_log(0, "SETUP: channel %u listen %u p2p %u count %u", peer->GetChannel(), p->wListenPort, p->wP2PPort, bMapCount);
|
||||
|
||||
@@ -1202,7 +1202,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
|
||||
if (tmp == peer)
|
||||
continue;
|
||||
|
||||
// 채널이 0이라면 아직 SETUP 패킷이 오지 않은 피어 또는 auth라고 간주할 수 있음
|
||||
// 채널이 0이라면 아직 SETUP 패킷이 오지 않은 피어 또는 auth라고 간주할 수 있음
|
||||
if (0 == tmp->GetChannel())
|
||||
continue;
|
||||
|
||||
@@ -1211,7 +1211,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
|
||||
}
|
||||
|
||||
//
|
||||
// 로그인 및 빌링정보 보내기
|
||||
// 로그인 및 빌링정보 보내기
|
||||
//
|
||||
TPacketLoginOnSetup * pck = (TPacketLoginOnSetup *) c_pData;;
|
||||
std::vector<TPacketBillingRepair> vec_repair;
|
||||
@@ -1284,8 +1284,8 @@ void CClientManager::QUERY_ITEM_SAVE(CPeer * pkPeer, const char * c_pData)
|
||||
{
|
||||
TPlayerItem * p = (TPlayerItem *) c_pData;
|
||||
|
||||
// 창고면 캐쉬하지 않고, 캐쉬에 있던 것도 빼버려야 한다.
|
||||
// auction은 이 루트를 타지 않아야 한다. EnrollInAuction을 타야한다.
|
||||
// 창고면 캐쉬하지 않고, 캐쉬에 있던 것도 빼버려야 한다.
|
||||
// auction은 이 루트를 타지 않아야 한다. EnrollInAuction을 타야한다.
|
||||
|
||||
if (p->window == SAFEBOX || p->window == MALL)
|
||||
{
|
||||
@@ -1424,7 +1424,7 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
|
||||
|
||||
c = GetItemCache(pNew->id);
|
||||
|
||||
// 아이템 새로 생성
|
||||
// 아이템 새로 생성
|
||||
if (!c)
|
||||
{
|
||||
if (g_log)
|
||||
@@ -1433,15 +1433,15 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
|
||||
c = new CItemCache;
|
||||
m_map_itemCache.insert(TItemCacheMap::value_type(pNew->id, c));
|
||||
}
|
||||
// 있을시
|
||||
// 있을시
|
||||
else
|
||||
{
|
||||
if (g_log)
|
||||
sys_log(0, "ITEM_CACHE: PutItemCache ==> Have Cache");
|
||||
// 소유자가 틀리면
|
||||
// 소유자가 틀리면
|
||||
if (pNew->owner != c->Get()->owner)
|
||||
{
|
||||
// 이미 이 아이템을 가지고 있었던 유저로 부터 아이템을 삭제한다.
|
||||
// 이미 이 아이템을 가지고 있었던 유저로 부터 아이템을 삭제한다.
|
||||
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner);
|
||||
|
||||
if (it != m_map_pkItemCacheSetPtr.end())
|
||||
@@ -1453,7 +1453,7 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
|
||||
}
|
||||
}
|
||||
|
||||
// 새로운 정보 업데이트
|
||||
// 새로운 정보 업데이트
|
||||
c->Put(pNew, bSkipQuery);
|
||||
|
||||
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner);
|
||||
@@ -1468,8 +1468,8 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
|
||||
}
|
||||
else
|
||||
{
|
||||
// 현재 소유자가 없으므로 바로 저장해야 다음 접속이 올 때 SQL에 쿼리하여
|
||||
// 받을 수 있으므로 바로 저장한다.
|
||||
// 현재 소유자가 없으므로 바로 저장해야 다음 접속이 올 때 SQL에 쿼리하여
|
||||
// 받을 수 있으므로 바로 저장한다.
|
||||
if (g_log)
|
||||
sys_log(0, "ITEM_CACHE: direct save %u id %u", c->Get()->owner, c->Get()->id);
|
||||
else
|
||||
@@ -1529,7 +1529,7 @@ void CClientManager::UpdatePlayerCache()
|
||||
|
||||
c->Flush();
|
||||
|
||||
// Item Cache도 업데이트
|
||||
// Item Cache도 업데이트
|
||||
UpdateItemCacheSet(c->Get()->id);
|
||||
}
|
||||
else if (c->CheckFlushTimeout())
|
||||
@@ -1555,7 +1555,7 @@ void CClientManager::UpdateItemCache()
|
||||
{
|
||||
CItemCache * c = (it++)->second;
|
||||
|
||||
// 아이템은 Flush만 한다.
|
||||
// 아이템은 Flush만 한다.
|
||||
if (c->CheckFlushTimeout())
|
||||
{
|
||||
if (g_test_server)
|
||||
@@ -1602,7 +1602,7 @@ void CClientManager::QUERY_ITEM_DESTROY(CPeer * pkPeer, const char * c_pData)
|
||||
if (g_log)
|
||||
sys_log(0, "HEADER_GD_ITEM_DESTROY: PID %u ID %u", dwPID, dwID);
|
||||
|
||||
if (dwPID == 0) // 아무도 가진 사람이 없었다면, 비동기 쿼리
|
||||
if (dwPID == 0) // 아무도 가진 사람이 없었다면, 비동기 쿼리
|
||||
CDBManager::instance().AsyncQuery(szQuery);
|
||||
else
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_DESTROY, pkPeer->GetHandle(), NULL);
|
||||
@@ -1680,7 +1680,7 @@ void CClientManager::QUERY_RELOAD_PROTO()
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
*/
|
||||
void CClientManager::AddGuildPriv(TPacketGiveGuildPriv* p)
|
||||
{
|
||||
@@ -2161,8 +2161,8 @@ void CClientManager::WeddingEnd(TPacketWeddingEnd * p)
|
||||
}
|
||||
|
||||
//
|
||||
// 캐시에 가격정보가 있으면 캐시를 업데이트 하고 캐시에 가격정보가 없다면
|
||||
// 우선 기존의 데이터를 로드한 뒤에 기존의 정보로 캐시를 만들고 새로 받은 가격정보를 업데이트 한다.
|
||||
// 캐시에 가격정보가 있으면 캐시를 업데이트 하고 캐시에 가격정보가 없다면
|
||||
// 우선 기존의 데이터를 로드한 뒤에 기존의 정보로 캐시를 만들고 새로 받은 가격정보를 업데이트 한다.
|
||||
//
|
||||
|
||||
// Old code:
|
||||
@@ -2242,7 +2242,7 @@ void CClientManager::MyshopPricelistUpdate(const TItemPriceListTable* pPacket)
|
||||
}
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
// 캐시된 가격정보가 있으면 캐시를 읽어 바로 전송하고 캐시에 정보가 없으면 DB 에 쿼리를 한다.
|
||||
// 캐시된 가격정보가 있으면 캐시를 읽어 바로 전송하고 캐시에 정보가 없으면 DB 에 쿼리를 한다.
|
||||
//
|
||||
void CClientManager::MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID)
|
||||
{
|
||||
@@ -2656,15 +2656,15 @@ void CClientManager::ProcessPackets(CPeer * peer)
|
||||
ComeToVote(peer, dwHandle, data);
|
||||
break;
|
||||
|
||||
case HEADER_GD_RMCANDIDACY: //< 후보 제거 (운영자)
|
||||
case HEADER_GD_RMCANDIDACY: //< 후보 제거 (운영자)
|
||||
RMCandidacy(peer, dwHandle, data);
|
||||
break;
|
||||
|
||||
case HEADER_GD_SETMONARCH: ///<군주설정 (운영자)
|
||||
case HEADER_GD_SETMONARCH: ///<군주설정 (운영자)
|
||||
SetMonarch(peer, dwHandle, data);
|
||||
break;
|
||||
|
||||
case HEADER_GD_RMMONARCH: ///<군주삭제
|
||||
case HEADER_GD_RMMONARCH: ///<군주삭제
|
||||
RMMonarch(peer, dwHandle, data);
|
||||
break;
|
||||
//END_MONARCH
|
||||
@@ -2857,9 +2857,9 @@ CPeer * CClientManager::GetAnyPeer()
|
||||
return m_peerList.front();
|
||||
}
|
||||
|
||||
// DB 매니저로 부터 받은 결과를 처리한다.
|
||||
// DB 매니저로 부터 받은 결과를 처리한다.
|
||||
//
|
||||
// @version 05/06/10 Bang2ni - 가격정보 관련 쿼리(QID_ITEMPRICE_XXX) 추가
|
||||
// @version 05/06/10 Bang2ni - 가격정보 관련 쿼리(QID_ITEMPRICE_XXX) 추가
|
||||
int CClientManager::AnalyzeQueryResult(SQLMsg * msg)
|
||||
{
|
||||
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
|
||||
@@ -2977,7 +2977,7 @@ void UsageLog()
|
||||
char *time_s;
|
||||
struct tm lt;
|
||||
|
||||
int avg = g_dwUsageAvg / 3600; // 60 초 * 60 분
|
||||
int avg = g_dwUsageAvg / 3600; // 60 초 * 60 분
|
||||
|
||||
fp = fopen("usage.txt", "a+");
|
||||
|
||||
@@ -3010,7 +3010,7 @@ int CClientManager::Process()
|
||||
++thecore_heart->pulse;
|
||||
|
||||
/*
|
||||
//30분마다 변경
|
||||
//30분마다 변경
|
||||
if (((thecore_pulse() % (60 * 30 * 10)) == 0))
|
||||
{
|
||||
g_iPlayerCacheFlushSeconds = MAX(60, rand() % 180);
|
||||
@@ -3088,11 +3088,11 @@ int CClientManager::Process()
|
||||
m_iCacheFlushCount = 0;
|
||||
|
||||
|
||||
//플레이어 플러쉬
|
||||
//플레이어 플러쉬
|
||||
UpdatePlayerCache();
|
||||
//아이템 플러쉬
|
||||
//아이템 플러쉬
|
||||
UpdateItemCache();
|
||||
//로그아웃시 처리- 캐쉬셋 플러쉬
|
||||
//로그아웃시 처리- 캐쉬셋 플러쉬
|
||||
UpdateLogoutPlayer();
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
@@ -3162,13 +3162,13 @@ int CClientManager::Process()
|
||||
/////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 60))) // 60초에 한번
|
||||
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 60))) // 60초에 한번
|
||||
{
|
||||
// 유니크 아이템을 위한 시간을 보낸다.
|
||||
// 유니크 아이템을 위한 시간을 보낸다.
|
||||
CClientManager::instance().SendTime();
|
||||
}
|
||||
|
||||
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 3600))) // 한시간에 한번
|
||||
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 3600))) // 한시간에 한번
|
||||
{
|
||||
CMoneyLog::instance().Save();
|
||||
}
|
||||
@@ -3178,7 +3178,7 @@ int CClientManager::Process()
|
||||
int idx;
|
||||
CPeer * peer;
|
||||
|
||||
for (idx = 0; idx < num_events; ++idx) // 인풋
|
||||
for (idx = 0; idx < num_events; ++idx) // 인풋
|
||||
{
|
||||
peer = (CPeer *) fdwatch_get_client_data(m_fdWatcher, idx);
|
||||
|
||||
@@ -3258,7 +3258,7 @@ int CClientManager::Process()
|
||||
|
||||
DWORD CClientManager::GetUserCount()
|
||||
{
|
||||
// 단순히 로그인 카운트를 센다.. --;
|
||||
// 단순히 로그인 카운트를 센다.. --;
|
||||
return m_map_kLogonAccount.size();
|
||||
}
|
||||
|
||||
@@ -3318,7 +3318,7 @@ bool CClientManager::InitializeNowItemID()
|
||||
{
|
||||
DWORD dwMin, dwMax;
|
||||
|
||||
//아이템 ID를 초기화 한다.
|
||||
//아이템 ID를 초기화 한다.
|
||||
if (!CConfig::instance().GetTwoValue("ITEM_ID_RANGE", &dwMin, &dwMax))
|
||||
{
|
||||
sys_err("conf.txt: Cannot find ITEM_ID_RANGE [start_item_id] [end_item_id]");
|
||||
@@ -3748,7 +3748,7 @@ bool CClientManager::InitializeLocalization()
|
||||
|
||||
bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec)
|
||||
{
|
||||
//szIP == NULL 일경우 모든서버에 운영자 권한을 갖는다.
|
||||
//szIP == NULL 일경우 모든서버에 운영자 권한을 갖는다.
|
||||
char szQuery[512];
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
"SELECT mID,mAccount,mName,mContactIP,mServerIP,mAuthority FROM gmlist WHERE mServerIP='ALL' or mServerIP='%s'",
|
||||
@@ -4312,7 +4312,7 @@ void CClientManager::SendSpareItemIDRange(CPeer* peer)
|
||||
}
|
||||
|
||||
//
|
||||
// Login Key만 맵에서 지운다.
|
||||
// Login Key만 맵에서 지운다.
|
||||
//
|
||||
void CClientManager::DeleteLoginKey(TPacketDC *data)
|
||||
{
|
||||
@@ -4425,7 +4425,7 @@ void CClientManager::EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrol
|
||||
sys_err ("Player id %d doesn't have item %d.", owner_id, data->get_item_id());
|
||||
return;
|
||||
}
|
||||
// 현재 시각 + 24시간 후.
|
||||
// 현재 시각 + 24시간 후.
|
||||
time_t expired_time = time(0) + 24 * 60 * 60;
|
||||
TAuctionItemInfo auctioned_item_info (item->vnum, data->get_bid_price(),
|
||||
data->get_impur_price(), owner_id, "", expired_time, data->get_item_id(), 0, data->get_empire());
|
||||
@@ -4444,7 +4444,7 @@ void CClientManager::EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrol
|
||||
}
|
||||
else
|
||||
{
|
||||
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
|
||||
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
|
||||
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner);
|
||||
|
||||
if (it != m_map_pkItemCacheSetPtr.end())
|
||||
@@ -4497,7 +4497,7 @@ void CClientManager::EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSa
|
||||
sys_err ("Player id %d doesn't have item %d.", owner_id, data->get_item_id());
|
||||
return;
|
||||
}
|
||||
// 현재 시각 + 24시간 후.
|
||||
// 현재 시각 + 24시간 후.
|
||||
time_t expired_time = time(0) + 24 * 60 * 60;
|
||||
TSaleItemInfo sold_item_info (item->vnum, data->get_sale_price(),
|
||||
owner_id, player->name, data->get_item_id(), data->get_wisher_id());
|
||||
@@ -4516,7 +4516,7 @@ void CClientManager::EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSa
|
||||
}
|
||||
else
|
||||
{
|
||||
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
|
||||
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
|
||||
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner);
|
||||
|
||||
if (it != m_map_pkItemCacheSetPtr.end())
|
||||
@@ -4556,7 +4556,7 @@ void CClientManager::EnrollInWish (CPeer * peer, DWORD wisher_id, AuctionEnrollW
|
||||
CPlayerTableCache* player_cache = it->second;
|
||||
TPlayerTable* player = player_cache->Get(false);
|
||||
|
||||
// 현재 시각 + 24시간 후.
|
||||
// 현재 시각 + 24시간 후.
|
||||
time_t expired_time = time(0) + 24 * 60 * 60;
|
||||
TWishItemInfo wished_item_info (data->get_item_num(), data->get_wish_price(), wisher_id, player->name, expired_time, data->get_empire());
|
||||
|
||||
@@ -4923,11 +4923,11 @@ void CClientManager::AuctionDeleteSaleItem (CPeer * peer, DWORD actor_id, DWORD
|
||||
AuctionManager::instance().DeleteSaleItem (actor_id, item_id);
|
||||
}
|
||||
|
||||
// ReBid는 이전 입찰금액에 더해서 입찰한다.
|
||||
// ReBid에선 data->bid_price가 이전 입찰가에 더해져서
|
||||
// 그 금액으로 rebid하는 것.
|
||||
// 이렇게 한 이유는 rebid에 실패 했을 때,
|
||||
// 유저의 호주머니에서 뺀 돈을 돌려주기 편하게 하기 위함이다.
|
||||
// ReBid는 이전 입찰금액에 더해서 입찰한다.
|
||||
// ReBid에선 data->bid_price가 이전 입찰가에 더해져서
|
||||
// 그 금액으로 rebid하는 것.
|
||||
// 이렇게 한 이유는 rebid에 실패 했을 때,
|
||||
// 유저의 호주머니에서 뺀 돈을 돌려주기 편하게 하기 위함이다.
|
||||
|
||||
void CClientManager::AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data)
|
||||
{
|
||||
@@ -4952,14 +4952,14 @@ void CClientManager::AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo
|
||||
{
|
||||
sys_log(0, "ReBid Success. bidder_id item_id %d %d", bidder_id, data->get_item_id());
|
||||
}
|
||||
// 이건 FAIL이 떠서는 안돼.
|
||||
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
|
||||
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
|
||||
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
|
||||
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
|
||||
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
|
||||
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
|
||||
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
|
||||
// 이건 FAIL이 떠서는 안돼.
|
||||
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
|
||||
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
|
||||
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
|
||||
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
|
||||
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
|
||||
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
|
||||
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
|
||||
if (result <= AUCTION_FAIL)
|
||||
{
|
||||
TPacketDGResultAuction enroll_result;
|
||||
@@ -4994,14 +4994,14 @@ void CClientManager::AuctionBidCancel (CPeer * peer, DWORD bidder_id, DWORD item
|
||||
{
|
||||
AuctionResult result = AuctionManager::instance().BidCancel (bidder_id, item_id);
|
||||
|
||||
// 이건 FAIL이 떠서는 안돼.
|
||||
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
|
||||
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
|
||||
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
|
||||
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
|
||||
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
|
||||
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
|
||||
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
|
||||
// 이건 FAIL이 떠서는 안돼.
|
||||
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
|
||||
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
|
||||
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
|
||||
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
|
||||
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
|
||||
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
|
||||
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
|
||||
if (result <= AUCTION_FAIL)
|
||||
{
|
||||
TPacketDGResultAuction enroll_result;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_CLIENTMANAGER_H__
|
||||
#define __INC_CLIENTMANAGER_H__
|
||||
|
||||
@@ -40,10 +40,10 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
typedef std::unordered_map<short, BYTE> TChannelStatusMap;
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
/// 아이템 가격정보 리스트 요청 정보
|
||||
/// 아이템 가격정보 리스트 요청 정보
|
||||
/**
|
||||
* first: Peer handle
|
||||
* second: 요청한 플레이어의 ID
|
||||
* second: 요청한 플레이어의 ID
|
||||
*/
|
||||
typedef std::pair< DWORD, DWORD > TItemPricelistReqInfo;
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
@@ -69,7 +69,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
pAccountTable = NULL;
|
||||
player_id = dwPID;
|
||||
};
|
||||
//독일선물기능용 생성자
|
||||
//독일선물기능용 생성자
|
||||
ClientHandleInfo(DWORD argHandle, DWORD dwPID, DWORD accountId)
|
||||
{
|
||||
dwHandle = argHandle;
|
||||
@@ -108,7 +108,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
void SetChinaEventServer(bool flag) { m_bChinaEventServer = flag; }
|
||||
bool IsChinaEventServer() { return m_bChinaEventServer; }
|
||||
|
||||
DWORD GetUserCount(); // 접속된 사용자 수를 리턴 한다.
|
||||
DWORD GetUserCount(); // 접속된 사용자 수를 리턴 한다.
|
||||
|
||||
void SendAllGuildSkillRechargePacket();
|
||||
void SendTime();
|
||||
@@ -128,23 +128,23 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
void UpdateItemCache();
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
/// 가격정보 리스트 캐시를 가져온다.
|
||||
/// 가격정보 리스트 캐시를 가져온다.
|
||||
/**
|
||||
* @param [in] dwID 가격정보 리스트의 소유자.(플레이어 ID)
|
||||
* @return 가격정보 리스트 캐시의 포인터
|
||||
* @param [in] dwID 가격정보 리스트의 소유자.(플레이어 ID)
|
||||
* @return 가격정보 리스트 캐시의 포인터
|
||||
*/
|
||||
CItemPriceListTableCache* GetItemPriceListCache(DWORD dwID);
|
||||
|
||||
/// 가격정보 리스트 캐시를 넣는다.
|
||||
/// 가격정보 리스트 캐시를 넣는다.
|
||||
/**
|
||||
* @param [in] pItemPriceList 캐시에 넣을 아이템 가격정보 리스트
|
||||
* @param [in] pItemPriceList 캐시에 넣을 아이템 가격정보 리스트
|
||||
*
|
||||
* 캐시가 이미 있으면 Update 가 아닌 replace 한다.
|
||||
* 캐시가 이미 있으면 Update 가 아닌 replace 한다.
|
||||
*/
|
||||
void PutItemPriceListCache(const TItemPriceListTable* pItemPriceList);
|
||||
|
||||
|
||||
/// Flush 시간이 만료된 아이템 가격정보 리스트 캐시를 Flush 해주고 캐시에서 삭제한다.
|
||||
/// Flush 시간이 만료된 아이템 가격정보 리스트 캐시를 Flush 해주고 캐시에서 삭제한다.
|
||||
void UpdateItemPriceListCache(void);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
@@ -162,8 +162,8 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
|
||||
void SendNotice(const char * c_pszFormat, ...);
|
||||
|
||||
char* GetCommand(char* str); //독일선물기능에서 명령어 얻는 함수
|
||||
void ItemAward(CPeer * peer, char* login); //독일 선물 기능
|
||||
char* GetCommand(char* str); //독일선물기능에서 명령어 얻는 함수
|
||||
void ItemAward(CPeer * peer, char* login); //독일 선물 기능
|
||||
|
||||
protected:
|
||||
void Destroy();
|
||||
@@ -184,9 +184,9 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
bool InitializeObjectTable();
|
||||
bool InitializeMonarch();
|
||||
|
||||
// mob_proto.txt, item_proto.txt에서 읽은 mob_proto, item_proto를 real db에 반영.
|
||||
// item_proto, mob_proto를 db에 반영하지 않아도, 게임 돌아가는데는 문제가 없지만,
|
||||
// 운영툴 등에서 db의 item_proto, mob_proto를 읽어 쓰기 때문에 문제가 발생한다.
|
||||
// mob_proto.txt, item_proto.txt에서 읽은 mob_proto, item_proto를 real db에 반영.
|
||||
// item_proto, mob_proto를 db에 반영하지 않아도, 게임 돌아가는데는 문제가 없지만,
|
||||
// 운영툴 등에서 db의 item_proto, mob_proto를 읽어 쓰기 때문에 문제가 발생한다.
|
||||
bool MirrorMobTableIntoDB();
|
||||
bool MirrorItemTableIntoDB();
|
||||
|
||||
@@ -251,20 +251,20 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
// END_PLAYER_INDEX_CREATE_BUG_FIX
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
/// 가격정보 로드 쿼리에 대한 Result 처리
|
||||
/// 가격정보 로드 쿼리에 대한 Result 처리
|
||||
/**
|
||||
* @param peer 가격정보를 요청한 Game server 의 peer 객체 포인터
|
||||
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
|
||||
* @param peer 가격정보를 요청한 Game server 의 peer 객체 포인터
|
||||
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
|
||||
*
|
||||
* 로드된 가격정보 리스트를 캐시에 저장하고 peer 에게 리스트를 보내준다.
|
||||
* 로드된 가격정보 리스트를 캐시에 저장하고 peer 에게 리스트를 보내준다.
|
||||
*/
|
||||
void RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg);
|
||||
|
||||
/// 가격정보 업데이트를 위한 로드 쿼리에 대한 Result 처리
|
||||
/// 가격정보 업데이트를 위한 로드 쿼리에 대한 Result 처리
|
||||
/**
|
||||
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
|
||||
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
|
||||
*
|
||||
* 로드된 정보로 가격정보 리스트 캐시를 만들고 업데이트 받은 가격정보로 업데이트 한다.
|
||||
* 로드된 정보로 가격정보 리스트 캐시를 만들고 업데이트 받은 가격정보로 업데이트 한다.
|
||||
*/
|
||||
void RESULT_PRICELIST_LOAD_FOR_UPDATE(SQLMsg* pMsg);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
@@ -344,7 +344,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
void SendAllLoginToBilling();
|
||||
void SendLoginToBilling(CLoginData * pkLD, bool bLogin);
|
||||
|
||||
// 결혼
|
||||
// 결혼
|
||||
void MarriageAdd(TPacketMarriageAdd * p);
|
||||
void MarriageUpdate(TPacketMarriageUpdate * p);
|
||||
void MarriageRemove(TPacketMarriageRemove * p);
|
||||
@@ -354,20 +354,20 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
void WeddingEnd(TPacketWeddingEnd * p);
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
// 개인상점 가격정보
|
||||
// 개인상점 가격정보
|
||||
|
||||
/// 아이템 가격정보 리스트 업데이트 패킷(HEADER_GD_MYSHOP_PRICELIST_UPDATE) 처리함수
|
||||
/// 아이템 가격정보 리스트 업데이트 패킷(HEADER_GD_MYSHOP_PRICELIST_UPDATE) 처리함수
|
||||
/**
|
||||
* @param [in] pPacket 패킷 데이터의 포인터
|
||||
* @param [in] pPacket 패킷 데이터의 포인터
|
||||
*/
|
||||
// void MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* pPacket);
|
||||
void MyshopPricelistUpdate(const TItemPriceListTable* pPacket);
|
||||
|
||||
/// 아이템 가격정보 리스트 요청 패킷(HEADER_GD_MYSHOP_PRICELIST_REQ) 처리함수
|
||||
/// 아이템 가격정보 리스트 요청 패킷(HEADER_GD_MYSHOP_PRICELIST_REQ) 처리함수
|
||||
/**
|
||||
* @param peer 패킷을 보낸 Game server 의 peer 객체의 포인터
|
||||
* @param [in] dwHandle 가격정보를 요청한 peer 의 핸들
|
||||
* @param [in] dwPlayerID 가격정보 리스트를 요청한 플레이어의 ID
|
||||
* @param peer 패킷을 보낸 Game server 의 peer 객체의 포인터
|
||||
* @param [in] dwHandle 가격정보를 요청한 peer 의 핸들
|
||||
* @param [in] dwPlayerID 가격정보 리스트를 요청한 플레이어의 ID
|
||||
*/
|
||||
void MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID);
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
@@ -387,7 +387,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
|
||||
private:
|
||||
int m_looping;
|
||||
socket_t m_fdAccept; // 접속 받는 소켓
|
||||
socket_t m_fdAccept; // 접속 받는 소켓
|
||||
TPeerList m_peerList;
|
||||
|
||||
CPeer * m_pkAuthPeer;
|
||||
@@ -404,7 +404,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
typedef std::unordered_map<DWORD, CLoginData *> TLoginDataByAID;
|
||||
TLoginDataByAID m_map_pkLoginDataByAID;
|
||||
|
||||
// Login LoginData pair (실제 로그인 되어있는 계정)
|
||||
// Login LoginData pair (실제 로그인 되어있는 계정)
|
||||
typedef std::unordered_map<std::string, CLoginData *> TLogonAccountMap;
|
||||
TLogonAccountMap m_map_kLogonAccount;
|
||||
|
||||
@@ -436,14 +436,14 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
|
||||
bool m_bShutdowned;
|
||||
|
||||
TPlayerTableCacheMap m_map_playerCache; // 플레이어 id가 key
|
||||
TPlayerTableCacheMap m_map_playerCache; // 플레이어 id가 key
|
||||
|
||||
TItemCacheMap m_map_itemCache; // 아이템 id가 key
|
||||
TItemCacheSetPtrMap m_map_pkItemCacheSetPtr; // 플레이어 id가 key, 이 플레이어가 어떤 아이템 캐쉬를 가지고 있나?
|
||||
TItemCacheMap m_map_itemCache; // 아이템 id가 key
|
||||
TItemCacheSetPtrMap m_map_pkItemCacheSetPtr; // 플레이어 id가 key, 이 플레이어가 어떤 아이템 캐쉬를 가지고 있나?
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
/// 플레이어별 아이템 가격정보 리스트 map. key: 플레이어 ID, value: 가격정보 리스트 캐시
|
||||
TItemPriceListCacheMap m_mapItemPriceListCache; ///< 플레이어별 아이템 가격정보 리스트
|
||||
/// 플레이어별 아이템 가격정보 리스트 map. key: 플레이어 ID, value: 가격정보 리스트 캐시
|
||||
TItemPriceListCacheMap m_mapItemPriceListCache; ///< 플레이어별 아이템 가격정보 리스트
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
|
||||
TChannelStatusMap m_mChannelStatus;
|
||||
@@ -481,7 +481,7 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
|
||||
|
||||
//BOOT_LOCALIZATION
|
||||
public:
|
||||
/* 로컬 정보 초기화
|
||||
/* 로컬 정보 초기화
|
||||
**/
|
||||
bool InitializeLocalization();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include "stdafx.h"
|
||||
@@ -172,42 +172,42 @@ class FCompareVnum
|
||||
|
||||
bool CClientManager::InitializeMobTable()
|
||||
{
|
||||
//================== 함수 설명 ==================//
|
||||
//1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고,
|
||||
// (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable)
|
||||
//2. 순서
|
||||
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
// 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
|
||||
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[mob_table] 테이블을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
|
||||
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
|
||||
//3. 테스트
|
||||
// 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료
|
||||
// 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지.
|
||||
// 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지.
|
||||
// 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지.
|
||||
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
|
||||
//================== 함수 설명 ==================//
|
||||
//1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고,
|
||||
// (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable)
|
||||
//2. 순서
|
||||
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
// 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
|
||||
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[mob_table] 테이블을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
|
||||
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
|
||||
//3. 테스트
|
||||
// 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료
|
||||
// 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지.
|
||||
// 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지.
|
||||
// 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지.
|
||||
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
|
||||
//_______________________________________________//
|
||||
|
||||
|
||||
//===============================================//
|
||||
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다.
|
||||
//<(a)localMap 맵 생성>
|
||||
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다.
|
||||
//<(a)localMap 맵 생성>
|
||||
map<int,const char*> localMap;
|
||||
bool isNameFile = true;
|
||||
//<파일 읽기>
|
||||
//<파일 읽기>
|
||||
cCsvTable nameData;
|
||||
if(!nameData.Load("mob_names.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "mob_names.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "mob_names.txt 파일을 읽어오지 못했습니다\n");
|
||||
isNameFile = false;
|
||||
} else {
|
||||
nameData.Next(); //설명row 생략.
|
||||
nameData.Next(); //설명row 생략.
|
||||
while(nameData.Next()) {
|
||||
localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1);
|
||||
}
|
||||
@@ -216,35 +216,35 @@ bool CClientManager::InitializeMobTable()
|
||||
|
||||
|
||||
//===============================================//
|
||||
// 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로
|
||||
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
|
||||
// 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로
|
||||
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
|
||||
//0.
|
||||
set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용.
|
||||
//1. 파일 읽어오기
|
||||
set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용.
|
||||
//1. 파일 읽어오기
|
||||
bool isTestFile = true;
|
||||
cCsvTable test_data;
|
||||
if(!test_data.Load("mob_proto_test.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "테스트 파일이 없습니다. 그대로 진행합니다.\n");
|
||||
fprintf(stderr, "테스트 파일이 없습니다. 그대로 진행합니다.\n");
|
||||
isTestFile = false;
|
||||
}
|
||||
//2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성.
|
||||
//2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성.
|
||||
map<DWORD, TMobTable *> test_map_mobTableByVnum;
|
||||
if (isTestFile) {
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
|
||||
//ㄱ. 테스트 몬스터 테이블 생성.
|
||||
//ㄱ. 테스트 몬스터 테이블 생성.
|
||||
TMobTable * test_mob_table = NULL;
|
||||
int test_MobTableSize = test_data.m_File.GetRowCount()-1;
|
||||
test_mob_table = new TMobTable[test_MobTableSize];
|
||||
memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize);
|
||||
|
||||
//ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기.
|
||||
//ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기.
|
||||
while(test_data.Next()) {
|
||||
|
||||
if (!Set_Proto_Mob_Table(test_mob_table, test_data, localMap))
|
||||
{
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
test_map_mobTableByVnum.insert(std::map<DWORD, TMobTable *>::value_type(test_mob_table->dwVnum, test_mob_table));
|
||||
@@ -255,22 +255,22 @@ bool CClientManager::InitializeMobTable()
|
||||
|
||||
}
|
||||
|
||||
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[mob_table] 테이블을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
|
||||
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[mob_table] 테이블을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
|
||||
|
||||
//1. 파일 읽기.
|
||||
//1. 파일 읽기.
|
||||
cCsvTable data;
|
||||
if(!data.Load("mob_proto.txt",'\t')) {
|
||||
fprintf(stderr, "mob_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "mob_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
return false;
|
||||
}
|
||||
data.Next(); //설명 row 넘어가기
|
||||
//2. (!)[mob_table] 생성하기
|
||||
//2.1 새로 추가되는 갯수를 파악
|
||||
data.Next(); //설명 row 넘어가기
|
||||
//2. (!)[mob_table] 생성하기
|
||||
//2.1 새로 추가되는 갯수를 파악
|
||||
int addNumber = 0;
|
||||
while(data.Next()) {
|
||||
int vnum = atoi(data.AsStringByIndex(0));
|
||||
@@ -280,15 +280,15 @@ bool CClientManager::InitializeMobTable()
|
||||
addNumber++;
|
||||
}
|
||||
}
|
||||
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
|
||||
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
|
||||
data.Destroy();
|
||||
if(!data.Load("mob_proto.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "mob_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "mob_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
return false;
|
||||
}
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
//2.2 크기에 맞게 mob_table 생성
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
//2.2 크기에 맞게 mob_table 생성
|
||||
if (!m_vec_mobTable.empty())
|
||||
{
|
||||
sys_log(0, "RELOAD: mob_proto");
|
||||
@@ -297,18 +297,18 @@ bool CClientManager::InitializeMobTable()
|
||||
m_vec_mobTable.resize(data.m_File.GetRowCount()-1 + addNumber);
|
||||
memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size());
|
||||
TMobTable * mob_table = &m_vec_mobTable[0];
|
||||
//2.3 데이터 채우기
|
||||
//2.3 데이터 채우기
|
||||
while (data.Next())
|
||||
{
|
||||
int col = 0;
|
||||
//(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사.
|
||||
//(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사.
|
||||
bool isSameRow = true;
|
||||
std::map<DWORD, TMobTable *>::iterator it_map_mobTable;
|
||||
it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col)));
|
||||
if(it_map_mobTable == test_map_mobTableByVnum.end()) {
|
||||
isSameRow = false;
|
||||
}
|
||||
//같은 row 가 있으면 (b)에서 읽어온다.
|
||||
//같은 row 가 있으면 (b)에서 읽어온다.
|
||||
if(isSameRow) {
|
||||
TMobTable *tempTable = it_map_mobTable->second;
|
||||
|
||||
@@ -379,13 +379,13 @@ bool CClientManager::InitializeMobTable()
|
||||
|
||||
if (!Set_Proto_Mob_Table(mob_table, data, localMap))
|
||||
{
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//셋에 vnum 추가
|
||||
//셋에 vnum 추가
|
||||
vnumSet.insert(mob_table->dwVnum);
|
||||
|
||||
|
||||
@@ -396,22 +396,22 @@ bool CClientManager::InitializeMobTable()
|
||||
//_____________________________________________________//
|
||||
|
||||
|
||||
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
|
||||
//파일 다시 읽어오기.
|
||||
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
|
||||
//파일 다시 읽어오기.
|
||||
test_data.Destroy();
|
||||
isTestFile = true;
|
||||
test_data;
|
||||
if(!test_data.Load("mob_proto_test.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "테스트 파일이 없습니다. 그대로 진행합니다.\n");
|
||||
fprintf(stderr, "테스트 파일이 없습니다. 그대로 진행합니다.\n");
|
||||
isTestFile = false;
|
||||
}
|
||||
if(isTestFile) {
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
|
||||
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
|
||||
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
|
||||
{
|
||||
//중복되는 부분이면 넘어간다.
|
||||
//중복되는 부분이면 넘어간다.
|
||||
set<int>::iterator itVnum;
|
||||
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
|
||||
if (itVnum != vnumSet.end()) {
|
||||
@@ -420,7 +420,7 @@ bool CClientManager::InitializeMobTable()
|
||||
|
||||
if (!Set_Proto_Mob_Table(mob_table, test_data, localMap))
|
||||
{
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "몹 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
sys_log(0, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire);
|
||||
@@ -448,8 +448,8 @@ bool CClientManager::InitializeShopTable()
|
||||
|
||||
std::unique_ptr<SQLMsg> pkMsg2(CDBManager::instance().DirectQuery(s_szQuery));
|
||||
|
||||
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
|
||||
// 고처야할부분
|
||||
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
|
||||
// 고처야할부분
|
||||
SQLResult * pRes2 = pkMsg2->Get();
|
||||
|
||||
if (!pRes2->uiNumRows)
|
||||
@@ -488,7 +488,7 @@ bool CClientManager::InitializeShopTable()
|
||||
|
||||
str_to_number(shop_table->dwNPCVnum, data[col++]);
|
||||
|
||||
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
|
||||
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
|
||||
continue;
|
||||
|
||||
TShopItemTable * pItem = &shop_table->items[shop_table->byItemCount];
|
||||
@@ -561,7 +561,7 @@ bool CClientManager::InitializeQuestItemTable()
|
||||
continue;
|
||||
}
|
||||
|
||||
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
|
||||
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
|
||||
tbl.bSize = 1;
|
||||
|
||||
m_vec_itemTable.push_back(tbl);
|
||||
@@ -572,39 +572,39 @@ bool CClientManager::InitializeQuestItemTable()
|
||||
|
||||
bool CClientManager::InitializeItemTable()
|
||||
{
|
||||
//================== 함수 설명 ==================//
|
||||
//1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고,
|
||||
// <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다.
|
||||
//2. 순서
|
||||
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
|
||||
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
|
||||
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
|
||||
//3. 테스트
|
||||
// 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료
|
||||
// 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지.
|
||||
// 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지.
|
||||
// 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지.
|
||||
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
|
||||
//================== 함수 설명 ==================//
|
||||
//1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고,
|
||||
// <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다.
|
||||
//2. 순서
|
||||
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
|
||||
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
|
||||
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
|
||||
//3. 테스트
|
||||
// 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료
|
||||
// 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지.
|
||||
// 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지.
|
||||
// 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지.
|
||||
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
|
||||
//_______________________________________________//
|
||||
|
||||
|
||||
|
||||
//=================================================================================//
|
||||
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
|
||||
//=================================================================================//
|
||||
bool isNameFile = true;
|
||||
map<int,const char*> localMap;
|
||||
cCsvTable nameData;
|
||||
if(!nameData.Load("item_names.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "item_names.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "item_names.txt 파일을 읽어오지 못했습니다\n");
|
||||
isNameFile = false;
|
||||
} else {
|
||||
nameData.Next();
|
||||
@@ -615,32 +615,32 @@ bool CClientManager::InitializeItemTable()
|
||||
//_________________________________________________________________//
|
||||
|
||||
//=================================================================//
|
||||
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
|
||||
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
|
||||
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
|
||||
//=================================================================//
|
||||
map<DWORD, TItemTable *> test_map_itemTableByVnum;
|
||||
//1. 파일 읽어오기.
|
||||
//1. 파일 읽어오기.
|
||||
cCsvTable test_data;
|
||||
if(!test_data.Load("item_proto_test.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "item_proto_test.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "item_proto_test.txt 파일을 읽어오지 못했습니다\n");
|
||||
//return false;
|
||||
} else {
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
|
||||
//2. 테스트 아이템 테이블 생성.
|
||||
//2. 테스트 아이템 테이블 생성.
|
||||
TItemTable * test_item_table = NULL;
|
||||
int test_itemTableSize = test_data.m_File.GetRowCount()-1;
|
||||
test_item_table = new TItemTable[test_itemTableSize];
|
||||
memset(test_item_table, 0, sizeof(TItemTable) * test_itemTableSize);
|
||||
|
||||
//3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기.
|
||||
//3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기.
|
||||
while(test_data.Next()) {
|
||||
|
||||
|
||||
if (!Set_Proto_Item_Table(test_item_table, test_data, localMap))
|
||||
{
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
test_map_itemTableByVnum.insert(std::map<DWORD, TItemTable *>::value_type(test_item_table->dwVnum, test_item_table));
|
||||
@@ -652,25 +652,25 @@ bool CClientManager::InitializeItemTable()
|
||||
|
||||
|
||||
//========================================================================//
|
||||
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
|
||||
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
|
||||
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
|
||||
// <참고>
|
||||
// 각 row 들 중,
|
||||
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
|
||||
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
|
||||
//========================================================================//
|
||||
|
||||
//vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다.
|
||||
//vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다.
|
||||
set<int> vnumSet;
|
||||
|
||||
//파일 읽어오기.
|
||||
//파일 읽어오기.
|
||||
cCsvTable data;
|
||||
if(!data.Load("item_proto.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "item_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "item_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
return false;
|
||||
}
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
|
||||
if (!m_vec_itemTable.empty())
|
||||
{
|
||||
@@ -679,8 +679,8 @@ bool CClientManager::InitializeItemTable()
|
||||
m_map_itemTableByVnum.clear();
|
||||
}
|
||||
|
||||
//===== 아이템 테이블 생성 =====//
|
||||
//새로 추가되는 갯수를 파악한다.
|
||||
//===== 아이템 테이블 생성 =====//
|
||||
//새로 추가되는 갯수를 파악한다.
|
||||
int addNumber = 0;
|
||||
while(data.Next()) {
|
||||
int vnum = atoi(data.AsStringByIndex(0));
|
||||
@@ -690,14 +690,14 @@ bool CClientManager::InitializeItemTable()
|
||||
addNumber++;
|
||||
}
|
||||
}
|
||||
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
|
||||
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
|
||||
data.Destroy();
|
||||
if(!data.Load("item_proto.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "item_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "item_proto.txt 파일을 읽어오지 못했습니다\n");
|
||||
return false;
|
||||
}
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
|
||||
|
||||
m_vec_itemTable.resize(data.m_File.GetRowCount() - 1 + addNumber);
|
||||
memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size());
|
||||
@@ -712,16 +712,16 @@ bool CClientManager::InitializeItemTable()
|
||||
std::map<DWORD, TItemTable *>::iterator it_map_itemTable;
|
||||
it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col)));
|
||||
if(it_map_itemTable == test_map_itemTableByVnum.end()) {
|
||||
//각 칼럼 데이터 저장
|
||||
//각 칼럼 데이터 저장
|
||||
|
||||
if (!Set_Proto_Item_Table(item_table, data, localMap))
|
||||
{
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다!
|
||||
} else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다!
|
||||
TItemTable *tempTable = it_map_itemTable->second;
|
||||
|
||||
item_table->dwVnum = tempTable->dwVnum;
|
||||
@@ -778,19 +778,19 @@ bool CClientManager::InitializeItemTable()
|
||||
//_______________________________________________________________________//
|
||||
|
||||
//========================================================================//
|
||||
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
|
||||
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
|
||||
//========================================================================//
|
||||
test_data.Destroy();
|
||||
if(!test_data.Load("item_proto_test.txt",'\t'))
|
||||
{
|
||||
fprintf(stderr, "item_proto_test.txt 파일을 읽어오지 못했습니다\n");
|
||||
fprintf(stderr, "item_proto_test.txt 파일을 읽어오지 못했습니다\n");
|
||||
//return false;
|
||||
} else {
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
test_data.Next(); //설명 로우 넘어가기.
|
||||
|
||||
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
|
||||
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
|
||||
{
|
||||
//중복되는 부분이면 넘어간다.
|
||||
//중복되는 부분이면 넘어간다.
|
||||
set<int>::iterator itVnum;
|
||||
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
|
||||
if (itVnum != vnumSet.end()) {
|
||||
@@ -799,7 +799,7 @@ bool CClientManager::InitializeItemTable()
|
||||
|
||||
if (!Set_Proto_Item_Table(item_table, test_data, localMap))
|
||||
{
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
fprintf(stderr, "아이템 프로토 테이블 셋팅 실패.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Main.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Main.h"
|
||||
@@ -126,13 +126,13 @@ const char* __GetWarType(int n)
|
||||
switch (n)
|
||||
{
|
||||
case 0 :
|
||||
return "패왕";
|
||||
return "패왕";
|
||||
case 1 :
|
||||
return "맹장";
|
||||
return "맹장";
|
||||
case 2 :
|
||||
return "수호";
|
||||
return "수호";
|
||||
default :
|
||||
return "없는 번호";
|
||||
return "없는 번호";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
|
||||
|
||||
case GUILD_WAR_WAIT_START:
|
||||
sys_log(0, "GuildWar: GUILD_WAR_WAIT_START type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
case GUILD_WAR_RESERVE: // 길드전 예약
|
||||
case GUILD_WAR_RESERVE: // 길드전 예약
|
||||
if (p->bWar != GUILD_WAR_WAIT_START)
|
||||
sys_log(0, "GuildWar: GUILD_WAR_RESERVE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
@@ -173,21 +173,21 @@ void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
|
||||
|
||||
break;
|
||||
|
||||
case GUILD_WAR_ON_WAR: // 길드전을 시작 시킨다. (필드전은 바로 시작 됨)
|
||||
case GUILD_WAR_ON_WAR: // 길드전을 시작 시킨다. (필드전은 바로 시작 됨)
|
||||
sys_log(0, "GuildWar: GUILD_WAR_ON_WAR type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo);
|
||||
break;
|
||||
|
||||
case GUILD_WAR_OVER: // 길드전 정상 종료
|
||||
case GUILD_WAR_OVER: // 길드전 정상 종료
|
||||
sys_log(0, "GuildWar: GUILD_WAR_OVER type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice);
|
||||
break;
|
||||
|
||||
case GUILD_WAR_END: // 길드전 비정상 종료
|
||||
case GUILD_WAR_END: // 길드전 비정상 종료
|
||||
sys_log(0, "GuildWar: GUILD_WAR_END type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
|
||||
return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.
|
||||
return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.
|
||||
|
||||
case GUILD_WAR_CANCEL :
|
||||
sys_log(0, "GuildWar: GUILD_WAR_CANCEL type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
@@ -249,7 +249,7 @@ TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
|
||||
TAccountTable * pkTab = new TAccountTable;
|
||||
memset(pkTab, 0, sizeof(TAccountTable));
|
||||
|
||||
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
|
||||
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
|
||||
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
|
||||
str_to_number(pkTab->id, row[col++]);
|
||||
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
|
||||
@@ -373,7 +373,7 @@ void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
|
||||
|
||||
if (info->account_index == 0)
|
||||
{
|
||||
// 계정이 없네?
|
||||
// 계정이 없네?
|
||||
if (msg->Get()->uiNumRows == 0)
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: no account");
|
||||
@@ -415,14 +415,14 @@ void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info->pAccountTable) // 이럴리는 없겠지만;;
|
||||
if (!info->pAccountTable) // 이럴리는 없겠지만;;
|
||||
{
|
||||
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
|
||||
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
|
||||
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
|
||||
{
|
||||
sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#include "stdafx.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Config.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "ClientManager.h"
|
||||
@@ -32,7 +32,7 @@ bool CreateItemTableFromRes(MYSQL_RES * res, std::vector<TPlayerItem> * pVec, DW
|
||||
|
||||
int rows;
|
||||
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
|
||||
{
|
||||
pVec->clear();
|
||||
return true;
|
||||
@@ -159,7 +159,7 @@ size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * p
|
||||
pkTab->horse.sStamina,
|
||||
pkTab->horse_skill_point);
|
||||
|
||||
// Binary 로 바꾸기 위한 임시 공간
|
||||
// Binary 로 바꾸기 위한 임시 공간
|
||||
static char text[8192 + 1];
|
||||
|
||||
CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills));
|
||||
@@ -211,7 +211,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
TPlayerTable * pTab;
|
||||
|
||||
//
|
||||
// 한 계정에 속한 모든 캐릭터들 캐쉬처리
|
||||
// 한 계정에 속한 모든 캐릭터들 캐쉬처리
|
||||
//
|
||||
CLoginData * pLoginData = GetLoginDataByAID(packet->account_id);
|
||||
|
||||
@@ -223,12 +223,12 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
|
||||
// 2. 유저정보가 DBCache 에 없음 : DB에서
|
||||
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
|
||||
// 2. 유저정보가 DBCache 에 없음 : DB에서
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
//----------------------------------
|
||||
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
|
||||
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
|
||||
//----------------------------------
|
||||
if ((c = GetPlayerCache(packet->player_id)))
|
||||
{
|
||||
@@ -268,13 +268,13 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
sys_log(0, "[PLAYER_LOAD] ID %s pid %d gold %d ", pTab->name, pTab->id, pTab->gold);
|
||||
|
||||
//--------------------------------------------
|
||||
// 아이템 & AFFECT & QUEST 로딩 :
|
||||
// 아이템 & AFFECT & QUEST 로딩 :
|
||||
//--------------------------------------------
|
||||
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
|
||||
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
|
||||
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
|
||||
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
|
||||
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
|
||||
/////////////////////////////////////////////
|
||||
if (pSet)
|
||||
{
|
||||
@@ -289,7 +289,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
CItemCache * c = *it++;
|
||||
TPlayerItem * p = c->Get();
|
||||
|
||||
if (p->vnum) // vnum이 없으면 삭제된 아이템이다.
|
||||
if (p->vnum) // vnum이 없으면 삭제된 아이템이다.
|
||||
thecore_memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem));
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle));
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
|
||||
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
|
||||
/////////////////////////////////////////////
|
||||
else
|
||||
{
|
||||
@@ -350,7 +350,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
//return;
|
||||
}
|
||||
//----------------------------------
|
||||
// 2. 유저정보가 DBCache 에 없음 : DB에서
|
||||
// 2. 유저정보가 DBCache 에 없음 : DB에서
|
||||
//----------------------------------
|
||||
else
|
||||
{
|
||||
@@ -359,7 +359,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
char queryStr[QUERY_MAX_LEN];
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// 캐릭터 정보 얻어오기 : 무조건 DB에서
|
||||
// 캐릭터 정보 얻어오기 : 무조건 DB에서
|
||||
//--------------------------------------------------------------
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT "
|
||||
@@ -375,7 +375,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo);
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// 아이템 가져오기
|
||||
// 아이템 가져오기
|
||||
//--------------------------------------------------------------
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 "
|
||||
@@ -384,15 +384,15 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
|
||||
CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// QUEST 가져오기
|
||||
// QUEST 가져오기
|
||||
//--------------------------------------------------------------
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d",
|
||||
GetTablePostfix(), packet->player_id);
|
||||
CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id));
|
||||
//독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다
|
||||
//독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다
|
||||
//--------------------------------------------------------------
|
||||
// AFFECT 가져오기
|
||||
// AFFECT 가져오기
|
||||
//--------------------------------------------------------------
|
||||
snprintf(queryStr, sizeof(queryStr),
|
||||
"SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d",
|
||||
@@ -409,21 +409,21 @@ void CClientManager::ItemAward(CPeer * peer,char* login)
|
||||
std::set<TItemAward *> * pSet = ItemAwardManager::instance().GetByLogin(login_t);
|
||||
if(pSet == NULL)
|
||||
return;
|
||||
__typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴
|
||||
__typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴
|
||||
while(it != pSet->end() )
|
||||
{
|
||||
TItemAward * pItemAward = *(it++);
|
||||
char* whyStr = pItemAward->szWhy; //why 콜룸 읽기
|
||||
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
|
||||
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
|
||||
char* whyStr = pItemAward->szWhy; //why 콜룸 읽기
|
||||
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
|
||||
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
|
||||
char command[20] = "";
|
||||
strcpy(command,GetCommand(cmdStr)); // command 얻기
|
||||
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
|
||||
strcpy(command,GetCommand(cmdStr)); // command 얻기
|
||||
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
|
||||
{
|
||||
TPacketItemAwardInfromer giftData;
|
||||
strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사
|
||||
strcpy(giftData.command, command); //명령어 복사
|
||||
giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사
|
||||
strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사
|
||||
strcpy(giftData.command, command); //명령어 복사
|
||||
giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사
|
||||
ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
|
||||
}
|
||||
}
|
||||
@@ -444,7 +444,7 @@ char* CClientManager::GetCommand(char* str)
|
||||
|
||||
bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
|
||||
{
|
||||
if (mysql_num_rows(res) == 0) // 데이터 없음
|
||||
if (mysql_num_rows(res) == 0) // 데이터 없음
|
||||
return false;
|
||||
|
||||
memset(pkTab, 0, sizeof(TPlayerTable));
|
||||
@@ -531,11 +531,11 @@ bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
|
||||
int max_point = pkTab->level - 9;
|
||||
|
||||
int skill_point =
|
||||
MIN(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력
|
||||
MIN(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광
|
||||
MIN(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON 말소환
|
||||
MIN(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HP보강
|
||||
MIN(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항
|
||||
MIN(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력
|
||||
MIN(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광
|
||||
MIN(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON 말소환
|
||||
MIN(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HP보강
|
||||
MIN(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항
|
||||
|
||||
pkTab->sub_skill_point = max_point - skill_point;
|
||||
}
|
||||
@@ -575,13 +575,13 @@ void CClientManager::RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD
|
||||
{
|
||||
sys_log(0, "QID_QUEST %u", info->dwHandle);
|
||||
RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
|
||||
//aid얻기
|
||||
//aid얻기
|
||||
ClientHandleInfo* temp1 = info.get();
|
||||
if (temp1 == NULL)
|
||||
break;
|
||||
|
||||
CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); //
|
||||
//독일 선물 기능
|
||||
//독일 선물 기능
|
||||
if( pLoginData1->GetAccountRef().login == NULL)
|
||||
break;
|
||||
if( pLoginData1 == NULL )
|
||||
@@ -672,14 +672,14 @@ void CClientManager::RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHa
|
||||
void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID)
|
||||
{
|
||||
static std::vector<TPlayerItem> s_items;
|
||||
//DB에서 아이템 정보를 읽어온다.
|
||||
//DB에서 아이템 정보를 읽어온다.
|
||||
CreateItemTableFromRes(pRes, &s_items, dwPID);
|
||||
DWORD dwCount = s_items.size();
|
||||
|
||||
peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
|
||||
peer->EncodeDWORD(dwCount);
|
||||
|
||||
//CacheSet을 만든다
|
||||
//CacheSet을 만든다
|
||||
CreateItemCacheSet(dwPID);
|
||||
|
||||
// ITEM_LOAD_LOG_ATTACH_PID
|
||||
@@ -691,7 +691,7 @@ void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHa
|
||||
peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
|
||||
|
||||
for (DWORD i = 0; i < dwCount; ++i)
|
||||
PutItemCache(&s_items[i], true); // 로드한 것은 따로 저장할 필요 없으므로, 인자 bSkipQuery에 true를 넣는다.
|
||||
PutItemCache(&s_items[i], true); // 로드한 것은 따로 저장할 필요 없으므로, 인자 bSkipQuery에 true를 넣는다.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ void CClientManager::RESULT_AFFECT_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dw
|
||||
{
|
||||
int iNumRows;
|
||||
|
||||
if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
|
||||
if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
|
||||
return;
|
||||
|
||||
static std::vector<TPacketAffectElement> s_elements;
|
||||
@@ -796,7 +796,7 @@ void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerC
|
||||
int queryLen;
|
||||
int player_id;
|
||||
|
||||
// 한 계정에 X초 내로 캐릭터 생성을 할 수 없다.
|
||||
// 한 계정에 X초 내로 캐릭터 생성을 할 수 없다.
|
||||
time_by_id_map_t::iterator it = s_createTimeByAccountID.find(packet->account_id);
|
||||
|
||||
if (it != s_createTimeByAccountID.end())
|
||||
@@ -1027,7 +1027,7 @@ void CClientManager::__QUERY_PLAYER_DELETE(CPeer* peer, DWORD dwHandle, TPlayerD
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/06/10 Bang2ni - 플레이어 삭제시 가격정보 리스트 삭제 추가.
|
||||
// @version 05/06/10 Bang2ni - 플레이어 삭제시 가격정보 리스트 삭제 추가.
|
||||
//
|
||||
void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
|
||||
{
|
||||
@@ -1078,14 +1078,14 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
// 삭제 성공
|
||||
// 삭제 성공
|
||||
sys_log(0, "PLAYER_DELETE SUCCESS %u", dwPID);
|
||||
|
||||
char account_index_string[16];
|
||||
|
||||
snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index);
|
||||
|
||||
// 플레이어 테이블을 캐쉬에서 삭제한다.
|
||||
// 플레이어 테이블을 캐쉬에서 삭제한다.
|
||||
CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id);
|
||||
|
||||
if (pkPlayerCache)
|
||||
@@ -1094,7 +1094,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
|
||||
delete pkPlayerCache;
|
||||
}
|
||||
|
||||
// 아이템들을 캐쉬에서 삭제한다.
|
||||
// 아이템들을 캐쉬에서 삭제한다.
|
||||
TItemCacheSet * pSet = GetItemCacheSet(pi->player_id);
|
||||
|
||||
if (pSet)
|
||||
@@ -1157,7 +1157,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
|
||||
}
|
||||
else
|
||||
{
|
||||
// 삭제 실패
|
||||
// 삭제 실패
|
||||
sys_log(0, "PLAYER_DELETE FAIL NO ROW");
|
||||
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
|
||||
peer->EncodeBYTE(pi->account_index);
|
||||
@@ -1242,7 +1242,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
|
||||
|
||||
if (res->uiNumRows == 0)
|
||||
{
|
||||
// 새로운 하이스코어를 삽입
|
||||
// 새로운 하이스코어를 삽입
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
|
||||
CDBManager::instance().AsyncQuery(buf);
|
||||
@@ -1277,7 +1277,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
|
||||
CDBManager::instance().AsyncQuery(buf);
|
||||
}
|
||||
}
|
||||
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
|
||||
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
|
||||
delete pi;
|
||||
}
|
||||
|
||||
@@ -1285,10 +1285,10 @@ void CClientManager::InsertLogoutPlayer(DWORD pid)
|
||||
{
|
||||
TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
|
||||
|
||||
// 존재하지 않을경우 추가
|
||||
// 존재하지 않을경우 추가
|
||||
if (it != m_map_logout.end())
|
||||
{
|
||||
// 존재할경우 시간만 갱신
|
||||
// 존재할경우 시간만 갱신
|
||||
if (g_log)
|
||||
sys_log(0, "LOGOUT: Update player time pid(%d)", pid);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_CONFIG_H__
|
||||
#ifndef __INC_CONFIG_H__
|
||||
#define __INC_CONFIG_H__
|
||||
|
||||
typedef std::map<std::string, std::string> TValueMap;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "CsvReader.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
@@ -11,14 +11,14 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
/// 파싱용 state 열거값
|
||||
/// 파싱용 state 열거값
|
||||
enum ParseState
|
||||
{
|
||||
STATE_NORMAL = 0, ///< 일반 상태
|
||||
STATE_QUOTE ///< 따옴표 뒤의 상태
|
||||
STATE_NORMAL = 0, ///< 일반 상태
|
||||
STATE_QUOTE ///< 따옴표 뒤의 상태
|
||||
};
|
||||
|
||||
/// 문자열 좌우의 공백을 제거해서 반환한다.
|
||||
/// 문자열 좌우의 공백을 제거해서 반환한다.
|
||||
std::string Trim(std::string str)
|
||||
{
|
||||
str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
|
||||
@@ -26,7 +26,7 @@ namespace
|
||||
return str;
|
||||
}
|
||||
|
||||
/// \brief 주어진 문장에 있는 알파벳을 모두 소문자로 바꾼다.
|
||||
/// \brief 주어진 문장에 있는 알파벳을 모두 소문자로 바꾼다.
|
||||
std::string Lower(std::string original)
|
||||
{
|
||||
std::transform(original.begin(), original.end(), original.begin(), tolower);
|
||||
@@ -35,9 +35,9 @@ namespace
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
/// \param name 셀 이름
|
||||
/// \param index 셀 인덱스
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
/// \param name 셀 이름
|
||||
/// \param index 셀 인덱스
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvAlias::AddAlias(const char* name, size_t index)
|
||||
{
|
||||
@@ -51,7 +51,7 @@ void cCsvAlias::AddAlias(const char* name, size_t index)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 모든 데이터를 삭제한다.
|
||||
/// \brief 모든 데이터를 삭제한다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvAlias::Destroy()
|
||||
{
|
||||
@@ -60,9 +60,9 @@ void cCsvAlias::Destroy()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 숫자 인덱스를 이름으로 변환한다.
|
||||
/// \param index 숫자 인덱스
|
||||
/// \return const char* 이름
|
||||
/// \brief 숫자 인덱스를 이름으로 변환한다.
|
||||
/// \param index 숫자 인덱스
|
||||
/// \return const char* 이름
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const char* cCsvAlias::operator [] (size_t index) const
|
||||
{
|
||||
@@ -78,9 +78,9 @@ const char* cCsvAlias::operator [] (size_t index) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 이름을 숫자 인덱스로 변환한다.
|
||||
/// \param name 이름
|
||||
/// \return size_t 숫자 인덱스
|
||||
/// \brief 이름을 숫자 인덱스로 변환한다.
|
||||
/// \param name 이름
|
||||
/// \return size_t 숫자 인덱스
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t cCsvAlias::operator [] (const char* name) const
|
||||
{
|
||||
@@ -96,11 +96,11 @@ size_t cCsvAlias::operator [] (const char* name) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 로드했다면 true, 아니라면 false
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 로드했다면 true, 아니라면 false
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
|
||||
{
|
||||
@@ -109,7 +109,7 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
|
||||
std::ifstream file(fileName, std::ios::in);
|
||||
if (!file) return false;
|
||||
|
||||
Destroy(); // 기존의 데이터를 삭제
|
||||
Destroy(); // 기존의 데이터를 삭제
|
||||
|
||||
cCsvRow* row = NULL;
|
||||
ParseState state = STATE_NORMAL;
|
||||
@@ -124,33 +124,33 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
|
||||
std::string line(Trim(buf));
|
||||
if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
|
||||
|
||||
std::string text = std::string(line) + " "; // 파싱 lookahead 때문에 붙여준다.
|
||||
std::string text = std::string(line) + " "; // 파싱 lookahead 때문에 붙여준다.
|
||||
size_t cur = 0;
|
||||
|
||||
while (cur < text.size())
|
||||
{
|
||||
// 현재 모드가 QUOTE 모드일 때,
|
||||
// 현재 모드가 QUOTE 모드일 때,
|
||||
if (state == STATE_QUOTE)
|
||||
{
|
||||
// '"' 문자의 종류는 두 가지이다.
|
||||
// 1. 셀 내부에 특수 문자가 있을 경우 이를 알리는 셀 좌우의 것
|
||||
// 2. 셀 내부의 '"' 문자가 '"' 2개로 치환된 것
|
||||
// 이 중 첫번째 경우의 좌측에 있는 것은 CSV 파일이 정상적이라면,
|
||||
// 무조건 STATE_NORMAL에 걸리게 되어있다.
|
||||
// 그러므로 여기서 걸리는 것은 1번의 우측 경우나, 2번 경우 뿐이다.
|
||||
// 2번의 경우에는 무조건 '"' 문자가 2개씩 나타난다. 하지만 1번의
|
||||
// 우측 경우에는 아니다. 이를 바탕으로 해서 코드를 짜면...
|
||||
// '"' 문자의 종류는 두 가지이다.
|
||||
// 1. 셀 내부에 특수 문자가 있을 경우 이를 알리는 셀 좌우의 것
|
||||
// 2. 셀 내부의 '"' 문자가 '"' 2개로 치환된 것
|
||||
// 이 중 첫번째 경우의 좌측에 있는 것은 CSV 파일이 정상적이라면,
|
||||
// 무조건 STATE_NORMAL에 걸리게 되어있다.
|
||||
// 그러므로 여기서 걸리는 것은 1번의 우측 경우나, 2번 경우 뿐이다.
|
||||
// 2번의 경우에는 무조건 '"' 문자가 2개씩 나타난다. 하지만 1번의
|
||||
// 우측 경우에는 아니다. 이를 바탕으로 해서 코드를 짜면...
|
||||
if (text[cur] == quote)
|
||||
{
|
||||
// 다음 문자가 '"' 문자라면, 즉 연속된 '"' 문자라면
|
||||
// 이는 셀 내부의 '"' 문자가 치환된 것이다.
|
||||
// 다음 문자가 '"' 문자라면, 즉 연속된 '"' 문자라면
|
||||
// 이는 셀 내부의 '"' 문자가 치환된 것이다.
|
||||
if (text[cur+1] == quote)
|
||||
{
|
||||
token += quote;
|
||||
++cur;
|
||||
}
|
||||
// 다음 문자가 '"' 문자가 아니라면
|
||||
// 현재의 '"'문자는 셀의 끝을 알리는 문자라고 할 수 있다.
|
||||
// 다음 문자가 '"' 문자가 아니라면
|
||||
// 현재의 '"'문자는 셀의 끝을 알리는 문자라고 할 수 있다.
|
||||
else
|
||||
{
|
||||
state = STATE_NORMAL;
|
||||
@@ -161,25 +161,25 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
|
||||
token += text[cur];
|
||||
}
|
||||
}
|
||||
// 현재 모드가 NORMAL 모드일 때,
|
||||
// 현재 모드가 NORMAL 모드일 때,
|
||||
else if (state == STATE_NORMAL)
|
||||
{
|
||||
if (row == NULL)
|
||||
row = new cCsvRow();
|
||||
|
||||
// ',' 문자를 만났다면 셀의 끝의 의미한다.
|
||||
// 토큰으로서 셀 리스트에다가 집어넣고, 토큰을 초기화한다.
|
||||
// ',' 문자를 만났다면 셀의 끝의 의미한다.
|
||||
// 토큰으로서 셀 리스트에다가 집어넣고, 토큰을 초기화한다.
|
||||
if (text[cur] == seperator)
|
||||
{
|
||||
row->push_back(token);
|
||||
token.clear();
|
||||
}
|
||||
// '"' 문자를 만났다면, QUOTE 모드로 전환한다.
|
||||
// '"' 문자를 만났다면, QUOTE 모드로 전환한다.
|
||||
else if (text[cur] == quote)
|
||||
{
|
||||
state = STATE_QUOTE;
|
||||
}
|
||||
// 다른 일반 문자라면 현재 토큰에다가 덧붙인다.
|
||||
// 다른 일반 문자라면 현재 토큰에다가 덧붙인다.
|
||||
else
|
||||
{
|
||||
token += text[cur];
|
||||
@@ -189,8 +189,8 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
|
||||
++cur;
|
||||
}
|
||||
|
||||
// 마지막 셀은 끝에 ',' 문자가 없기 때문에 여기서 추가해줘야한다.
|
||||
// 단, 처음에 파싱 lookahead 때문에 붙인 스페이스 문자 두 개를 뗀다.
|
||||
// 마지막 셀은 끝에 ',' 문자가 없기 때문에 여기서 추가해줘야한다.
|
||||
// 단, 처음에 파싱 lookahead 때문에 붙인 스페이스 문자 두 개를 뗀다.
|
||||
if (state == STATE_NORMAL)
|
||||
{
|
||||
Assert(row != NULL);
|
||||
@@ -209,49 +209,49 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 가지고 있는 내용을 CSV 파일에다 저장한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param append true일 경우, 기존의 파일에다 덧붙인다. false인 경우에는
|
||||
/// 기존의 파일 내용을 삭제하고, 새로 쓴다.
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 저장했다면 true, 에러가 생긴 경우에는 false
|
||||
/// \brief 가지고 있는 내용을 CSV 파일에다 저장한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param append true일 경우, 기존의 파일에다 덧붙인다. false인 경우에는
|
||||
/// 기존의 파일 내용을 삭제하고, 새로 쓴다.
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 저장했다면 true, 에러가 생긴 경우에는 false
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
|
||||
{
|
||||
Assert(seperator != quote);
|
||||
|
||||
// 출력 모드에 따라 파일을 적당한 플래그로 생성한다.
|
||||
// 출력 모드에 따라 파일을 적당한 플래그로 생성한다.
|
||||
std::ofstream file;
|
||||
if (append) { file.open(fileName, std::ios::out | std::ios::app); }
|
||||
else { file.open(fileName, std::ios::out | std::ios::trunc); }
|
||||
|
||||
// 파일을 열지 못했다면, false를 리턴한다.
|
||||
// 파일을 열지 못했다면, false를 리턴한다.
|
||||
if (!file) return false;
|
||||
|
||||
char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
|
||||
char quote_escape_string[3] = { quote, quote, 0 };
|
||||
|
||||
// 모든 행을 횡단하면서...
|
||||
// 모든 행을 횡단하면서...
|
||||
for (size_t i=0; i<m_Rows.size(); i++)
|
||||
{
|
||||
const cCsvRow& row = *((*this)[i]);
|
||||
|
||||
std::string line;
|
||||
|
||||
// 행 안의 모든 토큰을 횡단하면서...
|
||||
// 행 안의 모든 토큰을 횡단하면서...
|
||||
for (size_t j=0; j<row.size(); j++)
|
||||
{
|
||||
const std::string& token = row[j];
|
||||
|
||||
// 일반적인('"' 또는 ','를 포함하지 않은)
|
||||
// 토큰이라면 그냥 저장하면 된다.
|
||||
// 일반적인('"' 또는 ','를 포함하지 않은)
|
||||
// 토큰이라면 그냥 저장하면 된다.
|
||||
if (token.find_first_of(special_chars) == std::string::npos)
|
||||
{
|
||||
line += token;
|
||||
}
|
||||
// 특수문자를 포함한 토큰이라면 문자열 좌우에 '"'를 붙여주고,
|
||||
// 문자열 내부의 '"'를 두 개로 만들어줘야한다.
|
||||
// 특수문자를 포함한 토큰이라면 문자열 좌우에 '"'를 붙여주고,
|
||||
// 문자열 내부의 '"'를 두 개로 만들어줘야한다.
|
||||
else
|
||||
{
|
||||
line += quote;
|
||||
@@ -265,11 +265,11 @@ bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quot
|
||||
line += quote;
|
||||
}
|
||||
|
||||
// 마지막 셀이 아니라면 ','를 토큰의 뒤에다 붙여줘야한다.
|
||||
// 마지막 셀이 아니라면 ','를 토큰의 뒤에다 붙여줘야한다.
|
||||
if (j != row.size() - 1) { line += seperator; }
|
||||
}
|
||||
|
||||
// 라인을 출력한다.
|
||||
// 라인을 출력한다.
|
||||
file << line << std::endl;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quot
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 모든 데이터를 메모리에서 삭제한다.
|
||||
/// \brief 모든 데이터를 메모리에서 삭제한다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvFile::Destroy()
|
||||
{
|
||||
@@ -288,9 +288,9 @@ void cCsvFile::Destroy()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \param index 인덱스
|
||||
/// \return cCsvRow* 해당 행
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \param index 인덱스
|
||||
/// \return cCsvRow* 해당 행
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvRow* cCsvFile::operator [] (size_t index)
|
||||
{
|
||||
@@ -299,9 +299,9 @@ cCsvRow* cCsvFile::operator [] (size_t index)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \param index 인덱스
|
||||
/// \return const cCsvRow* 해당 행
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \param index 인덱스
|
||||
/// \return const cCsvRow* 해당 행
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const cCsvRow* cCsvFile::operator [] (size_t index) const
|
||||
{
|
||||
@@ -310,7 +310,7 @@ const cCsvRow* cCsvFile::operator [] (size_t index) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 생성자
|
||||
/// \brief 생성자
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvTable::cCsvTable()
|
||||
: m_CurRow(-1)
|
||||
@@ -318,18 +318,18 @@ cCsvTable::cCsvTable()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 소멸자
|
||||
/// \brief 소멸자
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cCsvTable::~cCsvTable()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 로드했다면 true, 아니라면 false
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \param fileName CSV 파일 이름
|
||||
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
|
||||
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
|
||||
/// \return bool 무사히 로드했다면 true, 아니라면 false
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
|
||||
{
|
||||
@@ -338,19 +338,19 @@ bool cCsvTable::Load(const char* fileName, const char seperator, const char quot
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 다음 행으로 넘어간다.
|
||||
/// \return bool 다음 행으로 무사히 넘어간 경우 true를 반환하고, 더 이상
|
||||
/// 넘어갈 행이 존재하지 않는 경우에는 false를 반환한다.
|
||||
/// \brief 다음 행으로 넘어간다.
|
||||
/// \return bool 다음 행으로 무사히 넘어간 경우 true를 반환하고, 더 이상
|
||||
/// 넘어갈 행이 존재하지 않는 경우에는 false를 반환한다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool cCsvTable::Next()
|
||||
{
|
||||
// 20억번 정도 호출하면 오버플로가 일어날텐데...괜찮겠지?
|
||||
// 20억번 정도 호출하면 오버플로가 일어날텐데...괜찮겠지?
|
||||
return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 현재 행의 셀 숫자를 반환한다.
|
||||
/// \return size_t 현재 행의 셀 숫자
|
||||
/// \brief 현재 행의 셀 숫자를 반환한다.
|
||||
/// \return size_t 현재 행의 셀 숫자
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t cCsvTable::ColCount() const
|
||||
{
|
||||
@@ -358,9 +358,9 @@ size_t cCsvTable::ColCount() const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 인덱스를 이용해 int 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return int 셀 값
|
||||
/// \brief 인덱스를 이용해 int 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return int 셀 값
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int cCsvTable::AsInt(size_t index) const
|
||||
{
|
||||
@@ -371,9 +371,9 @@ int cCsvTable::AsInt(size_t index) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 인덱스를 이용해 double 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return double 셀 값
|
||||
/// \brief 인덱스를 이용해 double 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return double 셀 값
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
double cCsvTable::AsDouble(size_t index) const
|
||||
{
|
||||
@@ -384,9 +384,9 @@ double cCsvTable::AsDouble(size_t index) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 인덱스를 이용해 std::string 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return const char* 셀 값
|
||||
/// \brief 인덱스를 이용해 std::string 형으로 셀 값을 반환한다.
|
||||
/// \param index 셀 인덱스
|
||||
/// \return const char* 셀 값
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const char* cCsvTable::AsStringByIndex(size_t index) const
|
||||
{
|
||||
@@ -397,7 +397,7 @@ const char* cCsvTable::AsStringByIndex(size_t index) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief alias를 포함해 모든 데이터를 삭제한다.
|
||||
/// \brief alias를 포함해 모든 데이터를 삭제한다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void cCsvTable::Destroy()
|
||||
{
|
||||
@@ -407,10 +407,10 @@ void cCsvTable::Destroy()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief 현재 행을 반환한다.
|
||||
/// \return const cCsvRow* 액세스가 가능한 현재 행이 존재하는 경우에는 그 행의
|
||||
/// 포인터를 반환하고, 더 이상 액세스 가능한 행이 없는 경우에는 NULL을
|
||||
/// 반환한다.
|
||||
/// \brief 현재 행을 반환한다.
|
||||
/// \return const cCsvRow* 액세스가 가능한 현재 행이 존재하는 경우에는 그 행의
|
||||
/// 포인터를 반환하고, 더 이상 액세스 가능한 행이 없는 경우에는 NULL을
|
||||
/// 반환한다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const cCsvRow* const cCsvTable::CurRow() const
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __CSVFILE_H__
|
||||
#ifndef __CSVFILE_H__
|
||||
#define __CSVFILE_H__
|
||||
|
||||
#include <string>
|
||||
@@ -12,28 +12,28 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvAlias
|
||||
/// \brief CSV 파일을 수정했을 때 발생하는 인덱스 문제를 줄이기 위한
|
||||
/// 별명 객체.
|
||||
/// \brief CSV 파일을 수정했을 때 발생하는 인덱스 문제를 줄이기 위한
|
||||
/// 별명 객체.
|
||||
///
|
||||
/// 예를 들어 0번 컬럼이 A에 관한 내용을 포함하고, 1번 컬럼이 B에 관한 내용을
|
||||
/// 포함하고 있었는데...
|
||||
/// 예를 들어 0번 컬럼이 A에 관한 내용을 포함하고, 1번 컬럼이 B에 관한 내용을
|
||||
/// 포함하고 있었는데...
|
||||
///
|
||||
/// <pre>
|
||||
/// int a = row.AsInt(0);
|
||||
/// int b = row.AsInt(1);
|
||||
/// </pre>
|
||||
///
|
||||
/// 그 사이에 C에 관한 내용을 포함하는 컬럼이 끼어든 경우, 하드코딩되어 있는
|
||||
/// 1번을 찾아서 고쳐야 하는데, 상당히 에러가 발생하기 쉬운 작업이다.
|
||||
/// 그 사이에 C에 관한 내용을 포함하는 컬럼이 끼어든 경우, 하드코딩되어 있는
|
||||
/// 1번을 찾아서 고쳐야 하는데, 상당히 에러가 발생하기 쉬운 작업이다.
|
||||
///
|
||||
/// <pre>
|
||||
/// int a = row.AsInt(0);
|
||||
/// int c = row.AsInt(1);
|
||||
/// int b = row.AsInt(2); <-- 이 부분을 일일이 신경써야 한다.
|
||||
/// int b = row.AsInt(2); <-- 이 부분을 일일이 신경써야 한다.
|
||||
/// </pre>
|
||||
///
|
||||
/// 이 부분을 문자열로 처리하면 유지보수에 들어가는 수고를 약간이나마 줄일 수
|
||||
/// 있다.
|
||||
/// 이 부분을 문자열로 처리하면 유지보수에 들어가는 수고를 약간이나마 줄일 수
|
||||
/// 있다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvAlias
|
||||
@@ -47,51 +47,51 @@ private:
|
||||
typedef std::map<size_t, std::string> INDEX2NAME_MAP;
|
||||
#endif
|
||||
|
||||
NAME2INDEX_MAP m_Name2Index; ///< 셀 인덱스 대신으로 사용하기 위한 이름들
|
||||
INDEX2NAME_MAP m_Index2Name; ///< 잘못된 alias를 검사하기 위한 추가적인 맵
|
||||
NAME2INDEX_MAP m_Name2Index; ///< 셀 인덱스 대신으로 사용하기 위한 이름들
|
||||
INDEX2NAME_MAP m_Index2Name; ///< 잘못된 alias를 검사하기 위한 추가적인 맵
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 생성자
|
||||
/// \brief 생성자
|
||||
cCsvAlias() {}
|
||||
|
||||
/// \brief 소멸자
|
||||
/// \brief 소멸자
|
||||
virtual ~cCsvAlias() {}
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
void AddAlias(const char* name, size_t index);
|
||||
|
||||
/// \brief 모든 데이터를 삭제한다.
|
||||
/// \brief 모든 데이터를 삭제한다.
|
||||
void Destroy();
|
||||
|
||||
/// \brief 숫자 인덱스를 이름으로 변환한다.
|
||||
/// \brief 숫자 인덱스를 이름으로 변환한다.
|
||||
const char* operator [] (size_t index) const;
|
||||
|
||||
/// \brief 이름을 숫자 인덱스로 변환한다.
|
||||
/// \brief 이름을 숫자 인덱스로 변환한다.
|
||||
size_t operator [] (const char* name) const;
|
||||
|
||||
|
||||
private:
|
||||
/// \brief 복사 생성자 금지
|
||||
/// \brief 복사 생성자 금지
|
||||
cCsvAlias(const cCsvAlias&) {}
|
||||
|
||||
/// \brief 대입 연산자 금지
|
||||
/// \brief 대입 연산자 금지
|
||||
const cCsvAlias& operator = (const cCsvAlias&) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvRow
|
||||
/// \brief CSV 파일의 한 행을 캡슐화한 클래스
|
||||
/// \brief CSV 파일의 한 행을 캡슐화한 클래스
|
||||
///
|
||||
/// CSV의 기본 포맷은 엑셀에서 보이는 하나의 셀을 ',' 문자로 구분한 것이다.
|
||||
/// 하지만, 셀 안에 특수 문자로 쓰이는 ',' 문자나 '"' 문자가 들어갈 경우,
|
||||
/// 모양이 약간 이상하게 변한다. 다음은 그 변화의 예이다.
|
||||
/// CSV의 기본 포맷은 엑셀에서 보이는 하나의 셀을 ',' 문자로 구분한 것이다.
|
||||
/// 하지만, 셀 안에 특수 문자로 쓰이는 ',' 문자나 '"' 문자가 들어갈 경우,
|
||||
/// 모양이 약간 이상하게 변한다. 다음은 그 변화의 예이다.
|
||||
///
|
||||
/// <pre>
|
||||
/// 엑셀에서 보이는 모양 | 실제 CSV 파일에 들어가있는 모양
|
||||
/// 엑셀에서 보이는 모양 | 실제 CSV 파일에 들어가있는 모양
|
||||
/// ---------------------+----------------------------------------------------
|
||||
/// ItemPrice | ItemPrice
|
||||
/// Item,Price | "Item,Price"
|
||||
@@ -101,9 +101,9 @@ private:
|
||||
/// Item",Price | "Item"",Price"
|
||||
/// </pre>
|
||||
///
|
||||
/// 이 예로서 다음과 같은 사항을 알 수 있다.
|
||||
/// - 셀 내부에 ',' 또는 '"' 문자가 들어갈 경우, 셀 좌우에 '"' 문자가 생긴다.
|
||||
/// - 셀 내부의 '"' 문자는 2개로 치환된다.
|
||||
/// 이 예로서 다음과 같은 사항을 알 수 있다.
|
||||
/// - 셀 내부에 ',' 또는 '"' 문자가 들어갈 경우, 셀 좌우에 '"' 문자가 생긴다.
|
||||
/// - 셀 내부의 '"' 문자는 2개로 치환된다.
|
||||
///
|
||||
/// \sa cCsvFile
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -111,51 +111,51 @@ private:
|
||||
class cCsvRow : public std::vector<std::string>
|
||||
{
|
||||
public:
|
||||
/// \brief 기본 생성자
|
||||
/// \brief 기본 생성자
|
||||
cCsvRow() {}
|
||||
|
||||
/// \brief 소멸자
|
||||
/// \brief 소멸자
|
||||
~cCsvRow() {}
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 해당 셀의 데이터를 int 형으로 반환한다.
|
||||
/// \brief 해당 셀의 데이터를 int 형으로 반환한다.
|
||||
int AsInt(size_t index) const { return atoi(at(index).c_str()); }
|
||||
|
||||
/// \brief 해당 셀의 데이터를 double 형으로 반환한다.
|
||||
/// \brief 해당 셀의 데이터를 double 형으로 반환한다.
|
||||
double AsDouble(size_t index) const { return atof(at(index).c_str()); }
|
||||
|
||||
/// \brief 해당 셀의 데이터를 문자열로 반환한다.
|
||||
/// \brief 해당 셀의 데이터를 문자열로 반환한다.
|
||||
const char* AsString(size_t index) const { return at(index).c_str(); }
|
||||
|
||||
/// \brief 해당하는 이름의 셀 데이터를 int 형으로 반환한다.
|
||||
/// \brief 해당하는 이름의 셀 데이터를 int 형으로 반환한다.
|
||||
int AsInt(const char* name, const cCsvAlias& alias) const {
|
||||
return atoi( at(alias[name]).c_str() );
|
||||
}
|
||||
|
||||
/// \brief 해당하는 이름의 셀 데이터를 int 형으로 반환한다.
|
||||
/// \brief 해당하는 이름의 셀 데이터를 int 형으로 반환한다.
|
||||
double AsDouble(const char* name, const cCsvAlias& alias) const {
|
||||
return atof( at(alias[name]).c_str() );
|
||||
}
|
||||
|
||||
/// \brief 해당하는 이름의 셀 데이터를 문자열로 반환한다.
|
||||
/// \brief 해당하는 이름의 셀 데이터를 문자열로 반환한다.
|
||||
const char* AsString(const char* name, const cCsvAlias& alias) const {
|
||||
return at(alias[name]).c_str();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/// \brief 복사 생성자 금지
|
||||
/// \brief 복사 생성자 금지
|
||||
cCsvRow(const cCsvRow&) {}
|
||||
|
||||
/// \brief 대입 연산자 금지
|
||||
/// \brief 대입 연산자 금지
|
||||
const cCsvRow& operator = (const cCsvRow&) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvFile
|
||||
/// \brief CSV(Comma Seperated Values) 파일을 read/write하기 위한 클래스
|
||||
/// \brief CSV(Comma Seperated Values) 파일을 read/write하기 위한 클래스
|
||||
///
|
||||
/// <b>sample</b>
|
||||
/// <pre>
|
||||
@@ -179,8 +179,8 @@ private:
|
||||
/// file.save("test.csv", false);
|
||||
/// </pre>
|
||||
///
|
||||
/// \todo 파일에서만 읽어들일 것이 아니라, 메모리 소스로부터 읽는 함수도
|
||||
/// 있어야 할 듯 하다.
|
||||
/// \todo 파일에서만 읽어들일 것이 아니라, 메모리 소스로부터 읽는 함수도
|
||||
/// 있어야 할 듯 하다.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class cCsvFile
|
||||
@@ -188,55 +188,55 @@ class cCsvFile
|
||||
private:
|
||||
typedef std::vector<cCsvRow*> ROWS;
|
||||
|
||||
ROWS m_Rows; ///< 행 컬렉션
|
||||
ROWS m_Rows; ///< 행 컬렉션
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 생성자
|
||||
/// \brief 생성자
|
||||
cCsvFile() {}
|
||||
|
||||
/// \brief 소멸자
|
||||
/// \brief 소멸자
|
||||
virtual ~cCsvFile() { Destroy(); }
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
bool Load(const char* fileName, const char seperator=',', const char quote='"');
|
||||
|
||||
/// \brief 가지고 있는 내용을 CSV 파일에다 저장한다.
|
||||
/// \brief 가지고 있는 내용을 CSV 파일에다 저장한다.
|
||||
bool Save(const char* fileName, bool append=false, char seperator=',', char quote='"') const;
|
||||
|
||||
/// \brief 모든 데이터를 메모리에서 삭제한다.
|
||||
/// \brief 모든 데이터를 메모리에서 삭제한다.
|
||||
void Destroy();
|
||||
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
cCsvRow* operator [] (size_t index);
|
||||
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
/// \brief 해당하는 인덱스의 행을 반환한다.
|
||||
const cCsvRow* operator [] (size_t index) const;
|
||||
|
||||
/// \brief 행의 갯수를 반환한다.
|
||||
/// \brief 행의 갯수를 반환한다.
|
||||
size_t GetRowCount() const { return m_Rows.size(); }
|
||||
|
||||
|
||||
private:
|
||||
/// \brief 복사 생성자 금지
|
||||
/// \brief 복사 생성자 금지
|
||||
cCsvFile(const cCsvFile&) {}
|
||||
|
||||
/// \brief 대입 연산자 금지
|
||||
/// \brief 대입 연산자 금지
|
||||
const cCsvFile& operator = (const cCsvFile&) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class cCsvTable
|
||||
/// \brief CSV 파일을 이용해 테이블 데이터를 로드하는 경우가 많은데, 이 클래스는
|
||||
/// 그 작업을 좀 더 쉽게 하기 위해 만든 유틸리티 클래스다.
|
||||
/// \brief CSV 파일을 이용해 테이블 데이터를 로드하는 경우가 많은데, 이 클래스는
|
||||
/// 그 작업을 좀 더 쉽게 하기 위해 만든 유틸리티 클래스다.
|
||||
///
|
||||
/// CSV 파일을 로드하는 경우, 숫자를 이용해 셀을 액세스해야 하는데, CSV
|
||||
/// 파일의 포맷이 바뀌는 경우, 이 숫자들을 변경해줘야한다. 이 작업이 꽤
|
||||
/// 신경 집중을 요구하는 데다가, 에러가 발생하기 쉽다. 그러므로 숫자로
|
||||
/// 액세스하기보다는 문자열로 액세스하는 것이 약간 느리지만 낫다고 할 수 있다.
|
||||
/// CSV 파일을 로드하는 경우, 숫자를 이용해 셀을 액세스해야 하는데, CSV
|
||||
/// 파일의 포맷이 바뀌는 경우, 이 숫자들을 변경해줘야한다. 이 작업이 꽤
|
||||
/// 신경 집중을 요구하는 데다가, 에러가 발생하기 쉽다. 그러므로 숫자로
|
||||
/// 액세스하기보다는 문자열로 액세스하는 것이 약간 느리지만 낫다고 할 수 있다.
|
||||
///
|
||||
/// <b>sample</b>
|
||||
/// <pre>
|
||||
@@ -259,63 +259,63 @@ private:
|
||||
class cCsvTable
|
||||
{
|
||||
public :
|
||||
cCsvFile m_File; ///< CSV 파일 객체
|
||||
cCsvFile m_File; ///< CSV 파일 객체
|
||||
private:
|
||||
cCsvAlias m_Alias; ///< 문자열을 셀 인덱스로 변환하기 위한 객체
|
||||
int m_CurRow; ///< 현재 횡단 중인 행 번호
|
||||
cCsvAlias m_Alias; ///< 문자열을 셀 인덱스로 변환하기 위한 객체
|
||||
int m_CurRow; ///< 현재 횡단 중인 행 번호
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 생성자
|
||||
/// \brief 생성자
|
||||
cCsvTable();
|
||||
|
||||
/// \brief 소멸자
|
||||
/// \brief 소멸자
|
||||
virtual ~cCsvTable();
|
||||
|
||||
|
||||
public:
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
/// \brief 지정된 이름의 CSV 파일을 로드한다.
|
||||
bool Load(const char* fileName, const char seperator=',', const char quote='"');
|
||||
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
|
||||
void AddAlias(const char* name, size_t index) { m_Alias.AddAlias(name, index); }
|
||||
|
||||
/// \brief 다음 행으로 넘어간다.
|
||||
/// \brief 다음 행으로 넘어간다.
|
||||
bool Next();
|
||||
|
||||
/// \brief 현재 행의 셀 숫자를 반환한다.
|
||||
/// \brief 현재 행의 셀 숫자를 반환한다.
|
||||
size_t ColCount() const;
|
||||
|
||||
/// \brief 인덱스를 이용해 int 형으로 셀값을 반환한다.
|
||||
/// \brief 인덱스를 이용해 int 형으로 셀값을 반환한다.
|
||||
int AsInt(size_t index) const;
|
||||
|
||||
/// \brief 인덱스를 이용해 double 형으로 셀값을 반환한다.
|
||||
/// \brief 인덱스를 이용해 double 형으로 셀값을 반환한다.
|
||||
double AsDouble(size_t index) const;
|
||||
|
||||
/// \brief 인덱스를 이용해 std::string 형으로 셀값을 반환한다.
|
||||
/// \brief 인덱스를 이용해 std::string 형으로 셀값을 반환한다.
|
||||
const char* AsStringByIndex(size_t index) const;
|
||||
|
||||
/// \brief 셀 이름을 이용해 int 형으로 셀값을 반환한다.
|
||||
/// \brief 셀 이름을 이용해 int 형으로 셀값을 반환한다.
|
||||
int AsInt(const char* name) const { return AsInt(m_Alias[name]); }
|
||||
|
||||
/// \brief 셀 이름을 이용해 double 형으로 셀값을 반환한다.
|
||||
/// \brief 셀 이름을 이용해 double 형으로 셀값을 반환한다.
|
||||
double AsDouble(const char* name) const { return AsDouble(m_Alias[name]); }
|
||||
|
||||
/// \brief 셀 이름을 이용해 std::string 형으로 셀값을 반환한다.
|
||||
/// \brief 셀 이름을 이용해 std::string 형으로 셀값을 반환한다.
|
||||
const char* AsString(const char* name) const { return AsStringByIndex(m_Alias[name]); }
|
||||
|
||||
/// \brief alias를 포함해 모든 데이터를 삭제한다.
|
||||
/// \brief alias를 포함해 모든 데이터를 삭제한다.
|
||||
void Destroy();
|
||||
|
||||
|
||||
private:
|
||||
/// \brief 현재 행을 반환한다.
|
||||
/// \brief 현재 행을 반환한다.
|
||||
const cCsvRow* const CurRow() const;
|
||||
|
||||
/// \brief 복사 생성자 금지
|
||||
/// \brief 복사 생성자 금지
|
||||
cCsvTable(const cCsvTable&) {}
|
||||
|
||||
/// \brief 대입 연산자 금지
|
||||
/// \brief 대입 연산자 금지
|
||||
const cCsvTable& operator = (const cCsvTable&) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "DBManager.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN2_DB_DBMANAGER_H__
|
||||
#ifndef __INC_METIN2_DB_DBMANAGER_H__
|
||||
#define __INC_METIN2_DB_DBMANAGER_H__
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "GuildManager.h"
|
||||
#include "Main.h"
|
||||
#include "ClientManager.h"
|
||||
@@ -242,7 +242,7 @@ void CGuildManager::ResultRanking(MYSQL_RES * pRes)
|
||||
|
||||
void CGuildManager::Update()
|
||||
{
|
||||
ProcessReserveWar(); // 예약 전쟁 처리
|
||||
ProcessReserveWar(); // 예약 전쟁 처리
|
||||
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
|
||||
@@ -462,7 +462,7 @@ void CGuildManager::RemoveWar(DWORD GID1, DWORD GID2)
|
||||
}
|
||||
|
||||
//
|
||||
// 길드전 비정상 종료 및 필드전 종료
|
||||
// 길드전 비정상 종료 및 필드전 종료
|
||||
//
|
||||
void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
|
||||
{
|
||||
@@ -493,7 +493,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
|
||||
|
||||
bool bDraw = false;
|
||||
|
||||
if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다.
|
||||
if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다.
|
||||
{
|
||||
if (pData->iScore[0] > pData->iScore[1])
|
||||
{
|
||||
@@ -508,7 +508,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
|
||||
else
|
||||
bDraw = true;
|
||||
}
|
||||
else // 강제 무승부일 경우에는 무조건 무승부
|
||||
else // 강제 무승부일 경우에는 무조건 무승부
|
||||
bDraw = true;
|
||||
|
||||
if (bDraw)
|
||||
@@ -516,14 +516,14 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
|
||||
else
|
||||
ProcessWinLose(win_guild, lose_guild);
|
||||
|
||||
// DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다.
|
||||
// DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다.
|
||||
CClientManager::instance().for_each_peer(FSendPeerWar(0, GUILD_WAR_END, GID1, GID2));
|
||||
|
||||
RemoveWar(GID1, GID2);
|
||||
}
|
||||
|
||||
//
|
||||
// 길드전 정상 종료
|
||||
// 길드전 정상 종료
|
||||
//
|
||||
void CGuildManager::RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bDraw, long lWarPrice)
|
||||
{
|
||||
@@ -571,7 +571,7 @@ void CGuildManager::RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bD
|
||||
void CGuildManager::RecvWarEnd(DWORD GID1, DWORD GID2)
|
||||
{
|
||||
sys_log(0, "GuildWar: RecvWarEnded : %u vs %u", GID1, GID2);
|
||||
WarEnd(GID1, GID2, true); // 무조건 비정상 종료 시켜야 한다.
|
||||
WarEnd(GID1, GID2, true); // 무조건 비정상 종료 시켜야 한다.
|
||||
}
|
||||
|
||||
void CGuildManager::StartWar(BYTE bType, DWORD GID1, DWORD GID2, CGuildWarReserve * pkReserve)
|
||||
@@ -745,7 +745,7 @@ void CGuildManager::ChangeLadderPoint(DWORD GID, int change)
|
||||
sys_log(0, "GuildManager::ChangeLadderPoint %u %d", GID, r.ladder_point);
|
||||
sys_log(0, "%s", buf);
|
||||
|
||||
// Packet 보내기
|
||||
// Packet 보내기
|
||||
TPacketGuildLadder p;
|
||||
|
||||
p.dwGuild = GID;
|
||||
@@ -808,7 +808,7 @@ void CGuildManager::WithdrawMoney(CPeer* peer, DWORD dwGuild, INT iGold)
|
||||
return;
|
||||
}
|
||||
|
||||
// 돈이있으니 출금하고 올려준다
|
||||
// 돈이있으니 출금하고 올려준다
|
||||
if (it->second.gold >= iGold)
|
||||
{
|
||||
it->second.gold -= iGold;
|
||||
@@ -839,7 +839,7 @@ void CGuildManager::WithdrawMoneyReply(DWORD dwGuild, BYTE bGiveSuccess, INT iGo
|
||||
}
|
||||
|
||||
//
|
||||
// 예약 길드전(관전자가 배팅할 수 있다)
|
||||
// 예약 길드전(관전자가 배팅할 수 있다)
|
||||
//
|
||||
const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] =
|
||||
{
|
||||
@@ -869,7 +869,7 @@ const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] =
|
||||
const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
|
||||
{
|
||||
0,
|
||||
55000, // 1위
|
||||
55000, // 1위
|
||||
50000,
|
||||
45000,
|
||||
40000,
|
||||
@@ -878,7 +878,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
|
||||
28000,
|
||||
24000,
|
||||
21000,
|
||||
18000, // 10위
|
||||
18000, // 10위
|
||||
15000,
|
||||
12000,
|
||||
10000,
|
||||
@@ -888,7 +888,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
|
||||
3000,
|
||||
2000,
|
||||
1000,
|
||||
500 // 20위
|
||||
500 // 20위
|
||||
};
|
||||
|
||||
void CGuildManager::BootReserveWar()
|
||||
@@ -932,8 +932,8 @@ void CGuildManager::BootReserveWar()
|
||||
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "GuildWar: BootReserveWar : step %d id %u GID1 %u GID2 %u", i, t.dwID, t.dwGuildFrom, t.dwGuildTo);
|
||||
// i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다.
|
||||
// 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다)
|
||||
// i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다.
|
||||
// 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다)
|
||||
//if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 60 * 5)
|
||||
if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 0)
|
||||
{
|
||||
@@ -1010,7 +1010,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
|
||||
|
||||
int lvp, rkp, alv, mc;
|
||||
|
||||
// 파워 계산
|
||||
// 파워 계산
|
||||
TGuild & k1 = TouchGuild(GID1);
|
||||
|
||||
lvp = c_aiScoreByLevel[MIN(GUILD_MAX_LEVEL, k1.level)];
|
||||
@@ -1026,7 +1026,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
|
||||
t.lPowerFrom = (long) polyPower.Eval();
|
||||
sys_log(0, "GuildWar: %u lvp %d rkp %d alv %d mc %d power %d", GID1, lvp, rkp, alv, mc, t.lPowerFrom);
|
||||
|
||||
// 파워 계산
|
||||
// 파워 계산
|
||||
TGuild & k2 = TouchGuild(GID2);
|
||||
|
||||
lvp = c_aiScoreByLevel[MIN(GUILD_MAX_LEVEL, k2.level)];
|
||||
@@ -1042,7 +1042,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
|
||||
t.lPowerTo = (long) polyPower.Eval();
|
||||
sys_log(0, "GuildWar: %u lvp %d rkp %d alv %d mc %d power %d", GID2, lvp, rkp, alv, mc, t.lPowerTo);
|
||||
|
||||
// 핸디캡 계산
|
||||
// 핸디캡 계산
|
||||
if (t.lPowerTo > t.lPowerFrom)
|
||||
{
|
||||
polyHandicap.SetVar("pA", t.lPowerTo);
|
||||
@@ -1057,7 +1057,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
|
||||
t.lHandicap = (long) polyHandicap.Eval();
|
||||
sys_log(0, "GuildWar: handicap %d", t.lHandicap);
|
||||
|
||||
// 쿼리
|
||||
// 쿼리
|
||||
char szQuery[512];
|
||||
|
||||
snprintf(szQuery, sizeof(szQuery),
|
||||
@@ -1094,7 +1094,7 @@ void CGuildManager::ProcessReserveWar()
|
||||
CGuildWarReserve * pk = it2->second;
|
||||
TGuildWarReserve & r = pk->GetDataRef();
|
||||
|
||||
if (!r.bStarted && r.dwTime - 1800 <= dwCurTime) // 30분 전부터 알린다.
|
||||
if (!r.bStarted && r.dwTime - 1800 <= dwCurTime) // 30분 전부터 알린다.
|
||||
{
|
||||
int iMin = (int) ceil((int)(r.dwTime - dwCurTime) / 60.0);
|
||||
|
||||
@@ -1135,9 +1135,9 @@ void CGuildManager::ProcessReserveWar()
|
||||
pk->SetLastNoticeMin(iMin);
|
||||
|
||||
if (!g_stLocale.compare("euckr"))
|
||||
CClientManager::instance().SendNotice("%s 길드와 %s 길드의 전쟁이 약 %d분 후 시작 됩니다!", r_1.szName, r_2.szName, iMin);
|
||||
CClientManager::instance().SendNotice("%s 길드와 %s 길드의 전쟁이 약 %d분 후 시작 됩니다!", r_1.szName, r_2.szName, iMin);
|
||||
else if (!g_stLocale.compare("gb2312"))
|
||||
CClientManager::instance().SendNotice("%s 곤삔뵨 %s 곤삔돨곤삔濫轢쉥瞳 %d롸爐빈역迦!", r_1.szName, r_2.szName, iMin);
|
||||
CClientManager::instance().SendNotice("%s 곤삔뵨 %s 곤삔돨곤삔濫轢쉥瞳 %d롸爐빈역迦!", r_1.szName, r_2.szName, iMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1239,7 @@ void CGuildWarReserve::Initialize()
|
||||
|
||||
void CGuildWarReserve::OnSetup(CPeer * peer)
|
||||
{
|
||||
if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다.
|
||||
if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다.
|
||||
return;
|
||||
|
||||
FSendPeerWar(m_data.bType, GUILD_WAR_RESERVE, m_data.dwGuildFrom, m_data.dwGuildTo) (peer);
|
||||
@@ -1325,8 +1325,8 @@ bool CGuildWarReserve::Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild)
|
||||
}
|
||||
|
||||
//
|
||||
// 무승부 처리: 대부분 승부가 나야 정상이지만, 서버 문제 등 특정 상황일 경우에는
|
||||
// 무승부 처리가 있어야 한다.
|
||||
// 무승부 처리: 대부분 승부가 나야 정상이지만, 서버 문제 등 특정 상황일 경우에는
|
||||
// 무승부 처리가 있어야 한다.
|
||||
//
|
||||
void CGuildWarReserve::Draw()
|
||||
{
|
||||
@@ -1458,7 +1458,7 @@ void CGuildWarReserve::End(int iScoreFrom, int iScoreTo)
|
||||
|
||||
double ratio = (double) it->second.second / dwWinnerBet;
|
||||
|
||||
// 10% 세금 공제 후 분배
|
||||
// 10% 세금 공제 후 분배
|
||||
sys_log(0, "WAR_REWARD: %s %u ratio %f", it->first.c_str(), it->second.second, ratio);
|
||||
|
||||
DWORD dwGold = (DWORD) (dwTotalBet * ratio * 0.9);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_GUILD_MANAGER_H
|
||||
#define __INC_GUILD_MANAGER_H
|
||||
|
||||
@@ -150,7 +150,7 @@ class CGuildWarReserve
|
||||
void SetLastNoticeMin(int iMin) { m_iLastNoticeMin = iMin; }
|
||||
|
||||
private:
|
||||
CGuildWarReserve(); // 기본 생성자를 사용하지 못하도록 의도적으로 구현하지 않음
|
||||
CGuildWarReserve(); // 기본 생성자를 사용하지 못하도록 의도적으로 구현하지 않음
|
||||
|
||||
TGuildWarReserve m_data;
|
||||
// <login, <guild, gold>>
|
||||
@@ -235,7 +235,7 @@ class CGuildManager : public singleton<CGuildManager>
|
||||
std::map<DWORD, TGuild> m_map_kGuild;
|
||||
std::map<DWORD, std::map<DWORD, time_t> > m_mapGuildWarEndTime;
|
||||
|
||||
std::set<TGuildDeclareInfo> m_DeclareMap; // 선전 포고 상태를 저장
|
||||
std::set<TGuildDeclareInfo> m_DeclareMap; // 선전 포고 상태를 저장
|
||||
std::map<DWORD, std::map<DWORD, TGuildWarInfo> > m_WarMap;
|
||||
|
||||
typedef std::pair<time_t, TGuildWarPQElement *> stPairGuildWar;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "HB.h"
|
||||
#include "Main.h"
|
||||
#include "DBManager.h"
|
||||
@@ -30,7 +30,7 @@ bool PlayerHB::Initialize()
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/07/05 Bang2ni - id 에 해당하는 data 가 없을 때 쿼리하고 data 를 insert 하는코드 추가.
|
||||
// @version 05/07/05 Bang2ni - id 에 해당하는 data 가 없을 때 쿼리하고 data 를 insert 하는코드 추가.
|
||||
//
|
||||
void PlayerHB::Put(DWORD id)
|
||||
{
|
||||
@@ -48,7 +48,7 @@ void PlayerHB::Put(DWORD id)
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/07/05 Bang2ni - Query string 버퍼가 작아서 늘려줌.
|
||||
// @version 05/07/05 Bang2ni - Query string 버퍼가 작아서 늘려줌.
|
||||
//
|
||||
bool PlayerHB::Query(DWORD id)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_METIN_II_PLAYERHB_H__
|
||||
#define __INC_METIN_II_PLAYERHB_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "QID.h"
|
||||
#include "DBManager.h"
|
||||
#include "ItemAwardManager.h"
|
||||
@@ -54,19 +54,19 @@ void ItemAwardManager::Load(SQLMsg * pMsg)
|
||||
if (row[col])
|
||||
{
|
||||
strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy));
|
||||
//게임 중에 why콜룸에 변동이 생기면
|
||||
char* whyStr = kData->szWhy; //why 콜룸 읽기
|
||||
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
|
||||
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
|
||||
//게임 중에 why콜룸에 변동이 생기면
|
||||
char* whyStr = kData->szWhy; //why 콜룸 읽기
|
||||
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
|
||||
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
|
||||
char command[20] = "";
|
||||
strcpy(command,CClientManager::instance().GetCommand(cmdStr)); // command 얻기
|
||||
strcpy(command,CClientManager::instance().GetCommand(cmdStr)); // command 얻기
|
||||
//sys_err("%d, %s",pItemAward->dwID,command);
|
||||
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
|
||||
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
|
||||
{
|
||||
TPacketItemAwardInfromer giftData;
|
||||
strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사
|
||||
strcpy(giftData.command, command); //명령어 복사
|
||||
giftData.vnum = kData->dwVnum; //아이템 vnum도 복사
|
||||
strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사
|
||||
strcpy(giftData.command, command); //명령어 복사
|
||||
giftData.vnum = kData->dwVnum; //아이템 vnum도 복사
|
||||
CClientManager::instance().ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_ITEM_AWARD_H
|
||||
#define __INC_ITEM_AWARD_H
|
||||
#include <map>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "ItemIDRangeManager.h"
|
||||
#include "Main.h"
|
||||
#include "DBManager.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=4 sw=4
|
||||
// vim:ts=4 sw=4
|
||||
#ifndef __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
|
||||
#define __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Lock.h"
|
||||
|
||||
CLock::CLock()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_LOCK_H__
|
||||
#define __INC_LOCK_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "LoginData.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim:ts=8 sw=4
|
||||
// vim:ts=8 sw=4
|
||||
#ifndef __INC_METIN_II_DB_LOGINDATA_H__
|
||||
#define __INC_METIN_II_DB_LOGINDATA_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
#include "Peer.h"
|
||||
#include "DBManager.h"
|
||||
@@ -30,11 +30,11 @@ std::string g_stPlayerDBName = "";
|
||||
bool g_bHotBackup = false;
|
||||
BOOL g_test_server = false;
|
||||
|
||||
//단위 초
|
||||
//단위 초
|
||||
int g_iPlayerCacheFlushSeconds = 60*7;
|
||||
int g_iItemCacheFlushSeconds = 60*5;
|
||||
|
||||
//g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다.
|
||||
//g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다.
|
||||
int g_iLogoutSeconds = 60*10;
|
||||
|
||||
int g_log = 1;
|
||||
@@ -123,13 +123,13 @@ int main()
|
||||
|
||||
void emptybeat(LPHEART heart, int pulse)
|
||||
{
|
||||
if (!(pulse % heart->passes_per_sec)) // 1초에 한번
|
||||
if (!(pulse % heart->passes_per_sec)) // 1초에 한번
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/06/13 Bang2ni - 아이템 가격정보 캐시 flush timeout 설정 추가.
|
||||
// @version 05/06/13 Bang2ni - 아이템 가격정보 캐시 flush timeout 설정 추가.
|
||||
//
|
||||
int Start()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_MAIN_H__
|
||||
#ifndef __INC_MAIN_H__
|
||||
#define __INC_MAIN_H__
|
||||
|
||||
int Start();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=4 sw=4
|
||||
// vim: ts=4 sw=4
|
||||
#ifndef __MARRIAGE_H
|
||||
#define __MARRIAGE_H
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace marriage
|
||||
DWORD pid2;
|
||||
int love_point;
|
||||
DWORD time;
|
||||
BYTE is_married; // false : ¾àÈ¥ »óÅÂ, true : °áÈ¥ »óÅÂ
|
||||
BYTE is_married; // false : 약혼 상태, true : 결혼 상태
|
||||
std::string name1;
|
||||
std::string name2;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=4 sw=4
|
||||
// vim: ts=4 sw=4
|
||||
#ifndef METIN2_MONARCH_H
|
||||
#define METIN2_MONARCH_H
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "MoneyLog.h"
|
||||
#include "ClientManager.h"
|
||||
#include "Peer.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_MONEY_LOG
|
||||
#define __INC_MONEY_LOG
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "NetBase.h"
|
||||
#include "Config.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_NETWORKBASE_H__
|
||||
#define __INC_NETWORKBASE_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Peer.h"
|
||||
#include "ItemIDRangeManager.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PEER_H__
|
||||
#define __INC_PEER_H__
|
||||
|
||||
@@ -66,9 +66,9 @@ class CPeer : public CPeerBase
|
||||
BYTE m_bChannel;
|
||||
DWORD m_dwHandle;
|
||||
DWORD m_dwUserCount;
|
||||
WORD m_wListenPort; // 게임서버가 클라이언트를 위해 listen 하는 포트
|
||||
WORD m_wP2PPort; // 게임서버가 게임서버 P2P 접속을 위해 listen 하는 포트
|
||||
long m_alMaps[32]; // 어떤 맵을 관장하고 있는가?
|
||||
WORD m_wListenPort; // 게임서버가 클라이언트를 위해 listen 하는 포트
|
||||
WORD m_wP2PPort; // 게임서버가 게임서버 P2P 접속을 위해 listen 하는 포트
|
||||
long m_alMaps[32]; // 어떤 맵을 관장하고 있는가?
|
||||
|
||||
TItemIDRangeTable m_itemRange;
|
||||
TItemIDRangeTable m_itemSpareRange;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "PeerBase.h"
|
||||
|
||||
CPeerBase::CPeerBase() : m_fd(INVALID_SOCKET), m_BytesRemain(0), m_outBuffer(NULL), m_inBuffer(NULL)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PEERBASE_H__
|
||||
#define __INC_PEERBASE_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "PrivManager.h"
|
||||
#include "ClientManager.h"
|
||||
|
||||
@@ -20,7 +20,7 @@ CPrivManager::~CPrivManager()
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/06/07 Bang2ni - 중복적으로 보너스가 적용 된 길드에 대한 처리
|
||||
// @version 05/06/07 Bang2ni - 중복적으로 보너스가 적용 된 길드에 대한 처리
|
||||
//
|
||||
void CPrivManager::Update()
|
||||
{
|
||||
@@ -37,8 +37,8 @@ void CPrivManager::Update()
|
||||
__typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id);
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
// 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로
|
||||
// TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다.
|
||||
// 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로
|
||||
// TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다.
|
||||
if (it != m_aPrivGuild[p->type].end() && it->second == p) {
|
||||
m_aPrivGuild[p->type].erase(it);
|
||||
SendChangeGuildPriv(p->guild_id, p->type, 0, 0);
|
||||
@@ -113,7 +113,7 @@ void CPrivManager::AddCharPriv(DWORD pid, BYTE type, int value)
|
||||
}
|
||||
|
||||
//
|
||||
// @version 05/06/07 Bang2ni - 이미 보너스가 적용 된 길드에 보너스 설정
|
||||
// @version 05/06/07 Bang2ni - 이미 보너스가 적용 된 길드에 보너스 설정
|
||||
//
|
||||
void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t duration_sec)
|
||||
{
|
||||
@@ -131,8 +131,8 @@ void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t dur
|
||||
m_pqPrivGuild.push(std::make_pair(end, p));
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
// 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다.
|
||||
// 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다.
|
||||
// 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다.
|
||||
// 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다.
|
||||
if (it != m_aPrivGuild[type].end())
|
||||
it->second = p;
|
||||
else
|
||||
@@ -158,8 +158,8 @@ void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t durat
|
||||
time_t now = CClientManager::instance().GetCurrentTime();
|
||||
time_t end = now+duration_sec;
|
||||
|
||||
// 이전 설정값 무효화
|
||||
// priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire]
|
||||
// 이전 설정값 무효화
|
||||
// priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire]
|
||||
{
|
||||
if (m_aaPrivEmpire[type][empire])
|
||||
m_aaPrivEmpire[type][empire]->bRemoved = true;
|
||||
@@ -177,7 +177,7 @@ void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t durat
|
||||
}
|
||||
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
*/
|
||||
struct FSendChangeGuildPriv
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_PRIV_MANAGER_H
|
||||
#define __INC_PRIV_MANAGER_H
|
||||
|
||||
@@ -23,7 +23,7 @@ struct TPrivEmpireData
|
||||
};
|
||||
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
* @version 05/06/08 Bang2ni - 지속시간 추가
|
||||
*/
|
||||
struct TPrivGuildData
|
||||
{
|
||||
@@ -33,7 +33,7 @@ struct TPrivGuildData
|
||||
DWORD guild_id;
|
||||
|
||||
// ADD_GUILD_PRIV_TIME
|
||||
time_t end_time_sec; ///< 지속시간
|
||||
time_t end_time_sec; ///< 지속시간
|
||||
|
||||
TPrivGuildData(BYTE type, int value, DWORD guild_id, time_t _end_time_sec)
|
||||
: type(type), value(value), bRemoved(false), guild_id(guild_id), end_time_sec(_end_time_sec )
|
||||
@@ -53,7 +53,7 @@ struct TPrivCharData
|
||||
};
|
||||
|
||||
/**
|
||||
* @version 05/06/08 Bang2ni - Guild privilege 관련 함수 지속 시간 추가
|
||||
* @version 05/06/08 Bang2ni - Guild privilege 관련 함수 지속 시간 추가
|
||||
*/
|
||||
class CPrivManager : public singleton<CPrivManager>
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "ProtoReader.h"
|
||||
@@ -25,23 +25,23 @@ string trim(const string& str){return trim_left(trim_right(str));}
|
||||
|
||||
static string* StringSplit(string strOrigin, string strTok)
|
||||
{
|
||||
int cutAt; //자르는위치
|
||||
int index = 0; //문자열인덱스
|
||||
string* strResult = new string[30]; //결과return 할변수
|
||||
int cutAt; //자르는위치
|
||||
int index = 0; //문자열인덱스
|
||||
string* strResult = new string[30]; //결과return 할변수
|
||||
|
||||
//strTok을찾을때까지반복
|
||||
//strTok을찾을때까지반복
|
||||
while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos)
|
||||
{
|
||||
if (cutAt > 0) //자르는위치가0보다크면(성공시)
|
||||
if (cutAt > 0) //자르는위치가0보다크면(성공시)
|
||||
{
|
||||
strResult[index++] = strOrigin.substr(0, cutAt); //결과배열에추가
|
||||
strResult[index++] = strOrigin.substr(0, cutAt); //결과배열에추가
|
||||
}
|
||||
strOrigin = strOrigin.substr(cutAt+1); //원본은자른부분제외한나머지
|
||||
strOrigin = strOrigin.substr(cutAt+1); //원본은자른부분제외한나머지
|
||||
}
|
||||
|
||||
if(strOrigin.length() > 0) //원본이아직남았으면
|
||||
if(strOrigin.length() > 0) //원본이아직남았으면
|
||||
{
|
||||
strResult[index++] = strOrigin.substr(0, cutAt); //나머지를결과배열에추가
|
||||
strResult[index++] = strOrigin.substr(0, cutAt); //나머지를결과배열에추가
|
||||
}
|
||||
|
||||
for( int i=0;i<index;i++)
|
||||
@@ -49,7 +49,7 @@ static string* StringSplit(string strOrigin, string strTok)
|
||||
strResult[i] = trim(strResult[i]);
|
||||
}
|
||||
|
||||
return strResult; //결과return
|
||||
return strResult; //결과return
|
||||
}
|
||||
|
||||
|
||||
@@ -60,25 +60,25 @@ int get_Item_Type_Value(string inputString)
|
||||
"ITEM_ARMOR", "ITEM_USE",
|
||||
"ITEM_AUTOUSE", "ITEM_MATERIAL",
|
||||
"ITEM_SPECIAL", "ITEM_TOOL",
|
||||
"ITEM_LOTTERY", "ITEM_ELK", //10개
|
||||
"ITEM_LOTTERY", "ITEM_ELK", //10개
|
||||
|
||||
"ITEM_METIN", "ITEM_CONTAINER",
|
||||
"ITEM_FISH", "ITEM_ROD",
|
||||
"ITEM_RESOURCE", "ITEM_CAMPFIRE",
|
||||
"ITEM_UNIQUE", "ITEM_SKILLBOOK",
|
||||
"ITEM_QUEST", "ITEM_POLYMORPH", //20개
|
||||
"ITEM_QUEST", "ITEM_POLYMORPH", //20개
|
||||
|
||||
"ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY",
|
||||
"ITEM_SKILLFORGET", "ITEM_GIFTBOX",
|
||||
"ITEM_PICK", "ITEM_HAIR",
|
||||
"ITEM_TOTEM", "ITEM_BLEND",
|
||||
"ITEM_COSTUME", "ITEM_DS", //30개
|
||||
"ITEM_COSTUME", "ITEM_DS", //30개
|
||||
|
||||
"ITEM_SPECIAL_DS", "ITEM_EXTRACT",
|
||||
"ITEM_SECONDARY_COIN", //33개
|
||||
"ITEM_SECONDARY_COIN", //33개
|
||||
|
||||
"ITEM_RING",
|
||||
"ITEM_BELT", //35개 (EItemTypes 값으로 치면 34)
|
||||
"ITEM_BELT", //35개 (EItemTypes 값으로 치면 34)
|
||||
};
|
||||
|
||||
|
||||
@@ -159,8 +159,8 @@ int get_Item_SubType_Value(int type_value, string inputString)
|
||||
arSub29, //30
|
||||
arSub31, //31
|
||||
0, //32
|
||||
0, //33 반지
|
||||
0, //34 벨트
|
||||
0, //33 반지
|
||||
0, //34 벨트
|
||||
};
|
||||
static int arNumberOfSubtype[_countof(arSubType)] = {
|
||||
0,
|
||||
@@ -196,21 +196,21 @@ int get_Item_SubType_Value(int type_value, string inputString)
|
||||
sizeof(arSub29)/sizeof(arSub29[0]),
|
||||
sizeof(arSub31)/sizeof(arSub31[0]),
|
||||
0, // 32
|
||||
0, // 33 반지
|
||||
0, // 34 벨트
|
||||
0, // 33 반지
|
||||
0, // 34 벨트
|
||||
};
|
||||
|
||||
|
||||
assert(_countof(arSubType) > type_value && "Subtype rule: Out of range!!");
|
||||
|
||||
// assert 안 먹히는 듯..
|
||||
// assert 안 먹히는 듯..
|
||||
if (_countof(arSubType) <= type_value)
|
||||
{
|
||||
sys_err("SubType : Out of range!! (type_value: %d, count of registered subtype: %d", type_value, _countof(arSubType));
|
||||
return -1;
|
||||
}
|
||||
|
||||
//아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴
|
||||
//아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴
|
||||
if (arSubType[type_value]==0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -246,13 +246,13 @@ int get_Item_AntiFlag_Value(string inputString)
|
||||
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arAntiFlag)/sizeof(arAntiFlag[0]);i++) {
|
||||
string tempString = arAntiFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -275,13 +275,13 @@ int get_Item_Flag_Value(string inputString)
|
||||
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arFlag)/sizeof(arFlag[0]);i++) {
|
||||
string tempString = arFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -303,13 +303,13 @@ int get_Item_WearFlag_Value(string inputString)
|
||||
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arWearrFlag)/sizeof(arWearrFlag[0]);i++) {
|
||||
string tempString = arWearrFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -329,13 +329,13 @@ int get_Item_Immune_Value(string inputString)
|
||||
string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arImmune)/sizeof(arImmune[0]);i++) {
|
||||
string tempString = arImmune[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ int get_Item_ApplyType_Value(string inputString)
|
||||
}
|
||||
|
||||
|
||||
//몬스터 프로토도 읽는다.
|
||||
//몬스터 프로토도 읽는다.
|
||||
|
||||
|
||||
int get_Mob_Rank_Value(string inputString)
|
||||
@@ -508,13 +508,13 @@ int get_Mob_AIFlag_Value(string inputString)
|
||||
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arAIFlag)/sizeof(arAIFlag[0]);i++) {
|
||||
string tempString = arAIFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -533,13 +533,13 @@ int get_Mob_RaceFlag_Value(string inputString)
|
||||
"ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arRaceFlag)/sizeof(arRaceFlag[0]);i++) {
|
||||
string tempString = arRaceFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -557,13 +557,13 @@ int get_Mob_ImmuneFlag_Value(string inputString)
|
||||
string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR", "REFLECT"};
|
||||
|
||||
int retValue = 0;
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
|
||||
for(int i =0;i<sizeof(arImmuneFlag)/sizeof(arImmuneFlag[0]);i++) {
|
||||
string tempString = arImmuneFlag[i];
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
|
||||
{
|
||||
string tempString2 = arInputString[j];
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
|
||||
retValue = retValue + pow((float)2,(float)i);
|
||||
}
|
||||
|
||||
@@ -581,14 +581,14 @@ int get_Mob_ImmuneFlag_Value(string inputString)
|
||||
|
||||
#ifndef __DUMP_PROTO__
|
||||
|
||||
//몹 테이블을 셋팅해준다.
|
||||
//몹 테이블을 셋팅해준다.
|
||||
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
|
||||
{
|
||||
int col = 0;
|
||||
str_to_number(mobTable->dwVnum, csvTable.AsStringByIndex(col++));
|
||||
strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName));
|
||||
|
||||
//3. 지역별 이름 넣어주기.
|
||||
//3. 지역별 이름 넣어주기.
|
||||
map<int,const char*>::iterator it;
|
||||
it = nameMap.find(mobTable->dwVnum);
|
||||
if (it != nameMap.end()) {
|
||||
@@ -750,11 +750,11 @@ bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<in
|
||||
col = col + 1;
|
||||
}
|
||||
|
||||
// vnum 및 vnum range 읽기.
|
||||
// vnum 및 vnum range 읽기.
|
||||
{
|
||||
std::string s(csvTable.AsStringByIndex(0));
|
||||
int pos = s.find("~");
|
||||
// vnum 필드에 '~'가 없다면 패스
|
||||
// vnum 필드에 '~'가 없다면 패스
|
||||
if (std::string::npos == pos)
|
||||
{
|
||||
itemTable->dwVnum = dataArray[0];
|
||||
@@ -778,7 +778,7 @@ bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<in
|
||||
}
|
||||
|
||||
strlcpy(itemTable->szName, csvTable.AsStringByIndex(1), sizeof(itemTable->szName));
|
||||
//지역별 이름 넣어주기.
|
||||
//지역별 이름 넣어주기.
|
||||
map<int,const char*>::iterator it;
|
||||
it = nameMap.find(itemTable->dwVnum);
|
||||
if (it != nameMap.end()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __Item_CSV_READER_H__
|
||||
#ifndef __Item_CSV_READER_H__
|
||||
#define __Item_CSV_READER_H__
|
||||
|
||||
#include <iostream>
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
#include "CsvReader.h"
|
||||
|
||||
//csv 파일을 읽어와서 아이템 테이블에 넣어준다.
|
||||
void putItemIntoTable(); //(테이블, 테스트여부)
|
||||
//csv 파일을 읽어와서 아이템 테이블에 넣어준다.
|
||||
void putItemIntoTable(); //(테이블, 테스트여부)
|
||||
|
||||
int get_Item_Type_Value(std::string inputString);
|
||||
int get_Item_SubType_Value(int type_value, std::string inputString);
|
||||
@@ -19,7 +19,7 @@ int get_Item_LimitType_Value(std::string inputString);
|
||||
int get_Item_ApplyType_Value(std::string inputString);
|
||||
|
||||
|
||||
//몬스터 프로토도 읽을 수 있다.
|
||||
//몬스터 프로토도 읽을 수 있다.
|
||||
int get_Mob_Rank_Value(std::string inputString);
|
||||
int get_Mob_Type_Value(std::string inputString);
|
||||
int get_Mob_BattleType_Value(std::string inputString);
|
||||
|
||||
12
src/db/QID.h
12
src/db/QID.h
@@ -1,8 +1,8 @@
|
||||
#ifndef __INC_METIN_II_DB_QID_H__
|
||||
#ifndef __INC_METIN_II_DB_QID_H__
|
||||
#define __INC_METIN_II_DB_QID_H__
|
||||
|
||||
/**
|
||||
* @version 05/06/10 Bang2ni - 아이템 가격정보 쿼리 추가(QID_ITEMPRICE_XXX)
|
||||
* @version 05/06/10 Bang2ni - 아이템 가격정보 쿼리 추가(QID_ITEMPRICE_XXX)
|
||||
*/
|
||||
enum QID
|
||||
{
|
||||
@@ -29,10 +29,10 @@ enum QID
|
||||
QID_GUILD_RANKING, // 20
|
||||
|
||||
// MYSHOP_PRICE_LIST
|
||||
QID_ITEMPRICE_SAVE, ///< 21, 아이템 가격정보 저장 쿼리
|
||||
QID_ITEMPRICE_DESTROY, ///< 22, 아이템 가격정보 삭제 쿼리
|
||||
QID_ITEMPRICE_LOAD_FOR_UPDATE, ///< 23, 가격정보 업데이트를 위한 아이템 가격정보 로드 쿼리
|
||||
QID_ITEMPRICE_LOAD, ///< 24, 아이템 가격정보 로드 쿼리
|
||||
QID_ITEMPRICE_SAVE, ///< 21, 아이템 가격정보 저장 쿼리
|
||||
QID_ITEMPRICE_DESTROY, ///< 22, 아이템 가격정보 삭제 쿼리
|
||||
QID_ITEMPRICE_LOAD_FOR_UPDATE, ///< 23, 가격정보 업데이트를 위한 아이템 가격정보 로드 쿼리
|
||||
QID_ITEMPRICE_LOAD, ///< 24, 아이템 가격정보 로드 쿼리
|
||||
// END_OF_MYSHOP_PRICE_LIST
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <string.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "../../libthecore/include/memcpy.h"
|
||||
#include "../../common/stl.h"
|
||||
@@ -29,7 +29,7 @@ void CGrid::Clear()
|
||||
|
||||
int CGrid::FindBlank(int w, int h)
|
||||
{
|
||||
// 크기가 더 크다면 확인할 필요 없이 그냥 리턴
|
||||
// 크기가 더 크다면 확인할 필요 없이 그냥 리턴
|
||||
if (w > m_iWidth || h > m_iHeight)
|
||||
return -1;
|
||||
|
||||
@@ -87,7 +87,7 @@ bool CGrid::IsEmpty(int iPos, int w, int h)
|
||||
{
|
||||
int iRow = iPos / m_iWidth;
|
||||
|
||||
// Grid 안쪽인가를 먼저 검사
|
||||
// Grid 안쪽인가를 먼저 검사
|
||||
if (iRow + h > m_iHeight)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// vim: ts=8 sw=4
|
||||
// vim: ts=8 sw=4
|
||||
#ifndef __INC_METIN_II_GRID_H__
|
||||
#define __INC_METIN_II_GRID_H__
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METiN_II_DBSERV_STDAFX_H__
|
||||
#ifndef __INC_METiN_II_DBSERV_STDAFX_H__
|
||||
#define __INC_METiN_II_DBSERV_STDAFX_H__
|
||||
|
||||
#include "../../libthecore/include/stdafx.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void WriteVersion()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "constants.h"
|
||||
#include "BattleArena.h"
|
||||
#include "start_position.h"
|
||||
@@ -102,14 +102,14 @@ EVENTFUNC(battle_arena_event)
|
||||
case 0:
|
||||
{
|
||||
++pInfo->state;
|
||||
BroadcastNotice(LC_TEXT("몬스터들의 공격까지 5분 남았습니다!!!"));
|
||||
BroadcastNotice(LC_TEXT("몬스터들의 공격까지 5분 남았습니다!!!"));
|
||||
}
|
||||
return test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(60*4);
|
||||
|
||||
case 1:
|
||||
{
|
||||
++pInfo->state;
|
||||
BroadcastNotice(LC_TEXT("몬스터들의 공격까지 1분 남았습니다!!!"));
|
||||
BroadcastNotice(LC_TEXT("몬스터들의 공격까지 1분 남았습니다!!!"));
|
||||
}
|
||||
return test_server ? PASSES_PER_SEC(10) : PASSES_PER_SEC(60);
|
||||
|
||||
@@ -119,7 +119,7 @@ EVENTFUNC(battle_arena_event)
|
||||
pInfo->wait_count = 0;
|
||||
|
||||
quest::CQuestManager::instance().RequestSetEventFlag("battle_arena", 0);
|
||||
BroadcastNotice(LC_TEXT("몬스터들이 성을 공격하기 시작했습니다."));
|
||||
BroadcastNotice(LC_TEXT("몬스터들이 성을 공격하기 시작했습니다."));
|
||||
|
||||
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(pInfo->nMapIndex);
|
||||
|
||||
@@ -141,7 +141,7 @@ EVENTFUNC(battle_arena_event)
|
||||
if ( SECTREE_MANAGER::instance().GetMonsterCountInMap(pInfo->nMapIndex) <= 0 )
|
||||
{
|
||||
pInfo->state = 6;
|
||||
SendNoticeMap(LC_TEXT("중앙 제단에 악의 기운이 모여듭니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("중앙 제단에 악의 기운이 모여듭니다."), pInfo->nMapIndex, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,7 +150,7 @@ EVENTFUNC(battle_arena_event)
|
||||
if ( pInfo->wait_count >= 5 )
|
||||
{
|
||||
pInfo->state++;
|
||||
SendNoticeMap(LC_TEXT("몬스터들이 물러갈 조짐을 보입니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("몬스터들이 물러갈 조짐을 보입니다."), pInfo->nMapIndex, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,8 +163,8 @@ EVENTFUNC(battle_arena_event)
|
||||
case 4 :
|
||||
{
|
||||
pInfo->state++;
|
||||
SendNoticeMap(LC_TEXT("몬스터들이 물러가기 시작했습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("몬스터들이 물러가기 시작했습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
|
||||
SECTREE_MANAGER::instance().PurgeMonstersInMap(pInfo->nMapIndex);
|
||||
}
|
||||
@@ -189,8 +189,8 @@ EVENTFUNC(battle_arena_event)
|
||||
pInfo->state++;
|
||||
pInfo->wait_count = 0;
|
||||
|
||||
SendNoticeMap(LC_TEXT("몬스터들의 대장이 나타났습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("30분 내로 귀목령주를 물리쳐주세요."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("몬스터들의 대장이 나타났습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("30분 내로 귀목령주를 물리쳐주세요."), pInfo->nMapIndex, false);
|
||||
|
||||
CBattleArena::instance().SpawnLastBoss();
|
||||
}
|
||||
@@ -200,8 +200,8 @@ EVENTFUNC(battle_arena_event)
|
||||
{
|
||||
if ( SECTREE_MANAGER::instance().GetMonsterCountInMap(pInfo->nMapIndex) <= 0 )
|
||||
{
|
||||
SendNoticeMap(LC_TEXT("귀목령주와 그의 부하들을 모두 물리쳤습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("귀목령주와 그의 부하들을 모두 물리쳤습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
|
||||
pInfo->state = 5;
|
||||
|
||||
@@ -212,8 +212,8 @@ EVENTFUNC(battle_arena_event)
|
||||
|
||||
if ( pInfo->wait_count >= 6 )
|
||||
{
|
||||
SendNoticeMap(LC_TEXT("귀목령주가 퇴각하였습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("귀목령주가 퇴각하였습니다."), pInfo->nMapIndex, false);
|
||||
SendNoticeMap(LC_TEXT("잠시 후 마을로 돌아갑니다."), pInfo->nMapIndex, false);
|
||||
|
||||
SECTREE_MANAGER::instance().PurgeMonstersInMap(pInfo->nMapIndex);
|
||||
SECTREE_MANAGER::instance().PurgeStonesInMap(pInfo->nMapIndex);
|
||||
@@ -243,9 +243,9 @@ bool CBattleArena::Start(int nEmpire)
|
||||
m_nEmpire = nEmpire;
|
||||
|
||||
char szBuf[1024];
|
||||
snprintf(szBuf, sizeof(szBuf), LC_TEXT("%s의 성으로 몬스터들이 진군하고 있습니다."), EMPIRE_NAME(m_nEmpire));
|
||||
snprintf(szBuf, sizeof(szBuf), LC_TEXT("%s의 성으로 몬스터들이 진군하고 있습니다."), EMPIRE_NAME(m_nEmpire));
|
||||
BroadcastNotice(szBuf);
|
||||
BroadcastNotice(LC_TEXT("10분 뒤 성을 공격할 예정입니다."));
|
||||
BroadcastNotice(LC_TEXT("10분 뒤 성을 공격할 예정입니다."));
|
||||
|
||||
if (m_pEvent != NULL) {
|
||||
event_cancel(&m_pEvent);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
const static int nBATTLE_ARENA_MAP[] = { 0, 190, 191, 192 };
|
||||
const static std::string strRegen[] =
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "BlueDragon.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
extern int BlueDragon_StateBattle (LPCHARACTER);
|
||||
extern time_t UseBlueDragonSkill (LPCHARACTER, unsigned int);
|
||||
extern int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER attacker, int dam);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "BlueDragon_Binder.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
enum BLUEDRAGON_STONE_EFFECT
|
||||
{
|
||||
DEF_BONUS = 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
struct FSkillBreath
|
||||
{
|
||||
EJobs Set1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "ClientPackageCryptInfo.h"
|
||||
#include "../../common/stl.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
#ifndef __INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
#define __INC_CLIENTPACKAGE_CRYPTINFO_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "DragonLair.h"
|
||||
@@ -91,7 +91,7 @@ EVENTFUNC( DragonLair_Collapse_Event )
|
||||
if (0 == pInfo->step)
|
||||
{
|
||||
char buf[512];
|
||||
snprintf(buf, 512, LC_TEXT("용가리가 %d 초만에 죽어써효ㅠㅠ"), pInfo->pLair->GetEstimatedTime());
|
||||
snprintf(buf, 512, LC_TEXT("용가리가 %d 초만에 죽어써효ㅠㅠ"), pInfo->pLair->GetEstimatedTime());
|
||||
SendNoticeMap(buf, pInfo->InstanceMapIndex, true);
|
||||
|
||||
pInfo->step++;
|
||||
@@ -146,7 +146,7 @@ DWORD CDragonLair::GetEstimatedTime() const
|
||||
|
||||
void CDragonLair::OnDragonDead(LPCHARACTER pDragon)
|
||||
{
|
||||
sys_log(0, "DragonLair: 도라곤이 죽어써효");
|
||||
sys_log(0, "DragonLair: 도라곤이 죽어써효");
|
||||
|
||||
LogManager::instance().DragonSlayLog( GuildID_, pDragon->GetMobTable().dwVnum, StartTime_, get_global_time() );
|
||||
}
|
||||
@@ -239,7 +239,7 @@ void CDragonLairManager::OnDragonDead(LPCHARACTER pDragon, DWORD KillerGuildID)
|
||||
|
||||
iter->second->OnDragonDead( pDragon );
|
||||
|
||||
// 애들 다 집으로 보내고 맵 없애기
|
||||
// 애들 다 집으로 보내고 맵 없애기
|
||||
|
||||
tag_DragonLair_Collapse_EventInfo* info;
|
||||
info = AllocEventInfo<tag_DragonLair_Collapse_EventInfo>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../common/stl.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "constants.h"
|
||||
#include "item.h"
|
||||
#include "item_manager.h"
|
||||
@@ -37,7 +37,7 @@ int Gamble(std::vector<float>& vec_probs)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 가중치 테이블(prob_lst)을 받아 random_set.size()개의 index를 선택하여 random_set을 return
|
||||
// 가중치 테이블(prob_lst)을 받아 random_set.size()개의 index를 선택하여 random_set을 return
|
||||
bool MakeDistinctRandomNumberSet(std::list <float> prob_lst, OUT std::vector<int>& random_set)
|
||||
{
|
||||
int size = prob_lst.size();
|
||||
@@ -73,11 +73,11 @@ bool MakeDistinctRandomNumberSet(std::list <float> prob_lst, OUT std::vector<int
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 용혼석 Vnum에 대한 comment
|
||||
* ITEM VNUM을 10만 자리부터, FEDCBA라고 한다면
|
||||
* FE : 용혼석 종류. D : 등급
|
||||
* C : 단계 B : 강화
|
||||
* A : 여벌의 번호들...
|
||||
/* 용혼석 Vnum에 대한 comment
|
||||
* ITEM VNUM을 10만 자리부터, FEDCBA라고 한다면
|
||||
* FE : 용혼석 종류. D : 등급
|
||||
* C : 단계 B : 강화
|
||||
* A : 여벌의 번호들...
|
||||
*/
|
||||
|
||||
BYTE GetType(DWORD dwVnum)
|
||||
@@ -175,7 +175,7 @@ bool DSManager::RefreshItemAttributes(LPITEM pDS)
|
||||
return false;
|
||||
}
|
||||
|
||||
// add_min과 add_max는 더미로 읽음.
|
||||
// add_min과 add_max는 더미로 읽음.
|
||||
int basic_apply_num, add_min, add_max;
|
||||
if (!m_pTable->GetApplyNumSettings(ds_type, grade_idx, basic_apply_num, add_min, add_max))
|
||||
{
|
||||
@@ -321,14 +321,14 @@ int DSManager::GetDuration(const LPITEM pItem) const
|
||||
return pItem->GetDuration();
|
||||
}
|
||||
|
||||
// 용혼석을 받아서 용심을 추출하는 함수
|
||||
// 용혼석을 받아서 용심을 추출하는 함수
|
||||
bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor)
|
||||
{
|
||||
if (NULL == ch || NULL == pItem)
|
||||
return false;
|
||||
if (pItem->IsEquipped())
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("착용 중인 용혼석은 추출할 수 없습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("착용 중인 용혼석은 추출할 수 없습니다."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtract
|
||||
}
|
||||
LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_FAIL", "");
|
||||
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 실패하였습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 실패하였습니다."));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -399,12 +399,12 @@ bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtract
|
||||
std::string s = boost::lexical_cast <std::string> (iCharge);
|
||||
s += "%s";
|
||||
LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_SUCCESS", s.c_str());
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 성공하였습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 성공하였습니다."));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
|
||||
// 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
|
||||
bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM pExtractor)
|
||||
{
|
||||
if (NULL == ch || NULL == pItem)
|
||||
@@ -413,13 +413,13 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
|
||||
return false;
|
||||
}
|
||||
|
||||
// 목표 위치가 valid한지 검사 후, valid하지 않다면 임의의 빈 공간을 찾는다.
|
||||
// 목표 위치가 valid한지 검사 후, valid하지 않다면 임의의 빈 공간을 찾는다.
|
||||
if (!IsValidCellForThisItem(pItem, DestCell))
|
||||
{
|
||||
int iEmptyCell = ch->GetEmptyDragonSoulInventory(pItem);
|
||||
if (iEmptyCell < 0)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다."));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -437,14 +437,14 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
|
||||
int iBonus = 0;
|
||||
float fProb;
|
||||
float fDice;
|
||||
// 용혼석 추출 성공 여부 결정.
|
||||
// 용혼석 추출 성공 여부 결정.
|
||||
{
|
||||
DWORD dwVnum = pItem->GetVnum();
|
||||
|
||||
BYTE ds_type, grade_idx, step_idx, strength_idx;
|
||||
GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
|
||||
|
||||
// 추출 정보가 없다면 일단 무조건 성공하는 것이라 생각하자.
|
||||
// 추출 정보가 없다면 일단 무조건 성공하는 것이라 생각하자.
|
||||
if (!m_pTable->GetDragonSoulExtValues(ds_type, grade_idx, fProb, dwByProduct))
|
||||
{
|
||||
pItem->AddToCharacter(ch, DestCell);
|
||||
@@ -461,7 +461,7 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
|
||||
bSuccess = fDice <= (fProb * (100 + iBonus) / 100.f);
|
||||
}
|
||||
|
||||
// 캐릭터의 용혼석 추출 및 추가 혹은 제거. 부산물 제공.
|
||||
// 캐릭터의 용혼석 추출 및 추가 혹은 제거. 부산물 제공.
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
@@ -476,7 +476,7 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
|
||||
sprintf(buf, "dice(%d) prob(%d)", fDice, fProb);
|
||||
}
|
||||
LogManager::instance().ItemLog(ch, pItem, "DS_PULL_OUT_SUCCESS", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 성공하였습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 성공하였습니다."));
|
||||
pItem->AddToCharacter(ch, DestCell);
|
||||
return true;
|
||||
}
|
||||
@@ -497,12 +497,12 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
|
||||
{
|
||||
LPITEM pByProduct = ch->AutoGiveItem(dwByProduct, true);
|
||||
if (pByProduct)
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하여 %s를 얻었습니다."), pByProduct->GetName());
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하여 %s를 얻었습니다."), pByProduct->GetName());
|
||||
else
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
|
||||
}
|
||||
else
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,8 +526,8 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
return false;
|
||||
}
|
||||
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
std::set <LPITEM> set_items;
|
||||
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
|
||||
{
|
||||
@@ -536,10 +536,10 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
LPITEM pItem = ch->GetItem(aItemPoses[i]);
|
||||
if (NULL != pItem)
|
||||
{
|
||||
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
|
||||
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
|
||||
if (!pItem->IsDragonSoul())
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
|
||||
return false;
|
||||
@@ -564,7 +564,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
BYTE ds_type, grade_idx, step_idx, strength_idx;
|
||||
int result_grade;
|
||||
|
||||
// 가장 처음 것을 강화의 기준으로 삼는다.
|
||||
// 가장 처음 것을 강화의 기준으로 삼는다.
|
||||
std::set <LPITEM>::iterator it = set_items.begin();
|
||||
{
|
||||
LPITEM pItem = *it;
|
||||
@@ -573,7 +573,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
|
||||
if (!m_pTable->GetRefineGradeValues(ds_type, grade_idx, need_count, fee, vec_probs))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량할 수 없는 용혼석입니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량할 수 없는 용혼석입니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
|
||||
return false;
|
||||
@@ -583,8 +583,8 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
{
|
||||
LPITEM pItem = *it;
|
||||
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
if (pItem->IsEquipped())
|
||||
{
|
||||
return false;
|
||||
@@ -592,14 +592,14 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
|
||||
if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
|
||||
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
|
||||
if (count != need_count)
|
||||
{
|
||||
sys_err ("Possiblity of invalid client. Name %s", ch->GetName());
|
||||
@@ -610,7 +610,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
|
||||
if (ch->GetGold() < fee)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
|
||||
return false;
|
||||
}
|
||||
@@ -655,7 +655,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
char buf[128];
|
||||
sprintf(buf, "GRADE : %d -> %d", grade_idx, result_grade);
|
||||
LogManager::instance().ItemLog(ch, pResultItem, "DS_GRADE_REFINE_SUCCESS", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 성공했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 성공했습니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
|
||||
return true;
|
||||
}
|
||||
@@ -664,7 +664,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
|
||||
char buf[128];
|
||||
sprintf(buf, "GRADE : %d -> %d", grade_idx, result_grade);
|
||||
LogManager::instance().ItemLog(ch, pResultItem, "DS_GRADE_REFINE_FAIL", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 실패했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 실패했습니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -686,18 +686,18 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
return false;
|
||||
}
|
||||
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
std::set <LPITEM> set_items;
|
||||
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
|
||||
{
|
||||
LPITEM pItem = ch->GetItem(aItemPoses[i]);
|
||||
if (NULL != pItem)
|
||||
{
|
||||
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
|
||||
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
|
||||
if (!pItem->IsDragonSoul())
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -720,7 +720,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
BYTE ds_type, grade_idx, step_idx, strength_idx;
|
||||
int result_step;
|
||||
|
||||
// 가장 처음 것을 강화의 기준으로 삼는다.
|
||||
// 가장 처음 것을 강화의 기준으로 삼는다.
|
||||
std::set <LPITEM>::iterator it = set_items.begin();
|
||||
{
|
||||
LPITEM pItem = *it;
|
||||
@@ -728,7 +728,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
|
||||
if (!m_pTable->GetRefineStepValues(ds_type, step_idx, need_count, fee, vec_probs))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량할 수 없는 용혼석입니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량할 수 없는 용혼석입니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -737,21 +737,21 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
while(++it != set_items.end())
|
||||
{
|
||||
LPITEM pItem = *it;
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
if (pItem->IsEquipped())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()) || step_idx != GetStepIdx(pItem->GetVnum()))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
|
||||
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
|
||||
if (count != need_count)
|
||||
{
|
||||
sys_err ("Possiblity of invalid client. Name %s", ch->GetName());
|
||||
@@ -762,7 +762,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
|
||||
if (ch->GetGold() < fee)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
|
||||
return false;
|
||||
}
|
||||
@@ -807,7 +807,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
char buf[128];
|
||||
sprintf(buf, "STEP : %d -> %d", step_idx, result_step);
|
||||
LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_SUCCESS", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 성공했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 성공했습니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
|
||||
return true;
|
||||
}
|
||||
@@ -816,7 +816,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
|
||||
char buf[128];
|
||||
sprintf(buf, "STEP : %d -> %d", step_idx, result_step);
|
||||
LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_FAIL", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 실패했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 실패했습니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -847,8 +847,8 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
return false;
|
||||
}
|
||||
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
|
||||
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
|
||||
std::set <LPITEM> set_items;
|
||||
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
|
||||
{
|
||||
@@ -870,15 +870,15 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++)
|
||||
{
|
||||
LPITEM pItem = *it;
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
|
||||
// 별도의 알림 처리는 안함.
|
||||
if (pItem->IsEquipped())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 용혼석과 강화석만이 개량창에 있을 수 있다.
|
||||
// 그리고 하나씩만 있어야한다.
|
||||
// 용혼석과 강화석만이 개량창에 있을 수 있다.
|
||||
// 그리고 하나씩만 있어야한다.
|
||||
if (pItem->IsDragonSoul())
|
||||
{
|
||||
if (pDragonSoul != NULL)
|
||||
@@ -899,7 +899,7 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 필요한 재료가 아닙니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 필요한 재료가 아닙니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -919,17 +919,17 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
GetDragonSoulInfo(pDragonSoul->GetVnum(), bType, bGrade, bStep, bStrength);
|
||||
|
||||
float fWeight = 0.f;
|
||||
// 가중치 값이 없다면 강화할 수 없는 용혼석
|
||||
// 가중치 값이 없다면 강화할 수 없는 용혼석
|
||||
if (!m_pTable->GetWeight(bType, bGrade, bStep, bStrength + 1, fWeight))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
|
||||
return false;
|
||||
}
|
||||
// 강화했을 때 가중치가 0이라면 더 이상 강화되서는 안된다.
|
||||
// 강화했을 때 가중치가 0이라면 더 이상 강화되서는 안된다.
|
||||
if (fWeight < FLT_EPSILON)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
|
||||
return false;
|
||||
}
|
||||
@@ -938,7 +938,7 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
float fProb;
|
||||
if (!m_pTable->GetRefineStrengthValues(bType, pRefineStone->GetSubType(), bStrength, fee, fProb))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
|
||||
|
||||
return false;
|
||||
@@ -946,7 +946,7 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
|
||||
if (ch->GetGold() < fee)
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
|
||||
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
|
||||
return false;
|
||||
}
|
||||
@@ -974,7 +974,7 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
char buf[128];
|
||||
sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength + 1);
|
||||
LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_SUCCESS", buf);
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 성공했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 성공했습니다."));
|
||||
ch->AutoGiveItem(pResult, true);
|
||||
bSubHeader = DS_SUB_HEADER_REFINE_SUCCEED;
|
||||
}
|
||||
@@ -995,10 +995,10 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
|
||||
|
||||
char buf[128];
|
||||
sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength - 1);
|
||||
// strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김.
|
||||
// strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김.
|
||||
LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_FAIL", buf);
|
||||
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 실패했습니다."));
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 실패했습니다."));
|
||||
pDragonSoul->SetCount(pDragonSoul->GetCount() - 1);
|
||||
pRefineStone->SetCount(pRefineStone->GetCount() - 1);
|
||||
if (NULL != pResult)
|
||||
@@ -1036,12 +1036,12 @@ int DSManager::LeftTime(LPITEM pItem) const
|
||||
if (pItem == NULL)
|
||||
return false;
|
||||
|
||||
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
|
||||
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
|
||||
if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
|
||||
{
|
||||
return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC);
|
||||
}
|
||||
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
|
||||
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
|
||||
else
|
||||
{
|
||||
return INT_MAX;
|
||||
@@ -1053,12 +1053,12 @@ bool DSManager::IsTimeLeftDragonSoul(LPITEM pItem) const
|
||||
if (pItem == NULL)
|
||||
return false;
|
||||
|
||||
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
|
||||
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
|
||||
if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
|
||||
{
|
||||
return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC) > 0;
|
||||
}
|
||||
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
|
||||
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
|
||||
else
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_GAME_DRAGON_SOUL_H__
|
||||
#ifndef __INC_METIN_II_GAME_DRAGON_SOUL_H__
|
||||
#define __INC_METIN_II_GAME_DRAGON_SOUL_H__
|
||||
|
||||
#include "../../common/length.h"
|
||||
@@ -16,23 +16,23 @@ public:
|
||||
bool ReadDragonSoulTableFile(const char * c_pszFileName);
|
||||
|
||||
void GetDragonSoulInfo(DWORD dwVnum, OUT BYTE& bType, OUT BYTE& bGrade, OUT BYTE& bStep, OUT BYTE& bRefine) const;
|
||||
// fixme : titempos로
|
||||
// fixme : titempos로
|
||||
WORD GetBasePosition(const LPITEM pItem) const;
|
||||
bool IsValidCellForThisItem(const LPITEM pItem, const TItemPos& Cell) const;
|
||||
int GetDuration(const LPITEM pItem) const;
|
||||
|
||||
// 용혼석을 받아서 특정 용심을 추출하는 함수
|
||||
// 용혼석을 받아서 특정 용심을 추출하는 함수
|
||||
bool ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor = NULL);
|
||||
|
||||
// 특정 용혼석(pItem)을 장비창에서 제거할 때에 성공 여부를 결정하고,
|
||||
// 실패시 부산물을 주는 함수.(부산물은 dragon_soul_table.txt에 정의)
|
||||
// DestCell에 invalid한 값을 넣으면 성공 시, 용혼석을 빈 공간에 자동 추가.
|
||||
// 실패 시, 용혼석(pItem)은 delete됨.
|
||||
// 추출아이템이 있다면 추출 성공 확률이 pExtractor->GetValue(0)%만큼 증가함.
|
||||
// 부산물은 언제나 자동 추가.
|
||||
// 특정 용혼석(pItem)을 장비창에서 제거할 때에 성공 여부를 결정하고,
|
||||
// 실패시 부산물을 주는 함수.(부산물은 dragon_soul_table.txt에 정의)
|
||||
// DestCell에 invalid한 값을 넣으면 성공 시, 용혼석을 빈 공간에 자동 추가.
|
||||
// 실패 시, 용혼석(pItem)은 delete됨.
|
||||
// 추출아이템이 있다면 추출 성공 확률이 pExtractor->GetValue(0)%만큼 증가함.
|
||||
// 부산물은 언제나 자동 추가.
|
||||
bool PullOut(LPCHARACTER ch, TItemPos DestCell, IN OUT LPITEM& pItem, LPITEM pExtractor = NULL);
|
||||
|
||||
// 용혼석 업그레이드 함수
|
||||
// 용혼석 업그레이드 함수
|
||||
bool DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
bool DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
bool DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
private:
|
||||
void SendRefineResultPacket(LPCHARACTER ch, BYTE bSubHeader, const TItemPos& pos);
|
||||
|
||||
// 캐릭터의 용혼석 덱을 살펴보고, 활성화 된 용혼석이 없다면, 캐릭터의 용혼석 활성 상태를 off 시키는 함수.
|
||||
// 캐릭터의 용혼석 덱을 살펴보고, 활성화 된 용혼석이 없다면, 캐릭터의 용혼석 활성 상태를 off 시키는 함수.
|
||||
void RefreshDragonSoulState(LPCHARACTER ch);
|
||||
|
||||
DWORD MakeDragonSoulVnum(BYTE bType, BYTE grade, BYTE step, BYTE refine);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Local Includes
|
||||
// Local Includes
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef _fsm_fsm_h
|
||||
#ifndef _fsm_fsm_h
|
||||
#define _fsm_fsm_h
|
||||
|
||||
// Local Includes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "FileMonitor_FreeBSD.h"
|
||||
#include "../../libthecore/include/log.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef FILEMONITOR_FREEBSD_INCLUDED
|
||||
#ifndef FILEMONITOR_FREEBSD_INCLUDED
|
||||
#define FILEMONITOR_FREEBSD_INCLUDED
|
||||
|
||||
#include "IFileMonitor.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "HackShield.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#ifndef HACK_SHIELD_MANAGER_H_
|
||||
#define HACK_SHIELD_MANAGER_H_
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "HackShield_Impl.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#ifndef HACK_SHIELD_IMPL_H_
|
||||
#define HACK_SHIELD_IMPL_H_
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef IFILEMONITOR_INCLUDED
|
||||
#ifndef IFILEMONITOR_INCLUDED
|
||||
#define IFILEMONITOR_INCLUDED
|
||||
|
||||
//#include <boost/function.hpp>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "MarkManager.h"
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
@@ -30,14 +30,14 @@ static Pixel * LoadOldGuildMarkImageFile()
|
||||
|
||||
bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
{
|
||||
// 폴더 생성
|
||||
// 폴더 생성
|
||||
#ifndef OS_WINDOWS
|
||||
mkdir("mark", S_IRWXU);
|
||||
#else
|
||||
_mkdir("mark");
|
||||
#endif
|
||||
|
||||
// 인덱스 파일이 있나?
|
||||
// 인덱스 파일이 있나?
|
||||
#ifndef OS_WINDOWS
|
||||
if (0 != access(OLD_MARK_INDEX_FILENAME, F_OK))
|
||||
#else
|
||||
@@ -45,13 +45,13 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
#endif
|
||||
return true;
|
||||
|
||||
// 인덱스 파일 열기
|
||||
// 인덱스 파일 열기
|
||||
FILE* fp = fopen(OLD_MARK_INDEX_FILENAME, "r");
|
||||
|
||||
if (NULL == fp)
|
||||
return false;
|
||||
|
||||
// 이미지 파일 열기
|
||||
// 이미지 파일 열기
|
||||
Pixel * oldImagePtr = LoadOldGuildMarkImageFile();
|
||||
|
||||
if (NULL == oldImagePtr)
|
||||
@@ -61,8 +61,8 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
}
|
||||
|
||||
/*
|
||||
// guild_mark.tga가 실제 targa 파일이 아니고, 512 * 512 * 4 크기의 raw 파일이다.
|
||||
// 눈으로 확인하기 위해 실제 targa 파일로 만든다.
|
||||
// guild_mark.tga가 실제 targa 파일이 아니고, 512 * 512 * 4 크기의 raw 파일이다.
|
||||
// 눈으로 확인하기 위해 실제 targa 파일로 만든다.
|
||||
CGuildMarkImage * pkImage = new CGuildMarkImage;
|
||||
pkImage->Build("guild_mark_real.tga");
|
||||
pkImage->Load("guild_mark_real.tga");
|
||||
@@ -86,7 +86,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
continue;
|
||||
}
|
||||
|
||||
// mark id -> 이미지에서의 위치 찾기
|
||||
// mark id -> 이미지에서의 위치 찾기
|
||||
uint row = mark_id / 32;
|
||||
uint col = mark_id % 32;
|
||||
|
||||
@@ -102,7 +102,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
Pixel * src = oldImagePtr + sy * 512 + sx;
|
||||
Pixel * dst = mark;
|
||||
|
||||
// 옛날 이미지에서 마크 한개 복사
|
||||
// 옛날 이미지에서 마크 한개 복사
|
||||
for (int y = 0; y != SGuildMark::HEIGHT; ++y)
|
||||
{
|
||||
for (int x = 0; x != SGuildMark::WIDTH; ++x)
|
||||
@@ -111,7 +111,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
src += 512;
|
||||
}
|
||||
|
||||
// 새 길드 마크 시스템에 넣는다.
|
||||
// 새 길드 마크 시스템에 넣는다.
|
||||
CGuildMarkManager::instance().SaveMark(guild_id, (BYTE *) mark);
|
||||
line[0] = '\0';
|
||||
}
|
||||
@@ -119,7 +119,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
|
||||
free(oldImagePtr);
|
||||
fclose(fp);
|
||||
|
||||
// 컨버트는 한번만 하면되므로 파일을 옮겨준다.
|
||||
// 컨버트는 한번만 하면되므로 파일을 옮겨준다.
|
||||
#ifndef OS_WINDOWS
|
||||
system("mv -f guild_mark.idx guild_mark.idx.removable");
|
||||
system("mv -f guild_mark.tga guild_mark.tga.removable");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "MarkImage.h"
|
||||
|
||||
#include "crc32.h"
|
||||
@@ -129,10 +129,10 @@ void CGuildMarkImage::GetData(UINT x, UINT y, UINT width, UINT height, void * da
|
||||
ilCopyPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
// 이미지 = 512x512
|
||||
// 블럭 = 마크 4 x 4
|
||||
// 마크 = 16 x 12
|
||||
// 한 이미지의 블럭 = 8 x 10
|
||||
// 이미지 = 512x512
|
||||
// 블럭 = 마크 4 x 4
|
||||
// 마크 = 16 x 12
|
||||
// 한 이미지의 블럭 = 8 x 10
|
||||
|
||||
// SERVER
|
||||
bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
|
||||
@@ -143,14 +143,14 @@ bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 마크를 전체 이미지에 그린다.
|
||||
// 마크를 전체 이미지에 그린다.
|
||||
DWORD colMark = posMark % MARK_COL_COUNT;
|
||||
DWORD rowMark = posMark / MARK_COL_COUNT;
|
||||
|
||||
printf("PutMark pos %u %ux%u\n", posMark, colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT);
|
||||
PutData(colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT, SGuildMark::WIDTH, SGuildMark::HEIGHT, pbImage);
|
||||
|
||||
// 그려진 곳의 블럭을 업데이트
|
||||
// 그려진 곳의 블럭을 업데이트
|
||||
DWORD rowBlock = rowMark / SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT;
|
||||
DWORD colBlock = colMark / SGuildMarkBlock::MARK_PER_BLOCK_WIDTH;
|
||||
|
||||
@@ -197,7 +197,7 @@ bool CGuildMarkImage::SaveBlockFromCompressedData(DWORD posBlock, const BYTE * p
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGuildMarkImage::BuildAllBlocks() // 이미지 전체를 블럭화
|
||||
void CGuildMarkImage::BuildAllBlocks() // 이미지 전체를 블럭화
|
||||
{
|
||||
Pixel apxBuf[SGuildMarkBlock::SIZE];
|
||||
sys_log(0, "GuildMarkImage::BuildAllBlocks");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_MARKIMAGE_H__
|
||||
#ifndef __INC_METIN_II_MARKIMAGE_H__
|
||||
#define __INC_METIN_II_MARKIMAGE_H__
|
||||
|
||||
#include <IL/il.h>
|
||||
@@ -16,7 +16,7 @@ struct SGuildMark
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Pixel m_apxBuf[SIZE]; // 실제 이미지
|
||||
Pixel m_apxBuf[SIZE]; // 실제 이미지
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void Clear();
|
||||
@@ -38,11 +38,11 @@ struct SGuildMarkBlock
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Pixel m_apxBuf[SIZE]; // 실제 이미지
|
||||
Pixel m_apxBuf[SIZE]; // 실제 이미지
|
||||
|
||||
BYTE m_abCompBuf[MAX_COMP_SIZE]; // 압축된 데이터
|
||||
lzo_uint m_sizeCompBuf; // 압축된 크기
|
||||
DWORD m_crc; // 압축된 데이터의 CRC
|
||||
BYTE m_abCompBuf[MAX_COMP_SIZE]; // 압축된 데이터
|
||||
lzo_uint m_sizeCompBuf; // 압축된 크기
|
||||
DWORD m_crc; // 압축된 데이터의 CRC
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DWORD GetCRC() const;
|
||||
@@ -87,9 +87,9 @@ class CGuildMarkImage
|
||||
|
||||
bool SaveMark(DWORD posMark, BYTE * pbMarkImage);
|
||||
bool DeleteMark(DWORD posMark);
|
||||
bool SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize); // 서버 -> 클라이언트
|
||||
bool SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize); // 서버 -> 클라이언트
|
||||
|
||||
DWORD GetEmptyPosition(); // 빈 마크 위치를 얻는다.
|
||||
DWORD GetEmptyPosition(); // 빈 마크 위치를 얻는다.
|
||||
|
||||
void GetBlockCRCList(DWORD * crcList);
|
||||
void GetDiffBlocks(const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "MarkManager.h"
|
||||
|
||||
#include "crc32.h"
|
||||
@@ -15,7 +15,7 @@ void CGuildMarkManager::__DeleteImage(CGuildMarkImage * pkImgDel)
|
||||
|
||||
CGuildMarkManager::CGuildMarkManager()
|
||||
{
|
||||
// 남은 mark id 셋을 만든다. (서버용)
|
||||
// 남은 mark id 셋을 만든다. (서버용)
|
||||
for (DWORD i = 0; i < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT; ++i)
|
||||
m_setFreeMarkID.insert(i);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void CGuildMarkManager::SetMarkPathPrefix(const char * prefix)
|
||||
m_pathPrefix = prefix;
|
||||
}
|
||||
|
||||
// 마크 인덱스 불러오기 (서버에서만 사용)
|
||||
// 마크 인덱스 불러오기 (서버에서만 사용)
|
||||
bool CGuildMarkManager::LoadMarkIndex()
|
||||
{
|
||||
char buf[64];
|
||||
@@ -178,7 +178,7 @@ DWORD CGuildMarkManager::__AllocMarkID(DWORD guildID)
|
||||
DWORD markID = *it;
|
||||
|
||||
DWORD imgIdx = markID / CGuildMarkImage::MARK_TOTAL_COUNT;
|
||||
CGuildMarkImage * pkImage = __GetImage(imgIdx); // 이미지가 없다면 만들기 위해
|
||||
CGuildMarkImage * pkImage = __GetImage(imgIdx); // 이미지가 없다면 만들기 위해
|
||||
|
||||
if (pkImage && AddMarkIDByGuildID(guildID, markID))
|
||||
return markID;
|
||||
@@ -264,7 +264,7 @@ void CGuildMarkManager::GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::
|
||||
{
|
||||
mapDiffBlocks.clear();
|
||||
|
||||
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
|
||||
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
|
||||
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
|
||||
{
|
||||
sys_err("invalid idx %u", imgIdx);
|
||||
@@ -291,7 +291,7 @@ bool CGuildMarkManager::SaveBlockFromCompressedData(DWORD imgIdx, DWORD posBlock
|
||||
// CLIENT
|
||||
bool CGuildMarkManager::GetBlockCRCList(DWORD imgIdx, DWORD * crcList)
|
||||
{
|
||||
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
|
||||
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
|
||||
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
|
||||
{
|
||||
sys_err("invalid idx %u", imgIdx);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
|
||||
#ifndef __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
|
||||
#define __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
|
||||
|
||||
#include "MarkImage.h"
|
||||
@@ -32,11 +32,11 @@ class CGuildMarkManager : public singleton<CGuildMarkManager>
|
||||
//
|
||||
void SetMarkPathPrefix(const char * prefix);
|
||||
|
||||
bool LoadMarkIndex(); // 마크 인덱스 불러오기 (서버에서만 사용)
|
||||
bool SaveMarkIndex(); // 마크 인덱스 저장하기
|
||||
bool LoadMarkIndex(); // 마크 인덱스 불러오기 (서버에서만 사용)
|
||||
bool SaveMarkIndex(); // 마크 인덱스 저장하기
|
||||
|
||||
void LoadMarkImages(); // 모든 마크 이미지를 불러오기
|
||||
void SaveMarkImage(DWORD imgIdx); // 마크 이미지 저장
|
||||
void LoadMarkImages(); // 모든 마크 이미지를 불러오기
|
||||
void SaveMarkImage(DWORD imgIdx); // 마크 이미지 저장
|
||||
|
||||
bool GetMarkImageFilename(DWORD imgIdx, std::string & path) const;
|
||||
bool AddMarkIDByGuildID(DWORD guildID, DWORD markID);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "constants.h"
|
||||
#include "config.h"
|
||||
#include "questmanager.h"
|
||||
@@ -155,11 +155,11 @@ bool COXEventManager::ShowQuizList(LPCHARACTER pkChar)
|
||||
{
|
||||
for (size_t j = 0; j < m_vec_quiz[i].size(); ++j, ++c)
|
||||
{
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, "%d %s %s", m_vec_quiz[i][j].level, m_vec_quiz[i][j].Quiz, m_vec_quiz[i][j].answer ? LC_TEXT("曼") : LC_TEXT("芭窿"));
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, "%d %s %s", m_vec_quiz[i][j].level, m_vec_quiz[i][j].Quiz, m_vec_quiz[i][j].answer ? LC_TEXT("참") : LC_TEXT("거짓"));
|
||||
}
|
||||
}
|
||||
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("醚 柠令 荐: %d"), c);
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("총 퀴즈 수: %d"), c);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,31 +197,31 @@ EVENTFUNC(oxevent_timer)
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
SendNoticeMap(LC_TEXT("10檬第 魄沥窍摆嚼聪促."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("10초뒤 판정하겠습니다."), OXEVENT_MAP_INDEX, true);
|
||||
flag++;
|
||||
return PASSES_PER_SEC(10);
|
||||
|
||||
case 1:
|
||||
SendNoticeMap(LC_TEXT("沥翠篮"), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("정답은"), OXEVENT_MAP_INDEX, true);
|
||||
|
||||
if (info->answer == true)
|
||||
{
|
||||
COXEventManager::instance().CheckAnswer(true);
|
||||
SendNoticeMap(LC_TEXT("O 涝聪促"), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("O 입니다"), OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
COXEventManager::instance().CheckAnswer(false);
|
||||
SendNoticeMap(LC_TEXT("X 涝聪促"), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("X 입니다"), OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
|
||||
if (LC_IsJapan())
|
||||
{
|
||||
SendNoticeMap("娫堘偊偨曽乆傪奜偵堏摦偝偣傑偡丅", OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap("듩댾궑궫뺴갲귩둖궸댷벍궠궧귏궥갃", OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendNoticeMap(LC_TEXT("5檬 第 撇府脚 盒甸阑 官冰栏肺 捞悼 矫虐摆嚼聪促."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("5초 뒤 틀리신 분들을 바깥으로 이동 시키겠습니다."), OXEVENT_MAP_INDEX, true);
|
||||
}
|
||||
|
||||
flag++;
|
||||
@@ -230,7 +230,7 @@ EVENTFUNC(oxevent_timer)
|
||||
case 2:
|
||||
COXEventManager::instance().WarpToAudience();
|
||||
COXEventManager::instance().SetStatus(OXEVENT_CLOSE);
|
||||
SendNoticeMap(LC_TEXT("促澜 巩力 霖厚秦林技夸."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("다음 문제 준비해주세요."), OXEVENT_MAP_INDEX, true);
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
@@ -247,9 +247,9 @@ bool COXEventManager::Quiz(unsigned char level, int timelimit)
|
||||
|
||||
int idx = number(0, m_vec_quiz[level].size()-1);
|
||||
|
||||
SendNoticeMap(LC_TEXT("巩力 涝聪促."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("문제 입니다."), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(m_vec_quiz[level][idx].Quiz, OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("嘎栏搁 O, 撇府搁 X肺 捞悼秦林技夸"), OXEVENT_MAP_INDEX, true);
|
||||
SendNoticeMap(LC_TEXT("맞으면 O, 틀리면 X로 이동해주세요"), OXEVENT_MAP_INDEX, true);
|
||||
|
||||
if (m_timedEvent != NULL) {
|
||||
event_cancel(&m_timedEvent);
|
||||
@@ -312,17 +312,17 @@ bool COXEventManager::CheckAnswer(bool answer)
|
||||
}
|
||||
else
|
||||
{
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("沥翠涝聪促!"));
|
||||
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("정답입니다!"));
|
||||
// pkChar->CreateFly(number(FLY_FIREWORK1, FLY_FIREWORK6), pkChar);
|
||||
char chatbuf[256];
|
||||
int len = snprintf(chatbuf, sizeof(chatbuf),
|
||||
"%s %u %u", number(0, 1) == 1 ? "cheer1" : "cheer2", (DWORD)pkChar->GetVID(), 0);
|
||||
|
||||
// 府畔蔼捞 sizeof(chatbuf) 捞惑老 版快 truncate登菌促绰 舵..
|
||||
// 리턴값이 sizeof(chatbuf) 이상일 경우 truncate되었다는 뜻..
|
||||
if (len < 0 || len >= (int) sizeof(chatbuf))
|
||||
len = sizeof(chatbuf) - 1;
|
||||
|
||||
// \0 巩磊 器窃
|
||||
// \0 문자 포함
|
||||
++len;
|
||||
|
||||
TPacketGCChat pack_chat;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#define OXEVENT_MAP_INDEX 113
|
||||
|
||||
struct tag_Quiz
|
||||
@@ -10,10 +10,10 @@ struct tag_Quiz
|
||||
|
||||
enum OXEventStatus
|
||||
{
|
||||
OXEVENT_FINISH = 0, // OX이벤트가 완전히 끝난 상태
|
||||
OXEVENT_OPEN = 1, // OX이벤트가 시작됨. 을두지(20012)를 통해서 입장가능
|
||||
OXEVENT_CLOSE = 2, // OX이벤트의 참가가 끝남. 을두지(20012)를 통한 입장이 차단됨
|
||||
OXEVENT_QUIZ = 3, // 퀴즈를 출제함.
|
||||
OXEVENT_FINISH = 0, // OX이벤트가 완전히 끝난 상태
|
||||
OXEVENT_OPEN = 1, // OX이벤트가 시작됨. 을두지(20012)를 통해서 입장가능
|
||||
OXEVENT_CLOSE = 2, // OX이벤트의 참가가 끝남. 을두지(20012)를 통한 입장이 차단됨
|
||||
OXEVENT_QUIZ = 3, // 퀴즈를 출제함.
|
||||
|
||||
OXEVENT_ERR = 0xff
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include "vector.h"
|
||||
#include "char.h"
|
||||
@@ -18,13 +18,13 @@ EVENTINFO(petsystem_event_info)
|
||||
CPetSystem* pPetSystem;
|
||||
};
|
||||
|
||||
// PetSystem을 update 해주는 event.
|
||||
// PetSystem은 CHRACTER_MANAGER에서 기존 FSM으로 update 해주는 기존 chracters와 달리,
|
||||
// Owner의 STATE를 update 할 때 _UpdateFollowAI 함수로 update 해준다.
|
||||
// 그런데 owner의 state를 update를 CHRACTER_MANAGER에서 해주기 때문에,
|
||||
// petsystem을 update하다가 pet을 unsummon하는 부분에서 문제가 생겼다.
|
||||
// (CHRACTER_MANAGER에서 update 하면 chracter destroy가 pending되어, CPetSystem에서는 dangling 포인터를 가지고 있게 된다.)
|
||||
// 따라서 PetSystem만 업데이트 해주는 event를 발생시킴.
|
||||
// PetSystem을 update 해주는 event.
|
||||
// PetSystem은 CHRACTER_MANAGER에서 기존 FSM으로 update 해주는 기존 chracters와 달리,
|
||||
// Owner의 STATE를 update 할 때 _UpdateFollowAI 함수로 update 해준다.
|
||||
// 그런데 owner의 state를 update를 CHRACTER_MANAGER에서 해주기 때문에,
|
||||
// petsystem을 update하다가 pet을 unsummon하는 부분에서 문제가 생겼다.
|
||||
// (CHRACTER_MANAGER에서 update 하면 chracter destroy가 pending되어, CPetSystem에서는 dangling 포인터를 가지고 있게 된다.)
|
||||
// 따라서 PetSystem만 업데이트 해주는 event를 발생시킴.
|
||||
EVENTFUNC(petsystem_update_event)
|
||||
{
|
||||
petsystem_event_info* info = dynamic_cast<petsystem_event_info*>( event->info );
|
||||
@@ -41,12 +41,12 @@ EVENTFUNC(petsystem_update_event)
|
||||
|
||||
|
||||
pPetSystem->Update(0);
|
||||
// 0.25초마다 갱신.
|
||||
// 0.25초마다 갱신.
|
||||
return PASSES_PER_SEC(1) / 4;
|
||||
}
|
||||
|
||||
/// NOTE: 1캐릭터가 몇개의 펫을 가질 수 있는지 제한... 캐릭터마다 개수를 다르게 할거라면 변수로 넣등가... 음..
|
||||
/// 가질 수 있는 개수와 동시에 소환할 수 있는 개수가 틀릴 수 있는데 이런건 기획 없으니 일단 무시
|
||||
/// NOTE: 1캐릭터가 몇개의 펫을 가질 수 있는지 제한... 캐릭터마다 개수를 다르게 할거라면 변수로 넣등가... 음..
|
||||
/// 가질 수 있는 개수와 동시에 소환할 수 있는 개수가 틀릴 수 있는데 이런건 기획 없으니 일단 무시
|
||||
const float PET_COUNT_LIMIT = 3;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -119,7 +119,7 @@ void CPetActor::Unsummon()
|
||||
{
|
||||
if (true == this->IsSummoned())
|
||||
{
|
||||
// 버프 삭제
|
||||
// 버프 삭제
|
||||
this->ClearBuff();
|
||||
this->SetSummonItem(NULL);
|
||||
if (NULL != m_pkOwner)
|
||||
@@ -175,14 +175,14 @@ DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
|
||||
// m_pkOwner->DetailLog();
|
||||
// m_pkChar->DetailLog();
|
||||
|
||||
//펫의 국가를 주인의 국가로 설정함.
|
||||
//펫의 국가를 주인의 국가로 설정함.
|
||||
m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
|
||||
|
||||
m_dwVID = m_pkChar->GetVID();
|
||||
|
||||
this->SetName(petName);
|
||||
|
||||
// SetSummonItem(pSummonItem)를 부른 후에 ComputePoints를 부르면 버프 적용됨.
|
||||
// SetSummonItem(pSummonItem)를 부른 후에 ComputePoints를 부르면 버프 적용됨.
|
||||
this->SetSummonItem(pSummonItem);
|
||||
m_pkOwner->ComputePoints();
|
||||
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
|
||||
@@ -197,11 +197,11 @@ bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
|
||||
float dest_x = GetOwner()->GetX() + fDist * cos(r);
|
||||
float dest_y = GetOwner()->GetY() + fDist * sin(r);
|
||||
|
||||
//m_pkChar->SetRotation(number(0, 359)); // 방향은 랜덤으로 설정
|
||||
//m_pkChar->SetRotation(number(0, 359)); // 방향은 랜덤으로 설정
|
||||
|
||||
//GetDeltaByDegree(m_pkChar->GetRotation(), fDist, &fx, &fy);
|
||||
|
||||
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
|
||||
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
|
||||
//if (!(SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx, m_pkChar->GetY() + (int) fy)
|
||||
// && SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx/2, m_pkChar->GetY() + (int) fy/2)))
|
||||
// return true;
|
||||
@@ -218,7 +218,7 @@ bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
|
||||
return true;
|
||||
}
|
||||
|
||||
// char_state.cpp StateHorse함수 그냥 C&P -_-;
|
||||
// char_state.cpp StateHorse함수 그냥 C&P -_-;
|
||||
bool CPetActor::_UpdateFollowAI()
|
||||
{
|
||||
if (0 == m_pkChar->m_pkMobData)
|
||||
@@ -227,9 +227,9 @@ bool CPetActor::_UpdateFollowAI()
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: 캐릭터(펫)의 원래 이동 속도를 알아야 하는데, 해당 값(m_pkChar->m_pkMobData->m_table.sMovingSpeed)을 직접적으로 접근해서 알아낼 수도 있지만
|
||||
// m_pkChar->m_pkMobData 값이 invalid한 경우가 자주 발생함. 현재 시간관계상 원인은 다음에 파악하고 일단은 m_pkChar->m_pkMobData 값을 아예 사용하지 않도록 함.
|
||||
// 여기서 매번 검사하는 이유는 최초 초기화 할 때 정상 값을 제대로 못얻어오는 경우도 있음.. -_-;; ㅠㅠㅠㅠㅠㅠㅠㅠㅠ
|
||||
// NOTE: 캐릭터(펫)의 원래 이동 속도를 알아야 하는데, 해당 값(m_pkChar->m_pkMobData->m_table.sMovingSpeed)을 직접적으로 접근해서 알아낼 수도 있지만
|
||||
// m_pkChar->m_pkMobData 값이 invalid한 경우가 자주 발생함. 현재 시간관계상 원인은 다음에 파악하고 일단은 m_pkChar->m_pkMobData 값을 아예 사용하지 않도록 함.
|
||||
// 여기서 매번 검사하는 이유는 최초 초기화 할 때 정상 값을 제대로 못얻어오는 경우도 있음.. -_-;; ㅠㅠㅠㅠㅠㅠㅠㅠㅠ
|
||||
if (0 == m_originalMoveSpeed)
|
||||
{
|
||||
const CMob* mobData = CMobManager::Instance().Get(m_dwVnum);
|
||||
@@ -237,14 +237,14 @@ bool CPetActor::_UpdateFollowAI()
|
||||
if (0 != mobData)
|
||||
m_originalMoveSpeed = mobData->m_table.sMovingSpeed;
|
||||
}
|
||||
float START_FOLLOW_DISTANCE = 300.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
|
||||
float START_RUN_DISTANCE = 900.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
|
||||
float START_FOLLOW_DISTANCE = 300.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
|
||||
float START_RUN_DISTANCE = 900.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
|
||||
|
||||
float RESPAWN_DISTANCE = 4500.f; // 이 거리 이상 멀어지면 주인 옆으로 소환함.
|
||||
int APPROACH = 200; // 접근 거리
|
||||
float RESPAWN_DISTANCE = 4500.f; // 이 거리 이상 멀어지면 주인 옆으로 소환함.
|
||||
int APPROACH = 200; // 접근 거리
|
||||
|
||||
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
|
||||
bool bRun = false; // 뛰어야 하나?
|
||||
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
|
||||
bool bRun = false; // 뛰어야 하나?
|
||||
|
||||
DWORD currentTime = get_dword_time();
|
||||
|
||||
@@ -272,7 +272,7 @@ bool CPetActor::_UpdateFollowAI()
|
||||
bRun = true;
|
||||
}
|
||||
|
||||
m_pkChar->SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
|
||||
m_pkChar->SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
|
||||
|
||||
Follow(APPROACH);
|
||||
|
||||
@@ -288,7 +288,7 @@ bool CPetActor::_UpdateFollowAI()
|
||||
// m_dwLastActionTime = currentTime;
|
||||
// }
|
||||
//}
|
||||
// Follow 중이지만 주인과 일정 거리 이내로 가까워졌다면 멈춤
|
||||
// Follow 중이지만 주인과 일정 거리 이내로 가까워졌다면 멈춤
|
||||
else
|
||||
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
||||
//else if (currentTime - m_dwLastActionTime > number(5000, 12000))
|
||||
@@ -303,8 +303,8 @@ bool CPetActor::Update(DWORD deltaTime)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
// 펫 주인이 죽었거나, 소환된 펫의 상태가 이상하다면 펫을 없앰. (NOTE: 가끔가다 이런 저런 이유로 소환된 펫이 DEAD 상태에 빠지는 경우가 있음-_-;)
|
||||
// 펫을 소환한 아이템이 없거나, 내가 가진 상태가 아니라면 펫을 없앰.
|
||||
// 펫 주인이 죽었거나, 소환된 펫의 상태가 이상하다면 펫을 없앰. (NOTE: 가끔가다 이런 저런 이유로 소환된 펫이 DEAD 상태에 빠지는 경우가 있음-_-;)
|
||||
// 펫을 소환한 아이템이 없거나, 내가 가진 상태가 아니라면 펫을 없앰.
|
||||
if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead())
|
||||
|| NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())
|
||||
|| ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner()
|
||||
@@ -320,10 +320,10 @@ bool CPetActor::Update(DWORD deltaTime)
|
||||
return bResult;
|
||||
}
|
||||
|
||||
//NOTE : 주의!!! MinDistance를 크게 잡으면 그 변위만큼의 변화동안은 follow하지 않는다,
|
||||
//NOTE : 주의!!! MinDistance를 크게 잡으면 그 변위만큼의 변화동안은 follow하지 않는다,
|
||||
bool CPetActor::Follow(float fMinDistance)
|
||||
{
|
||||
// 가려는 위치를 바라봐야 한다.
|
||||
// 가려는 위치를 바라봐야 한다.
|
||||
if( !m_pkOwner || !m_pkChar)
|
||||
return false;
|
||||
|
||||
@@ -367,7 +367,7 @@ void CPetActor::SetSummonItem (LPITEM pItem)
|
||||
|
||||
void CPetActor::GiveBuff()
|
||||
{
|
||||
// 파황 펫 버프는 던전에서만 발생함.
|
||||
// 파황 펫 버프는 던전에서만 발생함.
|
||||
if (34004 == m_dwVnum || 34009 == m_dwVnum)
|
||||
{
|
||||
if (NULL == m_pkOwner->GetDungeon())
|
||||
@@ -432,15 +432,15 @@ void CPetSystem::Destroy()
|
||||
m_petActorMap.clear();
|
||||
}
|
||||
|
||||
/// 펫 시스템 업데이트. 등록된 펫들의 AI 처리 등을 함.
|
||||
/// 펫 시스템 업데이트. 등록된 펫들의 AI 처리 등을 함.
|
||||
bool CPetSystem::Update(DWORD deltaTime)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
DWORD currentTime = get_dword_time();
|
||||
|
||||
// CHARACTER_MANAGER에서 캐릭터류 Update할 때 매개변수로 주는 (Pulse라고 되어있는)값이 이전 프레임과의 시간차이인줄 알았는데
|
||||
// 전혀 다른 값이라서-_-; 여기에 입력으로 들어오는 deltaTime은 의미가 없음ㅠㅠ
|
||||
// CHARACTER_MANAGER에서 캐릭터류 Update할 때 매개변수로 주는 (Pulse라고 되어있는)값이 이전 프레임과의 시간차이인줄 알았는데
|
||||
// 전혀 다른 값이라서-_-; 여기에 입력으로 들어오는 deltaTime은 의미가 없음ㅠㅠ
|
||||
|
||||
if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime)
|
||||
return true;
|
||||
@@ -473,7 +473,7 @@ bool CPetSystem::Update(DWORD deltaTime)
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/// 관리 목록에서 펫을 지움
|
||||
/// 관리 목록에서 펫을 지움
|
||||
void CPetSystem::DeletePet(DWORD mobVnum)
|
||||
{
|
||||
TPetActorMap::iterator iter = m_petActorMap.find(mobVnum);
|
||||
@@ -494,7 +494,7 @@ void CPetSystem::DeletePet(DWORD mobVnum)
|
||||
m_petActorMap.erase(iter);
|
||||
}
|
||||
|
||||
/// 관리 목록에서 펫을 지움
|
||||
/// 관리 목록에서 펫을 지움
|
||||
void CPetSystem::DeletePet(CPetActor* petActor)
|
||||
{
|
||||
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
||||
@@ -542,7 +542,7 @@ CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* pet
|
||||
{
|
||||
CPetActor* petActor = this->GetByVnum(mobVnum);
|
||||
|
||||
// 등록된 펫이 아니라면 새로 생성 후 관리 목록에 등록함.
|
||||
// 등록된 펫이 아니라면 새로 생성 후 관리 목록에 등록함.
|
||||
if (0 == petActor)
|
||||
{
|
||||
petActor = M2_NEW CPetActor(m_pkOwner, mobVnum, options);
|
||||
@@ -557,7 +557,7 @@ CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* pet
|
||||
|
||||
info->pPetSystem = this;
|
||||
|
||||
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25초
|
||||
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25초
|
||||
}
|
||||
|
||||
return petActor;
|
||||
@@ -589,7 +589,7 @@ CPetActor* CPetSystem::GetByVID(DWORD vid) const
|
||||
return bFound ? petActor : 0;
|
||||
}
|
||||
|
||||
/// 등록 된 펫 중에서 주어진 몹 VNUM을 가진 액터를 반환하는 함수.
|
||||
/// 등록 된 펫 중에서 주어진 몹 VNUM을 가진 액터를 반환하는 함수.
|
||||
CPetActor* CPetSystem::GetByVnum(DWORD vnum) const
|
||||
{
|
||||
CPetActor* petActor = 0;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef __HEADER_PET_SYSTEM__
|
||||
#ifndef __HEADER_PET_SYSTEM__
|
||||
#define __HEADER_PET_SYSTEM__
|
||||
|
||||
|
||||
class CHARACTER;
|
||||
|
||||
// TODO: 펫으로서의 능력치? 라던가 친밀도, 배고픔 기타등등... 수치
|
||||
// TODO: 펫으로서의 능력치? 라던가 친밀도, 배고픔 기타등등... 수치
|
||||
struct SPetAbility
|
||||
{
|
||||
};
|
||||
@@ -34,8 +34,8 @@ protected:
|
||||
virtual bool Update(DWORD deltaTime);
|
||||
|
||||
protected:
|
||||
virtual bool _UpdateFollowAI(); ///< 주인을 따라다니는 AI 처리
|
||||
virtual bool _UpdatAloneActionAI(float fMinDist, float fMaxDist); ///< 주인 근처에서 혼자 노는 AI 처리
|
||||
virtual bool _UpdateFollowAI(); ///< 주인을 따라다니는 AI 처리
|
||||
virtual bool _UpdatAloneActionAI(float fMinDist, float fMaxDist); ///< 주인 근처에서 혼자 노는 AI 처리
|
||||
|
||||
/// @TODO
|
||||
//virtual bool _UpdateCombatAI();
|
||||
@@ -62,13 +62,13 @@ public:
|
||||
bool IsSummoned() const { return 0 != m_pkChar; }
|
||||
void SetSummonItem (LPITEM pItem);
|
||||
DWORD GetSummonItemVID () { return m_dwSummonItemVID; }
|
||||
// 버프 주는 함수와 거두는 함수.
|
||||
// 이게 좀 괴랄한게, 서버가 ㅄ라서,
|
||||
// POINT_MOV_SPEED, POINT_ATT_SPEED, POINT_CAST_SPEED는 PointChange()란 함수만 써서 변경해 봐야 소용이 없는게,
|
||||
// PointChange() 이후에 어디선가 ComputePoints()를 하면 싹다 초기화되고,
|
||||
// 더 웃긴건, ComputePoints()를 부르지 않으면 클라의 POINT는 전혀 변하지 않는다는 거다.
|
||||
// 그래서 버프를 주는 것은 ComputePoints() 내부에서 petsystem->RefreshBuff()를 부르도록 하였고,
|
||||
// 버프를 빼는 것은 ClearBuff()를 부르고, ComputePoints를 하는 것으로 한다.
|
||||
// 버프 주는 함수와 거두는 함수.
|
||||
// 이게 좀 괴랄한게, 서버가 ㅄ라서,
|
||||
// POINT_MOV_SPEED, POINT_ATT_SPEED, POINT_CAST_SPEED는 PointChange()란 함수만 써서 변경해 봐야 소용이 없는게,
|
||||
// PointChange() 이후에 어디선가 ComputePoints()를 하면 싹다 초기화되고,
|
||||
// 더 웃긴건, ComputePoints()를 부르지 않으면 클라의 POINT는 전혀 변하지 않는다는 거다.
|
||||
// 그래서 버프를 주는 것은 ComputePoints() 내부에서 petsystem->RefreshBuff()를 부르도록 하였고,
|
||||
// 버프를 빼는 것은 ClearBuff()를 부르고, ComputePoints를 하는 것으로 한다.
|
||||
void GiveBuff();
|
||||
void ClearBuff();
|
||||
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
LPCHARACTER m_pkChar; // Instance of pet(CHARACTER)
|
||||
LPCHARACTER m_pkOwner;
|
||||
|
||||
// SPetAbility m_petAbility; // 능력치
|
||||
// SPetAbility m_petAbility; // 능력치
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
class CPetSystem
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<DWORD, CPetActor*> TPetActorMap; /// <VNUM, PetActor> map. (한 캐릭터가 같은 vnum의 펫을 여러개 가질 일이 있을까..??)
|
||||
typedef std::unordered_map<DWORD, CPetActor*> TPetActorMap; /// <VNUM, PetActor> map. (한 캐릭터가 같은 vnum의 펫을 여러개 가질 일이 있을까..??)
|
||||
|
||||
public:
|
||||
CPetSystem(LPCHARACTER owner);
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
bool Update(DWORD deltaTime);
|
||||
void Destroy();
|
||||
|
||||
size_t CountSummoned() const; ///< 현재 소환된(실체화 된 캐릭터가 있는) 펫의 개수
|
||||
size_t CountSummoned() const; ///< 현재 소환된(실체화 된 캐릭터가 있는) 펫의 개수
|
||||
|
||||
public:
|
||||
void SetUpdatePeriod(DWORD ms);
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
void Unsummon(DWORD mobVnum, bool bDeleteFromList = false);
|
||||
void Unsummon(CPetActor* petActor, bool bDeleteFromList = false);
|
||||
|
||||
// TODO: 진짜 펫 시스템이 들어갈 때 구현. (캐릭터가 보유한 펫의 정보를 추가할 때 라던가...)
|
||||
// TODO: 진짜 펫 시스템이 들어갈 때 구현. (캐릭터가 보유한 펫의 정보를 추가할 때 라던가...)
|
||||
CPetActor* AddPet(DWORD mobVnum, const char* petName, const SPetAbility& ability, DWORD options = CPetActor::EPetOption_Followable | CPetActor::EPetOption_Summonable | CPetActor::EPetOption_Combatable);
|
||||
|
||||
void DeletePet(DWORD mobVnum);
|
||||
@@ -126,8 +126,8 @@ public:
|
||||
|
||||
private:
|
||||
TPetActorMap m_petActorMap;
|
||||
LPCHARACTER m_pkOwner; ///< 펫 시스템의 Owner
|
||||
DWORD m_dwUpdatePeriod; ///< 업데이트 주기 (ms단위)
|
||||
LPCHARACTER m_pkOwner; ///< 펫 시스템의 Owner
|
||||
DWORD m_dwUpdatePeriod; ///< 업데이트 주기 (ms단위)
|
||||
DWORD m_dwLastUpdateTime;
|
||||
LPEVENT m_pkPetSystemUpdateEvent;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user