avatar_Paladium

Единый Blood Castle : как сделать из 8-и BC единый для всех. Подробный гайд!

Автор Paladium, 2016 Янв. 10, 21:07

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Ключевые слова [SEO] mu onlineобучениеblood castle

Paladium

Задача сделать из 8-и BC единый для всех. (зачем надо, для своих целей))



В общем через Gate перенаправил 1-7 bc на 52мапу то есть на BC8. Все бы хорошо но как начинается BC игрока выкидывает с него в девиас. То есть если на бц нет ни одного игрока с 3профой, то бц не засчитывает нелигалов )) и закрывается.

Конкретно как это можно подправить? или другие варианты по созданию единого бц.

positive

Думаю, чтобы не кикало игроков без профы, нужно посмотреть в код гса. Так должна быть такая проверка.

Moon

Однозначно в ГС лезть нужно.

Paladium

#3
Ну это понятно что в ГСе, если мыслить логически  :) Но я в C++ не селен поэтому и написал на форум за помощью.

Может есть добрые люди которые посмотрят BloodCastle.h /cpp и подскажут что подправить  (think)

#ifndef BLOODCASTLE_H
#define BLOODCASTLE_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "..commonzzzitem.h"
#include "user.h"
#include "MasterLevelSystem.h"
#include <list>

#define MAX_BLOOD_CASTLE_LEVEL 8
#define MAX_BLOOD_CASTLE_SUB_BRIDGE 10
#define MAX_BLOOD_CASTLE_BOSS_MONSTER 20
#define MAX_CLOACK_LEVEL (MAX_BLOOD_CASTLE_LEVEL+1)

#define BC_STATE_NONE 0
#define BC_STATE_CLOSED 1
#define BC_STATE_PLAYING 2
#define BC_STATE_PLAYEND 3

//1.01.00
#define BC_BLOCK_NONE 1000+BC_STATE_NONE
#define BC_BLOCK_CLOSED 1000+BC_STATE_CLOSED
#define BC_BLOCK_PLAYING 1000+BC_STATE_PLAYING
#define BC_BLOCK_PLAYEND 1000+BC_STATE_PLAYEND

#define BC_MAP_RANGE(value) ( ( value == MAP_INDEX_BLOODCASTLE8 ) ? TRUE : ( value < MAP_INDEX_BLOODCASTLE1 ) ? FALSE : ( value > MAP_INDEX_BLOODCASTLE7) ? FALSE : TRUE )

#define BC_TIME_RANGE(x) ( (((x))<0)?FALSE:(((x))>1)?FALSE:TRUE  )
#define BC_STATUE_RANGE(x) ( (((x))<0)?FALSE:(((x))>2)?FALSE:TRUE  )
#define BC_WEAPON_LEVEL_RANGE(x) ( (((x))<0)?FALSE:(((x))>2)?FALSE:TRUE  )
#define BC_BRIDGE_RANGE(x) ( ((x)<0)?FALSE:((x)>MAX_BLOOD_CASTLE_LEVEL-1)?FALSE:TRUE  )
#define BC_SUB_BRIDGE_RANGE(x) ( ((x)<0)?FALSE:((x)>MAX_BLOOD_CASTLE_SUB_BRIDGE-1)?FALSE:TRUE  )
#define BC_CLOACK_LEVEL_RANGE(x)  (  ((x)<0)?FALSE:((x)>MAX_CLOACK_LEVEL-1)?FALSE:TRUE )

struct BLOODCASTLE_START_TIME
{
int m_iHour; // 0
int m_iMinute; // 4
};

struct PMSG_SETMAPATTR_COUNT
{
PBMSG_HEAD h; // C1:46
BYTE btType; // 3
BYTE btMapAttr; // 4
BYTE btMapSetType; // 5
BYTE btCount; // 6
};

struct PMSG_SETMAPATTR
{
BYTE btX; // 0
BYTE btY; // 1
};

typedef struct _BLOODCASTLE_USER
{
int m_iIndex; // 0 18
int m_iEXP; // 4 1C
int m_iScore; // 8 20
int m_iUserState; // C 24
bool m_bSendQuitMsg; // 10
bool m_bLiveWhenDoorBreak; // 11

} BLOODCASTLE_USER, * LPBLOODCASTLE_USER;

typedef struct _BLOODCASTLE_BRIDGE
{
CRITICAL_SECTION m_critUserData; // 0
BLOODCASTLE_USER m_UserData[MAX_BLOOD_CASTLE_SUB_BRIDGE]; // 18
int m_nBossMonsterPosNum[MAX_BLOOD_CASTLE_BOSS_MONSTER]; // E0
int m_nSaintStatuePosNum; // 130
int m_nCastleDoorPosNum; // 134
int m_iTOTAL_EXP; // 138
int m_iMapNumber; // 13C
int m_iBridgeIndex; // 140
int m_iMISSION_SUCCESS; // 144
BOOL m_bCASTLE_DOOR_LIVE; // 148
int m_iBC_STATE; // 14C
int m_iBC_REMAIN_MSEC; // 150
int m_iBC_TICK_COUNT; // 154
int m_iBC_NOTIFY_COUNT; // 158
bool m_bBC_MONSTER_KILL_COMPLETE; // 15C
bool m_bBC_BOSS_MONSTER_KILL_COMPLETE; // 15D
bool m_bBC_DOOR_TERMINATE_COMPLETE; // 15E
bool m_bBC_CAN_ENTER; // 15F
bool m_bBC_CAN_PARTY; // 160
bool m_bBC_PLAY_START; // 161
bool m_bBC_REWARDED; // 162
bool m_bBC_MSG_BEFORE_ENTER; // 163
bool m_bBC_MSG_BEFORE_PLAY; // 164
bool m_bBC_MSG_BEFORE_END; // 165
bool m_bBC_MSG_BEFORE_QUIT; // 166
float m_iCastleStatueHealth; // 168
float m_iCastleDoorHealth; // 16C
int m_iBC_MONSTER_MAX_COUNT; // 170
int m_iBC_MONSTER_KILL_COUNT; // 174
int m_iBC_MONSTER_SUCCESS_MSG_COUNT; // 178
DWORD m_dwBC_TICK_DOOR_OPEN; // 17C
int m_iBC_BOSS_MONSTER_MAX_COUNT; // 180
int m_iBC_BOSS_MONSTER_KILL_COUNT; // 184
int m_iBC_BOSS_MONSTER_SUCCESS_MSG_COUNT; // 188
DWORD m_nBC_QUESTITEM_SERIAL; // 18C
int m_iBC_QUEST_ITEM_USER_INDEX; // 190
BYTE m_btBC_QUEST_ITEM_NUMBER; // 194
int m_iAngelKingPosNum; // 198
int m_iExtraEXP_Kill_Door_Party; // 19C
int m_iExtraEXP_Kill_Door_Index; // 1A0
char m_szKill_Door_AccountID[11]; // 1A4
char m_szKill_Door_CharName[11]; // 1AF
int m_iExtraEXP_Kill_Statue_Party; // 1BC
int m_iExtraEXP_Kill_Statue_Index; // 1C0
char m_szKill_Status_CharName[11]; // 1C4
char m_szKill_Status_AccountID[11]; // 1CF
int m_iExtraEXP_Win_Quest_Party; // 1DC
int m_iExtraEXP_Win_Quest_Index; // 1E0
char m_szWin_Quest_CharName[11]; // 1E4
char m_szWin_Quest_AccountID[11]; // 1EF
int m_iBC_COMPLETE_USER_INDEX; // 1FC
int m_iBC_DOOR_MONSTER_INDEX; // 200

int m_BlockInfo; //1.01.00

float m_iBC_REWARD_EXP; //208

} BLOODCASTLE_BRIDGE, * LPBLOODCASTLE_BRIDGE;

#ifdef __CUSTOMS__
struct BLOODCASTLE_ITEMREWARD
{
BYTE CastleLevel;
BYTE ItemCount;
WORD ItemID;
BYTE ItemLevel;
};
#endif

class CBloodCastle
{

public:
int CheckChoasMixItem(int iIndex);
bool BloodCastleChaosMix(int iIndex, int iLEVEL);
bool AddExperience(int iIndex, int iEXP);
int CalcSendRewardEXP(int iIndex, int iEXP);
int CalcSendRewardZEN(int iIndex, int iZEN);
void DropChaosGem(int iIndex);
void SendRewardScore(int iIndex, int iSCORE, int iLeftTime, int iAlivePartyCount);
void GiveReward_Win(int iIndex, int iBridgeIndex);
void GiveReward_Fail(int iBridgeIndex);
void SearchUserDeleteQuestItem(int iIndex);
void SearchUserDropQuestItem(int iIndex);
void SetUserState(int iIndex, int iState);
void SendCastleEntranceBlockInfo(int iBridgeIndex, bool bLive);
void SendCastleBridgeBlockInfo(int iBridgeIndex, bool bLive);
void SendCastleDoorBlockInfo(int iBridgeIndex, bool bLive);
void SendAllUserAnyMsg(LPBYTE lpMsg, int iSize);
void SendBridgeAnyMsg(LPBYTE lpMsg, int iSize, int iBridgeIndex);
void SendNoticeMessage(int iBridgeIndex, char* lpszMSG);
void SendNoticeScore(int iBridgeIndex);
void SendNoticeState(int iBridgeIndex, int iPlayState);
bool CheckUserBridgeMember(int iBridgeIndex, int iIndex);
void BlockCastleEntrance(int iBridgeIndex);
void ReleaseCastleEntrance(int iBridgeIndex);
void BlockCastleBridge(int iBridgeIndex);
void ReleaseCastleBridge(int iBridgeIndex);
void BlockCastleDoor(int iBridgeIndex);
void ReleaseCastleDoor(int iBridgeIndex);
void SetMonsterKillCount(int iBridgeIndex);
bool CheckMonsterKillCount(int iBridgeIndex);
bool CheckMonsterKillSuccess(int iBridgeIndex);
bool CheckBossKillCount(int iBridgeIndex);
bool CheckBossKillSuccess(int iBridgeIndex);
bool CheckEveryUserDie(int iBridgeIndex);
bool CheckAngelKingExist(int iBridgeIndex);
int GetWhoGotUltimateWeapon(int iBridgeIndex);
int GetCurrentLiveUserCount(int iBridgeIndex);
BOOL DropItemDirectly(int iBridgeIndex, int iIndex, int iItemType, int iItemPos);
void ClearMonster(int iBridgeIndex, bool bClearCastleDoor);
void SetMonster(int iBridgeIndex);
void SetBossMonster(int iBridgeIndex);
void SetSaintStatue(int iBridgeIndex);
int LeaveUserBridge(int iBridgeIndex, int iBridgeSubIndex, int iUserIndex);
int EnterUserBridge(int iBridgeIndex, int iUserIndex);
int LevelUp(int iIndex, int iAddExp, int iEventType);
void CheckUsersOnConnect(int iBridgeIndex);
int GetCurrentState(int iBridgeIndex);
int GetRemainTime(int iBridgeIndex);
int GetCurrentRemainSec(int iBridgeIndex);
int CheckEnterLevel(int iIndex, int iLevel);
bool CheckEnterFreeTicket(int iIndex);
int CheckEnterItem(int iIndex);
int CheckQuestItem(int iIndex);
bool CheckWalk(int iIndex, int iMoveX, int iMoveY);
bool CheckCanEnter(int iBridgeIndex);
bool CheckCanParty(int iBridgeIndex);
bool CheckPlayStart(int iBridgeIndex);
bool CheckQuestItemSerial(int iBridgeIndex, CMapItem* lpItem);
bool CheckUserHaveUlimateWeapon(int iIndex);
bool CheckWinnerExist(int iBridgeIndex);
bool CheckWinnerValid(int iBridgeIndex);
bool CheckUserWinnerParty(int iBridgeIndex, int iIndex);
bool CheckPartyExist(int iIndex);
bool CheckWinnerPartyComplete(int iBridgeIndex);
bool SetBridgeWinner(int iBridgeIndex, int iIndex);
int GetWinnerPartyCompleteCount(int iBridgeIndex);
int GetWinnerPartyCompletePoint(int iBridgeIndex);
void ChangeMonsterState(int iBridgeIndex, int iIndex);
void FixUsersPlayStateWin(int iBridgeIndex);
void FixUsersPlayStateFail(int iBridgeIndex);
// ---- Season 3 (1.01.00 refixed)
int GetMapNumByBCBridge(int iBridgeIndex);//GetBridgeMapNumber(int iBridgeIndex);
int GetBridgeIndexByMapNum(int iMapNum);//GetBridgeIndex(int iMAP_NUM);
int GetMapNumByBC_CHAOSGEM(int iChaosGem);//GetItemMapNumberFirst(int iMAP_NUM);
int GetMapNumByBC_ULTIMATEWEAPON(int iUltimateWeapon);//GetItemMapNumberSecond(int iMAP_NUM);
// ---- 1.01.00
int ChangeUserIndex(int iExUserIndex, int iCurrentUserIndex, int iBridgeIndex);
void SendNoticeMessageToSpecificUser(int iBridgeIndex, int iUserIndex, int iPlayState);
int SetCastleBlockInfo(int iBridgeIndex, int iCastleBlockInfo);
int GetCastleBlockInfo(int iBridgeIndex);
int GetPlayUserCountRightNow(int iBridgeIndex);
// ----
void Run();
void Init(bool bEVENT_ENABLE);
void Load(LPSTR filename);
void LoadItemDropRate();
void SetState(int iBridgeIndex, int iBC_STATE);
// ----
CBloodCastle();
virtual ~CBloodCastle();

protected:

void CheckSync(int iBridgeIndex);
void ClearBridgeData(int iBridgeIndex);
void ProcState_None(int iBridgeIndex);
void ProcState_Closed(int iBridgeIndex);
void ProcState_Playing(int iBridgeIndex);
void ProcState_PlayEnd(int iBridgeIndex);
void SetState_None(int iBridgeIndex);
void SetState_Closed(int iBridgeIndex);
void SetState_Playing(int iBridgeIndex);
void SetState_PlayEnd(int iBridgeIndex);
void BlockSector(int iMAP_NUM, int iSTART_X, int iSTART_Y, int iEND_X, int iEND_Y);
void ReleaseSector(int iMAP_NUM, int iSTART_X, int iSTART_Y, int iEND_X, int iEND_Y);
int GetAliveUserTotalEXP(int iBridgeIndex);
public:

BLOODCASTLE_BRIDGE m_BridgeData[MAX_BLOOD_CASTLE_LEVEL]; // 4
#ifdef __CUSTOMS__
BLOODCASTLE_ITEMREWARD m_ItemReward[MAX_BLOOD_CASTLE_LEVEL];
#endif
bool m_bBC_EVENT_ENABLE; // E04
int m_iBC_TIME_MIN_OPEN; // E08
int m_iBC_TIME_MIN_PLAY; // E0C
int m_iBC_TIME_MIN_REST; // E10
int m_iBC_NORMAL_ITEM_DROP; // E14
int m_iBC_EXCEL_ITEM_DROP; // E18
int m_iBC_MONSTER_REGEN; // E1C
std::list<BLOODCASTLE_START_TIME> m_listBloodCastleOpenTime; //season 4.5 add-on
};

static struct _BLOOODCASTLE_LEVEL
{
int iLOWER_BOUND; // 0
int iUPPER_BOUND; // 4
int iLOWER_BOUND_MAGUMSA; // 8
int iUPPER_BOUND_MAGUMSA; // C

} g_sttBLOODCASTLE_LEVEL[MAX_BLOOD_CASTLE_LEVEL] =
{
// Blood Castle 1
15, 80, // DK, DW, Elf
10, 60, // MG, DL

// Blood Castle 2
81, 130, // DK, DW, Elf
61, 110, // MG, DL

// Blood Castle 3
131, 180, // DK, DW, Elf
111, 160, // MG, DL

// Blood Castle 4
181, 230, // DK, DW, Elf
161, 210, // MG, DL

// Blood Castle 5
231, 280, // DK, DW, Elf
211, 260, // MG, DL

// Blood Castle 6
281, 330, // DK, DW, Elf
261, 310, // MG, DL

// Blood Castle 7
331, MAX_CHAR_LEVEL, // DK, DW, Elf
311, MAX_CHAR_LEVEL, // MG, DL

//Blood C!stle 8 - with master level from 400
//MAX_CHAR_LEVEL, MAX_CHAR_LEVEL+MAX_MASTER_LEVEL-1, // DK, DW, Elf
//MAX_CHAR_LEVEL, MAX_CHAR_LEVEL+MAX_MASTER_LEVEL-1 // MG, DL

//Blood Castle 8 - with master level from 1
1, MAX_CHAR_LEVEL+MASTER_MAX_LEVEL-1, // DK, DW, Elf
1, MAX_CHAR_LEVEL+MASTER_MAX_LEVEL-1 // MG, DL

};

extern CBloodCastle g_BloodCastle;

#endif

[code]//GameServer 1.00.90 JPN - Completed
#include "stdafx.h"
#include "BloodCastle.h"
#include "ChaosCastle.h"
#include "GameMain.h"
#include "GameServer.h"
//#include "GameServerAuth.h"
#include "logproc.h"
#include "..includereadscript.h"
#include "DSProtocol.h"
#include "Protocol.h"
#include "TNotice.h"
#include "..commonwinutil.h"
#include "ObjUseSkill.h"
#include "MixSystem.h"
#include "CastleSiegeSync.h"
#include "DSProtocol.h"
#include "CrywolfSync.h"
#include "MasterLevelSystem.h"
#include "BuffEffectSlot.h"
#include "ItemSocketOptionSystem.h"
#ifdef WZQUEST
#include "QuestExpProgMng.h"
#endif
#ifdef __CUSTOMS__
#include "ShopPointEx.h"
#include "ResetSystem.h"
#endif

CBloodCastle g_BloodCastle;


static const struct BLOOD_ZONE
{
BYTE btStartX;
BYTE btStartY;
BYTE btEndX;
BYTE btEndY;

} g_btCastleEntranceMapXY[MAX_BLOOD_CASTLE_LEVEL] = {

13, 15, 15, 23,   // Blood Castle 1
13, 15, 15, 23,   // Blood Castle 2
13, 15, 15, 23,   // Blood Castle 3
13, 15, 15, 23,   // Blood Castle 4
13, 15, 15, 23,   // Blood Castle 5
13, 15, 15, 23,   // Blood Castle 6
13, 15, 15, 23,   // Blood Castle 7
13, 15, 15, 23   // Blood Castle 8

}, g_btCastleBridgeMapXY[MAX_BLOOD_CASTLE_LEVEL] = {

13, 70, 15, 75,   // Bridge of Blood Castle 1
13, 70, 15, 75,   // Bridge of Blood Castle 2
13, 70, 15, 75,   // Bridge of Blood Castle 3
13, 70, 15, 75,   // Bridge of Blood Castle 4
13, 70, 15, 75,   // Bridge of Blood Castle 5
13, 70, 15, 75,   // Bridge of Blood Castle 6
13, 70, 15, 75,   // Bridge of Blood Castle 7
13, 70, 15, 75   // Bridge of Blood Castle 8

}, g_btCastleDoorMapXY[MAX_BLOOD_CASTLE_LEVEL][3]= {

// Blood Castle 1
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 2
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 3
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 4
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 5
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 6
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 7
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83,   // Altar

// Blood Castle 8
13, 76, 15, 79,   // Door Itself
11, 80, 25, 89,   // Zone Beginh Door
8, 80, 10, 83   // Altar
};

static const struct ST_REWARD_ZEN
{
int NormalCharacter;
int SpecialCharacter;

} g_iQuestWinExpendZEN[MAX_BLOOD_CASTLE_LEVEL] = {

20000,   10000,
50000,   25000,
100000,   50000,
150000,   80000,
200000,   100000,
250000,   120000,
250000,   120000,
250000,   120000
};

CBloodCastle::CBloodCastle() //0058FBD0
{
this->m_bBC_EVENT_ENABLE = false;
this->m_iBC_TIME_MIN_OPEN = 10;
this->m_iBC_NORMAL_ITEM_DROP = 100;
this->m_iBC_EXCEL_ITEM_DROP = 1200;
this->m_iBC_MONSTER_REGEN = 0;

for ( int i =0; i<MAX_BLOOD_CASTLE_LEVEL ; i++ )
{
this->m_BridgeData.m_iBC_STATE = BC_STATE_NONE;
this->m_BridgeData.m_iMapNumber = this->GetMapNumByBCBridge(i);
this->m_BridgeData.m_iBridgeIndex = i;
this->m_BridgeData.m_iBC_REMAIN_MSEC = -1;
this->m_BridgeData.m_iBC_TICK_COUNT = -1;
this->m_BridgeData.m_nSaintStatuePosNum = -1;
this->m_BridgeData.m_nCastleDoorPosNum = -1;
this->m_BridgeData.m_iAngelKingPosNum = -1;
this->m_BridgeData.m_iBC_REWARD_EXP = 1.0f; //season 4.5 add-on
this->m_BridgeData.m_BlockInfo = 1000;   //1.01.00
InitializeCriticalSection(&this->m_BridgeData.m_critUserData);
this->ClearBridgeData(i);
}
}

CBloodCastle::~CBloodCastle()
{
for ( int i =0; i<MAX_BLOOD_CASTLE_LEVEL ; i++ )
{
DeleteCriticalSection(&this->m_BridgeData.m_critUserData);
}
}


//Identical
void CBloodCastle::Init(bool bEVENT_ENABLE) //00547FD0
{
this->m_bBC_EVENT_ENABLE = bEVENT_ENABLE;

for ( int i=0; i<MAX_BLOOD_CASTLE_LEVEL ; i++ )
{
for ( int n=0;n<MAX_BLOOD_CASTLE_BOSS_MONSTER;n++)
{
this->m_BridgeData.m_iAngelKingPosNum = -1;
this->m_BridgeData.m_nBossMonsterPosNum[n] = -1;
}
}

for ( int n =0; n<gMSetBase.m_Count;n++)
{
if ( BC_MAP_RANGE(gMSetBase.m_Mp[n].m_MapNumber ) != FALSE )
{
WORD wMonsterType = gMSetBase.m_Mp[n].m_Type; //season3 changed
BYTE btMapNumber = gMSetBase.m_Mp[n].m_MapNumber;
BYTE btBloodCastleIndex = this->GetBridgeIndexByMapNum(btMapNumber); //season3 changed

if ( wMonsterType == 232 )
{
this->m_BridgeData[btBloodCastleIndex].m_iAngelKingPosNum = n;
continue;
}

if ( BC_STATUE_RANGE(wMonsterType - 132) != FALSE )
{
this->m_BridgeData[btBloodCastleIndex].m_nSaintStatuePosNum = n;
continue;
}

if ( wMonsterType == 131 )
{
this->m_BridgeData[btBloodCastleIndex].m_nCastleDoorPosNum = n;
continue;
}

if ( wMonsterType == 89 || wMonsterType == 95 || wMonsterType == 112 || wMonsterType == 118 || wMonsterType == 124 || wMonsterType == 130 || wMonsterType == 143 || wMonsterType == 433 )
{
for ( int l=0;l<MAX_BLOOD_CASTLE_BOSS_MONSTER;l++)
{
if ( this->m_BridgeData[btBloodCastleIndex].m_nBossMonsterPosNum[l] == -1 )
{
this->m_BridgeData[btBloodCastleIndex].m_nBossMonsterPosNum[l] = n;
break;
}
}
}
}

}

for ( int i=0; i < MAX_BLOOD_CASTLE_LEVEL; i++ )
{
this->SetState(i, BC_STATE_CLOSED);
}
}

void CBloodCastle::Load(char* filename)
{
int Token;
int type;
int BridgeCount;
int iBridgeNum;
// ----
SMDFile=fopen(filename, "r");   //ok

if (SMDFile == 0)
{
MsgBox("[Blood Castle] Info file Load Fail [%s]", filename);
return;
}

type=-1;
BridgeCount=-1;

while ( true )
{
Token=GetToken();

if ( Token == 2 )
{
break;
}

type=TokenNumber;

while ( true )
{
if ( type == 0 )
{
Token=GetToken();

if (strcmp("end", &TokenString[0]) == 0)
{
break;
}

this->m_iBC_TIME_MIN_OPEN = TokenNumber;

Token = GetToken();
this->m_iBC_TIME_MIN_PLAY =TokenNumber;

Token = GetToken();
this->m_iBC_TIME_MIN_REST = TokenNumber;
}
else if ( type == 1 )
{
Token = GetToken();

if (strcmp("end", &TokenString[0]) == 0)
{
break;
}

this->m_iBC_NORMAL_ITEM_DROP = TokenNumber;

Token = GetToken();
this->m_iBC_EXCEL_ITEM_DROP = TokenNumber;

Token = GetToken();
this->m_iBC_MONSTER_REGEN = TokenNumber;
}
else if ( type == 2 )
{
Token = GetToken();

if (strcmp("end", &TokenString[0]) == 0)
{
break;
}

iBridgeNum = TokenNumber;

if ( BC_BRIDGE_RANGE(iBridgeNum) != FALSE )
{
Token = GetToken();
this->m_BridgeData[iBridgeNum].m_iCastleStatueHealth = TokenNumber;

Token = GetToken();
this->m_BridgeData[iBridgeNum].m_iCastleDoorHealth = TokenNumber;
}
else
{
Token = GetToken();
Token = GetToken();
}
}
else if ( type == 3 )
{
Token = GetToken();

if (strcmp("end", &TokenString[0]) == 0)
{
break;
}

iBridgeNum = TokenNumber;

if ( BC_BRIDGE_RANGE(iBridgeNum) != FALSE )
{
Token = GetToken();
this->m_BridgeData[iBridgeNum].m_iBC_REWARD_EXP = TokenNumber;
}
else
{
Token = GetToken();
}
}
else if ( type == 4 )
{
Token = GetToken();

if (strcmp("end", &TokenString[0]) == 0)
{
break;
}

BLOODCASTLE_START_TIME Schedule;

Schedule.m_iHour = TokenNumber;

Token = GetToken();
Schedule.m_iMinute = TokenNumber;

this->m_listBloodCastleOpenTime.push_back(Schedule);
}
#ifdef __CUSTOMS__
else if( type == 5 )
{
Token = GetToken();
// ----
if( !strcmp("end", &TokenString[0]) )
{
break;
}
// ----
BYTE CastleIndex = TokenNumber;
// ----
Token = GetToken();
this->m_ItemReward[CastleIndex].ItemCount = TokenNumber;
// ----
Token = GetToken();
WORD ItemID   = TokenNumber;
// ----
Token = GetToken();
WORD ItemIndex = TokenNumber;
// ----
this->m_ItemReward[CastleIndex].ItemID = ITEMGET(ItemID, ItemIndex);
// ----
Token = GetToken();
this->m_ItemReward[CastleIndex].ItemLevel = TokenNumber;
}
#endif
}
}

fclose(SMDFile);

LogAdd("%s file load!", filename);
}

void CBloodCastle::LoadItemDropRate()
{
g_bBloodCastle=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "BloodCastleEvent", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
g_iAngelKingsPaperDropRate=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "AngelKingsPaperDropRate", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
g_iBloodBoneDropRate=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "BloodBoneDropRate", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
g_iStoneDropRate=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "StoneDropRate", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
g_bStoneItemDrop=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "StoneItemDrop", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
g_iBloodCastle_Prize=GetPrivateProfileInt(COMMONSERVER_MAINSECTION, "BloodCastlePrize", 0, gDirPath.GetNewPath(COMMONSERVER_FILE));
}

void CBloodCastle::CheckSync(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

std::list<BLOODCASTLE_START_TIME>::iterator it;
BLOODCASTLE_START_TIME WebzenVar1;
BLOODCASTLE_START_TIME WebzenVar2;
int BaseTime = 0; //7
int CheckTime = 0; //8
DWORD CurrentTime = 0; //9

tm * today; //10
time_t ltime; //11

int loc12;
int loc13;

this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT = GetTickCount();

if(this->m_listBloodCastleOpenTime.size() == 0)
{
MsgBox("Error : Blood Castle StartTime size is 0");
return;
}

time(&ltime);
today = localtime(&ltime);


CurrentTime = (today->tm_hour * 60) + today->tm_min;
WebzenVar1 = *this->m_listBloodCastleOpenTime.begin();

for( it = this->m_listBloodCastleOpenTime.begin(); it != this->m_listBloodCastleOpenTime.end(); ++it )
{
WebzenVar2 = *it;
BaseTime = (WebzenVar1.m_iHour * 60) + WebzenVar1.m_iMinute;
CheckTime =   (WebzenVar2.m_iHour * 60) + WebzenVar2.m_iMinute;

if( BaseTime == CheckTime )
{
if( CurrentTime < CheckTime )
{
WebzenVar2 = *it;
break;
}
continue;
}

if( CurrentTime >= BaseTime && CurrentTime < CheckTime )
{
break;
}
else
{
WebzenVar1 = *it;
}
}

for(loc12 = 2;loc12--;)
{
if(it == this->m_listBloodCastleOpenTime.end())
{
it = this->m_listBloodCastleOpenTime.begin();

WebzenVar2 = (*it);
}

CheckTime = WebzenVar2.m_iHour*60+WebzenVar2.m_iMinute;

if(today->tm_hour <= WebzenVar2.m_iHour && CheckTime > CurrentTime)
{
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = ((CheckTime - CurrentTime)*60)*1000;
}
else
{
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = ((1440-CurrentTime+CheckTime)*60)*1000;
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ( this->m_iBC_TIME_MIN_OPEN * 60 * 1000 ))
{
it++;

if(it != this->m_listBloodCastleOpenTime.end())
{
WebzenVar2 = (*it);
}
}
else
{
break;
}
}

loc13 = GetTickCount();
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC -= today->tm_sec * 1000;

LogAddTD("[Blood Castle] (%d) Sync Open Time. [%d] min remain", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC/60000);
}

void CBloodCastle::ClearBridgeData(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->m_BridgeData[iBridgeIndex].m_iTOTAL_EXP = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_MONSTER_MAX_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_MONSTER_KILL_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_MONSTER_SUCCESS_MSG_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_BOSS_MONSTER_MAX_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_BOSS_MONSTER_KILL_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_iBC_BOSS_MONSTER_SUCCESS_MSG_COUNT = 0;
this->m_BridgeData[iBridgeIndex].m_btBC_QUEST_ITEM_NUMBER = 0;
this->m_BridgeData[iBridgeIndex].m_dwBC_TICK_DOOR_OPEN = -1;
this->m_BridgeData[iBridgeIndex].m_nBC_QUESTITEM_SERIAL = -1;
this->m_BridgeData[iBridgeIndex].m_iBC_QUEST_ITEM_USER_INDEX = -1;
this->m_BridgeData[iBridgeIndex].m_iMISSION_SUCCESS = -1;
this->m_BridgeData[iBridgeIndex].m_iBC_NOTIFY_COUNT = -1;
this->m_BridgeData[iBridgeIndex].m_bCASTLE_DOOR_LIVE = TRUE;
this->m_BridgeData[iBridgeIndex].m_bBC_REWARDED = false;
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_ENTER = false;
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_PLAY = false;
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_END = false;
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_QUIT = false;
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER = false;
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_PARTY = false;
this->m_BridgeData[iBridgeIndex].m_bBC_PLAY_START = false;
this->m_BridgeData[iBridgeIndex].m_bBC_MONSTER_KILL_COMPLETE = false;
this->m_BridgeData[iBridgeIndex].m_bBC_BOSS_MONSTER_KILL_COMPLETE = false;
this->m_BridgeData[iBridgeIndex].m_bBC_DOOR_TERMINATE_COMPLETE = false;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Kill_Door_Index = -10;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Kill_Door_Party = -10;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Kill_Statue_Index = -10;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Kill_Statue_Party = -10;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Win_Quest_Index = -10;
this->m_BridgeData[iBridgeIndex].m_iExtraEXP_Win_Quest_Party = -10;

memset(this->m_BridgeData[iBridgeIndex].m_szKill_Door_CharName , 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szKill_Door_CharName));
memset(this->m_BridgeData[iBridgeIndex].m_szKill_Status_CharName, 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szKill_Status_CharName));
memset(this->m_BridgeData[iBridgeIndex].m_szWin_Quest_CharName, 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szWin_Quest_CharName));
memset(this->m_BridgeData[iBridgeIndex].m_szKill_Door_AccountID, 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szKill_Door_AccountID));
memset(this->m_BridgeData[iBridgeIndex].m_szKill_Status_AccountID, 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szKill_Status_AccountID));
memset(this->m_BridgeData[iBridgeIndex].m_szWin_Quest_AccountID, 0, sizeof(this->m_BridgeData[iBridgeIndex].m_szWin_Quest_AccountID));


for ( int i=0;i<MAX_BLOOD_CASTLE_SUB_BRIDGE;i++)
{
if ( this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex != -1 )
{
gObj[this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex].m_iBloodCastleEXP = 0;
gObj[this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex].m_cBloodCastleIndex = -1;
gObj[this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex].m_cBloodCastleSubIndex = -1;
gObj[this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex].m_bBloodCastleComplete = false;
}

this->m_BridgeData[iBridgeIndex].m_UserData.m_iEXP = 0;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iScore = 0;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex = -1;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iUserState= 0;
this->m_BridgeData[iBridgeIndex].m_UserData.m_bSendQuitMsg = false;
this->m_BridgeData[iBridgeIndex].m_UserData.m_bLiveWhenDoorBreak = false;
this->m_BridgeData[iBridgeIndex].m_iBC_COMPLETE_USER_INDEX = -1;
this->m_BridgeData[iBridgeIndex].m_iBC_DOOR_MONSTER_INDEX = -1; //season 2.5 add-on
this->m_BridgeData[iBridgeIndex].m_BlockInfo = 1000;   //1.01.00
}
}

void CBloodCastle::SetState(int iBridgeIndex, int iBC_STATE)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

if ( iBC_STATE < BC_STATE_NONE || iBC_STATE > BC_STATE_PLAYEND )
{
return;
}

this->m_BridgeData[iBridgeIndex].m_iBC_STATE = iBC_STATE;

switch ( this->m_BridgeData[iBridgeIndex].m_iBC_STATE )
{
case BC_STATE_NONE:
this->SetState_None(iBridgeIndex);
break;

case BC_STATE_CLOSED:
this->SetState_Closed(iBridgeIndex);
break;

case BC_STATE_PLAYING:
this->SetState_Playing(iBridgeIndex);
break;

case BC_STATE_PLAYEND:
this->SetState_PlayEnd(iBridgeIndex);
break;
}
}

void CBloodCastle::Run()
{
if ( this->m_bBC_EVENT_ENABLE != false )
{
for (int iBridgeIndex=0;iBridgeIndex<MAX_BLOOD_CASTLE_LEVEL;iBridgeIndex++)
{
switch ( this->m_BridgeData[iBridgeIndex].m_iBC_STATE )
{
case BC_STATE_NONE:
this->ProcState_None(iBridgeIndex);
break;

case BC_STATE_CLOSED:
this->ProcState_Closed(iBridgeIndex);
break;

case BC_STATE_PLAYING:
this->ProcState_Playing(iBridgeIndex);
break;

case BC_STATE_PLAYEND:
this->ProcState_PlayEnd(iBridgeIndex);
break;
}
}
if ( szAuthKey[13] != AUTHKEY13 )
{
DestroyGIocp();
}
}

}

void CBloodCastle::ProcState_None(int iBridgeIndex)
{
}

void CBloodCastle::ProcState_Closed(int iBridgeIndex)
{
int iTICK_MSEC = GetTickCount() - this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT;

if ( iTICK_MSEC >= 1000 )
{
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC -= iTICK_MSEC;
this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT = GetTickCount();

if ( g_bBloodCastle != FALSE )
{
if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ( this->m_iBC_TIME_MIN_OPEN * 60 * 1000 ) && this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER == false)
{
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER = true;
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_PARTY = true;
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ( this->m_iBC_TIME_MIN_OPEN * 60 * 1000 ) && this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC > 0 && (this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC/60000) !=this->m_BridgeData[iBridgeIndex].m_iBC_NOTIFY_COUNT)
{
this->m_BridgeData[iBridgeIndex].m_iBC_NOTIFY_COUNT = this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC / 60000;

if ( iBridgeIndex == 0 )
{
PMSG_NOTICE pNotice;

TNotice::MakeNoticeMsgEx(&pNotice, 0, lMsg.Get( MSGGET(4, 136)), this->m_BridgeData[iBridgeIndex].m_iBC_NOTIFY_COUNT+1);
this->SendAllUserAnyMsg((LPBYTE)&pNotice, pNotice.h.size);
}
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 30000 && this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC > 0 && this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_ENTER == false )
{
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_ENTER = true;

if ( iBridgeIndex == 0 )
{
PMSG_SET_DEVILSQUARE pMsg;

PHeadSetB((LPBYTE)&pMsg, 0x92, sizeof(pMsg));
pMsg.Type = 3;

for (int i= OBJ_STARTUSERINDEX;i<OBJMAX;i++)
{
if ( gObj.Connected == PLAYER_PLAYING && gObj.Type == OBJ_USER)
{
if ( BC_MAP_RANGE(gObj.MapNumber) == FALSE )
{
if ( CC_MAP_RANGE(gObj.MapNumber) == FALSE )
{
DataSend(i,(LPBYTE)&pMsg, pMsg.h.size);
}
}
}
}
}
}
}
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 0 )
{
if ( g_bBloodCastle != FALSE )
{
this->SetState(iBridgeIndex, BC_STATE_PLAYING);
}
else
{
this->SetState(iBridgeIndex, BC_STATE_CLOSED);
}
}
}

void CBloodCastle::ProcState_Playing(int iBridgeIndex)
{
int iTICK_MSEC = GetTickCount() - this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT;

if ( iTICK_MSEC >= 1000 )
{
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC -= iTICK_MSEC;
this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT = GetTickCount();

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ((this->m_iBC_TIME_MIN_PLAY*60-30)*1000) )
{
if ( this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_PLAY == false )
{
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_PLAY = true;

PMSG_SET_DEVILSQUARE pMsg;
PHeadSetB((LPBYTE)&pMsg, 0x92, sizeof(pMsg));
pMsg.Type = 4;
this->SendBridgeAnyMsg((LPBYTE)&pMsg, sizeof(pMsg), iBridgeIndex);
}
}

if ( this->m_BridgeData[iBridgeIndex].m_bBC_MONSTER_KILL_COMPLETE != false   )
{
if ( this->m_BridgeData[iBridgeIndex].m_dwBC_TICK_DOOR_OPEN != -1 )
{
if ( GetTickCount() > this->m_BridgeData[iBridgeIndex].m_dwBC_TICK_DOOR_OPEN )
{
this->ReleaseCastleBridge(iBridgeIndex);
this->SendCastleBridgeBlockInfo(iBridgeIndex, 0);
LogAddTD("[Blood Castle] (%d) Bridge Change Bridge Attribute -> Open", iBridgeIndex+1);
this->m_BridgeData[iBridgeIndex].m_dwBC_TICK_DOOR_OPEN = -1; // Prevent multiple openings
this->m_BridgeData[iBridgeIndex].m_BlockInfo = BC_BLOCK_PLAYING;   //1.01.00

if(this->m_BridgeData[iBridgeIndex].m_iBC_DOOR_MONSTER_INDEX == -1) //season 2.5 add-on
{
LogAddTD("[Blood Castle] (%d) Door Not Subsist", iBridgeIndex+1);
}
else
{
LogAddTD("[Blood Castle] (%d) Door Subsist (%d)(Name: %s)(Dieregen:%d)", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_iBC_DOOR_MONSTER_INDEX, gObj[this->m_BridgeData[iBridgeIndex].m_iBC_DOOR_MONSTER_INDEX].Name, gObj[this->m_BridgeData[iBridgeIndex].m_iBC_DOOR_MONSTER_INDEX].DieRegen);
}
}
}
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ((this->m_iBC_TIME_MIN_PLAY*60-60)*1000) && this->m_BridgeData[iBridgeIndex].m_bBC_PLAY_START == false )
{
PMSG_NOTICE pNotice;

this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = (this->m_iBC_TIME_MIN_PLAY*60)*1000;
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_PARTY = false;
TNotice::MakeNoticeMsgEx((TNotice*)&pNotice, 0, lMsg.Get(MSGGET(4, 137)), iBridgeIndex+1);
this->SendBridgeAnyMsg( (LPBYTE)&pNotice, pNotice.h.size, iBridgeIndex);
this->ReleaseCastleEntrance(iBridgeIndex);
this->SendCastleEntranceBlockInfo(iBridgeIndex, 0);
this->m_BridgeData[iBridgeIndex].m_bBC_PLAY_START = true;
this->SetMonster(iBridgeIndex);
this->m_BridgeData[iBridgeIndex].m_BlockInfo = BC_BLOCK_CLOSED;   //1.01.00
this->SendNoticeState(iBridgeIndex, false);

LogAddTD("[Blood Castle] (%d) Blood Castle Quest Start", iBridgeIndex+1);
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 30000 && this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC > 0 && this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_END == false)   // Set counter to kick
{
this->m_BridgeData[iBridgeIndex].m_bBC_MSG_BEFORE_END = true;
PMSG_SET_DEVILSQUARE pMsg;
PHeadSetB((LPBYTE)&pMsg, 0x92, sizeof(pMsg));
pMsg.Type = 5;
this->SendBridgeAnyMsg((LPBYTE)&pMsg, sizeof(pMsg), iBridgeIndex);
}

if ( this->CheckEveryUserDie(iBridgeIndex) != false )
{
PMSG_NOTICE pNotice;

TNotice::MakeNoticeMsg(&pNotice, 0, lMsg.Get(MSGGET(4, 138)));
this->SendBridgeAnyMsg( (LPBYTE)&pNotice, pNotice.h.size, iBridgeIndex);

LogAddTD("[Blood Castle] (%d) Blood Castle Quest Fail Result -> Destroy Castle Door [%s][%s]", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_szKill_Door_AccountID, this->m_BridgeData[iBridgeIndex].m_szKill_Door_CharName);
LogAddTD("[Blood Castle] (%d) Blood Castle Quest Fail Result -> Destroy Saint Status [%s][%s]", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_szKill_Door_AccountID, this->m_BridgeData[iBridgeIndex].m_szKill_Status_CharName);

this->GiveReward_Fail(iBridgeIndex);
this->SetState(iBridgeIndex, BC_STATE_CLOSED);

LogAddTD("[Blood Castle] (%d) Blood Castle Quest Failed -> Every User Out", iBridgeIndex+1);
}
else
{
if ( this->m_BridgeData[iBridgeIndex].m_bBC_PLAY_START != false )
{
if ( this->m_BridgeData[iBridgeIndex].m_bBC_DOOR_TERMINATE_COMPLETE == false || this->m_BridgeData[iBridgeIndex].m_bBC_BOSS_MONSTER_KILL_COMPLETE != false )
{
this->SendNoticeState(iBridgeIndex, 1);
}
else
{
this->SendNoticeState(iBridgeIndex, 4);
}
}
}

if ( this->CheckWinnerExist(iBridgeIndex) == true )
{
if ( this->CheckWinnerValid(iBridgeIndex) == true )
{
if ( this->CheckWinnerPartyComplete(iBridgeIndex) == true )
{
this->GiveReward_Win(this->m_BridgeData[iBridgeIndex].m_iBC_COMPLETE_USER_INDEX, iBridgeIndex);
this->SetState(iBridgeIndex, BC_STATE_PLAYEND);

LogAddTD("[Blood Castle] (%d) CheckWinnerPartyComplete(iBridgeIndex) == true", iBridgeIndex+1);
return;
}
}
else
{
this->GiveReward_Fail(iBridgeIndex);
this->SetState(iBridgeIndex, BC_STATE_PLAYEND);

LogAddTD("[Blood Castle] (%d) CheckWinnerValid(iBridgeIndex) == false", iBridgeIndex+1);
return;
}
}
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 0 )
{
if ( this->m_BridgeData[iBridgeIndex].m_bBC_REWARDED == false )
{
LogAddTD("[Blood Castle] (%d) Blood Castle Quest Fail Result -> Destroy Castle Door [%s][%s]", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_szKill_Door_AccountID, this->m_BridgeData[iBridgeIndex].m_szKill_Door_CharName);
LogAddTD("[Blood Castle] (%d) Blood Castle Quest Fail Result -> Destroy Saint Status [%s][%s]", iBridgeIndex+1, this->m_BridgeData[iBridgeIndex].m_szKill_Status_AccountID, this->m_BridgeData[iBridgeIndex].m_szKill_Status_CharName);

this->GiveReward_Fail(iBridgeIndex);

LogAddTD("[Blood Castle] (%d) Blood Castle Quest Failed -> Time Out", iBridgeIndex+1);

}

this->SetState(iBridgeIndex, BC_STATE_PLAYEND);
}
}

void CBloodCastle::ProcState_PlayEnd(int iBridgeIndex)
{
int iTICK_MSEC = GetTickCount() - this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT;

if ( iTICK_MSEC >= 1000 )
{
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC -= iTICK_MSEC;
this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT = GetTickCount();

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 30000 && this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC > 0 && this->m_BridgeData[iBridgeIndex]. m_bBC_MSG_BEFORE_QUIT == false)
{
this->m_BridgeData[iBridgeIndex]. m_bBC_MSG_BEFORE_QUIT = true;

PMSG_SET_DEVILSQUARE pMsg;

PHeadSetB((LPBYTE)&pMsg, 0x92, sizeof(pMsg));
pMsg.Type = 6;

this->SendBridgeAnyMsg((LPBYTE)&pMsg, sizeof(pMsg), iBridgeIndex);
}


}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= 0 )
{
this->SetState(iBridgeIndex, BC_STATE_CLOSED);
}
}

//Identical
void CBloodCastle::SetState_None(int iBridgeIndex) //0054A820
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = -1;
this->m_BridgeData[iBridgeIndex].m_iBC_TICK_COUNT = -1;
this->SendNoticeState(iBridgeIndex, 2);
this->ClearBridgeData(iBridgeIndex);
this->ClearMonster(iBridgeIndex, 1);

for (int n=OBJ_STARTUSERINDEX;n<OBJMAX;n++)
{
int iMapNumber = this->GetMapNumByBCBridge(iBridgeIndex); //season3 add-on

if ( gObj[n].MapNumber == iMapNumber && gObj[n].Connected == PLAYER_PLAYING ) //season3 changed
{
gObjMoveGate(n, 22);
}
}

this->BlockCastleDoor(iBridgeIndex);
}

//Identical
void CBloodCastle::SetState_Closed(int iBridgeIndex) //0054A960
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->SendNoticeState(iBridgeIndex, 2);
this->ClearBridgeData(iBridgeIndex);
this->ClearMonster(iBridgeIndex, 1);
this->CheckAngelKingExist(iBridgeIndex);

for (int n=OBJ_STARTUSERINDEX;n<OBJMAX;n++)
{
int iMapNumber = this->GetMapNumByBCBridge(iBridgeIndex); //season3 add-on

if ( gObj[n].MapNumber == iMapNumber && gObj[n].Connected > PLAYER_LOGGED ) //season3 changed
{
this->SearchUserDeleteQuestItem(n);
gObjMoveGate(n, 22);
}
}

this->BlockCastleDoor(iBridgeIndex);
this->BlockCastleBridge(iBridgeIndex);
this->BlockCastleEntrance(iBridgeIndex);
this->CheckSync(iBridgeIndex);
LogAddTD("[Blood Castle] (%d) SetState CLOSED", iBridgeIndex+1);
}

//Identical
void CBloodCastle::SetState_Playing(int iBridgeIndex) //0054AAD0
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER = false;
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = this->m_iBC_TIME_MIN_PLAY*60*1000;
this->CheckUsersOnConnect(iBridgeIndex);

PMSG_NOTICE pNotice;

TNotice::MakeNoticeMsgEx(&pNotice, 1, lMsg.Get(MSGGET(4, 139)), iBridgeIndex+1, 60);
this->SendBridgeAnyMsg((LPBYTE)&pNotice, pNotice.h.size, iBridgeIndex);

PMSG_SERVERCMD ServerCmd;

PHeadSubSetB((LPBYTE)&ServerCmd, 0xF3, 0x40, sizeof(ServerCmd));
ServerCmd.CmdType = 1;
ServerCmd.X = 45;
ServerCmd.Y = 0;

this->SendBridgeAnyMsg((LPBYTE)&ServerCmd, ServerCmd.h.size, iBridgeIndex);

for (int n=OBJ_STARTUSERINDEX;n<OBJMAX;n++)
{
if ( gObj[n].MapNumber == this->GetMapNumByBCBridge(iBridgeIndex) && gObj[n].Connected > PLAYER_LOGGED ) //season3 changed
{
this->SearchUserDeleteQuestItem(n);
}
}

LogAddTD("[Blood Castle] (%d) SetState PLAYING", iBridgeIndex+1);
}

void CBloodCastle::SetState_PlayEnd(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->SendNoticeState(iBridgeIndex, 2);
this->ClearMonster(iBridgeIndex, 0);
this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER = false;
this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC = this->m_iBC_TIME_MIN_REST*60*1000;

LogAddTD("[Blood Castle] (%d) SetState PLAYEND", iBridgeIndex+1);

for (int n=0;n<MAX_BLOOD_CASTLE_SUB_BRIDGE;n++)
{
if ( OBJMAX_RANGE(this->m_BridgeData[iBridgeIndex].m_UserData[n].m_iIndex) != FALSE )
{
this->SearchUserDeleteQuestItem(this->m_BridgeData[iBridgeIndex].m_UserData[n].m_iIndex);
}
}
}

int CBloodCastle::GetCurrentState(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return -1;
}

return this->m_BridgeData[iBridgeIndex].m_iBC_STATE;
}

int CBloodCastle::GetCurrentRemainSec(int iBridgeIndex)
{
return this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC / 1000;
}

//005ef3c0
int  CBloodCastle::CheckEnterLevel(int iIndex, int iLevel)
{
if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return 2;
}

if ( gObj[iIndex].Type != OBJ_USER || gObj[iIndex].Connected <= PLAYER_LOGGED )
{
return 2;
}

if ( gObj[iIndex].Class == CLASS_DARKLORD
#ifdef MONK
|| gObj[iIndex].Class == CLASS_MONK
#endif
|| gObj[iIndex].Class == CLASS_MAGUMSA )
{
if ( gObj[iIndex].Level >= g_sttBLOODCASTLE_LEVEL[iLevel-1].iLOWER_BOUND_MAGUMSA && gObj[iIndex].Level <= g_sttBLOODCASTLE_LEVEL[iLevel-1].iUPPER_BOUND_MAGUMSA )
{
return 0;
}

if ( gObj[iIndex].Level < g_sttBLOODCASTLE_LEVEL[iLevel-1].iLOWER_BOUND_MAGUMSA )
{
return -1;
}

if ( gObj[iIndex].Level > g_sttBLOODCASTLE_LEVEL[iLevel-1].iUPPER_BOUND_MAGUMSA )
{
return 1;
}
}
else
{
if ( gObj[iIndex].Level >= g_sttBLOODCASTLE_LEVEL[iLevel-1].iLOWER_BOUND && gObj[iIndex].Level <= g_sttBLOODCASTLE_LEVEL[iLevel-1].iUPPER_BOUND )
{
return 0;
}

if ( gObj[iIndex].Level < g_sttBLOODCASTLE_LEVEL[iLevel-1].iLOWER_BOUND )
{
return -1;
}

if ( gObj[iIndex].Level > g_sttBLOODCASTLE_LEVEL[iLevel-1].iUPPER_BOUND )
{
return 1;
}
}

return 2;
}

bool CBloodCastle::CheckEnterFreeTicket(int iIndex)
{
if ( !OBJMAX_RANGE(iIndex) )
return false;

if ( gObj[iIndex].Type != OBJ_USER || gObj[iIndex].Connected <= PLAYER_LOGGED )
return false;

for (int x=0;x<MAIN_INVENTORY_SIZE;x++)
{
if ( gObj[iIndex].pInventory
  • .IsItem() == TRUE )
{
if ( gObj[iIndex].pInventory
  • .m_Type == ITEMGET(13,47) )
{
return true;
}
}
}

return false;
}

static const int g_iBC_ChoasMixSuccessRate[MAX_BLOOD_CASTLE_LEVEL] = { 80, 80, 80, 80, 80, 80, 80, 80 };
static const int g_iBC_ChoasMixMoney[MAX_BLOOD_CASTLE_LEVEL] = {50000 , 80000 , 150000, 250000, 400000, 600000, 850000, 1050000};

//Identical
bool CBloodCastle::BloodCastleChaosMix(int iIndex, int iLEVEL) //0054B2A0
{
if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return false;
}

int iMapNumber = this->GetMapNumByBCBridge(iLEVEL-1); //Season3 add-on

if ( BC_MAP_RANGE(iMapNumber)  == FALSE ) //season3 changed
{
return false;
}

BOOL bMIX_RESULT = FALSE;

PMSG_CHAOSMIXRESULT pMsg;

PHeadSetB((LPBYTE)&pMsg.h, 0x86, sizeof(PMSG_CHAOSMIXRESULT));
pMsg.Result = CB_ERROR; //
gObj[iIndex].ChaosLock = TRUE;

LogAddTD("[Blood Castle] ???????? Mix Chaos Mix Start (Account:%s, Name:%s, Level:%d)", gObj[iIndex].AccountID, gObj[iIndex].Name, iLEVEL);

char szTemp[17];
wsprintf(szTemp, "???????? Mix,%d", iLEVEL); //Season 2.5 add-on

g_MixSystem.LogChaosItem(&gObj[iIndex], szTemp);

int iMIX_SUCCESS_RATE = g_iBC_ChoasMixSuccessRate[iLEVEL - 1];

if ( iMIX_SUCCESS_RATE < 0 || iMIX_SUCCESS_RATE > 100 )
{
DataSend(iIndex, (LPBYTE)&pMsg, pMsg.h.size);
LogAddTD("[Blood Castle] ???????? Mix Chaos Mix Failed - MixRate Out of Bound (Account:%s, Name:%s, Level:%d)", gObj[iIndex].AccountID, gObj[iIndex].Name, iLEVEL);
return false;
}

if ( g_CrywolfSync.GetOccupationState() == 0 && g_iCrywolfApplyMvpBenefit )
{
iMIX_SUCCESS_RATE += g_CrywolfSync.GetPlusChaosRate();
}

if ( iMIX_SUCCESS_RATE > 80 )
{
iMIX_SUCCESS_RATE = 80;
}

if ( gObj[iIndex].ChaosSuccessRate > 10 )
{
pMsg.Result = 0xF0;
gObj[iIndex].ChaosLock = FALSE;

DataSend(iIndex, (LPBYTE)&pMsg, pMsg.h.size);
}

iMIX_SUCCESS_RATE += gObj[iIndex].ChaosSuccessRate;
int iMIX_NEED_MONEY = g_iBC_ChoasMixMoney[iLEVEL - 1];
int iChaosTaxMoney = (int)((__int64)(iMIX_NEED_MONEY) * (__int64)(g_CastleSiegeSync.GetTaxRateChaos(iIndex)) / (__int64)100);

if ( iChaosTaxMoney < 0 )
{
iChaosTaxMoney = 0;
}

iMIX_NEED_MONEY += iChaosTaxMoney;

if ( iMIX_NEED_MONEY <  0 )
{
DataSend(iIndex, (LPBYTE)&pMsg, pMsg.h.size);
LogAddTD("[Blood Castle] ???????? Mix Chaos Mix Failed - MixMoney < 0 (Account:%s, Name:%s, Level:%d)", gObj[iIndex].AccountID, gObj[iIndex].Name, iLEVEL);
return false;
}

if ( (gObj[iIndex].Money - iMIX_NEED_MONEY) < 0 )
{
pMsg.Result = CB_BC_NOT_ENOUGH_ZEN;
DataSend(iIndex, (LPBYTE)&pMsg, pMsg.h.size);
LogAddTD("[Blood Castle] ???????? Mix Chaos Mix Failed - Not Enough Money (Account:%s, Name:%s, Level:%d)", gObj[iIndex].AccountID, gObj[iIndex].Name, iLEVEL);
return false;
}

gObj[iIndex].Money -= iMIX_NEED_MONEY;
g_CastleSiegeSync.AddTributeMoney(iChaosTaxMoney);
GCMoneySend(iIndex, gObj[iIndex].Money);

if ( (rand()%100) < iMIX_SUCCESS_RATE )
{
int item_num = ITEMGET(13,18);
ItemSerialCreateSend(iIndex, -1, 0, 0, item_num, iLEVEL, 255, 0, 0, 0, -1, 0, 0);
LogAddTD("[???????? Mix] [%s][%s] CBMix Success %d Money : %d-%d", gObj[iIndex].AccountID, gObj[iIndex].Name, iMIX_SUCCESS_RATE, gObj[iIndex].Money, iMIX_NEED_MONEY);
}
else
{
g_MixSystem.ChaosBoxInit(&gObj[iIndex]);
GCUserChaosBoxSend(&gObj[iIndex], 0);
DataSend(iIndex, (LPBYTE)&pMsg, pMsg.h.size);
LogAddTD("[???????? Mix] [%s][%s] CBMix Fail %d Money : %d-%d", gObj[iIndex].AccountID, gObj[iIndex].Name, iMIX_SUCCESS_RATE, gObj[iIndex].Money, iMIX_NEED_MONEY);
return false;
}

::gObjInventoryCommit(iIndex);

return true;
}

static const struct ST_BC_EVENT_SCORE
{
int unk0;
int unk4;
int unk8;
int unkC;
int unk10;

} g_iBC_EventScore[MAX_BLOOD_CASTLE_LEVEL] =
{
600, 300, 1000, 800, 400,
600, 300, 1000, 800, 400,
600, 300, 1005, 800, 400,
600, 300, 1005, 800, 400,
600, 300, 1005, 800, 400,
600, 300, 1005, 800, 400,
600, 300, 1005, 800, 400,
600, 300, 1005, 800, 400 //8
};

static const int g_iBC_EventScore_Fail[MAX_BLOOD_CASTLE_LEVEL] = { -300,-300,-300,-300,-300,-300,-300,-300 };

static const struct  ST_BC_ADD_EXP
{
int unk0;
int unk4;
int unk8;
int unkC;

} g_iBC_Add_Exp[MAX_BLOOD_CASTLE_LEVEL] =
{
20000, 20000, 5000, 160,
50000, 50000, 10000, 180,
80000, 80000, 15000, 200,
90000, 90000, 20000, 220,
100000, 100000, 25000, 240,
110000, 110000, 30000, 260,
120000, 120000, 35000, 280,
130000, 130000, 40000, 300 //BC8
};

static const int g_iBC_Party_EventPoint[MAX_USER_IN_PARTY]   = {5, 10, 15, 20, 30 };

static const int g_iBC_MONSTER_CHANGE_STATE[2][3] =
{
//   DamageMin   DamageMax   Defense
10,   20,   -14,
20, 40, -32
};

//005efe70
int CBloodCastle::CheckChoasMixItem(int iIndex)
{
if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return -1;
}

int iCHAOS_MIX_LEVEL = 0;
BOOL bIsChaosGemExist = FALSE;
BOOL bIsAngelKingPaperExist = FALSE;
BOOL bIsBloodBoneExist = FALSE;
BOOL bIsOtherItemExist = FALSE;
int iEventItemCount = 0;
int iAngelKingPaperLevel = 0;
int iBloodBoneLevel = 0;
int iCharmOfLuckCount=0;

for ( int i=0;i<CHAOS_BOX_SIZE;i++)
{
if ( gObj[iIndex].pChaosBox.IsItem() == TRUE )
{
if ( gObj[iIndex].pChaosBox.m_Type == ITEMGET(12,15) )
{
bIsChaosGemExist = TRUE;
}
else if ( gObj[iIndex].pChaosBox.m_Type == ITEMGET(13,16) )
{
int iSCROLL_LEVEL = gObj[iIndex].pChaosBox.m_Level;
iEventItemCount++;
bIsAngelKingPaperExist = TRUE;
iAngelKingPaperLevel = iSCROLL_LEVEL;
}
else if ( gObj[iIndex].pChaosBox.m_Type == ITEMGET(13,17) )
{
int iBLOOD_BONE_LEVEL = gObj[iIndex].pChaosBox.m_Level;
iEventItemCount++;
bIsBloodBoneExist = TRUE;
iBloodBoneLevel = iBLOOD_BONE_LEVEL;
}
else if ( gObj[iIndex].pChaosBox.m_Type == ITEMGET(14,53) )
{
iCharmOfLuckCount += gObj[iIndex].pChaosBox.m_Durability;
}
else
{
bIsOtherItemExist = TRUE;
}
}
}

gObj[iIndex].ChaosSuccessRate = iCharmOfLuckCount;

if ( bIsOtherItemExist != FALSE )
{
return -8;
}

if ( bIsAngelKingPaperExist == FALSE && bIsBloodBoneExist == FALSE )
{
return -1;
}

if ( bIsAngelKingPaperExist == FALSE || bIsBloodBoneExist == FALSE )
{
return -11;
}

if ( iEventItemCount > 2 )
{
return -12;
}

if ( iCharmOfLuckCount > 10 )
{
return -15;
}

if ( iAngelKingPaperLevel != iBloodBoneLevel )
{
return -9;
}

if ( BC_BRIDGE_RANGE(iAngelKingPaperLevel-1) == FALSE )
{
return -9;
}

if ( BC_BRIDGE_RANGE(iBloodBoneLevel-1) == FALSE )
{
return -9;
}

if ( bIsChaosGemExist == FALSE )
{
return -10;
}

if ( gObj[iIndex].Class == CLASS_DARKLORD
#ifdef MONK
|| gObj[iIndex].Class == CLASS_MONK
#endif
|| gObj[iIndex].Class == CLASS_MAGUMSA )
{
if ( gObj[iIndex].Level < g_sttBLOODCASTLE_LEVEL[0].iLOWER_BOUND_MAGUMSA )
{
return -14;
}
}
else
{
if ( gObj[iIndex].Level < g_sttBLOODCASTLE_LEVEL[0].iLOWER_BOUND )
{
return -14;
}
}

if ( bIsChaosGemExist != FALSE && bIsAngelKingPaperExist != FALSE && bIsBloodBoneExist != FALSE )
{
return iAngelKingPaperLevel;
}

return -1;
}

int CBloodCastle::CheckEnterItem(int iIndex)
{
int iITEM_LEVEL = 0;

if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return 0;
}

if ( gObj[iIndex].Type != OBJ_USER || gObj[iIndex].Connected <= PLAYER_LOGGED )
{
return 0;
}

for ( int x=0;x<MAIN_INVENTORY_SIZE;x++)
{
if ( gObj[iIndex].pInventory
  • .IsItem() == TRUE )
{
if ( gObj[iIndex].pInventory
  • .m_Type == ITEMGET(13,18) )
{
iITEM_LEVEL = gObj[iIndex].pInventory
  • .m_Level;

if ( CHECK_LIMIT(iITEM_LEVEL, MAX_CLOACK_LEVEL) == FALSE )
{
iITEM_LEVEL = 0;

}

if ( iITEM_LEVEL != 0 )
{
return iITEM_LEVEL;
}
}

if ( gObj[iIndex].pInventory
  • .m_Type == ITEMGET(13,47) )
{
iITEM_LEVEL = 10;
}
}
}

return iITEM_LEVEL;
}

//Identical
int CBloodCastle::CheckQuestItem(int iIndex) //0054BEC0
{
int iITEM_LEVEL = -1;

if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return -1;
}

if ( BC_MAP_RANGE(gObj[iIndex].MapNumber) == FALSE )
{
return -1;
}

int iBridgeIndex = this->GetBridgeIndexByMapNum(gObj[iIndex].MapNumber); //season3 add-on

if ( this->m_BridgeData[iBridgeIndex].m_nBC_QUESTITEM_SERIAL == -1 )
{
return -1;
}

if ( gObj[iIndex].Type != OBJ_USER || gObj[iIndex].Connected <= PLAYER_LOGGED )
{
return -1;
}

for ( int x=0;x<MAIN_INVENTORY_SIZE;x++)
{
if ( gObj[iIndex].pInventory
  • .IsItem() == TRUE )
{
if ( gObj[iIndex].pInventory
  • .m_Type == ITEMGET(13,19) )
{
if ( gObj[iIndex].pInventory
  • .m_Number == this->m_BridgeData[iBridgeIndex].m_nBC_QUESTITEM_SERIAL )
{
iITEM_LEVEL = gObj[iIndex].pInventory
  • .m_Level;

if ( iITEM_LEVEL < 0 || iITEM_LEVEL > 2 )
{
iITEM_LEVEL = -1;
}

break;
}
}
}
}

return iITEM_LEVEL;
}

bool CBloodCastle::CheckWalk(int iIndex, int iMoveX, int iMoveY)
{
if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return false;
}

if ( BC_MAP_RANGE(gObj[iIndex].MapNumber) == FALSE )
{
return false;
}

if ( gObj[iIndex].Type != OBJ_USER || gObj[iIndex].Connected <= PLAYER_LOGGED )
{
return false;
}

if ( this->GetCurrentState(gObj[iIndex].MapNumber) == TRUE )
{
BYTE btMapAttr = MapC[gObj[iIndex].MapNumber].GetAttr(iMoveX, iMoveY);

if ( (btMapAttr&1) != 1 )
{
return true;
}
}

return false;
}

bool CBloodCastle::CheckCanEnter(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return false;
}

return this->m_BridgeData[iBridgeIndex].m_bBC_CAN_ENTER;
}

bool CBloodCastle::CheckCanParty(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return false;
}

return this->m_BridgeData[iBridgeIndex].m_bBC_CAN_PARTY;
}

bool CBloodCastle::CheckQuestItemSerial(int iBridgeIndex, CMapItem * lpItem)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return false;
}

if ( this->m_BridgeData[iBridgeIndex].m_nBC_QUESTITEM_SERIAL == -1 )
{
return false;
}

if ( lpItem->IsItem() == TRUE )
{
if ( lpItem->m_Type == ITEMGET(13,19) )
{
int iLEVEL = lpItem->m_Level;

if ( BC_WEAPON_LEVEL_RANGE(iLEVEL) != FALSE )
{
if ( this->m_BridgeData[iBridgeIndex].m_nBC_QUESTITEM_SERIAL == lpItem->m_Number )
{
return true;
}
}
}
}


return false;

}

bool CBloodCastle::CheckPlayStart(int iBridgeIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return false;
}

return this->m_BridgeData[iBridgeIndex].m_bBC_PLAY_START;
}

int  CBloodCastle::GetRemainTime(int iBridgeIndex) //005948A0
{
int iREMAIN_MINUTE = 0;

if ( this->GetCurrentState(iBridgeIndex) == 1 )
{
iREMAIN_MINUTE = this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC / 60000 - this->m_iBC_TIME_MIN_OPEN + 1;
}
else
{
std::list<BLOODCASTLE_START_TIME>::iterator it; //loc3 -> ebp C
BLOODCASTLE_START_TIME WebzenVar1; //loc 4-5 -> ebp 14
BLOODCASTLE_START_TIME WebzenVar2; //loc 6-7 -> epb 18
int BaseTime = 0; // loc8 -> ebp 1C
int CheckTime = 0; // loc9 -> ebp 20
DWORD CurrentTime = 0;   // loc10-> ebp 24

tm * today; //loc11 -> ebp 28
time_t ltime; //loc12 -> ebp 2C

int loc13; //ebp 34
int loc14; //ebp 38

time(&ltime); //
today = localtime(&ltime); //

CurrentTime = (today->tm_hour * 60) + today->tm_min;
WebzenVar1 = *this->m_listBloodCastleOpenTime.begin();

for( it = this->m_listBloodCastleOpenTime.begin(); it != this->m_listBloodCastleOpenTime.end(); ++it ) //for identical
{
WebzenVar2 = *it; // loc5-6
BaseTime = (WebzenVar1.m_iHour * 60) + WebzenVar1.m_iMinute;
CheckTime =   (WebzenVar2.m_iHour * 60) + WebzenVar2.m_iMinute;

if( BaseTime == CheckTime )
{
if( CurrentTime < CheckTime )
{
WebzenVar2 = *it;
break;
}
continue;
}

if( CurrentTime >= BaseTime && CurrentTime < CheckTime )
{
break;
}
else
{
WebzenVar1 = *it;
}
}

for(loc13 = 2;loc13--;) //good ->func identical so far
{
if(it == this->m_listBloodCastleOpenTime.end())
{
it = this->m_listBloodCastleOpenTime.begin();

WebzenVar2 = (*it);
}

CheckTime = WebzenVar2.m_iHour*60+WebzenVar2.m_iMinute;

if(today->tm_hour <= WebzenVar2.m_iHour && CheckTime > CurrentTime)
{
iREMAIN_MINUTE = ((CheckTime - CurrentTime)*60)*1000;
}
else
{
iREMAIN_MINUTE = ((1440-CurrentTime+CheckTime)*60)*1000;
}

if ( this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC <= ( this->m_iBC_TIME_MIN_OPEN * 60 * 1000 )) //should be if ( iREMAIN_MINUTE <= ( this->m_iBC_TIME_MIN_OPEN * 60 * 1000 ))
{
it++;

if(it != this->m_listBloodCastleOpenTime.end())
{
WebzenVar2 = (*it);
}
}
else
{
break;
}
}
loc14 = GetTickCount();
iREMAIN_MINUTE = this->m_BridgeData[iBridgeIndex].m_iBC_REMAIN_MSEC - today->tm_sec * 1000;
}

return iREMAIN_MINUTE;
}

//Identical
void CBloodCastle::ClearMonster(int iBridgeIndex, bool bClearCastleDoor) //0054C700
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

for ( int n=0;n<OBJ_MAXMONSTER;n++)
{
if ( gObj[n].MapNumber == this->GetMapNumByBCBridge(iBridgeIndex))
{
if ( bClearCastleDoor == false && gObj[n].Class == 131)
{
continue;
}

if ( gObj[n].Class == 232 )
{
continue;
}

gObjDel(n);
}
}
}

//Identical
void CBloodCastle::SetMonster(int iBridgeIndex) //0054C810
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

this->SetMonsterKillCount(iBridgeIndex);
int nCastleDoorPosNum = this->m_BridgeData[iBridgeIndex].m_nCastleDoorPosNum;

WORD wMonsterType = gMSetBase.m_Mp[nCastleDoorPosNum].m_Type; //season3 changed
BYTE btMapNumber = gMSetBase.m_Mp[nCastleDoorPosNum].m_MapNumber;
BYTE btBloodCastleIndex = this->GetBridgeIndexByMapNum(btMapNumber); //season3 changed

if ( nCastleDoorPosNum != -1 )
{
if ( wMonsterType == 131 )
{
int iIndex = ::gObjAddMonster(btMapNumber);

if ( iIndex >= 0 )
{
::gObjSetPosMonster(iIndex, nCastleDoorPosNum);
::gObjSetMonster(iIndex, wMonsterType);

gObj[iIndex].m_cBloodCastleIndex = btBloodCastleIndex;
gObj[iIndex].m_ItemRate = this->m_iBC_NORMAL_ITEM_DROP;
gObj[iIndex].Dir = 1;
gObj[iIndex].m_PosNum = -1;
gObj[iIndex].Live = TRUE;
gObj[iIndex].DieRegen = FALSE;
gObj[iIndex].m_State = 1;
gObj[iIndex].MaxRegenTime = 0;
gObj[iIndex].MaxLife = this->m_BridgeData[btBloodCastleIndex].m_iCastleStatueHealth;
gObj[iIndex].Life = this->m_BridgeData[btBloodCastleIndex].m_iCastleStatueHealth;

LogAddTD("[Blood Castle] (%d) Create Door Successfuly : Index(%d)", btBloodCastleIndex+1, this->m_BridgeData[btBloodCastleIndex].m_iBC_DOOR_MONSTER_INDEX = iIndex); //season 2.5 add-on
}
else
{
LogAddTD("[Blood Castle] (%d) Create Door Fail", btBloodCastleIndex+1); //season 2.5 add-on
}
}
else
{
LogAddTD("[Blood Castle] (%d) Door monster type Error", btBloodCastleIndex+1); //season 2.5 add-on
}
}

int result;
for ( int n=0;n<gMSetBase.m_Count;n++)
{
if ( BC_MAP_RANGE(gMSetBase.m_Mp[n].m_MapNumber) != FALSE  )
{
WORD wIndex = gMSetBase.m_Mp[n].m_Type;
BYTE btMap   = gMSetBase.m_Mp[n].m_MapNumber;
BYTE btBridgeIndex = this->GetBridgeIndexByMapNum(btMap); //season3 changed

if ( btBridgeIndex != iBridgeIndex )
{
continue;
}

if ( wIndex == 232 )
{
continue;
}

if ( wIndex == 131 )
{
continue;
}

if ( wIndex == 89 || wIndex == 95 || wIndex == 112  || wIndex == 118 || wIndex == 124 || wIndex == 130 || wIndex == 143 || wIndex == 433 ) //season3 changed
{
continue;
}

if ( BC_STATUE_RANGE(wIndex-132) != FALSE )
{
continue;
}

result = gObjAddMonster(gMSetBase.m_Mp[n].m_MapNumber);

if ( result >= 0 )
{
gObj[result].m_PosNum = n;
gObj[result].X = gMSetBase.m_Mp[n].m_X;
gObj[result].Y = gMSetBase.m_Mp[n].m_Y;
gObj[result].MapNumber = gMSetBase.m_Mp[n].m_MapNumber;
gObj[result].TX = gObj[result].X;
gObj[result].TY = gObj[result].Y;
gObj[result].m_OldX = gObj[result].X;
gObj[result].m_OldY = gObj[result].Y;
gObj[result].Dir = gMSetBase.m_Mp[n].m_Dir;
gObj[result].StartX = gObj[result].X;
gObj[result].StartY = gObj[result].Y;
gObjSetMonster(result, wIndex);
gObj[result].MaxRegenTime = this->m_iBC_MONSTER_REGEN;
gObj[result].m_cBloodCastleIndex = btBridgeIndex;
gObj[result].Dir = rand() % 8;
}
}
}

}

//Identical
void CBloodCastle::SetBossMonster(int iBridgeIndex) //0054CF50
{
int result;

if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

for ( int x=0;x<MAX_BLOOD_CASTLE_BOSS_MONSTER;x++)
{
if ( this->m_BridgeData[iBridgeIndex].m_nBossMonsterPosNum
  • != -1 )
{
int nBossMonsterPosNum = this->m_BridgeData[iBridgeIndex].m_nBossMonsterPosNum
  • ;

WORD wMonsterType = gMSetBase.m_Mp[nBossMonsterPosNum].m_Type; //season3 changed
BYTE btMapNumber = gMSetBase.m_Mp[nBossMonsterPosNum].m_MapNumber;
BYTE btBloodCastleIndex = this->GetBridgeIndexByMapNum(btMapNumber); //season3 changed

if ( btBloodCastleIndex != iBridgeIndex )
{
continue;
}

if ( wMonsterType == 89 || wMonsterType == 95 || wMonsterType == 112 || wMonsterType == 118 || wMonsterType == 124 || wMonsterType == 130 || wMonsterType == 143 || wMonsterType == 433)
{
result = ::gObjAddMonster(btMapNumber);

if ( result >= 0 )
{
::gObjSetPosMonster(result, nBossMonsterPosNum);
::gObjSetMonster(result, wMonsterType);
gObj[result].MaxRegenTime = this->m_iBC_MONSTER_REGEN;
gObj[result].m_cBloodCastleIndex = btBloodCastleIndex;
gObj[result].m_ItemRate = this->m_iBC_NORMAL_ITEM_DROP;
gObj[result].Dir = rand() % 8;
}
}
}
}
}

//Identical
void CBloodCastle::SetSaintStatue(int iBridgeIndex) //0054D1E0
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

int nSaintStatuePosNum = this->m_BridgeData[iBridgeIndex].m_nSaintStatuePosNum;

WORD wMonsterType = gMSetBase.m_Mp[nSaintStatuePosNum].m_Type; //season3 changed
BYTE btMapNumber = gMSetBase.m_Mp[nSaintStatuePosNum].m_MapNumber;
BYTE btBloodCastleIndex = this->GetBridgeIndexByMapNum(btMapNumber); //season3 changed

if ( nSaintStatuePosNum != -1 )
{
if ( BC_STATUE_RANGE(wMonsterType-132) != FALSE )
{
int result = gObjAddMonster(btMapNumber);

if ( result >= 0 )
{
::gObjSetPosMonster(result, nSaintStatuePosNum);
::gObjSetMonster(result, wMonsterType);
gObj[result].Class = rand() % 3 + 132;
gObj[result].m_cBloodCastleIndex = btBloodCastleIndex;
gObj[result].m_ItemRate = this->m_iBC_NORMAL_ITEM_DROP;
gObj[result].Dir = 1;
gObj[result].m_PosNum = -1;
gObj[result].Live = TRUE;
gObj[result].DieRegen = 0;
gObj[result].m_State = 1;
gObj[result].MaxRegenTime = 0;
gObj[result].MaxLife = this->m_BridgeData[btBloodCastleIndex].m_iCastleStatueHealth;
gObj[result].Life = this->m_BridgeData[btBloodCastleIndex].m_iCastleStatueHealth;

LogAddTD("[Blood Castle] (%d) Saint Status be created.", iBridgeIndex+1); //season 2.5 add-on
}
}
else
{
LogAddTD("[Blood Castle][Bug Tracer] (%d) It's not Saint Statue( Map:%d, BloodCastleIndex:%d, Type:%d )", iBridgeIndex+1, btMapNumber, this->GetBridgeIndexByMapNum(btMapNumber), wMonsterType); //season3 changed
}
}

}

int CBloodCastle::LeaveUserBridge(int iBridgeIndex, int iBridgeSubIndex, int iUserIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return -1;
}

if ( BC_SUB_BRIDGE_RANGE(iBridgeSubIndex) == FALSE )
{
return -1;
}

int iRET_VAL = -1;

::EnterCriticalSection(&this->m_BridgeData[iBridgeIndex].m_critUserData);

if ( this->m_BridgeData[iBridgeIndex].m_UserData[iBridgeSubIndex].m_iIndex == iUserIndex )
{
iRET_VAL = iUserIndex;
this->m_BridgeData[iBridgeIndex].m_UserData[iBridgeSubIndex].m_iIndex = -1;
this->m_BridgeData[iBridgeIndex].m_UserData[iBridgeSubIndex].m_iEXP = 0;
this->m_BridgeData[iBridgeIndex].m_UserData[iBridgeSubIndex].m_iScore = 0;
this->m_BridgeData[iBridgeIndex].m_UserData[iBridgeSubIndex].m_iUserState = 0;
}

::LeaveCriticalSection(&this->m_BridgeData[iBridgeIndex].m_critUserData);

return iRET_VAL;
}

int CBloodCastle::EnterUserBridge(int iBridgeIndex, int iUserIndex)
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return -1;
}

int iRET_VAL = -1;

::EnterCriticalSection(&this->m_BridgeData[iBridgeIndex].m_critUserData);

for ( int i=0;i<MAX_BLOOD_CASTLE_SUB_BRIDGE;i++)
{
if ( this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex != -1 )
{
if ( this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex == iUserIndex )
{
iRET_VAL = i;
break;
}
}

if ( this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex == -1 )
{
iRET_VAL = i;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex = iUserIndex;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iEXP = 0;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iScore = 0;
this->m_BridgeData[iBridgeIndex].m_UserData.m_iUserState = 0;
gObj[iUserIndex].m_bBloodCastleComplete = false;
break;
}
}

::LeaveCriticalSection(&this->m_BridgeData[iBridgeIndex].m_critUserData);

return iRET_VAL;
}

int CBloodCastle::LevelUp(int iIndex, int iAddExp, int iEventType)
{
if ( OBJMAX_RANGE(iIndex) == FALSE )
{
return 0;
}

int iLEFT_EXP = 0;

if(g_MasterLevelSystem.MasterLevelUp(&gObj[iIndex], iAddExp, true, 0) != 0)
{
return 0;
}

if(gObjPandaSprite(&gObj[iIndex]) == TRUE) //CashShop Panda Pet (Season 4.6 Add-on)
{
int ReWardEXP = iAddExp * 50 / 100;
iAddExp += (__int64)ReWardEXP;
}
if( gObjUnicornSprite(&gObj[iIndex]) == TRUE ) // Season 5 Episode 2 JPN
{
int ReWardEXP = iAddExp * 30 / 100;
iAddExp += (__int64)ReWardEXP;
}

::gObjSetExpPetItem(iIndex, iAddExp);

LogAddTD("Experience : Map[%d]-(%d,%d) [%s][%s](%d) %u %d MonsterIndex : %d, EventType : %d", gObj[iIndex].MapNumber, gObj[iIndex].X, gObj[iIndex].X, gObj[iIndex].AccountID, gObj[iIndex].Name, gObj[iIndex].Level, gObj[iIndex].Experience, iAddExp, 0, iEventType);

if ( gObj[iIndex].Level >= MAX_CHAR_LEVEL )
{
::GCServerMsgStringSend(lMsg.Get(MSGGET(4, 112)), gObj[iIndex].m_Index, 1);
return 0;
}

if ( (gObj[iIndex].Experience + iAddExp) < gObj[iIndex].NextExp )
{
gObj[iIndex].Experience += iAddExp;
}
else
{
iLEFT_EXP = gObj[iIndex].Experience + iAddExp - gObj[iIndex].NextExp;
gObj[iIndex].Experience = gObj[iIndex].NextExp;
gObj[iIndex].Level++;

if ( gObj[iIndex].Class == CLASS_DARKLORD
#ifdef MONK
|| gObj[iIndex].Class == CLASS_MONK
#endif
|| gObj[iIndex].Class == CLASS_MAGUMSA )
{
gObj[iIndex].LevelUpPoint += 7;
}
else
{
gObj[iIndex].LevelUpPoint += 5;
}

if( gObj[iIndex].PlusStatQuestClear && gObj[iIndex].Level >= g_ResetSystem.m_MarlonStatMinLevel )
{
gObj[iIndex].LevelUpPoint++;

LogAddTD("[%s][%s] LevelUp PlusStatQuest Clear AddStat %d",
gObj[iIndex].AccountID, gObj[iIndex].Name, gObj[iIndex].LevelUpPoint);
}

gObj[iIndex].MaxLife += DCInfo.DefClass[gObj[iIndex].Class].LevelLife;
gObj[iIndex].MaxMana += DCInfo.DefClass[gObj[iIndex].Class].LevelMana;
gObj[iIndex].Life = gObj[iIndex].MaxLife;
gObj[iIndex].Mana = gObj[iIndex].MaxMana;
gObjNextExpCal(&gObj[iIndex]);
gObjSetBP(gObj[iIndex].m_Index);

GCLevelUpMsgSend(gObj[iIndex].m_Index, 1);

gObjCalcMaxLifePower(gObj[iIndex].m_Index);
LogAddTD(lMsg.Get(MSGGET(2, 8)), gObj[iIndex].AccountID, gObj[iIndex].Name, gObj[iIndex].Level);

//----------------------------------------------------------------------------------------------

if( gObj[iIndex].Level == 400 && gObj[iIndex].PartyNumber >= 0 ) //Season 2.5 add-on (Party Level 400 Display)
{
int iPartyNumber = gObj[iIndex].PartyNumber;
char szMsg[256];
sprintf(szMsg,"400 LevelUp (%s)(%s) Party ",gObj[iIndex].AccountID,gObj[iIndex].Name);
int iPartyNumIndex;

for( int i = 0; i<MAX_USER_IN_PARTY; i++ )
{
iPartyNumIndex = gParty.m_PartyS[iPartyNumber].Number;

if( iPartyNumIndex >= 0  )
{
int iSize = strlen(szMsg);
sprintf(&szMsg[iSize],",(%s)(%s) ",gObj[iPartyNumIndex].AccountID,gObj[iPartyNumIndex].Name);
}
}
LogAddTD(szMsg);
}
}

GJSetCharacterInfo(&gObj[iIndex], gObj[iIndex].m_Index, 0, 0);

return iLEFT_EXP;
}

//Identical
void CBloodCastle::CheckUsersOnConnect(int iBridgeIndex) //0054DFA0
{
if ( BC_BRIDGE_RANGE(iBridgeIndex) == FALSE )
{
return;
}

::EnterCriticalSection(&this->m_BridgeData[iBridgeIndex].m_critUserData);

for ( int i=0;i<MAX_BLOOD_CASTLE_SUB_BRIDGE;i++)
{
if ( this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex != -1 )
{
if ( gObjIsConnected(this->m_BridgeData[iBridgeIndex].m_UserData.m_iIndex) == FALSE )
{
this->m_Bri

Profesor08

В 1 бц может пойти ограниченное кол-во человек. Вангую чувак хочет расширить этот лимит и ничего путного в голову не пришло кроме как перенаправить всех на одну карту.

Paladium

Цитата: Profesor08 от 2016 Янв. 12, 05:13  В 1 бц может пойти ограниченное кол-во человек. Вангую чувак хочет расширить этот лимит и ничего путного в голову не пришло кроме как перенаправить всех на одну карту.
Проф, ну для начала я тебе не чувак и ванговать что мне в голову нечего путного не пришло не разобравшись  в деталях это как минимум глупо и невежливо. Тем более ты "Супермодератор" - лицо этого форума, и на данный момент после такого ответа впечатление не очень приятное.

Далее этим вопросом я занимаюсь не из за лемита а из за того что я всё бц соединил в одном, ограничив на каждый мост свой лвл + в конце каждого моста замурован бос по уровню + основной квест в себя включает препятствия, такие как: топоры, шипы, мины, заморозки, квест мобы в двух клетках - несколько стратегий взятия квеста, далее закрытые вип респы, секретные комнаты с бафами и сундуки с разным добром, это если быть в вкратце.



Для всего этого мне хватает один бц с массовой зарубой на 30минут. Но это все неважно цель темы решить вопрос с выкидыванием, просьба не гадить и писать по теме если знаете решение, все остальное в ЛС.  Кто может помочь разобраться в этом вопросе в долгу не останусь, помогу частично чем умею, картами, psd дизайном, графикой, или созданием ботов для му либо для других приложений.

Profesor08

#6
Цитата: Paladium от 2016 Янв. 12, 16:20  Проф, ну для начала я тебе не чувак и ванговать что мне в голову нечего путного не пришло не разобравшись  в деталях это как минимум глупо и невежливо.
1. Значит мне надо было обращаться "эй никто", приму к сведению.
2. Добро пожаловать проф в 2016, где делать предположения - грубо и невежливо. Пожалуй останусь старомодным.

Похожие темы (5)