- Katılım
- 14 Ocak 2021
- Konular
- 11
- Mesajlar
- 482
- Çözüm
- 9
- Online süresi
- 6mo 10d
- Reaksiyon Skoru
- 403
- Altın Konu
- 0
- TM Yaşı
- 5 Yıl 4 Ay 22 Gün
- Başarım Puanı
- 130
- MmoLira
- 10,530
- DevLira
- 12
ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!
Ekleyenler yorumlarını eksik etmezse sevinirim.
Sistemin Faydaları:
1. Tekli statü verirken oyunda lag oluşması düzeldi
2. Bineğe in bin yaparken ata vs computepoint çağrıları olanlar oradaki lag da düzeltildi
3. Grup üyelerine verilen bonuslar sonucunda oluşan lag düzeldi
4. Normal pet sistemi pet kullanım sonucu computepoint çağrıları olanlar oradaki lag düzeldi
5. Statü sıfırlamada bulunan lag düzeldi
6. Reload proto çektiğinizde oluşan lag da iyileşme olmuştur
7. Beceri puanlarını verirken oluşan lag düzeldi
8. Süresi dolan affectler silinirken oluşan lag düzeldi
9. Oyuna giriş çıkışlarda oluşan paket fazlalığı azaldı lag azalması oldu
Bu sadece sıfır altyapılarda olan iyileşmeler sistem dolu bir oyunda kat kat daha fazla bir iyileşme oluşacaktır.
Ufak bir not : Bu optimizasyon herkesin kullandığı beceri renklendirme sisteminde(skill color) 1-120 projelerde updatepacket boyutunu 900 1000 baytlara kadar çıkarıyordu ve bu updatepacket fonksiyonu çok sık kullanılan bir şey bu optimizasyon updatepacket kullanımını azalttığı için onada biraz fayda sağlayabilir beceri renklendirmeyi büyük projeler denediği için 900 1000 bayt civarı olan paketde sorun çıkmıyordu bunda da sorun çıkacağını düşünmüyorum ama aktif bir şekilde test edilmeden sadece deneyseldir test edildiğinide bu optimizasyon tamamen onaylanır.
Skill color sistemini kullanan serverler bu optimizasyonu uygulayınca sunucu network trafiğince ciddi düşüş yaşayabilir ve lag olasılığı azalabilir filesin kodlamasına göre bu iyileşme oranı değişkenlik gösterecektir.
[CODE lang="cpp" title="Gözden kaçan paylaşım hatası"]
(item.h update) , bool load = false removed
old : void ModifyPoints(bool bAdd, bool load = false, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
new : void ModifyPoints(bool bAdd, bool compute_point_status = false);//Fixed_[C]Martin#2376_001[/CODE]
Update Final paket boyutu tamamen düşürüldü maksimum 100 baytın üstüne çıkmıyor artık :
Sistemin Faydaları:
1. Tekli statü verirken oyunda lag oluşması düzeldi
2. Bineğe in bin yaparken ata vs computepoint çağrıları olanlar oradaki lag da düzeltildi
3. Grup üyelerine verilen bonuslar sonucunda oluşan lag düzeldi
4. Normal pet sistemi pet kullanım sonucu computepoint çağrıları olanlar oradaki lag düzeldi
5. Statü sıfırlamada bulunan lag düzeldi
6. Reload proto çektiğinizde oluşan lag da iyileşme olmuştur
7. Beceri puanlarını verirken oluşan lag düzeldi
8. Süresi dolan affectler silinirken oluşan lag düzeldi
9. Oyuna giriş çıkışlarda oluşan paket fazlalığı azaldı lag azalması oldu
Bu sadece sıfır altyapılarda olan iyileşmeler sistem dolu bir oyunda kat kat daha fazla bir iyileşme oluşacaktır.
Ufak bir not : Bu optimizasyon herkesin kullandığı beceri renklendirme sisteminde(skill color) 1-120 projelerde updatepacket boyutunu 900 1000 baytlara kadar çıkarıyordu ve bu updatepacket fonksiyonu çok sık kullanılan bir şey bu optimizasyon updatepacket kullanımını azalttığı için onada biraz fayda sağlayabilir beceri renklendirmeyi büyük projeler denediği için 900 1000 bayt civarı olan paketde sorun çıkmıyordu bunda da sorun çıkacağını düşünmüyorum ama aktif bir şekilde test edilmeden sadece deneyseldir test edildiğinide bu optimizasyon tamamen onaylanır.
Skill color sistemini kullanan serverler bu optimizasyonu uygulayınca sunucu network trafiğince ciddi düşüş yaşayabilir ve lag olasılığı azalabilir filesin kodlamasına göre bu iyileşme oranı değişkenlik gösterecektir.
[CODE lang="cpp" title="Gözden kaçan paylaşım hatası"]
(item.h update) , bool load = false removed
old : void ModifyPoints(bool bAdd, bool load = false, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
new : void ModifyPoints(bool bAdd, bool compute_point_status = false);//Fixed_[C]Martin#2376_001[/CODE]
Update Final paket boyutu tamamen düşürüldü maksimum 100 baytın üstüne çıkmıyor artık :
C++:
typedef struct character_point_instant
{
long points[POINT_MAX_NUM];
long points_computepoint[POINT_MAX_NUM];//Fixed_[C]Martin_001
//--------------------------------------------------------
void CHARACTER::ComputePoints()
{
compute_point_status = true;//Fixed_[C]Martin_001
memcpy(m_pointsInstant.points_computepoint, m_pointsInstant.points, sizeof(m_pointsInstant.points));//Fixed_[C]Martin_001
long comp_hp = GetHP();//Fixed_[C]Martin_001
long comp_max_hp = GetMaxHP();//Fixed_[C]Martin_001
long comp_sp = GetSP();//Fixed_[C]Martin_001
long comp_max_sp = GetMaxSP();//Fixed_[C]Martin_001
long comp_stamina = GetStamina();//Fixed_[C]Martin_001
long comp_max_stamina = GetMaxStamina();//Fixed_[C]Martin_001
long lStat = GetPoint(POINT_STAT);
long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT);
long lSkillActive = GetPoint(POINT_SKILL);
long lSkillSub = GetPoint(POINT_SUB_SKILL);
long lSkillHorse = GetPoint(POINT_HORSE_SKILL);
long lLevelStep = GetPoint(POINT_LEVEL_STEP);
long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS);
long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS);
long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS);
long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS);
long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS);
long lHPRecovery = GetPoint(POINT_HP_RECOVERY);
long lSPRecovery = GetPoint(POINT_SP_RECOVERY);
memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points));
BuffOnAttr_ClearAll();
m_SkillDamageBonus.clear();
SetPoint(POINT_STAT, lStat);
SetPoint(POINT_SKILL, lSkillActive);
SetPoint(POINT_SUB_SKILL, lSkillSub);
SetPoint(POINT_HORSE_SKILL, lSkillHorse);
SetPoint(POINT_LEVEL_STEP, lLevelStep);
SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount);
SetPoint(POINT_ST, GetRealPoint(POINT_ST));
SetPoint(POINT_HT, GetRealPoint(POINT_HT));
SetPoint(POINT_DX, GetRealPoint(POINT_DX));
SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
SetPart(PART_MAIN, GetOriginalPart(PART_MAIN));
SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON));
SetPart(PART_HEAD, GetOriginalPart(PART_HEAD));
SetPart(PART_HAIR, GetOriginalPart(PART_HAIR));
#ifdef ENABLE_ACCE_SYSTEM
SetPart(PART_ACCE, GetOriginalPart(PART_ACCE));
#endif
SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus);
SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus);
SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus);
SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus);
SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus);
SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus);
SetPoint(POINT_HP_RECOVERY, lHPRecovery);
SetPoint(POINT_SP_RECOVERY, lSPRecovery);
// PC_BANG_ITEM_ADD
SetPoint(POINT_PC_BANG_EXP_BONUS, 0);
SetPoint(POINT_PC_BANG_DROP_BONUS, 0);
// END_PC_BANG_ITEM_ADD
int iMaxHP, iMaxSP;
int iMaxStamina;
if (IsPC())
{
iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht;
iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq;
iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con;
{
CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP);
if (NULL != pkSk)
{
pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f);
iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval());
}
}
SetPoint(POINT_MOV_SPEED, 100);
SetPoint(POINT_ATT_SPEED, 100);
PointChange(POINT_ATT_SPEED, GetPoint(POINT_PARTY_HASTE_BONUS), false, false, compute_point_status);//Fixed_[C]Martin_001
SetPoint(POINT_CASTING_SPEED, 100);
}
else
{
iMaxHP = m_pkMobData->m_table.dwMaxHP;
iMaxSP = 0;
iMaxStamina = 0;
SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed);
SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed);
}
if (IsPC())
{
if (GetMountVnum())
{
if (GetHorseST() > GetPoint(POINT_ST))
PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), false, false, compute_point_status);//Fixed_[C]Martin_001
if (GetHorseDX() > GetPoint(POINT_DX))
PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), false, false, compute_point_status);//Fixed_[C]Martin_001
if (GetHorseHT() > GetPoint(POINT_HT))
PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), false, false, compute_point_status);//Fixed_[C]Martin_001
if (GetHorseIQ() > GetPoint(POINT_IQ))
PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), false, false, compute_point_status);//Fixed_[C]Martin_001
}
}
ComputeBattlePoints(compute_point_status);//Fixed_[C]Martin_001
if (iMaxHP != GetMaxHP())
{
SetRealPoint(POINT_MAX_HP, iMaxHP);
}
PointChange(POINT_MAX_HP, 0, false, false, compute_point_status);//Fixed_[C]Martin_001
if (iMaxSP != GetMaxSP())
{
SetRealPoint(POINT_MAX_SP, iMaxSP);
}
PointChange(POINT_MAX_SP, 0, false, false, compute_point_status);//Fixed_[C]Martin_001
SetMaxStamina(iMaxStamina);
// @fixme118 part1
int iCurHP = this->GetHP();
int iCurSP = this->GetSP();
m_pointsInstant.dwImmuneFlag = 0;
for (int i = 0 ; i < WEAR_MAX_NUM; i++)
{
LPITEM pItem = GetWear(i);
if (pItem)
{
pItem->ModifyPoints(true, compute_point_status);//Fixed_[C]Martin_001
SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag());
}
}
if (DragonSoul_IsDeckActivated())
{
for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck();
i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++)
{
LPITEM pItem = GetWear(i);
if (pItem)
{
if (DSManager::instance().IsTimeLeftDragonSoul(pItem))
pItem->ModifyPoints(true,compute_point_status);//Fixed_[C]Martin_001
}
}
}
if (GetHP() > GetMaxHP())
PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status);//Fixed_[C]Martin_001
if (GetSP() > GetMaxSP())
PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status);//Fixed_[C]Martin_001
ComputeSkillPoints();
RefreshAffect(compute_point_status);//Fixed_[C]Martin_001
CPetSystem * pPetSystem = GetPetSystem();
if (NULL != pPetSystem)
pPetSystem->RefreshBuff(compute_point_status);//Fixed_[C]Martin_001
// @fixme118 part2 (after petsystem stuff)
if (IsPC())
{
if (this->GetHP() != iCurHP)
this->PointChange(POINT_HP, iCurHP-this->GetHP(), false, false, compute_point_status);//Fixed_[C]Martin_001
if (this->GetSP() != iCurSP)
this->PointChange(POINT_SP, iCurSP-this->GetSP(), false, false, compute_point_status);//Fixed_[C]Martin_001
}
compute_point_status = false;//Fixed_[C]Martin_001
if (GetDesc())//Fixed_[C]Martin_001
{
BYTE send_count = 0;
auto it = compute_point_list.begin();
for (; it != compute_point_list.end(); it++)
{
if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val)
continue;
if (it->type == POINT_MAX_HP && comp_max_hp == it->val
|| it->type == POINT_HP && comp_hp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_SP && comp_max_sp == it->val
|| it->type == POINT_SP && comp_sp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val
|| it->type == POINT_STAMINA && comp_stamina == it->val
)
{
continue;
}
send_count++;
}
if (send_count == 1)
{
auto it = compute_point_list.begin();
for (; it != compute_point_list.end(); it++)
{
if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val)
continue;
if (it->type == POINT_MAX_HP && comp_max_hp == it->val
|| it->type == POINT_HP && comp_hp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_SP && comp_max_sp == it->val
|| it->type == POINT_SP && comp_sp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val
|| it->type == POINT_STAMINA && comp_stamina == it->val
)
{
continue;
}
struct packet_point_change pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
pack.dwVID = m_vid;
pack.type = it->type;
pack.value = it->val;
pack.amount = it->amount;
GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
}
}
else
{
if (send_count > 1)
{
TPacketGCPointChangeDynamic pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC;
pack.dwVID = m_vid;
pack.count = send_count;
TEMP_BUFFER buf;
buf.write(&pack, sizeof(TPacketGCPointChangeDynamic));
auto it = compute_point_list.begin();
for (; it != compute_point_list.end(); it++)
{
if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val)
continue;
if (it->type == POINT_MAX_HP && comp_max_hp == it->val
|| it->type == POINT_HP && comp_hp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_SP && comp_max_sp == it->val
|| it->type == POINT_SP && comp_sp == it->val
)
{
continue;
}
if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val
|| it->type == POINT_STAMINA && comp_stamina == it->val
)
{
continue;
}
TPacketGCPointChangeDynamicVal pack_val;
pack_val.type = it->type;
pack_val.value = it->val;
pack_val.amount = it->amount;
buf.write(&pack_val, sizeof(TPacketGCPointChangeDynamicVal));
}
GetDesc()->Packet(buf.read_peek(), buf.size());
}
}
}//Fixed_[C]Martin_001
compute_point_list.clear();//Fixed_[C]Martin_001
compute_point_list.shrink_to_fit();//Fixed_[C]Martin_001
UpdatePacket();
memset(m_pointsInstant.points_computepoint, 0, sizeof(m_pointsInstant.points_computepoint));//Fixed_[C]Martin_001
}
C++:
UYARI:
Bu bir deneysel optimizasyondur hiç bir aktif sunucu testi yapılmamıştır. localhost da test edilmiştir. bir sorun çıkmamıştır.
Cliente gönderilen değerler toplanıp tek pakette birleştirilmiştir her paket için 20 bayt yerine
bütün computepoint içinde geçen point işlemlerinin numaralarını kayıt edip tek bir dinamik paketle yollanmaktadır bunun sonucu 20*30 toplamı 600 bayt olan bir paketin birleşince 400 bayta düşmesi gözlemlenmiştir ve
bu sayede gereksiz python fonksiyonlarının tetiklenip oyunda kasma donma vb gibi durumlardada iyileşme olmuştur
aklıma takılan tek soru işareti paket büyümesi sonucu oyunculu bir sunucuda nasıl bir tepki vereceğidir
soket programlama konusunda bilgim biraz zayıf üst üste 30*20 bayt paket = 600 bayt yerine bunların birleşimi sonucu 400 500 bayt tek paket de birleşip yollanması [COLOR=rgb(250, 197, 28)]Update(maksimum 100 bayta düşüren güncelleme yayınlandı)[/COLOR]
bunu kullanacaklar computepoint çağrılarınızı gözden geçirmelisiniz olabildiğince en az computepoint kullanımı olmalı herhangi bir olumsuzluk durumuna karşı
yorumlara göre bu tarz optimizasyonların devamı gelecektir
yakında gelecek:
1. affect tablosunun optimizasyonu ve affectlerin cachelenmesi şu an sql sorgu üzerinden çalışıyor. her karakterde skil kullanınca bu tabloya sorgu gidiyor
2. karaktere giriş çıkışta giden gereksiz paketlerin optimizasyonu(tamamlandı. test ediliyor.)
NOT :
//Fixed_[C]Martin#2376_001
bunun bulunduğu yerleri kendinize göre uyarlıyorsunu
.h dosyasına diye yazdıklarımı da h dosyasının içinde uyarlıyorsunuz
ComputeBattlePoints
PointChange
ApplyPoint
ComputeAffect
RefreshAffect
üstteki yazdığım fonksiyonların içinde sizde ekstra olanları
//Fixed_[C]Martin#2376_001
ile geçen yerlerdeki uyarlamasına uygun şekilde uyarlayacaksınız
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
--------------------------- Server Source -------------------------
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
-- Char.h ye class içinde uygun bir yere ekle
class CHARACTER : public CEntity, public CFSM, public CHorseRider
{
++++++++++++++
private:
bool compute_point_status;//Fixed_[C]Martin#2376_001
typedef struct comput
{
BYTE type;
int amount;
int val;
}Tcomput;//Fixed_[C]Martin#2376_001
std::vector<Tcomput> compute_point_list;//Fixed_[C]Martin#2376_001
---------------------------------------------------------------------------------------------
-- Char.cpp fonksiyon içine uygun bir şekilde ekle
void CHARACTER::Initialize()
{
++++++++++++++++
compute_point_status = false;//Fixed_[C]Martin#2376_001
---------------------------------------------------------------------------------------------
-- Char.cpp //Fixed_[C]Martin#2376_001 bunları bul ve uygun şekilde kendine ekle yada düzenle bunları eklerken kodun uyumlu olduğunu kontrol edin
( char.h dosyasına )void ComputeBattlePoints(bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CHARACTER::ComputeBattlePoints(bool compute_point_status)//Fixed_[C]Martin#2376_001
{
if (IsPolymorphed())
{
DWORD dwMobVnum = GetPolymorphVnum();
const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
int iAtt = 0;
int iDef = 0;
if (pMob)
{
iAtt = GetLevel() * 2 + GetPolymorphPoint(POINT_ST) * 2;
iDef = GetLevel() + GetPolymorphPoint(POINT_HT) + pMob->m_table.wDef;
}
SetPoint(POINT_ATT_GRADE, iAtt);
SetPoint(POINT_DEF_GRADE, iDef);
SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
}
else if (IsPC())
{
SetPoint(POINT_ATT_GRADE, 0);
SetPoint(POINT_DEF_GRADE, 0);
SetPoint(POINT_CLIENT_DEF_GRADE, 0);
SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
//
// ATK = 2lev + 2str
//
int iAtk = GetLevel() * 2;
int iStatAtk = 0;
switch (GetJob())
{
case JOB_WARRIOR:
case JOB_SURA:
iStatAtk = (2 * GetPoint(POINT_ST));
break;
case JOB_ASSASSIN:
iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_DX)) / 3;
break;
case JOB_SHAMAN:
iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_IQ)) / 3;
break;
default:
sys_err("invalid job %d", GetJob());
iStatAtk = (2 * GetPoint(POINT_ST));
break;
}
if (GetMountVnum() && iStatAtk < 2 * GetPoint(POINT_ST))
iStatAtk = (2 * GetPoint(POINT_ST));
iAtk += iStatAtk;
if (GetMountVnum())
{
if (GetJob() == JOB_SURA && GetSkillGroup() == 1)
{
iAtk += (iAtk * GetHorseLevel()) / 60;
}
else
{
iAtk += (iAtk * GetHorseLevel()) / 30;
}
}
//
// ATK Setting
//
iAtk += GetPoint(POINT_ATT_GRADE_BONUS);
PointChange(POINT_ATT_GRADE, iAtk, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
// DEF = LEV + CON + ARMOR
int iShowDef = GetLevel() + GetPoint(POINT_HT);
int iDef = GetLevel() + (int) (GetPoint(POINT_HT) / 1.25); // For Other
int iArmor = 0;
LPITEM pkItem;
for (int i = 0; i < WEAR_MAX_NUM; ++i)
if ((pkItem = GetWear(i)) && pkItem->GetType() == ITEM_ARMOR)
{
if (pkItem->GetSubType() == ARMOR_BODY || pkItem->GetSubType() == ARMOR_HEAD || pkItem->GetSubType() == ARMOR_FOOTS || pkItem->GetSubType() == ARMOR_SHIELD)
{
iArmor += pkItem->GetValue(1);
iArmor += (2 * pkItem->GetValue(5));
}
}
if( true == IsHorseRiding() )
{
if (iArmor < GetHorseArmor())
iArmor = GetHorseArmor();
const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID());
if (pHorseName != NULL && strlen(pHorseName))
{
iArmor += 20;
}
}
iArmor += GetPoint(POINT_DEF_GRADE_BONUS);
iArmor += GetPoint(POINT_PARTY_DEFENDER_BONUS);
// INTERNATIONAL_VERSION
PointChange(POINT_DEF_GRADE, iDef + iArmor, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_CLIENT_DEF_GRADE, (iShowDef + iArmor) - GetPoint(POINT_DEF_GRADE), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
// END_OF_INTERNATIONAL_VERSION
PointChange(POINT_MAGIC_ATT_GRADE, GetLevel() * 2 + GetPoint(POINT_IQ) * 2 + GetPoint(POINT_MAGIC_ATT_GRADE_BONUS), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_MAGIC_DEF_GRADE, GetLevel() + (GetPoint(POINT_IQ) * 3 + GetPoint(POINT_HT)) / 3 + iArmor / 2 + GetPoint(POINT_MAGIC_DEF_GRADE_BONUS), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
else
{
// 2lev + str * 2
int iAtt = GetLevel() * 2 + GetPoint(POINT_ST) * 2;
// lev + con
int iDef = GetLevel() + GetPoint(POINT_HT) + GetMobTable().wDef;
SetPoint(POINT_ATT_GRADE, iAtt);
SetPoint(POINT_DEF_GRADE, iDef);
SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
}
}
-----
void CHARACTER::ComputePoints()
{
compute_point_status = true;//Fixed_[C]Martin#2376_001
long lStat = GetPoint(POINT_STAT);
long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT);
long lSkillActive = GetPoint(POINT_SKILL);
long lSkillSub = GetPoint(POINT_SUB_SKILL);
long lSkillHorse = GetPoint(POINT_HORSE_SKILL);
long lLevelStep = GetPoint(POINT_LEVEL_STEP);
long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS);
long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS);
long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS);
long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS);
long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS);
long lHPRecovery = GetPoint(POINT_HP_RECOVERY);
long lSPRecovery = GetPoint(POINT_SP_RECOVERY);
memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points));
BuffOnAttr_ClearAll();
m_SkillDamageBonus.clear();
SetPoint(POINT_STAT, lStat);
SetPoint(POINT_SKILL, lSkillActive);
SetPoint(POINT_SUB_SKILL, lSkillSub);
SetPoint(POINT_HORSE_SKILL, lSkillHorse);
SetPoint(POINT_LEVEL_STEP, lLevelStep);
SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount);
SetPoint(POINT_ST, GetRealPoint(POINT_ST));
SetPoint(POINT_HT, GetRealPoint(POINT_HT));
SetPoint(POINT_DX, GetRealPoint(POINT_DX));
SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
SetPart(PART_MAIN, GetOriginalPart(PART_MAIN));
SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON));
SetPart(PART_HEAD, GetOriginalPart(PART_HEAD));
SetPart(PART_HAIR, GetOriginalPart(PART_HAIR));
SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus);
SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus);
SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus);
SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus);
SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus);
SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus);
SetPoint(POINT_HP_RECOVERY, lHPRecovery);
SetPoint(POINT_SP_RECOVERY, lSPRecovery);
// PC_BANG_ITEM_ADD
SetPoint(POINT_PC_BANG_EXP_BONUS, 0);
SetPoint(POINT_PC_BANG_DROP_BONUS, 0);
// END_PC_BANG_ITEM_ADD
int iMaxHP, iMaxSP;
int iMaxStamina;
if (IsPC())
{
iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht;
iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq;
iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con;
{
CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP);
if (NULL != pkSk)
{
pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f);
iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval());
}
}
SetPoint(POINT_MOV_SPEED, 100);
SetPoint(POINT_ATT_SPEED, 100);
PointChange(POINT_ATT_SPEED, GetPoint(POINT_PARTY_HASTE_BONUS), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
SetPoint(POINT_CASTING_SPEED, 100);
}
else
{
iMaxHP = m_pkMobData->m_table.dwMaxHP;
iMaxSP = 0;
iMaxStamina = 0;
SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed);
SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed);
}
if (IsPC())
{
if (GetMountVnum())
{
if (GetHorseST() > GetPoint(POINT_ST))
PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (GetHorseDX() > GetPoint(POINT_DX))
PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (GetHorseHT() > GetPoint(POINT_HT))
PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (GetHorseIQ() > GetPoint(POINT_IQ))
PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
ComputeBattlePoints(compute_point_status);//Fixed_[C]Martin#2376_001
if (iMaxHP != GetMaxHP())
{
SetRealPoint(POINT_MAX_HP, iMaxHP);
}
PointChange(POINT_MAX_HP, 0, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (iMaxSP != GetMaxSP())
{
SetRealPoint(POINT_MAX_SP, iMaxSP);
}
PointChange(POINT_MAX_SP, 0, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
SetMaxStamina(iMaxStamina);
// @fixme118 part1
int iCurHP = this->GetHP();
int iCurSP = this->GetSP();
m_pointsInstant.dwImmuneFlag = 0;
for (int i = 0 ; i < WEAR_MAX_NUM; i++)
{
LPITEM pItem = GetWear(i);
if (pItem)
{
pItem->ModifyPoints(true, compute_point_status);//Fixed_[C]Martin#2376_001
SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag());
}
}
if (DragonSoul_IsDeckActivated())
{
for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck();
i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++)
{
LPITEM pItem = GetWear(i);
if (pItem)
{
if (DSManager::instance().IsTimeLeftDragonSoul(pItem))
pItem->ModifyPoints(true, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
}
if (GetHP() > GetMaxHP())
PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (GetSP() > GetMaxSP())
PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
ComputeSkillPoints();
RefreshAffect(compute_point_status);//Fixed_[C]Martin#2376_001
CPetSystem * pPetSystem = GetPetSystem();
if (NULL != pPetSystem)
pPetSystem->RefreshBuff(compute_point_status);//Fixed_[C]Martin#2376_001
// @fixme118 part2 (after petsystem stuff)
if (IsPC())
{
if (this->GetHP() != iCurHP)
this->PointChange(POINT_HP, iCurHP-this->GetHP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (this->GetSP() != iCurSP)
this->PointChange(POINT_SP, iCurSP-this->GetSP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
compute_point_status = false;//Fixed_[C]Martin#2376_001
if (GetDesc())//Fixed_[C]Martin#2376_001
{
TPacketGCPointChangeDynamic pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC;
pack.dwVID = m_vid;
pack.count = compute_point_list.size();
TEMP_BUFFER buf;
buf.write(&pack, sizeof(TPacketGCPointChangeDynamic));
auto it = compute_point_list.begin();
for (; it != compute_point_list.end(); it++)
{
TPacketGCPointChangeDynamicVal pack_val;
pack_val.type = it->type;
pack_val.value = it->val;
pack_val.amount = it->amount;
buf.write(&pack_val, sizeof(TPacketGCPointChangeDynamicVal));
}
GetDesc()->Packet(buf.read_peek(), buf.size());
}//Fixed_[C]Martin#2376_001
compute_point_list.clear();//Fixed_[C]Martin#2376_001
compute_point_list.shrink_to_fit();//Fixed_[C]Martin#2376_001
UpdatePacket();
}
----
( char.h dosyasına )void PointChange(BYTE type, int amount, bool bAmount = false, bool bBroadcast = false, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast, bool compute_point_status)//Fixed_[C]Martin#2376_001
{
int val = 0;
//sys_log(0, "PointChange %d %d | %d -> %d cHP %d mHP %d", type, amount, GetPoint(type), GetPoint(type)+amount, GetHP(), GetMaxHP());
switch (type)
{
case POINT_NONE:
return;
case POINT_LEVEL:
if ((GetLevel() + amount) > gPlayerMaxLevel)
return;
SetLevel(GetLevel() + amount);
val = GetLevel();
sys_log(0, "LEVELUP: %s %d NEXT EXP %d", GetName(), GetLevel(), GetNextExp());
PointChange(POINT_NEXT_EXP, GetNextExp(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (amount)
{
quest::CQuestManager::instance().LevelUp(GetPlayerID());
LogManager::instance().LevelLog(this, val, GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000);
if (GetGuild())
{
GetGuild()->LevelChange(GetPlayerID(), GetLevel());
}
if (GetParty())
{
GetParty()->RequestSetMemberLevel(GetPlayerID(), GetLevel());
}
}
break;
case POINT_NEXT_EXP:
val = GetNextExp();
bAmount = false;
break;
case POINT_EXP:
{
DWORD exp = GetExp();
DWORD next_exp = GetNextExp();
if ((amount < 0) && (exp < (DWORD)(-amount)))
{
sys_log(1, "%s AMOUNT < 0 %d, CUR EXP: %d", GetName(), -amount, exp);
amount = -exp;
SetExp(exp + amount);
val = GetExp();
}
else
{
if (gPlayerMaxLevel <= GetLevel())
return;
if (test_server)
ChatPacket(CHAT_TYPE_INFO, "You have gained %d exp.", amount);
DWORD iExpBalance = 0;
if (exp + amount >= next_exp)
{
iExpBalance = (exp + amount) - next_exp;
amount = next_exp - exp;
SetExp(0);
exp = next_exp;
}
else
{
SetExp(exp + amount);
exp = GetExp();
}
DWORD q = DWORD(next_exp / 4.0f);
int iLevStep = GetRealPoint(POINT_LEVEL_STEP);
if (iLevStep >= 4)
{
sys_err("%s LEVEL_STEP bigger than 4! (%d)", GetName(), iLevStep);
iLevStep = 4;
}
if (exp >= next_exp && iLevStep < 4)
{
for (int i = 0; i < 4 - iLevStep; ++i)
PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status);//Fixed_[C]Martin#2376_001
}
else if (exp >= q * 3 && iLevStep < 3)
{
for (int i = 0; i < 3 - iLevStep; ++i)
PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status);//Fixed_[C]Martin#2376_001
}
else if (exp >= q * 2 && iLevStep < 2)
{
for (int i = 0; i < 2 - iLevStep; ++i)
PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status);//Fixed_[C]Martin#2376_001
}
else if (exp >= q && iLevStep < 1)
PointChange(POINT_LEVEL_STEP, 1, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (iExpBalance)
{
PointChange(POINT_EXP, iExpBalance, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
val = GetExp();
}
}
break;
case POINT_LEVEL_STEP:
if (amount > 0)
{
val = GetPoint(POINT_LEVEL_STEP) + amount;
switch (val)
{
case 1:
case 2:
case 3:
if ((GetLevel() <= g_iStatusPointGetLevelLimit) &&
(GetLevel() <= gPlayerMaxLevel) ) // @fixme104
PointChange(POINT_STAT, 1, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case 4:
{
int iHP = number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end);
int iSP = number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end);
m_points.iRandomHP += iHP;
m_points.iRandomSP += iSP;
if (GetSkillGroup())
{
if (GetLevel() >= 5)
PointChange(POINT_SKILL, 1, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (GetLevel() >= 9)
PointChange(POINT_SUB_SKILL, 1, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
PointChange(POINT_MAX_HP, iHP, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_MAX_SP, iSP, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_LEVEL, 1, false, true, compute_point_status);//Fixed_[C]Martin#2376_001
val = 0;
}
break;
}
if (GetLevel() <= 10)
AutoGiveItem(27001, 2);
else if (GetLevel() <= 30)
AutoGiveItem(27002, 2);
else
{
AutoGiveItem(27002, 2);
// AutoGiveItem(27003, 2);
}
PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_STAMINA, GetMaxStamina() - GetStamina(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
SetPoint(POINT_LEVEL_STEP, val);
SetRealPoint(POINT_LEVEL_STEP, val);
Save();
}
else
val = GetPoint(POINT_LEVEL_STEP);
break;
case POINT_HP:
{
if (IsDead() || IsStun())
return;
int prev_hp = GetHP();
amount = MIN(GetMaxHP() - GetHP(), amount);
SetHP(GetHP() + amount);
val = GetHP();
BroadcastTargetPacket();
if (GetParty() && IsPC() && val != prev_hp)
GetParty()->SendPartyInfoOneToAll(this);
}
break;
case POINT_SP:
{
if (IsDead() || IsStun())
return;
amount = MIN(GetMaxSP() - GetSP(), amount);
SetSP(GetSP() + amount);
val = GetSP();
}
break;
case POINT_STAMINA:
{
if (IsDead() || IsStun())
return;
int prev_val = GetStamina();
amount = MIN(GetMaxStamina() - GetStamina(), amount);
SetStamina(GetStamina() + amount);
val = GetStamina();
if (val == 0)
{
// Stamina
SetNowWalking(true);
}
else if (prev_val == 0)
{
ResetWalking();
}
if (amount < 0 && val != 0)
return;
}
break;
case POINT_MAX_HP:
{
SetPoint(type, GetPoint(type) + amount);
//SetMaxHP(GetMaxHP() + amount);
int hp = GetRealPoint(POINT_MAX_HP);
int add_hp = MIN(3500, hp * GetPoint(POINT_MAX_HP_PCT) / 100);
add_hp += GetPoint(POINT_MAX_HP);
add_hp += GetPoint(POINT_PARTY_TANKER_BONUS);
SetMaxHP(hp + add_hp);
val = GetMaxHP();
}
break;
case POINT_MAX_SP:
{
SetPoint(type, GetPoint(type) + amount);
//SetMaxSP(GetMaxSP() + amount);
int sp = GetRealPoint(POINT_MAX_SP);
int add_sp = MIN(800, sp * GetPoint(POINT_MAX_SP_PCT) / 100);
add_sp += GetPoint(POINT_MAX_SP);
add_sp += GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
SetMaxSP(sp + add_sp);
val = GetMaxSP();
}
break;
case POINT_MAX_HP_PCT:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
PointChange(POINT_MAX_HP, 0, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case POINT_MAX_SP_PCT:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
PointChange(POINT_MAX_SP, 0, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case POINT_MAX_STAMINA:
SetMaxStamina(GetMaxStamina() + amount);
val = GetMaxStamina();
break;
case POINT_GOLD:
{
const int64_t nTotalMoney = static_cast<int64_t>(GetGold()) + static_cast<int64_t>(amount);
if (GOLD_MAX <= nTotalMoney)
{
sys_err("[OVERFLOW_GOLD] OriGold %d AddedGold %d id %u Name %s ", GetGold(), amount, GetPlayerID(), GetName());
LogManager::instance().CharLog(this, GetGold() + amount, "OVERFLOW_GOLD", "");
return;
}
SetGold(GetGold() + amount);
val = GetGold();
}
break;
case POINT_SKILL:
case POINT_STAT:
case POINT_SUB_SKILL:
case POINT_STAT_RESET_COUNT:
case POINT_HORSE_SKILL:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
SetRealPoint(type, val);
break;
case POINT_DEF_GRADE:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
PointChange(POINT_CLIENT_DEF_GRADE, amount, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case POINT_CLIENT_DEF_GRADE:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
break;
case POINT_ST:
case POINT_HT:
case POINT_DX:
case POINT_IQ:
case POINT_HP_REGEN:
case POINT_SP_REGEN:
case POINT_ATT_SPEED:
case POINT_ATT_GRADE:
case POINT_MOV_SPEED:
case POINT_CASTING_SPEED:
case POINT_MAGIC_ATT_GRADE:
case POINT_MAGIC_DEF_GRADE:
case POINT_BOW_DISTANCE:
case POINT_HP_RECOVERY:
case POINT_SP_RECOVERY:
case POINT_ATTBONUS_HUMAN: // 42
case POINT_ATTBONUS_ANIMAL: // 43
case POINT_ATTBONUS_ORC: // 44
case POINT_ATTBONUS_MILGYO: // 45
case POINT_ATTBONUS_UNDEAD: // 46
case POINT_ATTBONUS_DEVIL: // 47
case POINT_ATTBONUS_MONSTER:
case POINT_ATTBONUS_SURA:
case POINT_ATTBONUS_ASSASSIN:
case POINT_ATTBONUS_WARRIOR:
case POINT_ATTBONUS_SHAMAN:
case POINT_POISON_PCT:
case POINT_STUN_PCT:
case POINT_SLOW_PCT:
case POINT_BLOCK:
case POINT_DODGE:
case POINT_CRITICAL_PCT:
case POINT_RESIST_CRITICAL:
case POINT_PENETRATE_PCT:
case POINT_RESIST_PENETRATE:
case POINT_CURSE_PCT:
case POINT_STEAL_HP: // 48
case POINT_STEAL_SP: // 49
case POINT_MANA_BURN_PCT: // 50
case POINT_DAMAGE_SP_RECOVER: // 51
case POINT_RESIST_NORMAL_DAMAGE:
case POINT_RESIST_SWORD:
case POINT_RESIST_TWOHAND:
case POINT_RESIST_DAGGER:
case POINT_RESIST_BELL:
case POINT_RESIST_FAN:
case POINT_RESIST_BOW:
case POINT_RESIST_FIRE:
case POINT_RESIST_ELEC:
case POINT_RESIST_MAGIC:
case POINT_RESIST_WIND:
case POINT_RESIST_ICE:
case POINT_RESIST_EARTH:
case POINT_RESIST_DARK:
case POINT_REFLECT_MELEE: // 67
case POINT_REFLECT_CURSE: // 68
case POINT_POISON_REDUCE: // 69
case POINT_KILL_SP_RECOVER: // 70
case POINT_KILL_HP_RECOVERY: // 75
case POINT_HIT_HP_RECOVERY:
case POINT_HIT_SP_RECOVERY:
case POINT_MANASHIELD:
case POINT_ATT_BONUS:
case POINT_DEF_BONUS:
case POINT_SKILL_DAMAGE_BONUS:
case POINT_NORMAL_HIT_DAMAGE_BONUS:
// DEPEND_BONUS_ATTRIBUTES
case POINT_SKILL_DEFEND_BONUS:
case POINT_NORMAL_HIT_DEFEND_BONUS:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
break;
// END_OF_DEPEND_BONUS_ATTRIBUTES
case POINT_PARTY_ATTACKER_BONUS:
case POINT_PARTY_TANKER_BONUS:
case POINT_PARTY_BUFFER_BONUS:
case POINT_PARTY_SKILL_MASTER_BONUS:
case POINT_PARTY_HASTE_BONUS:
case POINT_PARTY_DEFENDER_BONUS:
case POINT_RESIST_WARRIOR :
case POINT_RESIST_ASSASSIN :
case POINT_RESIST_SURA :
case POINT_RESIST_SHAMAN :
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
break;
case POINT_MALL_ATTBONUS:
case POINT_MALL_DEFBONUS:
case POINT_MALL_EXPBONUS:
case POINT_MALL_ITEMBONUS:
case POINT_MALL_GOLDBONUS:
case POINT_MELEE_MAGIC_ATT_BONUS_PER:
if (GetPoint(type) + amount > 100)
{
sys_err("MALL_BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount);
amount = 100 - GetPoint(type);
}
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
break;
// PC_BANG_ITEM_ADD
case POINT_PC_BANG_EXP_BONUS :
case POINT_PC_BANG_DROP_BONUS :
case POINT_RAMADAN_CANDY_BONUS_EXP:
SetPoint(type, amount);
val = GetPoint(type);
break;
// END_PC_BANG_ITEM_ADD
case POINT_EXP_DOUBLE_BONUS: // 71
case POINT_GOLD_DOUBLE_BONUS: // 72
case POINT_ITEM_DROP_BONUS: // 73
case POINT_POTION_BONUS: // 74
if (GetPoint(type) + amount > 100)
{
sys_err("BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount);
amount = 100 - GetPoint(type);
}
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
break;
case POINT_IMMUNE_STUN: // 76
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
if (val)
{
// ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN SET_BIT type(%u) amount(%d)", type, amount);
SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
}
else
{
// ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN REMOVE_BIT type(%u) amount(%d)", type, amount);
REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
}
break;
case POINT_IMMUNE_SLOW: // 77
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
if (val)
{
SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
}
else
{
REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
}
break;
case POINT_IMMUNE_FALL: // 78
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
if (val)
{
SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
}
else
{
REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
}
break;
case POINT_ATT_GRADE_BONUS:
SetPoint(type, GetPoint(type) + amount);
PointChange(POINT_ATT_GRADE, amount, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
val = GetPoint(type);
break;
case POINT_DEF_GRADE_BONUS:
SetPoint(type, GetPoint(type) + amount);
PointChange(POINT_DEF_GRADE, amount, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
val = GetPoint(type);
break;
case POINT_MAGIC_ATT_GRADE_BONUS:
SetPoint(type, GetPoint(type) + amount);
PointChange(POINT_MAGIC_ATT_GRADE, amount, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
val = GetPoint(type);
break;
case POINT_MAGIC_DEF_GRADE_BONUS:
SetPoint(type, GetPoint(type) + amount);
PointChange(POINT_MAGIC_DEF_GRADE, amount, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
val = GetPoint(type);
break;
case POINT_VOICE:
case POINT_EMPIRE_POINT:
//sys_err("CHARACTER::PointChange: %s: point cannot be changed. use SetPoint instead (type: %d)", GetName(), type);
val = GetRealPoint(type);
break;
case POINT_POLYMORPH:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
SetPolymorph(val);
break;
case POINT_MOUNT:
SetPoint(type, GetPoint(type) + amount);
val = GetPoint(type);
MountVnum(val);
break;
case POINT_ENERGY:
case POINT_COSTUME_ATTR_BONUS:
{
int old_val = GetPoint(type);
SetPoint(type, old_val + amount);
val = GetPoint(type);
BuffOnAttr_ValueChange(type, old_val, val);
}
break;
default:
sys_err("CHARACTER::PointChange: %s: unknown point change type %d", GetName(), type);
return;
}
switch (type)
{
case POINT_LEVEL:
case POINT_ST:
case POINT_DX:
case POINT_IQ:
case POINT_HT:
ComputeBattlePoints(compute_point_status);//Fixed_[C]Martin#2376_001
break;
case POINT_MAX_HP:
case POINT_MAX_SP:
case POINT_MAX_STAMINA:
break;
}
if (type == POINT_HP && amount == 0)
return;
if (compute_point_status)//Fixed_[C]Martin#2376_001
{
bool valid = false;
for (std::vector<Tcomput>::iterator it = compute_point_list.begin(); it != compute_point_list.end(); it++)
{
if (it->type == type)
{
if (bAmount)
it->amount = amount;
else
it->amount = 0;
it->val = val;
valid = true;
}
}
if (!valid)
{
Tcomput ins;
ins.type = type;
if (bAmount)
ins.amount = amount;
else
ins.amount = 0;
ins.val = val;
compute_point_list.push_back(ins);
}
}//Fixed_[C]Martin#2376_001
if (GetDesc() && !compute_point_status)//Fixed_[C]Martin#2376_001
{
struct packet_point_change pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
pack.dwVID = m_vid;
pack.type = type;
pack.value = val;
if (bAmount)
pack.amount = amount;
else
pack.amount = 0;
if (!bBroadcast)
GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
else
PacketAround(&pack, sizeof(pack));
}
}
----------
( char.h dosyasına )void ApplyPoint(BYTE bApplyType, int iVal, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CHARACTER::ApplyPoint(BYTE bApplyType, int iVal, bool compute_point_status)//Fixed_[C]Martin#2376_001
{
switch (bApplyType)
{
case APPLY_NONE: // 0
break;;
case APPLY_CON:
PointChange(POINT_HT, iVal, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_MAX_HP, (iVal * JobInitialPoints[GetJob()].hp_per_ht), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_MAX_STAMINA, (iVal * JobInitialPoints[GetJob()].stamina_per_con), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case APPLY_INT:
PointChange(POINT_IQ, iVal, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
PointChange(POINT_MAX_SP, (iVal * JobInitialPoints[GetJob()].sp_per_iq), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
case APPLY_SKILL:
// SKILL_DAMAGE_BONUS
{
// 00000000 00000000 00000000 00000000
// vnum ^ add change
BYTE bSkillVnum = (BYTE) (((DWORD)iVal) >> 24);
int iAdd = iVal & 0x00800000;
int iChange = iVal & 0x007fffff;
sys_log(1, "APPLY_SKILL skill %d add? %d change %d", bSkillVnum, iAdd ? 1 : 0, iChange);
if (0 == iAdd)
iChange = -iChange;
boost::unordered_map<BYTE, int>::iterator iter = m_SkillDamageBonus.find(bSkillVnum);
if (iter == m_SkillDamageBonus.end())
m_SkillDamageBonus.insert(std::make_pair(bSkillVnum, iChange));
else
iter->second += iChange;
}
// END_OF_SKILL_DAMAGE_BONUS
break;
case APPLY_MAX_HP:
case APPLY_MAX_HP_PCT:
{
int i = GetMaxHP(); if(i == 0) break;
PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
float fRatio = (float)GetMaxHP() / (float)i;
PointChange(POINT_HP, GetHP() * fRatio - GetHP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
break;
case APPLY_MAX_SP:
case APPLY_MAX_SP_PCT:
{
int i = GetMaxSP(); if(i == 0) break;
PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
float fRatio = (float)GetMaxSP() / (float)i;
PointChange(POINT_SP, GetSP() * fRatio - GetSP(), false, false, compute_point_status);//Fixed_[C]Martin#2376_001
}
break;
case APPLY_STR:
case APPLY_DEX:
case APPLY_ATT_SPEED:
case APPLY_MOV_SPEED:
case APPLY_CAST_SPEED:
case APPLY_HP_REGEN:
case APPLY_SP_REGEN:
case APPLY_POISON_PCT:
case APPLY_STUN_PCT:
case APPLY_SLOW_PCT:
case APPLY_CRITICAL_PCT:
case APPLY_PENETRATE_PCT:
case APPLY_ATTBONUS_HUMAN:
case APPLY_ATTBONUS_ANIMAL:
case APPLY_ATTBONUS_ORC:
case APPLY_ATTBONUS_MILGYO:
case APPLY_ATTBONUS_UNDEAD:
case APPLY_ATTBONUS_DEVIL:
case APPLY_ATTBONUS_WARRIOR: // 59
case APPLY_ATTBONUS_ASSASSIN: // 60
case APPLY_ATTBONUS_SURA: // 61
case APPLY_ATTBONUS_SHAMAN: // 62
case APPLY_ATTBONUS_MONSTER: // 63
case APPLY_STEAL_HP:
case APPLY_STEAL_SP:
case APPLY_MANA_BURN_PCT:
case APPLY_DAMAGE_SP_RECOVER:
case APPLY_BLOCK:
case APPLY_DODGE:
case APPLY_RESIST_SWORD:
case APPLY_RESIST_TWOHAND:
case APPLY_RESIST_DAGGER:
case APPLY_RESIST_BELL:
case APPLY_RESIST_FAN:
case APPLY_RESIST_BOW:
case APPLY_RESIST_FIRE:
case APPLY_RESIST_ELEC:
case APPLY_RESIST_MAGIC:
case APPLY_RESIST_WIND:
case APPLY_RESIST_ICE:
case APPLY_RESIST_EARTH:
case APPLY_RESIST_DARK:
case APPLY_REFLECT_MELEE:
case APPLY_REFLECT_CURSE:
case APPLY_ANTI_CRITICAL_PCT:
case APPLY_ANTI_PENETRATE_PCT:
case APPLY_POISON_REDUCE:
case APPLY_KILL_SP_RECOVER:
case APPLY_EXP_DOUBLE_BONUS:
case APPLY_GOLD_DOUBLE_BONUS:
case APPLY_ITEM_DROP_BONUS:
case APPLY_POTION_BONUS:
case APPLY_KILL_HP_RECOVER:
case APPLY_IMMUNE_STUN:
case APPLY_IMMUNE_SLOW:
case APPLY_IMMUNE_FALL:
case APPLY_BOW_DISTANCE:
case APPLY_ATT_GRADE_BONUS:
case APPLY_DEF_GRADE_BONUS:
case APPLY_MAGIC_ATT_GRADE:
case APPLY_MAGIC_DEF_GRADE:
case APPLY_CURSE_PCT:
case APPLY_MAX_STAMINA:
case APPLY_MALL_ATTBONUS:
case APPLY_MALL_DEFBONUS:
case APPLY_MALL_EXPBONUS:
case APPLY_MALL_ITEMBONUS:
case APPLY_MALL_GOLDBONUS:
case APPLY_SKILL_DAMAGE_BONUS:
case APPLY_NORMAL_HIT_DAMAGE_BONUS:
// DEPEND_BONUS_ATTRIBUTES
case APPLY_SKILL_DEFEND_BONUS:
case APPLY_NORMAL_HIT_DEFEND_BONUS:
// END_OF_DEPEND_BONUS_ATTRIBUTES
case APPLY_PC_BANG_EXP_BONUS :
case APPLY_PC_BANG_DROP_BONUS :
case APPLY_RESIST_WARRIOR :
case APPLY_RESIST_ASSASSIN :
case APPLY_RESIST_SURA :
case APPLY_RESIST_SHAMAN :
case APPLY_ENERGY: // 82
case APPLY_DEF_GRADE: // 83
case APPLY_COSTUME_ATTR_BONUS: // 84
case APPLY_MAGIC_ATTBONUS_PER: // 85
case APPLY_MELEE_MAGIC_ATTBONUS_PER: // 86
PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
break;
default:
sys_err("Unknown apply type %d name %s", bApplyType, GetName());
break;
}
}
--------------------------------------------------
-- Char_affect.cpp
++++++++++
( char.h dosyasına )void RefreshAffect(bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CHARACTER::RefreshAffect(bool compute_point_status)//Fixed_[C]Martin#2376_001
{
itertype(m_list_pkAffect) it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
CAffect * pkAff = *it++;
ComputeAffect(pkAff, true, compute_point_status);
}
}
( char.h dosyasına )void ComputeAffect(CAffect * pkAff, bool bAdd, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd, bool compute_point_status)//Fixed_[C]Martin#2376_001
{
if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END)
{
if (!GetGuild())
return;
if (!GetGuild()->UnderAnyWar())
return;
}
if (pkAff->dwFlag)
{
if (!bAdd)
m_afAffectFlag.Reset(pkAff->dwFlag);
else
m_afAffectFlag.Set(pkAff->dwFlag);
}
if (bAdd)
PointChange(pkAff->bApplyOn, pkAff->lApplyValue, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
else
PointChange(pkAff->bApplyOn, -pkAff->lApplyValue, false, false, compute_point_status);//Fixed_[C]Martin#2376_001
if (pkAff->dwType == SKILL_MUYEONG)
{
if (bAdd)
StartMuyeongEvent();
else
StopMuyeongEvent();
}
}
-----------------------------------------------------------
-- item.cpp
NOT : Kuşak kullananlar buradaki ApplyPoint kodlarını benim düzenlediğim gibi ModifyPoints içerisindeki hepsini düzenlemeniz kerekiyor
++++++++
( item.h dosyasına )void ModifyPoints(bool bAdd, bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CItem::ModifyPoints(bool bAdd, bool compute_point_status)//Fixed_[C]Martin#2376_001
{
int accessoryGrade;
if (false == IsAccessoryForSocket())
{
if (m_pProto->bType == ITEM_WEAPON || m_pProto->bType == ITEM_ARMOR)
{
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
DWORD dwVnum;
if ((dwVnum = GetSocket(i)) <= 2)
continue;
TItemTable * p = ITEM_MANAGER::instance().GetTable(dwVnum);
if (!p)
{
sys_err("cannot find table by vnum %u", dwVnum);
continue;
}
if (ITEM_METIN == p->bType)
{
//m_pOwner->ApplyPoint(p->alValues[0], bAdd ? p->alValues[1] : -p->alValues[1]);
for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (p->aApplies[i].bType == APPLY_NONE)
continue;
if (p->aApplies[i].bType == APPLY_SKILL)
m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : p->aApplies[i].lValue ^ 0x00800000, compute_point_status);//Fixed_[C]Martin#2376_001
else
m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : -p->aApplies[i].lValue, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
}
}
accessoryGrade = 0;
}
else
{
accessoryGrade = MIN(GetAccessorySocketGrade(), ITEM_ACCESSORY_SOCKET_MAX_NUM);
}
for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (m_pProto->aApplies[i].bType == APPLY_NONE)
continue;
long value = m_pProto->aApplies[i].lValue;
if (m_pProto->aApplies[i].bType == APPLY_SKILL)
{
m_pOwner->ApplyPoint(m_pProto->aApplies[i].bType, bAdd ? value : value ^ 0x00800000, compute_point_status);//Fixed_[C]Martin#2376_001
}
else
{
if (0 != accessoryGrade)
value += MAX(accessoryGrade, value * aiAccessorySocketEffectivePct[accessoryGrade] / 100);
m_pOwner->ApplyPoint(m_pProto->aApplies[i].bType, bAdd ? value : -value, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
if (true == CItemVnumHelper::IsRamadanMoonRing(GetVnum()) || true == CItemVnumHelper::IsHalloweenCandy(GetVnum())
|| true == CItemVnumHelper::IsHappinessRing(GetVnum()) || true == CItemVnumHelper::IsLovePendant(GetVnum()))
{
// Do not anything.
}
else
{
for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
{
if (GetAttributeType(i))
{
const TPlayerItemAttribute& ia = GetAttribute(i);
if (ia.bType == APPLY_SKILL)
m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : ia.sValue ^ 0x00800000, compute_point_status);//Fixed_[C]Martin#2376_001
else
m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : -ia.sValue, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
}
switch (m_pProto->bType)
{
case ITEM_PICK:
case ITEM_ROD:
{
if (bAdd)
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, GetVnum());
}
else
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, 0);
}
}
break;
case ITEM_WEAPON:
{
if (bAdd)
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, GetVnum());
}
else
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, 0);
}
}
break;
case ITEM_ARMOR:
{
if (0 != m_pOwner->GetWear(WEAR_COSTUME_BODY))
break;
if (GetSubType() == ARMOR_BODY || GetSubType() == ARMOR_HEAD || GetSubType() == ARMOR_FOOTS || GetSubType() == ARMOR_SHIELD)
{
if (bAdd)
{
if (GetProto()->bSubType == ARMOR_BODY)
m_pOwner->SetPart(PART_MAIN, GetVnum());
}
else
{
if (GetProto()->bSubType == ARMOR_BODY)
m_pOwner->SetPart(PART_MAIN, m_pOwner->GetOriginalPart(PART_MAIN));
}
}
}
break;
case ITEM_COSTUME:
{
DWORD toSetValue = this->GetVnum();
EParts toSetPart = PART_MAX_NUM;
if (GetSubType() == COSTUME_BODY)
{
toSetPart = PART_MAIN;
if (false == bAdd)
{
const CItem* pArmor = m_pOwner->GetWear(WEAR_BODY);
toSetValue = (NULL != pArmor) ? pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN);
}
}
else if (GetSubType() == COSTUME_HAIR)
{
toSetPart = PART_HAIR;
toSetValue = (true == bAdd) ? this->GetValue(3) : 0;
}
if (PART_MAX_NUM != toSetPart)
{
m_pOwner->SetPart((BYTE)toSetPart, toSetValue);
if (!compute_point_status)//Fixed_[C]Martin#2376_001
m_pOwner->UpdatePacket();
}
}
break;
case ITEM_UNIQUE:
{
if (0 != GetSIGVnum())
{
const CSpecialItemGroup* pItemGroup = ITEM_MANAGER::instance().GetSpecialItemGroup(GetSIGVnum());
if (NULL == pItemGroup)
break;
DWORD dwAttrVnum = pItemGroup->GetAttrVnum(GetVnum());
const CSpecialAttrGroup* pAttrGroup = ITEM_MANAGER::instance().GetSpecialAttrGroup(dwAttrVnum);
if (NULL == pAttrGroup)
break;
for (itertype (pAttrGroup->m_vecAttrs) it = pAttrGroup->m_vecAttrs.begin(); it != pAttrGroup->m_vecAttrs.end(); it++)
{
m_pOwner->ApplyPoint(it->apply_type, bAdd ? it->apply_value : -it->apply_value, compute_point_status);//Fixed_[C]Martin#2376_001
}
}
}
break;
}
}
--------------------------------------------
-- PetSystem.cpp
++++
( PetSystem.h dosyasına )void GiveBuff(bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CPetActor::GiveBuff(bool compute_point_status)//Fixed_[C]Martin#2376_001
{
if (!__PetCheckBuff(this))
return;
LPITEM item = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID);
if (NULL != item)
item->ModifyPoints(true, compute_point_status);//Fixed_[C]Martin#2376_001
return ;
}
( PetSystem.h dosyasına )void RefreshBuff(bool compute_point_status = false);//Fixed_[C]Martin#2376_001
void CPetSystem::RefreshBuff(bool compute_point_status)//Fixed_[C]Martin#2376_001
{
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
CPetActor* petActor = iter->second;
if (0 != petActor)
{
if (petActor->IsSummoned())
{
petActor->GiveBuff(compute_point_status);//Fixed_[C]Martin#2376_001
}
}
}
}
------------------------------------------------
-- Packet.h
++++++
HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC = 50,//Fixed_[C]Martin#2376_001
typedef struct packet_point_change_dynamic
{
int header;
DWORD dwVID;
BYTE count;
} TPacketGCPointChangeDynamic;//Fixed_[C]Martin#2376_001
typedef struct packet_point_change_dynamic_val
{
BYTE type;
long amount;
long value;
} TPacketGCPointChangeDynamicVal;//Fixed_[C]Martin#2376_001
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
--------------------------- Client Source -------------------------
---------------------------------------------------------------------------------------------------------------
--------------------------------
-- Packet.h
+++
HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC = 50,//Fixed_[C]Martin#2376_001
typedef struct packet_point_change_dynamic
{
int header;
DWORD dwVID;
BYTE count;
} TPacketGCPointChangeDynamic;//Fixed_[C]Martin#2376_001
typedef struct packet_point_change_dynamic_val
{
BYTE Type;
long amount;
long value;
} TPacketGCPointChangeDynamicVal;//Fixed_[C]Martin#2376_001
------------------------
-- PythonNetworkStream.h
+++++++++
bool RecvPointChangeDynamic();//Fixed_[C]Martin#2376_001
------------------------
-- PythonNetworkStreamPhaseGame.cpp
+++++++++
case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC: //Fixed_[C]Martin#2376_001
ret = RecvPointChangeDynamic();
break;
+++++++++
bool CPythonNetworkStream::RecvPointChangeDynamic()//Fixed_[C]Martin#2376_001
{
TPacketGCPointChangeDynamic PointChange;
if (!Peek(sizeof(TPacketGCPointChangeDynamic), &PointChange))
{
Tracen("RecvPointChangeDynamic Packet Error #1");
return false;
}
if (!Peek(sizeof(TPacketGCPointChangeDynamicVal)*PointChange.count))
{
Tracen("RecvPointChangeDynamic Packet Error #2");
return false;
}
Recv(sizeof(TPacketGCPointChangeDynamic));
bool refresh_status = false;
bool refresh_skil_window = false;
bool refresh_point_gold = false;
int refresh_point_gold_val = 0;
for (BYTE loop = 0; loop < PointChange.count; loop++)
{
TPacketGCPointChangeDynamicVal point_val;
if (!Recv(sizeof(TPacketGCPointChangeDynamicVal), &point_val))
{
Tracen("Recv Point Change Packet Error");
return false;
}
CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance();
rkChrMgr.ShowPointEffect(point_val.Type, PointChange.dwVID);
CInstanceBase* pInstance = CPythonCharacterManager::Instance().GetMainInstancePtr();
if (pInstance && PointChange.dwVID == pInstance->GetVirtualID())
{
CPythonPlayer& rkPlayer = CPythonPlayer::Instance();
rkPlayer.SetStatus(point_val.Type, point_val.value);
switch (point_val.Type)
{
case POINT_STAT_RESET_COUNT:
refresh_status = true;
break;
case POINT_LEVEL:
case POINT_ST:
case POINT_DX:
case POINT_HT:
case POINT_IQ:
refresh_status = true;
refresh_skil_window = true;
break;
case POINT_SKILL:
case POINT_SUB_SKILL:
case POINT_HORSE_SKILL:
refresh_skil_window = true;
break;
case POINT_ENERGY:
if (point_val.value == 0)
{
rkPlayer.SetStatus(POINT_ENERGY_END_TIME, 0);
}
refresh_status = true;
break;
default:
refresh_status = true;
break;
}
if (POINT_GOLD == point_val.Type)
{
if (point_val.amount > 0)
{
refresh_point_gold = true;
refresh_point_gold_val = point_val.amount;
}
}
}
}
if (refresh_status)
{
__RefreshStatus();
}
if (refresh_skil_window)
{
__RefreshSkillWindow();
}
if (refresh_point_gold)
{
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "OnPickMoney", Py_BuildValue("(i)", refresh_point_gold_val));
}
return true;
}
-----------------------------
-- PythonNetworkStreamPhaseLoading.cpp
+++++++
case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC:
if (RecvPointChangeDynamic())
return;
break;
-----------------------------
-- PythonNetworkStreamPhaseSelect.cpp
+++++++
case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC:
TPacketGCPointChangeDynamic PointChangeDynamic;
if (!Peek(sizeof(TPacketGCPointChangeDynamic), &PointChangeDynamic))
{
Tracen("RecvPointChangeDynamic Packet Error #1");
return;
}
if (!Peek(sizeof(TPacketGCPointChangeDynamicVal) * PointChangeDynamic.count))
{
Tracen("RecvPointChangeDynamic Packet Error #2");
return;
}
Recv(sizeof(TPacketGCPointChangeDynamic));
for (size_t i = 0; i < PointChangeDynamic.count; i++)
{
TPacketGCPointChangeDynamicVal PointChangeDynamicVal;
Recv(sizeof(TPacketGCPointChangeDynamicVal), &PointChangeDynamicVal);
}
return;
break;
Ekli dosyalar
Son düzenleme:
En Çok Reaksiyon Alan Mesajlar
sen kodu tam okuyup anlamamışsın computepoint içinde gecen tüm poin change headeri ile point güncellemesini cliente göndermek yerine bunları kayıt ediyoruz ardından bunu başka bir paket numarası üzerinden dinamik olarak gönderiyoruz paket yapısına müdahale etmiyoruz sadece topluyoruz ve aynı paketleri gereksiz yere tekrar tekrar gönderilmesinin önüne geçiyoruz sadece 1 pakette işlem bitiyor.Öncelikle paylaşım için teşekkürler, computepoint Metin2 kaynak kodları sızdırıldığından beri yazılımcı arkadaşlar tarafından sürekli tartışması yapılan bir konu seneler için bir çok platformda buna benzer alternatif arayışları oldu ama gördüğüm en kapsamlı çözüm alternatifi sizinki dolayısıyla tebrik ederim bir Türk'ten çıkmış olması beni mutlu etti.
Uygulama konusuna gelirsek şuan büyük projelerle bu piyasada olan veya globalde bu işlerle uğraşan çoğu insan Metin2 kaynak kodları sızdırıldığında 2013 yılında aktif olarak official sunucuların alt yapısını oluşturan o dosyalarla hiçbir fix uygulamadan veya optimizasyon yapmadan defalarca kez sunucu açtı ve bazıları anlık 2-3 bin oyuncu gördü şimdi burada söylemek istediğim şu, bu dosyalar bu ilkel haliyle bile iyi bir server ile sorunsuz şekilde aktif olabilir.Tabi ki zamanın getirdiği düzenlemeler, yeni derleyiciler ile optimize etmek, memory leakleri çözmek, bug fixleri vs.vs. yapılmalı ama oyunun çekirdeğinin ana hatlarını oluşturan (örneğin paketler) içerikleri kurcalamak bana pek mantıklı gelmiyor umarım kendimi açıklayabilmişimdir, büyük proje hedefleyen arkadaşların kendi alt yapılarında bu riski almalarını önermiyorum ileride çeşitli paket hatalarıyla uğraşabilirler. Saygılar.
C++:for (int i = 0 ; i < WEAR_MAX_NUM; i++) { LPITEM pItem = GetWear(i); if (pItem) { pItem->ModifyPoints(true, load, compute_point_status);//Fixed_[C]Martin_001 SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag()); } }
bu kodu ele alırsak 5 tane itemde hp olsun bunları hesaplarken 5 tane hp için 5 paket gidiyor yani 5 tane update packet demek ama benim yaptığım dinamik yapıda bu tarz compute point içinde yapılan tüm point numaralarını 1 tane pakete toplayıp öyle gönderiliyor ve bu sayede 5 den 1 e düşüyor paket ve 1 kez update point çağrılıyor client de herhangi bir paket hatasına sebebiyet verebilecek birşeye dokunmuyoruz sadece toplayıp toplu olarak gönderiyoruz
kodu ekleyip test edersen daha net anlarsın
Teori'de sorun çıkarmaz gibi gözüküyor
Bu tarz işlemleri bende bazı sistemler üzerinde denedim hızlı yapılan işlemler toplu sandık açma item ayırma gibi gibi
Packet büyümesinin de bu güne kadar bir zararını görmedim
Fakat bunlar pratikte sorunsuz olacağı anlamına gelmiyor tam deneysel olmuş seninki biraz köklü bir değişiklik olmuş tutarsa çok faydalı olacağı kesin ondan şüphem yok defalarca deneyimledim
Konunun takipçisi olacam
Paylaşım için teşekkürler
Update Final paket boyutu tamamen düşürüldü maksimum 100 baytın üstüne çıkmıyor artık :
C++:typedef struct character_point_instant { long points[POINT_MAX_NUM]; long points_computepoint[POINT_MAX_NUM];//Fixed_[C]Martin_001 //-------------------------------------------------------- void CHARACTER::ComputePoints() { compute_point_status = true;//Fixed_[C]Martin_001 memcpy(m_pointsInstant.points_computepoint, m_pointsInstant.points, sizeof(m_pointsInstant.points));//Fixed_[C]Martin_001 long comp_hp = GetHP();//Fixed_[C]Martin_001 long comp_max_hp = GetMaxHP();//Fixed_[C]Martin_001 long comp_sp = GetSP();//Fixed_[C]Martin_001 long comp_max_sp = GetMaxSP();//Fixed_[C]Martin_001 long comp_stamina = GetStamina();//Fixed_[C]Martin_001 long comp_max_stamina = GetMaxStamina();//Fixed_[C]Martin_001 long lStat = GetPoint(POINT_STAT); long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT); long lSkillActive = GetPoint(POINT_SKILL); long lSkillSub = GetPoint(POINT_SUB_SKILL); long lSkillHorse = GetPoint(POINT_HORSE_SKILL); long lLevelStep = GetPoint(POINT_LEVEL_STEP); long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS); long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS); long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS); long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS); long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS); long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS); long lHPRecovery = GetPoint(POINT_HP_RECOVERY); long lSPRecovery = GetPoint(POINT_SP_RECOVERY); memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points)); BuffOnAttr_ClearAll(); m_SkillDamageBonus.clear(); SetPoint(POINT_STAT, lStat); SetPoint(POINT_SKILL, lSkillActive); SetPoint(POINT_SUB_SKILL, lSkillSub); SetPoint(POINT_HORSE_SKILL, lSkillHorse); SetPoint(POINT_LEVEL_STEP, lLevelStep); SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount); SetPoint(POINT_ST, GetRealPoint(POINT_ST)); SetPoint(POINT_HT, GetRealPoint(POINT_HT)); SetPoint(POINT_DX, GetRealPoint(POINT_DX)); SetPoint(POINT_IQ, GetRealPoint(POINT_IQ)); SetPart(PART_MAIN, GetOriginalPart(PART_MAIN)); SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON)); SetPart(PART_HEAD, GetOriginalPart(PART_HEAD)); SetPart(PART_HAIR, GetOriginalPart(PART_HAIR)); #ifdef ENABLE_ACCE_SYSTEM SetPart(PART_ACCE, GetOriginalPart(PART_ACCE)); #endif SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus); SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus); SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus); SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus); SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus); SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus); SetPoint(POINT_HP_RECOVERY, lHPRecovery); SetPoint(POINT_SP_RECOVERY, lSPRecovery); // PC_BANG_ITEM_ADD SetPoint(POINT_PC_BANG_EXP_BONUS, 0); SetPoint(POINT_PC_BANG_DROP_BONUS, 0); // END_PC_BANG_ITEM_ADD int iMaxHP, iMaxSP; int iMaxStamina; if (IsPC()) { iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht; iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq; iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con; { CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP); if (NULL != pkSk) { pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f); iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval()); } } SetPoint(POINT_MOV_SPEED, 100); SetPoint(POINT_ATT_SPEED, 100); PointChange(POINT_ATT_SPEED, GetPoint(POINT_PARTY_HASTE_BONUS), false, false, compute_point_status);//Fixed_[C]Martin_001 SetPoint(POINT_CASTING_SPEED, 100); } else { iMaxHP = m_pkMobData->m_table.dwMaxHP; iMaxSP = 0; iMaxStamina = 0; SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed); SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed); SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed); } if (IsPC()) { if (GetMountVnum()) { if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), false, false, compute_point_status);//Fixed_[C]Martin_001 if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), false, false, compute_point_status);//Fixed_[C]Martin_001 if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), false, false, compute_point_status);//Fixed_[C]Martin_001 if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), false, false, compute_point_status);//Fixed_[C]Martin_001 } } ComputeBattlePoints(compute_point_status);//Fixed_[C]Martin_001 if (iMaxHP != GetMaxHP()) { SetRealPoint(POINT_MAX_HP, iMaxHP); } PointChange(POINT_MAX_HP, 0, false, false, compute_point_status);//Fixed_[C]Martin_001 if (iMaxSP != GetMaxSP()) { SetRealPoint(POINT_MAX_SP, iMaxSP); } PointChange(POINT_MAX_SP, 0, false, false, compute_point_status);//Fixed_[C]Martin_001 SetMaxStamina(iMaxStamina); // @fixme118 part1 int iCurHP = this->GetHP(); int iCurSP = this->GetSP(); m_pointsInstant.dwImmuneFlag = 0; for (int i = 0 ; i < WEAR_MAX_NUM; i++) { LPITEM pItem = GetWear(i); if (pItem) { pItem->ModifyPoints(true, compute_point_status);//Fixed_[C]Martin_001 SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag()); } } if (DragonSoul_IsDeckActivated()) { for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck(); i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++) { LPITEM pItem = GetWear(i); if (pItem) { if (DSManager::instance().IsTimeLeftDragonSoul(pItem)) pItem->ModifyPoints(true,compute_point_status);//Fixed_[C]Martin_001 } } } if (GetHP() > GetMaxHP()) PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status);//Fixed_[C]Martin_001 if (GetSP() > GetMaxSP()) PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status);//Fixed_[C]Martin_001 ComputeSkillPoints(); RefreshAffect(compute_point_status);//Fixed_[C]Martin_001 CPetSystem * pPetSystem = GetPetSystem(); if (NULL != pPetSystem) pPetSystem->RefreshBuff(compute_point_status);//Fixed_[C]Martin_001 // @fixme118 part2 (after petsystem stuff) if (IsPC()) { if (this->GetHP() != iCurHP) this->PointChange(POINT_HP, iCurHP-this->GetHP(), false, false, compute_point_status);//Fixed_[C]Martin_001 if (this->GetSP() != iCurSP) this->PointChange(POINT_SP, iCurSP-this->GetSP(), false, false, compute_point_status);//Fixed_[C]Martin_001 } compute_point_status = false;//Fixed_[C]Martin_001 if (GetDesc())//Fixed_[C]Martin_001 { BYTE send_count = 0; auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } send_count++; } if (send_count == 1) { auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } struct packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = it->type; pack.value = it->val; pack.amount = it->amount; GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); } } else { if (send_count > 1) { TPacketGCPointChangeDynamic pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC; pack.dwVID = m_vid; pack.count = send_count; TEMP_BUFFER buf; buf.write(&pack, sizeof(TPacketGCPointChangeDynamic)); auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } TPacketGCPointChangeDynamicVal pack_val; pack_val.type = it->type; pack_val.value = it->val; pack_val.amount = it->amount; buf.write(&pack_val, sizeof(TPacketGCPointChangeDynamicVal)); } GetDesc()->Packet(buf.read_peek(), buf.size()); } } }//Fixed_[C]Martin_001 compute_point_list.clear();//Fixed_[C]Martin_001 compute_point_list.shrink_to_fit();//Fixed_[C]Martin_001 UpdatePacket(); memset(m_pointsInstant.points_computepoint, 0, sizeof(m_pointsInstant.points_computepoint));//Fixed_[C]Martin_001 }
SOLID Prensiplerine göre her fonksiyonun bir işlemi olmalıdır. Toplamak dağıtmaktan daha çok zarara uğratabilir.
Packetlerin başında ve sonunda başlangıç ve bitiş baytları var mesela. 600 KB lık packetin tamamını indiremediği durumlarda ne gibi sorunlar yaşanacak bunu düşünmek lazım. Parçalı şekilde gönderilen packetlerin tek bir işlem dışında başka yerlerde parça parça kullanılıyor mu bunu araştırmak lazım.
- Mesela statü puanı verildiğinde clientten servera gönderiliyor ve tekrardan cliente OK dönüyor. Bunu kaldırıp, direkt olarak clientten servera gönderip, serverdan geri dönüş beklenmemeli. Oyun karakteri bir dizide tutmalı ve ona göre işlem yapmalı. Metin2 o kadar çok serverı zorluyor ki, çoğu işlem clientte çözülmesi gerekiyor diye düşünüyorum.
- Mesela at çağırmayı kullandın, servera packet gitti, server geriye döndü hesaplama yaptı, spawn etti. Bunun yerine at çağırmaya basınca item_use gönderip, spawnı cliente bırakıp daha sonrasında ata bindiğinde kontrolü sağlanabilir.
- Questi mesela direkt olarak cliente taşıyıp packet ile kontrolü sağlanabilir.
- Marketteki itemler direkt olarak clientte tutulup, buy packeti gittiğinde olumlu veya olumsuz dönülebilir.Her Markete tıklandığında serverdan gereksiz yere shopu sorgulatıp ona göre cliente packet atılıyor.
- Refine_Proto komple cliente taşınıp + basma olarak gelen packet denetlenebilir.
Evet move, attact kısmı hile kontrolü amacıyla serverda halledilir ama kalan fazlalıkları cliente taşımak bence daha mantıklı
KomikArkadaşım olan emirhanda aynısını yaptı yüksek bir onlinede anlam veremediği konudan alakasız paket hataları çıkmıştı sanırım o bunun sorununu çözememişti bireysel 5 10 kişilik oyunlarda sorun vermiyor olabilir fakat yüksek onlinelerde emirhanın başına gelen başınıza gelebilir. Emeğiniz için ayrı teşekkürler.senin baya Arkadaşın var galiba bide her konuda seni görüyorum herşeyde bi arkadaşın oluyor ve onlar uyguluyor bu işlemleri
- Katılım
- 17 Tem 2018
- Konular
- 533
- Mesajlar
- 3,963
- Çözüm
- 34
- Online süresi
- 11mo 8d
- Reaksiyon Skoru
- 1,769
- Altın Konu
- 50
- TM Yaşı
- 7 Yıl 10 Ay 24 Gün
- Başarım Puanı
- 327
- MmoLira
- 9,296
- DevLira
- 45
Paylaşım için teşekkürler.
- Katılım
- 20 Kas 2016
- Konular
- 65
- Mesajlar
- 1,263
- Çözüm
- 12
- Online süresi
- 1mo 3d
- Reaksiyon Skoru
- 619
- Altın Konu
- 0
- TM Yaşı
- 9 Yıl 6 Ay 18 Gün
- Başarım Puanı
- 201
- MmoLira
- 2,443
- DevLira
- 82
Arkadaşım olan emirhanda aynısını yaptı yüksek bir onlinede anlam veremediği konudan alakasız paket hataları çıkmıştı sanırım o bunun sorununu çözememişti bireysel 5 10 kişilik oyunlarda sorun vermiyor olabilir fakat yüksek onlinelerde emirhanın başına gelen başınıza gelebilir. Emeğiniz için ayrı teşekkürler.
- Katılım
- 14 Ocak 2021
- Konular
- 11
- Mesajlar
- 482
- Çözüm
- 9
- Online süresi
- 6mo 10d
- Reaksiyon Skoru
- 403
- Altın Konu
- 0
- TM Yaşı
- 5 Yıl 4 Ay 22 Gün
- Başarım Puanı
- 130
- MmoLira
- 10,530
- DevLira
- 12
kime ne oldu daha açıklayıcı olabilirmisiniz bu paylaştığım kodlar olumlu mu olumsuz mu arkadaşınızın başına gelene göreArkadaşım olan emirhanda aynısını yaptı yüksek bir onlinede anlam veremediği konudan alakasız paket hataları çıkmıştı sanırım o bunun sorununu çözememişti bireysel 5 10 kişilik oyunlarda sorun vermiyor olabilir fakat yüksek onlinelerde emirhanın başına gelen başınıza gelebilir. Emeğiniz için ayrı teşekkürler.
- Katılım
- 12 Ara 2015
- Konular
- 106
- Mesajlar
- 1,849
- Çözüm
- 19
- Online süresi
- 1mo 7d
- Reaksiyon Skoru
- 934
- Altın Konu
- 1
- TM Yaşı
- 10 Yıl 5 Ay 27 Gün
- Başarım Puanı
- 211
- MmoLira
- 1,235
- DevLira
- 165
KomikArkadaşım olan emirhanda aynısını yaptı yüksek bir onlinede anlam veremediği konudan alakasız paket hataları çıkmıştı sanırım o bunun sorununu çözememişti bireysel 5 10 kişilik oyunlarda sorun vermiyor olabilir fakat yüksek onlinelerde emirhanın başına gelen başınıza gelebilir. Emeğiniz için ayrı teşekkürler.
senin baya Arkadaşın var galiba bide her konuda seni görüyorum herşeyde bi arkadaşın oluyor ve onlar uyguluyor bu işlemleri 
Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 10
- Görüntüleme
- 2K
- Cevaplar
- 149
- Görüntüleme
- 47K




