sábado, 31 de outubro de 2009

Floating point comparison

float left, right;
unsigned char res = 0;
__asm push eax;
__asm fld [right];
__asm fld [left];
__asm fcompp;
__asm fnstsw ax;
__asm mov [res], ah;
__asm pop eax



left | right | ah | op
------+-------+------+---------------
-1.0 | 0.0 | 0x01 | left < right
0.0 | 0.0 | 0x40 | left == right
1.0 | 0.0 | 0x00 | left > right

terça-feira, 12 de maio de 2009

AttackMotionTime (players, homuns, npcs)

for players: CPC::UpdateAttackMotionTime()
CITP* equipedWeapon = this->m_pcItemInventoryMgr.GetITPEquipedWeapon();
CITP* other = g_itpMgr.GetITP(this->m_pcItemInventoryMgr.GetEquipedItem(0x20)->itemid);
int attackSpeed;
// initialize attackSpeed
if( equipedWeapon )
{
if( other && other->GetType() == ITPTYPE_WEAPON )// two weapons (dual)
attackSpeed = ftol(
( (float)g_charMTInfo.GetAttackMT(m_jobClass,other->GetClass())+
(float)g_charMTInfo.GetAttackMT(m_jobClass,equipedWeapon->GetClass())
)/2.0*1.4);
else// right weapon
attackSpeed = g_charMTInfo.GetAttackMT(m_jobClass,equipedWeapon->GetClass());
}
else
{
if( other && other->GetType() == ITPTYPE_WEAPON )// left weapon
attackSpeed = g_charMTInfo.GetAttackMT(m_jobClass,other->GetClass());
else// no weapon (fists)
attackSpeed = g_charMTInfo.GetAttackMT(m_jobClass,0);
}
attackSpeed -= attackSpeed*GetAgiValue()/250 + attackSpeed*GetDexValue()/1000;
if( (m_effectState&EFFECTSTATE_RIDING) != 0 )
attackSpeed += 1000 - (KN_CAVALIERMASTERY.level*10+50)*1000/100;
attackSpeed -= -m_plusAttackSpeed*10;
{// percent bonuses
int percent = CPC::GetAttackSlowValue();
percent += CPC::GetAttackHasteValue1();
percent += CPC::GetAttackHasteValue2();
if( this->m_charBuff )
percent += this->m_charBuff.GetParameterValue(PARAM_PLUS_ASPD_PERCENT);
if( GetEffective(EFST_BERSERK,0) )
percent += 30;
attackSpeed += attackSpeed*percent*17/800;// wtf??? what kind of weird percent is this?
}
// other bonuses
if( m_isSpellCasting )
attackSpeed += attackSpeed*(10-SA_FREECAST.level)*5/100;
if( GetEffective(EFST_DEFENDER,0) )
attackSpeed += (5-GetEffective(EFST_DEFENDER,0))*50;
if( equipedWeapon && equipedWeapon->GetClass() == 15 )// book?
attackSpeed += -SA_ADVANCEDBOOK.level*val*5/1000;
if( attackSpeed < 100 )
attackSpeed = 100;
this->m_attackMotionTime = attackSpeed;
this->m_pcClientUpdater.NotifyParameter(PARAM_ATTACK_MOTION_TIME/*0x35*/,0);


for homuns: CNpcHomun::GetATKTime_Client()
int attackSpeed = this->m_rechargeTime;
attackSpeed -= attackSpeed*GetAgiValue()/250 + m_rechargeTime*GetDexValue()/1000;
if( attackSpeed < 100 )
attackSpeed = 100;
attackSpeed += attackSpeed*(CNPC::GetATKHasteVal2() + CNPC::GetAttackSlowValue())*17/800;
if( attackSpeed < 100 )
attackSpeed = 100;
return attackSpeed ;


for other npcs: CNPC::UpdateParameterValue(VAR_ASPD,amount)
MONPARAMETER* monster = g_monParameter.GetMonParameter(this->m_spriteType);// m_spriteType is class
if( monster == NULL )
this->m_attackSpeed = 100;
else
{
int attackSpeed = monster->attackMT;
int percent = CNPC::GetATKHasteVal2() + CNPC::GetAttackSlowValue() + CNPC::GetATKHasteVal1()
if( this->m_charBuff )
percent += this->m_charBuff.GetParameterValue(PARAM_PLUS_ASPD_PERCENT);// 0xa7, VAR_PLUSASPDPERCENT
attackSpeed = attackSpeed*percent*17/800;
if( attackSpeed < 100 )
attackSpeed = 100;
this->m_attackSpeed = attackSpeed;
}


-------------------- (auxiliary functions) --------------------


CPC::GetAttackSlowValue()
int val[6];
memset(val, 0, sizeof(val));
val[0] = -GetEffective(EFST_DONTFORGETME,0);
val[1] = (GetEffective(EFST_STEELBODY,0) ? -25 : 0);
if( GetEffective(EFST_JOINTBEAT,0)&2 != 0 )
val[2] -= 25;
if( GetEffective(EFST_JOINTBEAT,0)&4 != 0 )
val[2] -= 10;
val[3] = (GetEffective(EFST_SLOWDOWN,0) ? -75 : 0);
val[4] = -GetEffective(EFST_GRAVITATION,0);
val[5] = -GetEffective(EFST_LONGING,1);
return min_of(val);


CPC::GetAttackHasteValue1()
if( GetEffective(EFST_ATTHASTE_INFINITY,0) )
return GetEffective(EFST_ATTHASTE_INFINITY,0);
if( GetEffective(EFST_ATTHASTE_POTION3,0) )
return GetEffective(EFST_ATTHASTE_POTION3,0);
if( GetEffective(EFST_ATTHASTE_POTION2,0) )
return GetEffective(EFST_ATTHASTE_POTION2,0);
if( GetEffective(EFST_ATTHASTE_POTION1,0) )
return GetEffective(EFST_ATTHASTE_POTION1,0);
return 0;


CPC::GetAttackHasteValue2()
int val[10];
memset(val, 0, sizeof(val));
val[0] = GetEffective(EFST_TWOHANDQUICKEN,0);
val[1] = GetEffective(EFST_SPEARQUICKEN,0);
val[2] = GetEffective(EFST_ONEHANDQUICKEN,0);
val[3] = GetEffective(EFST_ADRENALINE,0);
val[4] = GetEffective(EFST_ADRENALINE2,0);
val[5] = GetEffective(EFST_ASSASSINCROSS,0);
val[6] = GetEffective(EFST_STAR_COMFORT,0) + GetEffective(EFST_DEVIL1,0);
val[7] = GetEffective(EFST_GS_GATLINGFEVER,0) + GetEffective(EFST_GS_MADNESSCANCEL,0);
val[8] = GetEffective(EFST_PSPEED,0);
val[9] = 0;
return max_of(val);


CNPC::GetAttackSlowValue()
int val[5];
memset(val, 0, sizeof(val));
val[0] = -GetEffective(EFST_DONTFORGETME,0);
val[1] = (GetEffective(EFST_STEELBODY,0) ? -25 : 0);
if( GetEffective(EFST_JOINTBEAT,0)&2 != 0 )
val[2] -= 25;
if( GetEffective(EFST_JOINTBEAT,0)&4 != 0 )
val[2] -= 10;
val[3] = (GetEffective(EFST_SLOWDOWN,0) ? -75 : 0);
val[4] = -GetEffective(EFST_GRAVITATION,0);
return min_of(val);


CNPC::GetATKHasteVal1()
if( GetEffective(EFST_ATTHASTE_POTION3,0) )
return GetEffective(EFST_ATTHASTE_POTION3,0);
if( GetEffective(EFST_ATTHASTE_POTION2,0) )
return GetEffective(EFST_ATTHASTE_POTION2,0);
if( GetEffective(EFST_ATTHASTE_POTION1,0) )
return GetEffective(EFST_ATTHASTE_POTION1,0);
return 0;


CNPC::GetATKHasteVal2()
int val[5];
memset(val, 0, sizeof(val));
val[0] = GetEffective(EFST_ATTHASTE_INFINITY,0);
val[1] = GetEffective(EFST_ADRENALINE,0);
val[2] = GetEffective(EFST_TWOHANDQUICKEN,0);
val[3] = GetEffective(EFST_HFLI_FLEET,0);
val[4] = 0;
return max_of(val);

quinta-feira, 7 de maio de 2009

Agit

castle defense points affect guardians and emperium like this:
* maxHp += defense*1000;
* def += (defense+2)/3;
* mdef += (defense+2)/3;
GD_GUARDUP gives level*9 ATKPercent and level*4 EFST_ATTHASTE_INFINITY
there are economy/5+4 treasures
castle state is saved every 600 seconds
payTime is triggered every 10 days, but doesn't do anything (maybe on other types of servers)

// script functions:
AgitEmblemFlag "" // registers the npc as a flag of the target agit map
AgitFunc // executes a task depending on the arguments
AgitGet // gets a property of this agit map (supports all)
AgitGet2 "" // gets a property of an agit map (supports 8,9,10,11; others use the current map instead)
AgitNpcGet // gets a property of an agit npc (supports all)
AgitNpcSet // sets a property of an agit npc (supports 0,2,4)
AgitRegister "" // registers the current npc as belonging to the castle in the target map (must be a flag, class 722)
AgitSet // sets a property of this agit map

// AgitEmblemFlag vs AgitRegister:
// these seam to do the same thing, but stores them in different places
// therefore i'm assuming AgitEmblemFlag is for agit maps in another zone and AgitRegister for agit maps in this zone
// AgitEmblemFlag adds the npc to:
// static map CAgitMapRes::ms_agitTable;// mapname -> FLAG_INFO*{int guildId; char agitName[24]; vector flags;}
// AgitRegister adds the npc to:
// vector CAgitMapRes::m_flags;

// AgitFunc arguments:
// // increases triggerE (if it still can)
// // increases triggerD (if it still can)
// // sets payTime to 10 days from now
// // if( map.IsSiegeTime() ) flush target guild (or all if 0) except the owner guild;
// // refreshes the effects of castle defense and GD_GUARDUP

// AgitGet/AgitGet2/AgitSet
// -----
// agit map properties:
// 0=economy value
// 1=economy condition (if it can invest)
// 2=economy invest money (for next invest)
// 3=economy triggerE (delayed points)
// 4=defense value
// 5=defense condition (if it can invest)
// 6=defense invest money (for next invest)
// 7=defense triggerD (delayed points)
// 8=guildId
// 9=agitName
// 10=(some kind of name in the guild: guild name or owner name)
// 11=(some kind of name in the guild: guild name or owner name)
// 12=level of GD_KAFRACONTRACT
// 13=level of GD_GUARDRESEARCH
// 14=(nothing)
// 15=(unknown flag related to OnChangeOwner)
// 16=killerName (who killed the emperium)

// AgitNpcGet/AgitNpcSet
// -----
// agit npc indexes:
// 0=manager
// 1=emperium
// 2=kafra
// 100+?=guardian[?] (up to 8 guardians)
// -----
// agit npc properties:
// 0=enabled
// 1=maxHp
// 2=hp
// 3=maxHp/3 (purpose is unknown)
// 4=sp
// 5=accountName (mob name)