5 leg() : StrengthBonus(0), AgilityBonus(0) { }
8 virtual void Save(outputfile
&) const;
9 virtual void Load(inputfile
&);
10 virtual int GetTotalResistance(int) const;
11 void SetBoot(item
* What
) { BootSlot
.PutInItem(What
); }
12 item
* GetBoot() const { return *BootSlot
; }
13 virtual void DropEquipment(stack
* = 0);
14 double GetKickToHitValue() const { return KickToHitValue
; }
15 double GetKickDamage() const { return KickDamage
; }
16 int GetKickMinDamage() const;
17 int GetKickMaxDamage() const;
18 int GetAttribute(int, truth
= true) const;
19 truth
EditAttribute(int, int);
20 void EditExperience(int, double, double);
21 virtual void InitSpecialAttributes();
22 virtual void Mutate();
23 sLong
GetKickAPCost() const { return KickAPCost
; }
24 virtual item
* GetEquipment(int) const;
25 virtual int GetEquipments() const { return 1; }
26 sLong
GetBaseKickStrength() const { return BaseKickStrength
; }
27 void SetBaseKickStrength(sLong What
) { BaseKickStrength
= What
; }
28 virtual void CalculateDamage();
29 virtual void CalculateToHitValue();
30 virtual void CalculateAPCost();
31 void ApplyEquipmentAttributeBonuses(item
*);
32 virtual void CalculateAttributeBonuses();
33 virtual void SignalEquipmentAdd(gearslot
*);
34 void ApplyAgilityPenalty(item
*);
35 void ApplyStrengthBonus (item
*Item
);
36 void ApplyAgilityBonus (item
*Item
);
37 virtual void SignalVolumeAndWeightChange();
38 virtual truth
DamageArmor(character
*, int, int);
39 virtual truth
EditAllAttributes(int);
40 void AddAttackInfo(felist
&) const;
41 virtual item
* GetArmorToReceiveFluid(truth
) const;
42 virtual void CopyAttributes(const bodypart
*);
43 double GetStrengthExperience() const { return StrengthExperience
; }
44 double GetAgilityExperience() const { return AgilityExperience
; }
45 virtual void SignalPossibleUsabilityChange();
48 void UpdateLegArmorPictures(graphicdata
&, graphicdata
&, int) const;
50 double StrengthExperience
;
51 double AgilityExperience
;
54 double KickToHitValue
;
65 int leg::GetKickMinDamage() const { return int(KickDamage
* 0.75); }
69 int leg::GetKickMaxDamage() const { return int(KickDamage
* 1.25 + 1); }
73 int leg::GetTotalResistance(int Type
) const
77 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
79 if(GetExternalBodyArmor())
80 Resistance
+= GetExternalBodyArmor()->GetResistance(Type
) >> 1;
83 Resistance
+= GetBoot()->GetResistance(Type
);
88 return GetResistance(Type
);
93 void leg::Save(outputfile
& SaveFile
) const
95 bodypart::Save(SaveFile
);
96 SaveFile
<< BaseKickStrength
<< StrengthExperience
<< AgilityExperience
;
102 void leg::Load(inputfile
& SaveFile
)
104 bodypart::Load(SaveFile
);
105 SaveFile
>> BaseKickStrength
>> StrengthExperience
>> AgilityExperience
;
106 SaveFile
>> BootSlot
;
111 void leg::CalculateDamage()
116 double WeaponStrength
= GetBaseKickStrength() * GetBaseKickStrength();
117 item
* Boot
= GetBoot();
120 WeaponStrength
+= Boot
->GetWeaponStrength();
122 double Base
= sqrt(5e-5 * WeaponStrength
);
125 Base
+= Boot
->GetDamageBonus();
127 KickDamage
= Base
* sqrt(1e-7 * GetAttribute(LEG_STRENGTH
))
128 * GetHumanoidMaster()->GetCWeaponSkill(KICK
)->GetBonus();
133 void leg::CalculateToHitValue()
138 double BonusMultiplier
= 10.;
139 item
* Boot
= GetBoot();
142 BonusMultiplier
+= Boot
->GetTHVBonus();
144 KickToHitValue
= GetAttribute(AGILITY
)
145 * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
))
146 * GetHumanoidMaster()->GetCWeaponSkill(KICK
)->GetBonus()
147 * Master
->GetMoveEase()
148 * BonusMultiplier
/ 10000000;
153 void leg::CalculateAPCost()
158 KickAPCost
= Max(sLong(20000000000. / (APBonus(GetAttribute(AGILITY
)) * Master
->GetMoveEase() * Master
->GetCWeaponSkill(KICK
)->GetBonus())), 100);
163 void leg::DropEquipment(stack
* Stack
)
168 GetBoot()->MoveTo(Stack
);
173 GetSlot()->AddFriendItem(GetBoot());
186 int leg::GetAttribute(int Identifier
, truth AllowBonus
) const
188 if(Identifier
== LEG_STRENGTH
)
190 int Base
= !UseMaterialAttributes()
191 ? int(StrengthExperience
* EXP_DIVISOR
)
192 : GetMainMaterial()->GetStrengthValue();
195 Base
+= StrengthBonus
;
197 return Max(!IsBadlyHurt() || !AllowBonus
? Base
: Base
/ 3, 1);
199 else if(Identifier
== AGILITY
)
201 int Base
= !UseMaterialAttributes()
202 ? int(AgilityExperience
* EXP_DIVISOR
)
203 : GetMainMaterial()->GetFlexibility() << 2;
206 Base
+= AgilityBonus
;
208 return Max(IsUsable() || !AllowBonus
? Base
: Base
/ 3, 1);
212 ABORT("Illegal leg attribute %d request!", Identifier
);
219 truth
leg::EditAttribute(int Identifier
, int Value
)
224 if(Identifier
== LEG_STRENGTH
)
226 if(!UseMaterialAttributes()
227 && Master
->RawEditAttribute(StrengthExperience
, Value
))
229 Master
->CalculateBurdenState();
230 Master
->CalculateBattleInfo();
234 else if(Identifier
== AGILITY
)
235 if(!UseMaterialAttributes()
236 && Master
->RawEditAttribute(AgilityExperience
, Value
))
238 Master
->CalculateBattleInfo();
247 void leg::EditExperience(int Identifier
, double Value
, double Speed
)
252 if(Identifier
== LEG_STRENGTH
)
254 if(!UseMaterialAttributes())
256 int Change
= Master
->RawEditExperience(StrengthExperience
,
257 Master
->GetNaturalExperience(LEG_STRENGTH
),
262 cchar
* Adj
= Change
> 0 ? "stronger" : "weaker";
264 if(Master
->IsPlayer())
265 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
266 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
267 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
269 Master
->CalculateBurdenState();
270 Master
->CalculateBattleInfo();
274 else if(Identifier
== AGILITY
)
276 if(!UseMaterialAttributes())
278 int Change
= Master
->RawEditExperience(AgilityExperience
,
279 Master
->GetNaturalExperience(AGILITY
),
284 cchar
* Adj
= Change
> 0 ? "very agile" : "slower";
286 if(Master
->IsPlayer())
287 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
288 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
289 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
291 Master
->CalculateBattleInfo();
296 ABORT("Illegal leg attribute %d experience edit request!", Identifier
);
301 void leg::InitSpecialAttributes()
303 if(!Master
->IsHuman() || Master
->IsInitializing())
305 StrengthExperience
= Master
->GetNaturalExperience(LEG_STRENGTH
);
306 AgilityExperience
= Master
->GetNaturalExperience(AGILITY
);
310 StrengthExperience
= game::GetAveragePlayerLegStrengthExperience();
311 AgilityExperience
= game::GetAveragePlayerAgilityExperience();
314 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
315 LimitRef(AgilityExperience
, MIN_EXP
, MAX_EXP
);
316 BaseKickStrength
= Master
->GetBaseKickStrength();
324 StrengthExperience
= StrengthExperience
* (1.5 - (RAND() & 1023) / 1023.);
325 AgilityExperience
= AgilityExperience
* (1.5 - (RAND() & 1023) / 1023.);
326 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
327 LimitRef(AgilityExperience
, MIN_EXP
, MAX_EXP
);
332 item
* leg::GetEquipment(int I
) const
334 return !I
? GetBoot() : 0;
339 void leg::SignalVolumeAndWeightChange()
341 bodypart::SignalVolumeAndWeightChange();
343 if(Master
&& !Master
->IsInitializing())
345 CalculateAttributeBonuses();
346 CalculateAttackInfo();
352 leg::leg(const leg
& Leg
) : mybase(Leg
), StrengthExperience(Leg
.StrengthExperience
), AgilityExperience(Leg
.AgilityExperience
), BaseKickStrength(Leg
.BaseKickStrength
)
358 void leg::SignalEquipmentAdd(gearslot
* Slot
)
360 int EquipmentIndex
= Slot
->GetEquipmentIndex();
362 if(Master
&& !Master
->IsInitializing())
364 item
* Equipment
= Slot
->GetItem();
366 if(Equipment
->IsInCorrectSlot(EquipmentIndex
))
367 ApplyEquipmentAttributeBonuses(Equipment
);
369 if(EquipmentIndex
== RIGHT_BOOT_INDEX
|| EquipmentIndex
== LEFT_BOOT_INDEX
)
370 ApplyAgilityPenalty(Equipment
);
374 Master
->SignalEquipmentAdd(EquipmentIndex
);
379 void leg::ApplyEquipmentAttributeBonuses(item
* Item
)
381 if(Item
->AffectsLegStrength())
383 StrengthBonus
+= Item
->GetEnchantment();
386 Master
->CalculateBurdenState();
389 if(Item
->AffectsAgility())
390 AgilityBonus
+= Item
->GetEnchantment();
395 void leg::CalculateAttributeBonuses()
397 StrengthBonus
= AgilityBonus
= 0;
399 for(int c
= 0; c
< GetEquipments(); ++c
)
401 item
* Equipment
= GetEquipment(c
);
403 if(Equipment
&& Equipment
->IsInCorrectSlot())
404 ApplyEquipmentAttributeBonuses(Equipment
);
407 ApplyAgilityPenalty(GetBoot());
411 ApplyAgilityPenalty(GetExternalCloak());
412 ApplyAgilityPenalty(GetExternalBodyArmor());
414 ApplyStrengthBonus(GetExternalHelmet());
415 ApplyStrengthBonus(GetExternalCloak());
416 ApplyStrengthBonus(GetExternalBodyArmor());
417 ApplyStrengthBonus(GetExternalBelt());
418 ApplyAgilityBonus(GetExternalHelmet());
419 ApplyAgilityBonus(GetExternalCloak());
420 ApplyAgilityBonus(GetExternalBodyArmor());
421 ApplyAgilityBonus(GetExternalBelt());
424 if(!UseMaterialAttributes())
426 StrengthBonus
-= CalculateScarAttributePenalty(GetAttribute(LEG_STRENGTH
, false));
427 AgilityBonus
-= CalculateScarAttributePenalty(GetAttribute(AGILITY
, false)) ;
433 void leg::ApplyAgilityPenalty(item
* Item
)
436 AgilityBonus
-= Item
->GetInElasticityPenalty(GetAttribute(AGILITY
, false));
441 truth
leg::DamageArmor(character
* Damager
, int Damage
, int Type
)
443 sLong AV
[3] = { 0, 0, 0 }, AVSum
= 0;
446 if((Armor
[0] = GetBoot()))
447 AVSum
+= AV
[0] = Max(Armor
[0]->GetStrengthValue(), 1);
449 if((Armor
[1] = GetExternalBodyArmor()))
450 AVSum
+= AV
[1] = Max(Armor
[1]->GetStrengthValue() >> 1, 1);
452 if((Armor
[2] = GetExternalCloak()))
453 AVSum
+= AV
[2] = Max(Armor
[2]->GetStrengthValue(), 1);
455 return AVSum
? Armor
[femath::WeightedRand(AV
, AVSum
)]->ReceiveDamage(Damager
, Damage
, Type
) : false;
460 truth
leg::EditAllAttributes(int Amount
)
462 LimitRef(StrengthExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
463 LimitRef(AgilityExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
465 && (StrengthExperience
!= MIN_EXP
|| AgilityExperience
!= MIN_EXP
))
467 && (StrengthExperience
!= MAX_EXP
|| AgilityExperience
!= MAX_EXP
));
472 void leg::AddAttackInfo(felist
& List
) const
474 festring Entry
= CONST_S(" kick attack");
476 Entry
<< GetKickMinDamage() << '-' << GetKickMaxDamage();
478 Entry
<< int(GetKickToHitValue());
480 Entry
<< GetKickAPCost();
481 List
.AddEntry(Entry
, LIGHT_GRAY
);
486 item
* leg::GetArmorToReceiveFluid(truth SteppedOn
) const
490 item
* Boot
= GetBoot();
491 return Boot
? Boot
: 0;
495 item
* Cloak
= GetExternalCloak();
497 if(Cloak
&& !(RAND() % 3))
500 item
* Boot
= GetBoot();
502 if(Boot
&& RAND() & 1)
505 item
* BodyArmor
= GetExternalBodyArmor();
506 return BodyArmor
? BodyArmor
: 0;
512 void leg::UpdateLegArmorPictures(graphicdata
& LegArmorGraphicData
, graphicdata
& BootGraphicData
, int SpecialFlags
) const
514 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
516 UpdateArmorPicture(LegArmorGraphicData
,
517 Master
? GetExternalBodyArmor() : 0,
519 &item::GetLegArmorBitmapPos
,
521 UpdateArmorPicture(BootGraphicData
,
524 &item::GetBootBitmapPos
);
530 void leg::CopyAttributes(const bodypart
* BodyPart
)
532 const leg
* Leg
= static_cast<const leg
*>(BodyPart
);
533 StrengthExperience
= Leg
->StrengthExperience
;
534 AgilityExperience
= Leg
->AgilityExperience
;
539 void leg::SignalPossibleUsabilityChange()
541 feuLong OldFlags
= Flags
;
544 if(Flags
!= OldFlags
&& !Master
->IsInitializing())
545 Master
->CalculateBattleInfo();
550 void leg::ApplyStrengthBonus (item
*Item
) {
551 if (Item
&& Item
->AffectsLegStrength()) StrengthBonus
+= Item
->GetEnchantment()/2;
556 void leg::ApplyAgilityBonus (item
*Item
) {
557 if (Item
&& Item
->AffectsAgility()) AgilityBonus
+= Item
->GetEnchantment()/2;