Files
2026-06-01 12:46:52 +02:00

322 lines
12 KiB
C++

#pragma once
// 전반적인 게임 공식/상수들.
// 헤더에는 아무것도 include 하지 말것.
//
// percentage 는 0 ~ 1 사이의 값
//
// 2004/05/21 by Testors
#pragma warning( disable : 4244 )
#include "GameType.h"
#include <mmo/ArType.h>
#include <toolkit/XRandom.h>
#include <toolkit/c_fixed.h>
struct QuestBase;
namespace GameRule
{
const int MAX_CHARACTER_NAME_SIZE = 18; ///< sonador #2.1.24
const int MAX_STATE_LEVEL = 125; ///< 최대 지속효과 레벨
const float DEFAULT_HUMAN_SIZE = 1.0f; ///< 표준 생물체(인간)의 지름
const float DEFAULT_ATTACK_RANGE = 0.5f; ///< 기본 사거리 (50센티 정도)
const int DEFAULT_UNIT_SIZE = 12; ///< 1미터가 좌표상으로 얼마인지를 정의
const float SKILL_CAST_COST = 0.2f; ///< 스킬 시전시 20% 소비
const float SKILL_FIRE_COST = 0.8f; ///< 스킬 발사시 80% 소비
const float SKILL_CANCEL_RATE = 0.03f; ///< 캐스팅 캔슬이 일어나기 위한 데미지 비율 (MAXHP 대비)
const int MAX_LEVEL = 300; ///< 최대 레벨
const int NORMAL_SUMMON_MAX_LEVEL = 70; ///< 소환수 기본형 최대 레벨
const int GROWTH_SUMMON_MAX_LEVEL = 100; ///< 소환수 성장형 최대 레벨
const int EVOLVE_SUMMON_MAX_LEVEL = 100; ///< 소환수 진화형 최대 레벨
const int ATTACK_RANGE_UNIT = 100; ///< 사정거리 단위. ( 내부적으로는 기획 DB 에서 ATTACK_RANGE_UNIT 를 곱한 값으로 처리된다 )
const AR_TIME TAMING_INTERVAL = 30000; ///< 테이밍 유지시간은 5분임
const int MAX_GOLD_DROP = 1000000; ///< 최대 골드 드랍양
const int MAX_FIRST_ATTACK_BONUS_TIME = 6000; ///< 선공 보너스 적용 시간
const float MAX_TAKE_ITEM_RANGE = 20.0f; /// 2010.10.14 최대 줍기 거리 - prodongi
const short DEFAULT_RUSH_SPEED = 140; ///< 러쉬일때 속도오~
const short DEFAULT_KNOCK_BACK_SPEED = 140; ///< 넉백일때 속도오~
const float UNMOUNT_PENALTY = 0.05f; ///< 말에서 떨어지면 체력 5% 감소
const int DEFAULT_UNMOUNT_PROBABILITY_ON_DAMAGE = 30;
const int DEFAULT_UNMOUNT_PROBABILITY_ON_CRITICAL_DAMAGE = 75;
const AR_TIME CASTING_DELAY_LOW = 20; ///< 캐스팅 딜레이
const AR_TIME CASTING_DELAY_MEDIUM = 50;
const AR_TIME CASTING_DELAY_HIGH = 100;
const AR_TIME DEFAULT_MP_DEC_TIME = 1000; ///< 오오라 시전시 MP 소진 시간
const int CASTING_CANCEL_LOW = 20; ///< 캐스팅 캔슬 확률 (%)
const int CASTING_CANCEL_MEDIUM = 50; ///< 캐스팅 캔슬 확률 (%)
const int CASTING_CANCEL_HIGH = 100; ///< 캐스팅 캔슬 확률 (%)
// 피로도 시스템 관련
const int DEFAULT_MAX_STAMINA = 475200;
const AR_TIME STAMINA_UPDATE_TIME = 6000;
const int STAMINA_REGEN_ON_GOOD = 110;
const int STAMINA_REGEN_ON_AVERAGE = 100;
const int STAMINA_REGEN_ON_BAD = 90;
const int STAMINA_REGEN_ON_LOGOUT_IN_FIELD = 30;
const int BAD_CONDITION_LIMIT = 158400 * 0.15f;
const int AVERAGE_CONDITION_LIMIT = 158400 * 0.85f;
const int GOOD_CONDITION_LIMIT = 158400;
// 기공
const int ENERGY_MAX = 10;
// PK 관련
const AR_TIME PK_ON_TIME = 100; // 1000
const AR_TIME PK_OFF_TIME = 100; // 3000
extern float fEXPRate; ///< 경치 비율
extern float fGoldDropRate; ///< 돈 드랍 비율
extern float fItemDropRate; ///< 아이템 드랍 비율
extern float fPartyEXPRate; ///< 파티 경치 보너스
extern float fChaosDropRate; ///< 혼돈 드랍 비율
extern bool bMonsterWandering; ///< 몬스터 방황 여부.-_-
const int nMaxCharactersPerAccount = 8;
const float MORAL_LIMIT = 100; ///< 블러디 캐릭터가 되기 위한 IP 수치
const float CRIME_LIMIT = 1000; ///< 데모니악 캐릭터가 되기 위한 IP 수치
const float BOW_AIMING_TIME_RATIO = 0.8f;
const AR_TIME DEFAULT_HEAVY_BOW_INTERVAL = 200; ///< 기본 활 휴지기
const AR_TIME DEFAULT_LIGHT_BOW_INTERVAL = 300; ///< 기본 활 휴지기
const AR_TIME DEFAULT_DOUBLE_SUMMON_TIME = 1000; ///< 기본 동시 소환 가능 시간
const AR_TIME BIND_SUMMON_UPDATE_TIME = 1000; ///< 소환 안된 크리쳐 업데이트 타임.
const AR_UNIT CHANGE_LOCATION_ERROR_RANGE = 10 * DEFAULT_UNIT_SIZE; ///< 위치 바꿀 때 오차범위
const AR_UNIT AGGRESIVE_MONSTER_REACTION_RANGE = 8 * DEFAULT_UNIT_SIZE; ///< 선공몹 어그로 범위
const AR_UNIT MONSTER_TRACKING_RANGE = 30 * DEFAULT_UNIT_SIZE; ///< 추적 범위 ( 이 이상 거리가 멀어지면 다른 타겟을 찾아갑니다~ )
const AR_UNIT MONSTER_COME_BACK_HOME_RANGE = 500 * DEFAULT_UNIT_SIZE; ///< 집-ㅅ-에서 너무 멀리 떨어져나와, 향수를 느껴 집으로 다시 돌아가게 되는 거리.
const int MONSTER_FIND_ATTACK_POS_RATIO = 10; ///< 공격 중 다른 몬스터와 겹칠때 적절한 위치를 찾을 확률
const int AUCTION_INFO_COUNT_PER_PAGE = 40; ///< { [sonador][3.1.2]경매장 구현
//
// 헌터홀릭 시스템 관련 상수 정의
//
const int HUNTAHOLIC_MAX_INSTANCE_NAME_LENGTH = 30;
const int HUNTAHOLIC_MAX_INSTANCE_PASSWORD_LENGTH = 16;
const int HUNTAHOLIC_MAX_INSTANCE_SLOT_ON_GUI = 8;
// #2.1.2.12
// 스킬 툴팁 관련 스트링 DB 오프셋
const int SKILL_EFFECT_TOOLTIP_STRING_OFFSET = 2000000000; ///< 효과+강화
const int SKILL_ENHANCE_TOOLTIP_STRING_OFFSET = 2100000000; ///< 강화
// #2.1.12
const unsigned int MAX_ACCOUNT_LEN = 60;
const unsigned int MAX_CRYPTO_BLOCK_LEN = 16;
// 2010.09.02. bintitle. 에테리얼스톤 최대 충전량.
const int MAX_ETHEREAL_STONE_DURABILITY = 100000000; // 최대 에테리얼 스톤 충전 가능량
// Monster Creature 관련
const char MAX_MONSTER_CREATURE_COUNT = 10;
int GetSummonEXPLimit( int depth, int level );
int GetPlayerEXPLimit( int level );
float GetSummonLevelPenalty( int master_level, int summon_level );
float GetSummonStatPenalty( int master_level, int summon_level );
float GetOverBreedLevelPenalty( int master_level, int overbreed_level, int summon_level );
float GetOverBreedStatPenalty( int master_level, int overbreed_level, int summon_level );
/// 먹자 방지 시간
inline int GetPickupOrderTime( int idx ) { return 3000 + idx * 1000; }
/// 시체 유지시간
inline int GetCorpseHoldTime() { return 3000; } // 10초
inline int GetCritical( int luck ) { return luck * 0.1f; }
inline int GetItemChance( int luck ) { return luck * 0.2f; }
/// 공격력
inline int GetAttackPoint( int strength, float level, float fCM ) { return ( 1 + ( level * 0.02f ) ) * ( strength * ( 0.3f + fCM * 0.3f ) ) + level; }
/// 마법 공격력
inline int GetMagicPoint( int intelligence, float level, float fCM ) { return ( 1 + ( level * 0.02f ) ) * ( intelligence * ( 0.3f + fCM * 0.3f) ) + level; }
/// 방어력
inline int GetDefence( float lv, int vital, float fCM ) { return ( vital * fCM + lv ) * 0.15f; }
/// 마법 방어력
inline int GetMagicDefence( float lv, int men, float fCM ) { return ( ( men * fCM ) + lv ) * 0.6f; }
/// 명중수치
inline int GetAccuracy( int dexterity, float level, float fCM ) { return level + ( dexterity * 0.5f ) * ( 0.8f + fCM * 0.2f ); }
/// 마법명중수치
inline int GetMagicAccuracy( int mental, int dexterity, float level, float fCM ) { return level + ( ( mental * 0.4f ) + ( dexterity * 0.1f ) ) * ( 0.7f + fCM * 0.3f ); }
/// 마법저항수치
inline int GetMagicAvoid( int mental, int agility, float level, float fCM ) { return level + ( ( mental * 0.4f ) + ( agility * 0.1f ) ) * ( 0.7f + fCM * 0.3f ); }
/// 회피수치
inline int GetAvoid( int agility, float level, float fCM ) { return level + ( agility * 0.5f ) * ( 0.8f + fCM * 0.2f ) + 30; }
/// 공격확률
inline float GetHitPercentage( int hit_value, int avoid_value ) { return ( 90 + hit_value - avoid_value ) / 100.0f; }
/// 시전속도
inline int GetCastingTime( int dexterity, int men, float level ) { return ( (dexterity * 8) + (men * 2) ) * 0.25 + (level * 0.2f); }
/// 이동속도
inline int GetBaseMoveSpeed() { return 100; }
/// 최대 HP
inline int GetMaxHP( int vital, float level, float fCM ) { return vital * fCM * level * 0.8f + 150; }
/// 최대 MP
inline int GetMaxMP( int intelligence, int level, float fCM ) { return intelligence * fCM * level * 0.8f + 20; }
inline int GetIntValueByRandom( float fValue )
{
float fmod = (int)fValue + (float) ( XFastRandom() % 100 ) / 100;
if( fmod < fValue )
{
return (int) fValue + 1;
}
return (int) fValue;
}
/// 공격속도
inline int GetAttackSpeed( int agility, int strength, float fCM )
{
int agi_speed = 0;
if( agility <= 300 ) agi_speed = agility * ( 0.7f + ( 300 - agility ) / 300.0f ) * 0.5f;
else agi_speed = agility * 0.35f;
int str_speed = 0;
if( strength <= 300 ) str_speed = strength * ( 0.7f + ( 300 - strength ) / 300.0f ) * 0.1f;
else str_speed = strength * 0.07f;
return ( 50 + ( agi_speed + str_speed ) * ( 0.8f + ( fCM * 0.2f ) ) ) - 20;
}
/// HP 리젠율% (100초당)
inline int GetHPRegenPercentage( int vitality, float fCM )
{
return (vitality * fCM * 0.2);
}
/// HP 리젠율+ (100초당)
inline int GetHPRegenPoint( float level, int max_hp )
{
return ( (1 + (level * 0.2f)) * 35 );
}
/// MP 리젠율% (100초당)
inline int GetMPRegenPercentage( int mentality, float fCM )
{
return (mentality * fCM * 0.2);
}
/// MP 리젠율 (100초당)
inline int GetMPRegenPoint( float level, int max_mp )
{
return ( (1 + (level * 0.1f)) * 35 );
}
float GetStaminaRatio( int level );
/// 플레이어가 최대로 들 수 있는 무게
int GetMaxWeight( int strength );
/// 물건을 주울 수 있는 거리
int GetPickableRange();
/// 등급에 따른 아이템 레벨 제한
int GetItemLevelLimit( int item_rank );
/// 아이템 레벨에 따른 페널티
float GetItemLevelPenalty( int creature_level, int item_min_level,int item_rank, int item_level, int item_limit_level );
/// 등급별 아이템 권장레벨 조정 테이블
int GetItemRecommendModTable( int item_rank );
/// 아이템 권장 레벨
int GetItemRecommendLevel( int item_min_level, int item_rank, int item_level );
/// 내구도에 따른 페널티 비율
float GetItemEndurancePenalty( float item_endurance_percentage );
/// 수리 비용
int GetRepairCost( int item_price, float item_endurance_percentage );
/// 각 레벨에 따른 성능 조정 (데미지, 방어구 동일)
int GetItemValue( float item_current_value, float item_endurance_percentage, int item_rank_value, int creature_level, int item_min_level, int item_rank, int item_level, int item_limit_level = -1 );
int GetItemSellPrice( int price, int rank, int lv, bool isEquipment );
bool IsValidName( const char* name, int nBufferSize, int nLimitMin, int nLimitMax );
// Integration of country-specific local bitsets and separation of Europe
// <Country-specific Local Flags>
enum LOCAL_BITSET
{
KR = ( 1 << 0 ), // South Korea 1
HK = ( 1 << 1 ), // Hong Kong 2
US = ( 1 << 2 ), // North America 4
DE = ( 1 << 3 ), // Germany 8
JP = ( 1 << 4 ), // Japan 16
TW = ( 1 << 5 ), // Taiwan 32
CN = ( 1 << 6 ), // China 64
FR = ( 1 << 7 ), // France 128
RU = ( 1 << 8 ), // Russia 256
MASG= ( 1 << 9 ), // Malaysia(Singapore) 512
PH = ( 1 << 10 ), // Philippines 1024
VN = ( 1 << 11 ), // Vietnam 2048
TL = ( 1 << 12 ), // Thailand 4096
ME = ( 1 << 13 ), // Middle East 8192
TR = ( 1 << 14 ), // Turkey 16384
PL = ( 1 << 15 ), // Poland 32768
IT = ( 1 << 16 ), // Italy 65536
BR = ( 1 << 17 ), // Brazil 131072
ES = ( 1 << 18 ), // Spain 262144
ID = ( 1 << 19 ), // Indonesia 524288
EXCLUDE_TEST_SERV = ( 1 << 29 ), // Test server excluded NPCs
EXCLUDE_SERVICE_SERV = ( 1 << 30 ) // Main server excluded NPCs
};
int GetCurrentLocalBitSet();
// 2010.07.12 prodongi
bool isSoutheastAsia();
/// 2011.10.07 - prodongi
bool isEurope();
// }
// #2.3.1.8 sonador
c_fixed10 GetQuestRewardFactor( QuestBase* questBase );
// #2.1.2.6.1
enum SETPART_COMPOSITION_FLAG
{
SETPART_NONE = 0,
SETPART_ARMO = 1 << 0,
SETPART_WEAPON1 = 1 << 1,
SETPART_WEAPON2 = 1 << 2,
SETPART_WEAPON3 = 1 << 3,
SETPART_WEAPON4 = 1 << 4,
SETPART_TWOHAND_WEAPON1 = 1 << 5,
SETPART_TWOHAND_WEAPON2 = 1 << 6,
SETPART_SHEILD = 1 << 7,
SETPART_HELM = 1 << 8,
};
const char* GetSetPartCompositionSlotOnEmoticonByPartId( int partId );
const char* GetSetPartCompositionSlotOffEmoticonByPartId( int partId );
};