3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
13 /* Compiled through itemset.cpp */
15 int bodypart::GetGraphicsContainerIndex() const { return GR_HUMANOID
; }
16 int bodypart::GetArticleMode() const { return IsUnique() ? FORCE_THE
: 0; }
17 truth
bodypart::IsAlive() const { return MainMaterial
->GetBodyFlags() & IS_ALIVE
; }
18 int bodypart::GetSpecialFlags() const { return SpecialFlags
|ST_OTHER_BODYPART
; }
19 col16
bodypart::GetMaterialColorA(int) const { return GetMainMaterial()->GetSkinColor(); }
20 truth
bodypart::IsWarm() const { return MainMaterial
->GetBodyFlags() & IS_WARM
; }
21 truth
bodypart::UseMaterialAttributes() const { return MainMaterial
->GetBodyFlags() & USE_MATERIAL_ATTRIBUTES
|| !Master
|| Master
->AlwaysUseMaterialAttributes(); }
22 truth
bodypart::CanRegenerate() const { return MainMaterial
->GetBodyFlags() & CAN_REGENERATE
; }
23 truth
bodypart::CanHaveParasite() const { return MainMaterial
->GetBodyFlags() & CAN_HAVE_PARASITE
; }
24 square
* bodypart::GetSquareUnder(int I
) const { return Master
? Slot
[0]->GetSquareUnder(I
) : Slot
[I
]->GetSquareUnder(); }
25 lsquare
* bodypart::GetLSquareUnder(int I
) const { return static_cast<lsquare
*>(Master
? Slot
[0]->GetSquareUnder(I
) : Slot
[I
]->GetSquareUnder()); }
26 item
* bodypart::GetExternalBodyArmor() const { return GetHumanoidMaster()->GetBodyArmor(); }
27 item
* bodypart::GetExternalCloak() const { return GetHumanoidMaster()->GetCloak(); }
28 truth
bodypart::AllowFluidBe() const { return !Master
|| !Master
->IsPolymorphed(); }
31 item
*bodypart::GetExternalHelmet () const { return GetHumanoidMaster()->GetHelmet(); }
32 item
*bodypart::GetExternalBelt () const { return GetHumanoidMaster()->GetBelt(); }
34 int head::GetBodyPartIndex() const { return HEAD_INDEX
; }
35 int head::GetBiteMinDamage() const { return int(BiteDamage
* 0.75); }
36 int head::GetBiteMaxDamage() const { return int(BiteDamage
* 1.25 + 1); }
38 int torso::GetBodyPartIndex() const { return TORSO_INDEX
; }
40 int normaltorso::GetGraphicsContainerIndex() const { return GR_CHARACTER
; }
42 int arm::GetMinDamage() const { return int(Damage
* 0.75); }
43 int arm::GetMaxDamage() const { return int(Damage
* 1.25 + 1); }
44 double arm::GetBlockValue() const { return GetToHitValue() * GetWielded()->GetBlockModifier() / 10000; }
46 int rightarm::GetBodyPartIndex() const { return RIGHT_ARM_INDEX
; }
47 int rightarm::GetSpecialFlags() const { return SpecialFlags
|ST_RIGHT_ARM
; }
49 int leftarm::GetBodyPartIndex() const { return LEFT_ARM_INDEX
; }
50 int leftarm::GetSpecialFlags() const { return SpecialFlags
|ST_LEFT_ARM
; }
52 int groin::GetBodyPartIndex() const { return GROIN_INDEX
; }
53 int groin::GetSpecialFlags() const { return SpecialFlags
|ST_GROIN
; }
55 int leg::GetKickMinDamage() const { return int(KickDamage
* 0.75); }
56 int leg::GetKickMaxDamage() const { return int(KickDamage
* 1.25 + 1); }
58 int rightleg::GetBodyPartIndex() const { return RIGHT_LEG_INDEX
; }
59 int rightleg::GetSpecialFlags() const { return SpecialFlags
|ST_RIGHT_LEG
; }
61 int leftleg::GetBodyPartIndex() const { return LEFT_LEG_INDEX
; }
62 int leftleg::GetSpecialFlags() const { return SpecialFlags
|ST_LEFT_LEG
; }
64 v2
eddytorso::GetBitmapPos(int Frame
) const { return torso::GetBitmapPos(Frame
) + v2((Frame
&0x6) << 3, 0); }
66 head
* corpse::Behead() { return Deceased
->Behead(); }
67 truth
corpse::CanBeCloned() const { return GetDeceased()->CanBeCloned(); }
68 int corpse::GetAttachedGod() const { return GetDeceased()->GetTorso()->GetAttachedGod(); }
70 v2
ennerhead::GetBitmapPos(int Frame
) const { return Frame
& 16 ? head::GetBitmapPos(Frame
) : head::GetBitmapPos(Frame
) + v2(16, 0); }
72 alpha
blinkdogtorso::GetAlphaA(int Frame
) const { return (Frame
& 31) != 31 ? 255 : 0; }
74 void bodypart::Save(outputfile
& SaveFile
) const
77 SaveFile
<< BitmapPos
<< ColorB
<< ColorC
<< ColorD
<< SpecialFlags
<< WobbleData
<< HP
;
78 SaveFile
<< OwnerDescription
<< BloodMaterial
<< NormalMaterial
<< Scar
<< DamageID
;
81 void bodypart::Load(inputfile
& SaveFile
)
84 SaveFile
>> BitmapPos
>> ColorB
>> ColorC
>> ColorD
>> SpecialFlags
>> WobbleData
>> HP
;
85 SaveFile
>> OwnerDescription
>> BloodMaterial
>> NormalMaterial
>> Scar
>> DamageID
;
88 int bodypart::GetStrengthValue() const
90 if(!UseMaterialAttributes())
91 return sLong(GetStrengthModifier()) * Master
->GetAttribute(ENDURANCE
) / 2000;
93 return sLong(GetStrengthModifier()) * GetMainMaterial()->GetStrengthValue() / 2000;
96 int head::GetTotalResistance(int Type
) const
100 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
103 Resistance
+= GetHelmet()->GetResistance(Type
);
105 if(GetExternalBodyArmor())
106 Resistance
+= GetExternalBodyArmor()->GetResistance(Type
) >> 2;
111 return GetResistance(Type
);
114 int normaltorso::GetTotalResistance(int Type
) const
117 return GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
119 return GetResistance(Type
);
122 int humanoidtorso::GetTotalResistance(int Type
) const
126 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
129 Resistance
+= GetBodyArmor()->GetResistance(Type
);
132 Resistance
+= GetBelt()->GetResistance(Type
);
137 return GetResistance(Type
);
140 int arm::GetTotalResistance(int Type
) const
144 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
146 if(GetExternalBodyArmor())
147 Resistance
+= GetExternalBodyArmor()->GetResistance(Type
) >> 1;
150 Resistance
+= GetGauntlet()->GetResistance(Type
);
155 return GetResistance(Type
);
158 int groin::GetTotalResistance(int Type
) const
162 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
164 if(GetExternalBodyArmor())
165 Resistance
+= GetExternalBodyArmor()->GetResistance(Type
);
167 if(GetHumanoidMaster()->GetBelt())
168 Resistance
+= GetHumanoidMaster()->GetBelt()->GetResistance(Type
);
173 return GetResistance(Type
);
176 int leg::GetTotalResistance(int Type
) const
180 int Resistance
= GetResistance(Type
) + Master
->GetGlobalResistance(Type
);
182 if(GetExternalBodyArmor())
183 Resistance
+= GetExternalBodyArmor()->GetResistance(Type
) >> 1;
186 Resistance
+= GetBoot()->GetResistance(Type
);
191 return GetResistance(Type
);
194 void head::Save(outputfile
& SaveFile
) const
196 bodypart::Save(SaveFile
);
197 SaveFile
<< (int)BaseBiteStrength
;
198 SaveFile
<< HelmetSlot
<< AmuletSlot
;
201 void head::Load(inputfile
& SaveFile
)
203 bodypart::Load(SaveFile
);
204 SaveFile
>> (int&)BaseBiteStrength
;
205 SaveFile
>> HelmetSlot
>> AmuletSlot
;
208 void humanoidtorso::Save(outputfile
& SaveFile
) const
210 bodypart::Save(SaveFile
);
211 SaveFile
<< BodyArmorSlot
<< CloakSlot
<< BeltSlot
;
214 void humanoidtorso::Load(inputfile
& SaveFile
)
216 bodypart::Load(SaveFile
);
217 SaveFile
>> BodyArmorSlot
>> CloakSlot
>> BeltSlot
;
220 void arm::Save(outputfile
& SaveFile
) const
222 bodypart::Save(SaveFile
);
223 SaveFile
<< (int)BaseUnarmedStrength
;
224 SaveFile
<< StrengthExperience
<< DexterityExperience
;
225 SaveFile
<< WieldedSlot
<< GauntletSlot
<< RingSlot
;
226 SaveFile
<< WieldedGraphicData
;
229 void arm::Load(inputfile
& SaveFile
)
231 bodypart::Load(SaveFile
);
232 SaveFile
>> (int&)BaseUnarmedStrength
;
233 SaveFile
>> StrengthExperience
>> DexterityExperience
;
234 SaveFile
>> WieldedSlot
>> GauntletSlot
>> RingSlot
;
235 SaveFile
>> WieldedGraphicData
;
238 void leg::Save(outputfile
& SaveFile
) const
240 bodypart::Save(SaveFile
);
241 SaveFile
<< BaseKickStrength
<< StrengthExperience
<< AgilityExperience
;
242 SaveFile
<< BootSlot
;
245 void leg::Load(inputfile
& SaveFile
)
247 bodypart::Load(SaveFile
);
248 SaveFile
>> BaseKickStrength
>> StrengthExperience
>> AgilityExperience
;
249 SaveFile
>> BootSlot
;
252 truth
bodypart::ReceiveDamage(character
* Damager
, int Damage
, int Type
, int)
256 if(Type
& POISON
&& !IsAlive())
261 if(HP
<= Damage
&& !CanBeSevered(Type
))
262 Damage
= GetHP() - 1;
269 if(Type
& DRAIN
&& IsAlive())
270 for(int c
= 0; c
< Damage
; ++c
)
271 Damager
->HealHitPoint();
273 truth WasBadlyHurt
= IsBadlyHurt();
278 if(DamageTypeCanScar(Type
) && !(RAND_N(25 + 25 * HP
/ MaxHP
)))
279 GenerateScar(Damage
, Type
);
281 if (Master
->IsPlayer()) {
282 if (HP
== 1 && BHP
> 1) {
283 if (IsAlive()) ADD_MESSAGE("Your %s bleeds very badly.", GetBodyPartName().CStr());
284 else ADD_MESSAGE("Your %s is in very bad condition.", GetBodyPartName().CStr());
285 if (Master
->BodyPartIsVital(GetBodyPartIndex())) game::AskForEscPress(CONST_S("Vital bodypart in serious danger!"));
286 } else if (IsBadlyHurt() && !WasBadlyHurt
) {
287 if (IsAlive()) ADD_MESSAGE("Your %s bleeds.", GetBodyPartName().CStr());
288 else ADD_MESSAGE("Your %s is in bad condition.", GetBodyPartName().CStr());
289 if (Master
->BodyPartIsVital(GetBodyPartIndex())) game::AskForEscPress(CONST_S("Vital bodypart in danger!"));
292 SignalPossibleUsabilityChange();
298 truth
bodypart::CanBeSevered(int Type
) const
300 if((HP
== MaxHP
&& HP
!= 1 && !Master
->IsExtraFragile())
301 || (Type
& (POISON
|SOUND
) && GetBodyPartIndex() != TORSO_INDEX
))
304 if(!Master
->BodyPartIsVital(GetBodyPartIndex()) || Master
->IsExtraFragile())
307 bodypart
* Torso
= Master
->GetTorso();
308 return Torso
->HP
!= Torso
->MaxHP
|| Torso
->HP
== 1;
311 double arm::GetUnarmedDamage() const
313 double WeaponStrength
= GetBaseUnarmedStrength() * GetBaseUnarmedStrength();
314 item
* Gauntlet
= GetGauntlet();
317 WeaponStrength
+= Gauntlet
->GetWeaponStrength();
319 double Base
= sqrt(5e-5 * WeaponStrength
);
322 Base
+= Gauntlet
->GetDamageBonus();
324 double Damage
= Base
* sqrt(1e-7 * GetAttribute(ARM_STRENGTH
))
325 * GetHumanoidMaster()->GetCWeaponSkill(UNARMED
)->GetBonus();
330 double arm::GetUnarmedToHitValue() const
332 double BonusMultiplier
= 10.;
333 item
* Gauntlet
= GetGauntlet();
336 BonusMultiplier
+= Gauntlet
->GetTHVBonus();
338 return GetAttribute(DEXTERITY
)
339 * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
))
340 * GetHumanoidMaster()->GetCWeaponSkill(UNARMED
)->GetBonus()
341 * Master
->GetMoveEase()
342 * BonusMultiplier
/ 5000000;
345 sLong
arm::GetUnarmedAPCost() const
347 return sLong(10000000000. / (APBonus(GetAttribute(DEXTERITY
)) * Master
->GetMoveEase() * Master
->GetCWeaponSkill(UNARMED
)->GetBonus()));
350 void arm::CalculateDamage()
357 else if(GetWielded())
358 Damage
= GetWieldedDamage();
359 else if(PairArmAllowsMelee())
360 Damage
= GetUnarmedDamage();
365 void arm::CalculateToHitValue()
371 ToHitValue
= GetWieldedToHitValue();
372 else if(PairArmAllowsMelee())
373 ToHitValue
= GetUnarmedToHitValue();
378 void arm::CalculateAPCost()
384 APCost
= GetWieldedAPCost();
385 else if(PairArmAllowsMelee())
386 APCost
= GetUnarmedAPCost();
393 truth
arm::PairArmAllowsMelee() const
395 const arm
* PairArm
= GetPairArm();
396 return !PairArm
|| !PairArm
->IsUsable() || !PairArm
->GetWielded()
397 || PairArm
->GetWielded()->IsShield(Master
);
400 double arm::GetWieldedDamage() const
402 citem
* Wielded
= GetWielded();
404 if(Wielded
->IsShield(Master
))
407 int HitStrength
= GetAttribute(ARM_STRENGTH
);
408 int Requirement
= Wielded
->GetStrengthRequirement();
410 if(TwoHandWieldIsActive())
412 HitStrength
+= GetPairArm()->GetAttribute(ARM_STRENGTH
);
416 if(HitStrength
> Requirement
)
418 /* I have no idea whether this works. It needs to be checked */
420 return Wielded
->GetBaseDamage() * sqrt(1e-13 * HitStrength
)
421 * GetCurrentSWeaponSkillBonus()
422 * GetHumanoidMaster()->GetCWeaponSkill(Wielded
->GetWeaponCategory())->GetBonus();
428 double arm::GetWieldedToHitValue() const
430 int HitStrength
= GetWieldedHitStrength();
435 citem
* Wielded
= GetWielded();
438 * Min(HitStrength
, 10)
439 * GetHumanoidMaster()->GetCWeaponSkill(Wielded
->GetWeaponCategory())->GetBonus()
440 * GetCurrentSWeaponSkillBonus()
441 * Master
->GetMoveEase()
442 * (10000. / (1000 + Wielded
->GetWeight()) + Wielded
->GetTHVBonus());
443 double ThisToHit
= GetAttribute(DEXTERITY
) * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
));
444 const arm
* PairArm
= GetPairArm();
446 if(PairArm
&& PairArm
->IsUsable())
448 citem
* PairWielded
= PairArm
->GetWielded();
452 if(Wielded
->IsTwoHanded() && !Wielded
->IsShield(Master
))
453 return Base
* (ThisToHit
+ PairArm
->GetAttribute(DEXTERITY
)
454 * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
))) / 2;
456 else if(!Wielded
->IsShield(Master
) && !PairWielded
->IsShield(Master
))
457 return Base
* ThisToHit
/ (1.0 + (500.0 + PairWielded
->GetWeight())
458 / (1000.0 + (Wielded
->GetWeight() << 1)));
461 return Base
* ThisToHit
;
464 sLong
arm::GetWieldedAPCost() const
466 citem
* Wielded
= GetWielded();
468 if(Wielded
->IsShield(Master
))
471 int HitStrength
= GetWieldedHitStrength();
476 return sLong(1 / (1e-14 * APBonus(GetAttribute(DEXTERITY
)) * Master
->GetMoveEase() * GetHumanoidMaster()->GetCWeaponSkill(Wielded
->GetWeaponCategory())->GetBonus() * (GetCurrentSWeaponSkillBonus() * Min(HitStrength
, 10))));
479 void head::CalculateDamage()
484 BiteDamage
= 7.07e-6 * GetBaseBiteStrength() * GetHumanoidMaster()->GetCWeaponSkill(BITE
)->GetBonus();
487 void head::CalculateToHitValue()
492 BiteToHitValue
= Master
->GetAttribute(AGILITY
) * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
)) * GetHumanoidMaster()->GetCWeaponSkill(KICK
)->GetBonus() * Master
->GetMoveEase() / 1000000;
495 void head::CalculateAPCost()
500 BiteAPCost
= Max(sLong(10000000000. / (APBonus(Master
->GetAttribute(AGILITY
)) * Master
->GetMoveEase() * Master
->GetCWeaponSkill(BITE
)->GetBonus())), 100);
503 void leg::CalculateDamage()
508 double WeaponStrength
= GetBaseKickStrength() * GetBaseKickStrength();
509 item
* Boot
= GetBoot();
512 WeaponStrength
+= Boot
->GetWeaponStrength();
514 double Base
= sqrt(5e-5 * WeaponStrength
);
517 Base
+= Boot
->GetDamageBonus();
519 KickDamage
= Base
* sqrt(1e-7 * GetAttribute(LEG_STRENGTH
))
520 * GetHumanoidMaster()->GetCWeaponSkill(KICK
)->GetBonus();
523 void leg::CalculateToHitValue()
528 double BonusMultiplier
= 10.;
529 item
* Boot
= GetBoot();
532 BonusMultiplier
+= Boot
->GetTHVBonus();
534 KickToHitValue
= GetAttribute(AGILITY
)
535 * sqrt(2.5 * Master
->GetAttribute(PERCEPTION
))
536 * GetHumanoidMaster()->GetCWeaponSkill(KICK
)->GetBonus()
537 * Master
->GetMoveEase()
538 * BonusMultiplier
/ 10000000;
541 void leg::CalculateAPCost()
546 KickAPCost
= Max(sLong(20000000000. / (APBonus(GetAttribute(AGILITY
)) * Master
->GetMoveEase() * Master
->GetCWeaponSkill(KICK
)->GetBonus())), 100);
549 humanoid
* bodypart::GetHumanoidMaster() const
551 return static_cast<humanoid
*>(Master
);
554 void corpse::Save(outputfile
& SaveFile
) const
556 item::Save(SaveFile
);
557 SaveFile
<< Deceased
;
560 void corpse::Load(inputfile
& SaveFile
)
562 item::Load(SaveFile
);
563 SaveFile
>> Deceased
;
564 Deceased
->SetMotherEntity(this);
568 void corpse::AddPostFix(festring
& String
, int) const
571 GetDeceased()->AddName(String
, INDEFINITE
);
574 int corpse::GetOfferValue(int Receiver
) const
578 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
580 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
583 OfferValue
+= BodyPart
->GetOfferValue(Receiver
);
589 double corpse::GetWeaponStrength() const
591 return GetFormModifier() * GetDeceased()->GetTorso()->GetMainMaterial()->GetStrengthValue() * sqrt(GetDeceased()->GetTorso()->GetMainMaterial()->GetWeight());
594 truth
corpse::CanBeEatenByAI(ccharacter
* Eater
) const
596 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
598 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
600 if(BodyPart
&& !BodyPart
->CanBeEatenByAI(Eater
))
607 int corpse::GetStrengthValue() const
609 return sLong(GetStrengthModifier()) * GetDeceased()->GetTorso()->GetMainMaterial()->GetStrengthValue() / 2000;
617 col16
corpse::GetMaterialColorA(int) const
619 return GetDeceased()->GetTorso()->GetMainMaterial()->GetColor();
622 alpha
corpse::GetAlphaA(int) const
624 return GetDeceased()->GetTorso()->GetMainMaterial()->GetAlpha();
627 col16
corpse::GetMaterialColorB(int) const
629 torso
* Torso
= GetDeceased()->GetTorso();
630 return Torso
->IsAlive() ? material::GetDataBase(GetDeceased()->GetBloodMaterial())->Color
: Torso
->GetMainMaterial()->GetColor();
633 alpha
corpse::GetAlphaB(int) const
635 torso
* Torso
= GetDeceased()->GetTorso();
636 return Torso
->IsAlive() ? 175 : Torso
->GetMainMaterial()->GetAlpha();
639 int corpse::GetSparkleFlags() const
641 torso
* Torso
= GetDeceased()->GetTorso();
642 material
* Material
= Torso
->GetMainMaterial();
643 return Material
->IsSparkling() ? SPARKLING_A
|(!Torso
->IsAlive() ? SPARKLING_B
: 0) : 0;
646 v2
corpse::GetBitmapPos(int) const
648 if(GetDeceased()->GetSize() < 50)
650 else if(GetDeceased()->GetSize() < 150)
656 int corpse::GetSize() const
658 return GetDeceased()->GetSize();
661 void corpse::SetDeceased(character
* What
)
664 Deceased
->SetMotherEntity(this);
665 SignalVolumeAndWeightChange();
666 SignalEmitationIncrease(Deceased
->GetEmitation());
671 void head::DropEquipment(stack
* Stack
)
676 GetHelmet()->MoveTo(Stack
);
679 GetAmulet()->MoveTo(Stack
);
684 GetSlot()->AddFriendItem(GetHelmet());
687 GetSlot()->AddFriendItem(GetAmulet());
691 void humanoidtorso::DropEquipment(stack
* Stack
)
696 GetBodyArmor()->MoveTo(Stack
);
699 GetCloak()->MoveTo(Stack
);
702 GetBelt()->MoveTo(Stack
);
707 GetSlot()->AddFriendItem(GetBodyArmor());
710 GetSlot()->AddFriendItem(GetCloak());
713 GetSlot()->AddFriendItem(GetBelt());
717 void arm::DropEquipment(stack
* Stack
)
722 GetWielded()->MoveTo(Stack
);
725 GetGauntlet()->MoveTo(Stack
);
728 GetRing()->MoveTo(Stack
);
733 GetSlot()->AddFriendItem(GetWielded());
736 GetSlot()->AddFriendItem(GetGauntlet());
739 GetSlot()->AddFriendItem(GetRing());
743 void leg::DropEquipment(stack
* Stack
)
748 GetBoot()->MoveTo(Stack
);
753 GetSlot()->AddFriendItem(GetBoot());
763 humanoidtorso::~humanoidtorso()
765 delete GetBodyArmor();
773 delete GetGauntlet();
782 truth
corpse::IsDestroyable(ccharacter
* Char
) const
784 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
786 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
788 if(BodyPart
&& !BodyPart
->IsDestroyable(Char
))
795 sLong
corpse::GetTruePrice() const
799 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
801 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
804 Price
+= BodyPart
->GetTruePrice();
810 material
* corpse::GetMaterial(int I
) const
812 return GetDeceased()->GetTorso()->GetMaterial(I
);
815 int bodypart::GetSparkleFlags() const
817 return (GetMainMaterial()->SkinColorIsSparkling() ? SPARKLING_A
: 0)
818 | (Flags
>> BODYPART_SPARKLE_SHIFT
& (SPARKLING_B
|SPARKLING_C
|SPARKLING_D
));
821 truth
corpse::RaiseTheDead(character
* Summoner
)
823 if(Summoner
&& Summoner
->IsPlayer())
824 game::DoEvilDeed(50);
826 GetDeceased()->Enable();
828 if(GetDeceased()->TryToRiseFromTheDead())
832 GetDeceased()->SetMotherEntity(0);
834 if(Summoner
&& GetDeceased()->IsCharmable() && !GetDeceased()->IsPlayer())
835 GetDeceased()->ChangeTeam(Summoner
->GetTeam());
837 GetDeceased()->PutToOrNear(Pos
);
838 GetDeceased()->SignalStepFrom(0);
845 GetDeceased()->Disable();
852 HelmetSlot
.Init(this, HELMET_INDEX
);
853 AmuletSlot
.Init(this, AMULET_INDEX
);
856 humanoidtorso::humanoidtorso()
858 BodyArmorSlot
.Init(this, BODY_ARMOR_INDEX
);
859 CloakSlot
.Init(this, CLOAK_INDEX
);
860 BeltSlot
.Init(this, BELT_INDEX
);
865 WieldedSlot
.Init(this, RIGHT_WIELDED_INDEX
);
866 GauntletSlot
.Init(this, RIGHT_GAUNTLET_INDEX
);
867 RingSlot
.Init(this, RIGHT_RING_INDEX
);
872 WieldedSlot
.Init(this, LEFT_WIELDED_INDEX
);
873 GauntletSlot
.Init(this, LEFT_GAUNTLET_INDEX
);
874 RingSlot
.Init(this, LEFT_RING_INDEX
);
879 BootSlot
.Init(this, RIGHT_BOOT_INDEX
);
884 BootSlot
.Init(this, LEFT_BOOT_INDEX
);
887 void arm::Hit(character
* Enemy
, v2 HitPos
, int Direction
, int Flags
)
889 sLong StrExp
= 50, DexExp
= 50;
891 item
* Wielded
= GetWielded();
895 sLong Weight
= Wielded
->GetWeight();
896 StrExp
= Limit(15 * Weight
/ 200, 75, 300);
897 DexExp
= Weight
? Limit(75000 / Weight
, 75, 300) : 300;
898 THW
= TwoHandWieldIsActive();
901 switch(Enemy
->TakeHit(Master
, Wielded
? Wielded
: GetGauntlet(), this, HitPos
, GetTypeDamage(Enemy
), GetToHitValue(), RAND() % 26 - RAND() % 26, Wielded
? WEAPON_ATTACK
: UNARMED_ATTACK
, Direction
, !(RAND() % Master
->GetCriticalModifier()), Flags
& SADIST_HIT
))
907 EditExperience(ARM_STRENGTH
, StrExp
, 1 << 9);
909 if(THW
&& GetPairArm())
910 GetPairArm()->EditExperience(ARM_STRENGTH
, StrExp
, 1 << 9);
913 EditExperience(DEXTERITY
, DexExp
, 1 << 9);
915 if(THW
&& GetPairArm())
916 GetPairArm()->EditExperience(DEXTERITY
, DexExp
, 1 << 9);
920 int arm::GetAttribute(int Identifier
, truth AllowBonus
) const
922 if(Identifier
== ARM_STRENGTH
)
924 int Base
= !UseMaterialAttributes()
925 ? int(StrengthExperience
* EXP_DIVISOR
)
926 : GetMainMaterial()->GetStrengthValue();
929 Base
+= StrengthBonus
;
931 return Max(!IsBadlyHurt() || !AllowBonus
? Base
: Base
/ 3, 1);
933 else if(Identifier
== DEXTERITY
)
935 int Base
= !UseMaterialAttributes()
936 ? int(DexterityExperience
* EXP_DIVISOR
)
937 : GetMainMaterial()->GetFlexibility() << 2;
940 Base
+= DexterityBonus
;
942 return Max(IsUsable() || !AllowBonus
? Base
: Base
/ 3, 1);
946 ABORT("Illegal arm attribute %d request!", Identifier
);
951 truth
arm::EditAttribute(int Identifier
, int Value
)
956 if(Identifier
== ARM_STRENGTH
)
958 if(!UseMaterialAttributes()
959 && Master
->RawEditAttribute(StrengthExperience
, Value
))
961 Master
->CalculateBattleInfo();
963 if(Master
->IsPlayerKind())
969 else if(Identifier
== DEXTERITY
)
970 if(!UseMaterialAttributes()
971 && Master
->RawEditAttribute(DexterityExperience
, Value
))
973 Master
->CalculateBattleInfo();
980 void arm::EditExperience(int Identifier
, double Value
, double Speed
)
985 if(Identifier
== ARM_STRENGTH
)
987 if(!UseMaterialAttributes())
989 int Change
= Master
->RawEditExperience(StrengthExperience
,
990 Master
->GetNaturalExperience(ARM_STRENGTH
),
995 cchar
* Adj
= Change
> 0 ? "stronger" : "weaker";
997 if(Master
->IsPlayer())
998 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
999 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
1000 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
1002 Master
->CalculateBattleInfo();
1004 if(Master
->IsPlayerKind())
1009 else if(Identifier
== DEXTERITY
)
1011 if(!UseMaterialAttributes())
1013 int Change
= Master
->RawEditExperience(DexterityExperience
,
1014 Master
->GetNaturalExperience(DEXTERITY
),
1019 cchar
* Adj
= Change
> 0 ? "quite dextrous" : "clumsy";
1021 if(Master
->IsPlayer())
1022 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
1023 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
1024 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
1026 Master
->CalculateBattleInfo();
1031 ABORT("Illegal arm attribute %d experience edit request!", Identifier
);
1034 int leg::GetAttribute(int Identifier
, truth AllowBonus
) const
1036 if(Identifier
== LEG_STRENGTH
)
1038 int Base
= !UseMaterialAttributes()
1039 ? int(StrengthExperience
* EXP_DIVISOR
)
1040 : GetMainMaterial()->GetStrengthValue();
1043 Base
+= StrengthBonus
;
1045 return Max(!IsBadlyHurt() || !AllowBonus
? Base
: Base
/ 3, 1);
1047 else if(Identifier
== AGILITY
)
1049 int Base
= !UseMaterialAttributes()
1050 ? int(AgilityExperience
* EXP_DIVISOR
)
1051 : GetMainMaterial()->GetFlexibility() << 2;
1054 Base
+= AgilityBonus
;
1056 return Max(IsUsable() || !AllowBonus
? Base
: Base
/ 3, 1);
1060 ABORT("Illegal leg attribute %d request!", Identifier
);
1065 truth
leg::EditAttribute(int Identifier
, int Value
)
1070 if(Identifier
== LEG_STRENGTH
)
1072 if(!UseMaterialAttributes()
1073 && Master
->RawEditAttribute(StrengthExperience
, Value
))
1075 Master
->CalculateBurdenState();
1076 Master
->CalculateBattleInfo();
1080 else if(Identifier
== AGILITY
)
1081 if(!UseMaterialAttributes()
1082 && Master
->RawEditAttribute(AgilityExperience
, Value
))
1084 Master
->CalculateBattleInfo();
1091 void leg::EditExperience(int Identifier
, double Value
, double Speed
)
1096 if(Identifier
== LEG_STRENGTH
)
1098 if(!UseMaterialAttributes())
1100 int Change
= Master
->RawEditExperience(StrengthExperience
,
1101 Master
->GetNaturalExperience(LEG_STRENGTH
),
1106 cchar
* Adj
= Change
> 0 ? "stronger" : "weaker";
1108 if(Master
->IsPlayer())
1109 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
1110 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
1111 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
1113 Master
->CalculateBurdenState();
1114 Master
->CalculateBattleInfo();
1118 else if(Identifier
== AGILITY
)
1120 if(!UseMaterialAttributes())
1122 int Change
= Master
->RawEditExperience(AgilityExperience
,
1123 Master
->GetNaturalExperience(AGILITY
),
1128 cchar
* Adj
= Change
> 0 ? "very agile" : "slower";
1130 if(Master
->IsPlayer())
1131 ADD_MESSAGE("Your %s feels %s!", GetBodyPartName().CStr(), Adj
);
1132 else if(Master
->IsPet() && Master
->CanBeSeenByPlayer())
1133 ADD_MESSAGE("Suddenly %s looks %s.", Master
->CHAR_NAME(DEFINITE
), Adj
);
1135 Master
->CalculateBattleInfo();
1140 ABORT("Illegal leg attribute %d experience edit request!", Identifier
);
1143 void head::InitSpecialAttributes()
1145 BaseBiteStrength
= Master
->GetBaseBiteStrength();
1148 void arm::InitSpecialAttributes()
1150 if(!Master
->IsHuman() || Master
->IsInitializing())
1152 StrengthExperience
= Master
->GetNaturalExperience(ARM_STRENGTH
);
1153 DexterityExperience
= Master
->GetNaturalExperience(DEXTERITY
);
1157 StrengthExperience
= game::GetAveragePlayerArmStrengthExperience();
1158 DexterityExperience
= game::GetAveragePlayerDexterityExperience();
1161 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
1162 LimitRef(DexterityExperience
, MIN_EXP
, MAX_EXP
);
1163 BaseUnarmedStrength
= Master
->GetBaseUnarmedStrength();
1166 void leg::InitSpecialAttributes()
1168 if(!Master
->IsHuman() || Master
->IsInitializing())
1170 StrengthExperience
= Master
->GetNaturalExperience(LEG_STRENGTH
);
1171 AgilityExperience
= Master
->GetNaturalExperience(AGILITY
);
1175 StrengthExperience
= game::GetAveragePlayerLegStrengthExperience();
1176 AgilityExperience
= game::GetAveragePlayerAgilityExperience();
1179 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
1180 LimitRef(AgilityExperience
, MIN_EXP
, MAX_EXP
);
1181 BaseKickStrength
= Master
->GetBaseKickStrength();
1184 void bodypart::SignalEquipmentAdd(gearslot
* Slot
)
1187 Master
->SignalEquipmentAdd(Slot
->GetEquipmentIndex());
1190 void bodypart::SignalEquipmentRemoval(gearslot
* Slot
, citem
* Item
)
1193 Master
->SignalEquipmentRemoval(Slot
->GetEquipmentIndex(), Item
);
1196 void bodypart::Mutate()
1198 GetMainMaterial()->SetVolume(sLong(GetVolume() * (1.5 - (RAND() & 1023) / 1023.)));
1204 StrengthExperience
= StrengthExperience
* (1.5 - (RAND() & 1023) / 1023.);
1205 DexterityExperience
= DexterityExperience
* (1.5 - (RAND() & 1023) / 1023.);
1206 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
1207 LimitRef(DexterityExperience
, MIN_EXP
, MAX_EXP
);
1213 StrengthExperience
= StrengthExperience
* (1.5 - (RAND() & 1023) / 1023.);
1214 AgilityExperience
= AgilityExperience
* (1.5 - (RAND() & 1023) / 1023.);
1215 LimitRef(StrengthExperience
, MIN_EXP
, MAX_EXP
);
1216 LimitRef(AgilityExperience
, MIN_EXP
, MAX_EXP
);
1219 arm
* rightarm::GetPairArm() const
1221 return GetHumanoidMaster() ? GetHumanoidMaster()->GetLeftArm() : 0;
1224 arm
* leftarm::GetPairArm() const
1226 return GetHumanoidMaster() ? GetHumanoidMaster()->GetRightArm() : 0;
1229 sweaponskill
** rightarm::GetCurrentSWeaponSkill() const
1231 return &GetHumanoidMaster()->CurrentRightSWeaponSkill
;
1234 sweaponskill
** leftarm::GetCurrentSWeaponSkill() const
1236 return &GetHumanoidMaster()->CurrentLeftSWeaponSkill
;
1239 alpha
bodypart::GetMaxAlpha() const
1241 if(Master
&& Master
->StateIsActivated(INVISIBLE
))
1247 void bodypart::AddPostFix(festring
& String
, int) const
1249 if(!OwnerDescription
.IsEmpty())
1250 String
<< ' ' << OwnerDescription
;
1253 void corpse::CalculateVolumeAndWeight()
1255 Volume
= Deceased
->GetVolume();
1256 Weight
= Deceased
->GetWeight();
1259 item
* head::GetEquipment(int I
) const
1263 case 0: return GetHelmet();
1264 case 1: return GetAmulet();
1270 item
* humanoidtorso::GetEquipment(int I
) const
1274 case 0: return GetBodyArmor();
1275 case 1: return GetCloak();
1276 case 2: return GetBelt();
1282 item
* arm::GetEquipment(int I
) const
1286 case 0: return GetWielded();
1287 case 1: return GetGauntlet();
1288 case 2: return GetRing();
1294 item
* leg::GetEquipment(int I
) const
1296 return !I
? GetBoot() : 0;
1299 void bodypart::CalculateVolumeAndWeight()
1301 item::CalculateVolumeAndWeight();
1303 BodyPartVolume
= Volume
;
1305 for(int c
= 0; c
< GetEquipments(); ++c
)
1307 item
* Equipment
= GetEquipment(c
);
1311 Volume
+= Equipment
->GetVolume();
1312 CarriedWeight
+= Equipment
->GetWeight();
1316 Weight
+= CarriedWeight
;
1319 void corpse::CalculateEmitation()
1321 Emitation
= Deceased
->GetEmitation();
1324 void bodypart::CalculateEmitation()
1326 item::CalculateEmitation();
1328 for(int c
= 0; c
< GetEquipments(); ++c
)
1330 item
* Equipment
= GetEquipment(c
);
1333 game::CombineLights(Emitation
, Equipment
->GetEmitation());
1337 void bodypart::CalculateMaxHP(feuLong Flags
)
1339 int HPDelta
= MaxHP
- HP
/*k8, OldMaxHP = MaxHP*/;
1344 if(!UseMaterialAttributes())
1346 sLong Endurance
= Master
->GetAttribute(ENDURANCE
);
1347 double DoubleHP
= GetBodyPartVolume() * Endurance
* Endurance
/ 200000;
1349 for(unsigned int c
= 0; c
< Scar
.size(); ++c
)
1350 DoubleHP
*= (100. - Scar
[c
].Severity
* 4) / 100;
1352 MaxHP
= int(DoubleHP
);
1356 sLong SV
= GetMainMaterial()->GetStrengthValue();
1357 MaxHP
= (GetBodyPartVolume() * SV
>> 4) * SV
/ 250000;
1363 if(Flags
& MAY_CHANGE_HPS
)
1365 if(MaxHP
- HPDelta
> 1)
1366 HP
= MaxHP
- HPDelta
;
1375 if(Flags
& CHECK_USABILITY
)
1376 SignalPossibleUsabilityChange();
1380 void bodypart::SignalVolumeAndWeightChange()
1382 item::SignalVolumeAndWeightChange();
1384 if(Master
&& !Master
->IsInitializing())
1387 Master
->CalculateHP();
1388 Master
->CalculateMaxHP();
1389 Master
->SignalBodyPartVolumeAndWeightChange();
1390 square
* SquareUnder
= GetSquareUnder();
1392 if(UpdateArmorPictures() && SquareUnder
)
1393 SquareUnder
->SendNewDrawRequest();
1400 damageid& D = DamageID.back();
1405 void bodypart::SetHP(int What
)
1411 Master
->CalculateHP();
1412 SignalPossibleUsabilityChange();
1416 void bodypart::EditHP(int SrcID
, int What
)
1421 RemoveDamageIDs(-What
);
1423 AddDamageID(SrcID
, What
);
1427 Master
->CalculateHP();
1428 SignalPossibleUsabilityChange();
1432 void arm::SignalVolumeAndWeightChange()
1434 bodypart::SignalVolumeAndWeightChange();
1436 if(Master
&& !Master
->IsInitializing())
1438 GetHumanoidMaster()->EnsureCurrentSWeaponSkillIsCorrect(*GetCurrentSWeaponSkill(), GetWielded());
1439 CalculateAttributeBonuses();
1440 CalculateAttackInfo();
1441 UpdateWieldedPicture();
1443 if(GetSquareUnder())
1444 GetSquareUnder()->SendNewDrawRequest();
1448 void leg::SignalVolumeAndWeightChange()
1450 bodypart::SignalVolumeAndWeightChange();
1452 if(Master
&& !Master
->IsInitializing())
1454 CalculateAttributeBonuses();
1455 CalculateAttackInfo();
1459 void humanoidtorso::SignalVolumeAndWeightChange()
1461 bodypart::SignalVolumeAndWeightChange();
1463 if(Master
&& !Master
->IsInitializing())
1465 humanoid
* HumanoidMaster
= GetHumanoidMaster();
1467 if(HumanoidMaster
->GetRightArm())
1468 HumanoidMaster
->GetRightArm()->CalculateAttributeBonuses();
1470 if(HumanoidMaster
->GetLeftArm())
1471 HumanoidMaster
->GetLeftArm()->CalculateAttributeBonuses();
1473 if(HumanoidMaster
->GetRightLeg())
1474 HumanoidMaster
->GetRightLeg()->CalculateAttributeBonuses();
1476 if(HumanoidMaster
->GetLeftLeg())
1477 HumanoidMaster
->GetLeftLeg()->CalculateAttributeBonuses();
1481 void bodypart::CalculateAttackInfo()
1484 CalculateToHitValue();
1488 truth
arm::TwoHandWieldIsActive() const
1490 citem
* Wielded
= GetWielded();
1492 if(Wielded
->IsTwoHanded() && !Wielded
->IsShield(Master
))
1494 arm
* PairArm
= GetPairArm();
1495 return PairArm
&& PairArm
->IsUsable() && !PairArm
->GetWielded();
1501 double bodypart::GetTimeToDie(int Damage
, double ToHitValue
, double DodgeValue
, truth AttackIsBlockable
, truth UseMaxHP
) const
1504 int TotalResistance
= GetTotalResistance(PHYSICAL_DAMAGE
);
1505 int Damage3
= (Damage
<< 1) + Damage
;
1506 int Damage5
= (Damage
<< 2) + Damage
;
1507 int TrueDamage
= (19 * (Max((Damage3
>> 2) - TotalResistance
, 0)
1508 + Max((Damage5
>> 2) + 1 - (TotalResistance
>> 1), 0))
1509 + (Max(((Damage3
+ (Damage3
>> 1)) >> 2) - TotalResistance
, 0)
1510 + Max(((Damage5
+ (Damage5
>> 1)) >> 2) + 3 - (TotalResistance
>> 1), 0))) / 40;
1512 int HP
= UseMaxHP
? GetMaxHP() : GetHP();
1516 double AverageDamage
;
1518 if(AttackIsBlockable
)
1521 Master
->CreateBlockPossibilityVector(Block
, ToHitValue
);
1525 double ChanceForNoBlock
= 1.0;
1528 for(uInt c
= 0; c
< Block
.size(); ++c
)
1530 ChanceForNoBlock
-= Block
[c
].first
;
1532 if(TrueDamage
- Block
[c
].second
> 0)
1533 AverageDamage
+= Block
[c
].first
* (TrueDamage
- Block
[c
].second
);
1536 AverageDamage
+= ChanceForNoBlock
* TrueDamage
;
1539 AverageDamage
= TrueDamage
;
1542 AverageDamage
= TrueDamage
;
1544 Durability
= HP
/ (AverageDamage
* GetRoughChanceToHit(ToHitValue
, DodgeValue
));
1549 if(Durability
> 1000)
1558 double bodypart::GetRoughChanceToHit(double ToHitValue
, double DodgeValue
) const
1560 return GLOBAL_WEAK_BODYPART_HIT_MODIFIER
* ToHitValue
* GetBodyPartVolume() / ((DodgeValue
/ ToHitValue
+ 1) * DodgeValue
* Master
->GetBodyVolume() * 100);
1563 double torso::GetRoughChanceToHit(double ToHitValue
, double DodgeValue
) const
1565 return 1 / (DodgeValue
/ ToHitValue
+ 1);
1568 void bodypart::RandomizePosition()
1570 SpecialFlags
|= 1 + RAND() % 7;
1574 double arm::GetBlockChance(double EnemyToHitValue
) const
1576 citem
* Wielded
= GetWielded();
1577 return Wielded
? Min(1.0 / (1 + EnemyToHitValue
/ (GetToHitValue() * Wielded
->GetBlockModifier()) * 10000), 1.0) : 0;
1580 int arm::GetBlockCapability() const
1582 citem
* Wielded
= GetWielded();
1587 int HitStrength
= GetWieldedHitStrength();
1589 if(HitStrength
<= 0)
1592 return Min(HitStrength
, 10) * Wielded
->GetStrengthValue() * GetHumanoidMaster()->GetCWeaponSkill(Wielded
->GetWeaponCategory())->GetBonus() * (*GetCurrentSWeaponSkill())->GetBonus() / 10000000;
1595 void arm::WieldedSkillHit(int Hits
)
1597 item
* Wielded
= GetWielded();
1599 if(Master
->GetCWeaponSkill(Wielded
->GetWeaponCategory())->AddHit(Hits
))
1601 CalculateAttackInfo();
1603 if(Master
->IsPlayer())
1605 int Category
= Wielded
->GetWeaponCategory();
1606 GetHumanoidMaster()->GetCWeaponSkill(Category
)->AddLevelUpMessage(Category
);
1610 if((*GetCurrentSWeaponSkill())->AddHit(Hits
))
1612 CalculateAttackInfo();
1614 if(Master
->IsPlayer())
1615 (*GetCurrentSWeaponSkill())->AddLevelUpMessage(Wielded
->CHAR_NAME(UNARTICLED
));
1619 head::head(const head
& Head
) : mybase(Head
), BaseBiteStrength(Head
.BaseBiteStrength
)
1621 HelmetSlot
.Init(this, HELMET_INDEX
);
1622 AmuletSlot
.Init(this, AMULET_INDEX
);
1625 humanoidtorso::humanoidtorso(const humanoidtorso
& Torso
) : mybase(Torso
)
1627 BodyArmorSlot
.Init(this, BODY_ARMOR_INDEX
);
1628 CloakSlot
.Init(this, CLOAK_INDEX
);
1629 BeltSlot
.Init(this, BELT_INDEX
);
1632 arm::arm(const arm
& Arm
) : mybase(Arm
), StrengthExperience(Arm
.StrengthExperience
), DexterityExperience(Arm
.DexterityExperience
), BaseUnarmedStrength(Arm
.BaseUnarmedStrength
)
1636 rightarm::rightarm(const rightarm
& Arm
) : mybase(Arm
)
1638 WieldedSlot
.Init(this, RIGHT_WIELDED_INDEX
);
1639 GauntletSlot
.Init(this, RIGHT_GAUNTLET_INDEX
);
1640 RingSlot
.Init(this, RIGHT_RING_INDEX
);
1643 leftarm::leftarm(const leftarm
& Arm
) : mybase(Arm
)
1645 WieldedSlot
.Init(this, LEFT_WIELDED_INDEX
);
1646 GauntletSlot
.Init(this, LEFT_GAUNTLET_INDEX
);
1647 RingSlot
.Init(this, LEFT_RING_INDEX
);
1650 leg::leg(const leg
& Leg
) : mybase(Leg
), StrengthExperience(Leg
.StrengthExperience
), AgilityExperience(Leg
.AgilityExperience
), BaseKickStrength(Leg
.BaseKickStrength
)
1654 rightleg::rightleg(const rightleg
& Leg
) : mybase(Leg
)
1656 BootSlot
.Init(this, RIGHT_BOOT_INDEX
);
1659 leftleg::leftleg(const leftleg
& Leg
) : mybase(Leg
)
1661 BootSlot
.Init(this, LEFT_BOOT_INDEX
);
1664 corpse::corpse(const corpse
& Corpse
) : mybase(Corpse
)
1666 Deceased
= Corpse
.Deceased
->Duplicate();
1667 Deceased
->SetMotherEntity(this);
1670 void bodypart::SignalSpoil(material
* Material
)
1673 Master
->SignalSpoil();
1675 item::SignalSpoil(Material
);
1678 void corpse::SignalSpoil(material
*)
1680 GetDeceased()->Disappear(this, "spoil", &item::IsVeryCloseToSpoiling
);
1683 void corpse::SignalDisappearance()
1685 GetDeceased()->Disappear(this, "disappear", &item::IsVeryCloseToDisappearance
);
1688 truth
bodypart::CanBePiledWith(citem
* Item
, ccharacter
* Viewer
) const
1690 return item::CanBePiledWith(Item
, Viewer
)
1691 && OwnerDescription
== static_cast<const bodypart
*>(Item
)->OwnerDescription
;
1694 truth
corpse::CanBePiledWith(citem
* Item
, ccharacter
* Viewer
) const
1696 if(GetType() != Item
->GetType()
1697 || GetConfig() != Item
->GetConfig()
1698 || GetWeight() != Item
->GetWeight()
1699 || Viewer
->GetCWeaponSkillLevel(this) != Viewer
->GetCWeaponSkillLevel(Item
)
1700 || Viewer
->GetSWeaponSkillLevel(this) != Viewer
->GetSWeaponSkillLevel(Item
))
1703 const corpse
* Corpse
= static_cast<const corpse
*>(Item
);
1705 if(Deceased
->GetBodyParts() != Corpse
->Deceased
->GetBodyParts())
1708 for(int c
= 0; c
< Deceased
->GetBodyParts(); ++c
)
1710 bodypart
* BodyPart1
= Deceased
->GetBodyPart(c
);
1711 bodypart
* BodyPart2
= Corpse
->Deceased
->GetBodyPart(c
);
1713 if(!BodyPart1
&& !BodyPart2
)
1716 if(!BodyPart1
|| !BodyPart2
|| !BodyPart1
->CanBePiledWith(BodyPart2
, Viewer
))
1720 if(Deceased
->GetName(UNARTICLED
) != Corpse
->Deceased
->GetName(UNARTICLED
))
1730 if(HP
< MaxHP
&& ++SpillBloodCounter
>= 4)
1732 if(Master
->IsEnabled())
1734 if(IsBadlyHurt() && !Master
->IsPolymorphed() && !(RAND() & 3))
1737 else if(!Master
->IsPolymorphed() && !(RAND() & 3))
1740 HP
+= Max(((MaxHP
- HP
) >> 2), 1);
1743 SpillBloodCounter
= 0;
1746 if(Master
->AllowSpoil() || !Master
->IsEnabled())
1747 MainMaterial
->Be(ItemFlags
);
1749 if (Exists() && LifeExpectancy
) {
1750 if (LifeExpectancy
== 1) Master
->SignalDisappearance(); else --LifeExpectancy
;
1755 if(HP
< MaxHP
&& ++SpillBloodCounter
>= 4)
1760 HP
+= Max(((MaxHP
- HP
) >> 2), 1);
1763 SpillBloodCounter
= 0;
1770 void bodypart::SpillBlood(int HowMuch
, v2 Pos
)
1772 if(HowMuch
&& (!Master
|| Master
->SpillsBlood()) && (IsAlive() || MainMaterial
->IsLiquid()) && !game::IsInWilderness())
1773 GetNearLSquare(Pos
)->SpillFluid(0, CreateBlood(sLong(HowMuch
* sqrt(BodyPartVolume
) / 2)), false, false);
1776 void bodypart::SpillBlood(int HowMuch
)
1778 if(HowMuch
&& (!Master
|| Master
->SpillsBlood()) && (IsAlive() || MainMaterial
->IsLiquid()) && !game::IsInWilderness())
1779 for(int c
= 0; c
< GetSquaresUnder(); ++c
)
1780 if(GetLSquareUnder(c
))
1781 GetLSquareUnder(c
)->SpillFluid(0, CreateBlood(sLong(HowMuch
* sqrt(BodyPartVolume
) / 2)), false, false);
1784 void bodypart::SignalEnchantmentChange()
1786 if(Master
&& !Master
->IsInitializing())
1788 Master
->CalculateAttributeBonuses();
1789 Master
->CalculateBattleInfo();
1793 void arm::SignalEquipmentAdd(gearslot
* Slot
)
1795 int EquipmentIndex
= Slot
->GetEquipmentIndex();
1797 if(Master
&& !Master
->IsInitializing())
1799 item
* Equipment
= Slot
->GetItem();
1801 if(Equipment
->IsInCorrectSlot(EquipmentIndex
))
1802 ApplyEquipmentAttributeBonuses(Equipment
);
1804 if(EquipmentIndex
== RIGHT_GAUNTLET_INDEX
|| EquipmentIndex
== LEFT_GAUNTLET_INDEX
)
1805 ApplyDexterityPenalty(Equipment
);
1807 if(EquipmentIndex
== RIGHT_WIELDED_INDEX
|| EquipmentIndex
== LEFT_WIELDED_INDEX
)
1809 UpdateWieldedPicture();
1810 GetSquareUnder()->SendNewDrawRequest();
1815 Master
->SignalEquipmentAdd(EquipmentIndex
);
1818 void arm::SignalEquipmentRemoval(gearslot
* Slot
, citem
* Item
)
1820 int EquipmentIndex
= Slot
->GetEquipmentIndex();
1822 if(Master
&& !Master
->IsInitializing())
1823 if(EquipmentIndex
== RIGHT_WIELDED_INDEX
|| EquipmentIndex
== LEFT_WIELDED_INDEX
)
1825 UpdateWieldedPicture();
1826 square
* Square
= GetSquareUnder();
1829 Square
->SendNewDrawRequest();
1833 Master
->SignalEquipmentRemoval(EquipmentIndex
, Item
);
1836 void leg::SignalEquipmentAdd(gearslot
* Slot
)
1838 int EquipmentIndex
= Slot
->GetEquipmentIndex();
1840 if(Master
&& !Master
->IsInitializing())
1842 item
* Equipment
= Slot
->GetItem();
1844 if(Equipment
->IsInCorrectSlot(EquipmentIndex
))
1845 ApplyEquipmentAttributeBonuses(Equipment
);
1847 if(EquipmentIndex
== RIGHT_BOOT_INDEX
|| EquipmentIndex
== LEFT_BOOT_INDEX
)
1848 ApplyAgilityPenalty(Equipment
);
1852 Master
->SignalEquipmentAdd(EquipmentIndex
);
1855 void arm::ApplyEquipmentAttributeBonuses(item
* Item
)
1857 if(Item
->AffectsArmStrength())
1858 StrengthBonus
+= Item
->GetEnchantment();
1860 if(Item
->AffectsDexterity())
1861 DexterityBonus
+= Item
->GetEnchantment();
1864 void leg::ApplyEquipmentAttributeBonuses(item
* Item
)
1866 if(Item
->AffectsLegStrength())
1868 StrengthBonus
+= Item
->GetEnchantment();
1871 Master
->CalculateBurdenState();
1874 if(Item
->AffectsAgility())
1875 AgilityBonus
+= Item
->GetEnchantment();
1878 void arm::CalculateAttributeBonuses()
1880 StrengthBonus
= DexterityBonus
= 0;
1882 for(int c
= 0; c
< GetEquipments(); ++c
)
1884 item
* Equipment
= GetEquipment(c
);
1886 if(Equipment
&& Equipment
->IsInCorrectSlot())
1887 ApplyEquipmentAttributeBonuses(Equipment
);
1890 ApplyDexterityPenalty(GetGauntlet());
1894 ApplyDexterityPenalty(GetExternalCloak());
1895 ApplyDexterityPenalty(GetExternalBodyArmor());
1897 ApplyStrengthBonus(GetExternalHelmet());
1898 ApplyStrengthBonus(GetExternalCloak());
1899 ApplyStrengthBonus(GetExternalBodyArmor());
1900 ApplyStrengthBonus(GetExternalBelt());
1901 ApplyDexterityBonus(GetExternalHelmet());
1902 ApplyDexterityBonus(GetExternalCloak());
1903 ApplyDexterityBonus(GetExternalBodyArmor());
1904 ApplyDexterityBonus(GetExternalBelt());
1907 if(!UseMaterialAttributes())
1909 StrengthBonus
-= CalculateScarAttributePenalty(GetAttribute(ARM_STRENGTH
, false));
1910 DexterityBonus
-= CalculateScarAttributePenalty(GetAttribute(DEXTERITY
, false)) ;
1914 void leg::CalculateAttributeBonuses()
1916 StrengthBonus
= AgilityBonus
= 0;
1918 for(int c
= 0; c
< GetEquipments(); ++c
)
1920 item
* Equipment
= GetEquipment(c
);
1922 if(Equipment
&& Equipment
->IsInCorrectSlot())
1923 ApplyEquipmentAttributeBonuses(Equipment
);
1926 ApplyAgilityPenalty(GetBoot());
1930 ApplyAgilityPenalty(GetExternalCloak());
1931 ApplyAgilityPenalty(GetExternalBodyArmor());
1933 ApplyStrengthBonus(GetExternalHelmet());
1934 ApplyStrengthBonus(GetExternalCloak());
1935 ApplyStrengthBonus(GetExternalBodyArmor());
1936 ApplyStrengthBonus(GetExternalBelt());
1937 ApplyAgilityBonus(GetExternalHelmet());
1938 ApplyAgilityBonus(GetExternalCloak());
1939 ApplyAgilityBonus(GetExternalBodyArmor());
1940 ApplyAgilityBonus(GetExternalBelt());
1943 if(!UseMaterialAttributes())
1945 StrengthBonus
-= CalculateScarAttributePenalty(GetAttribute(LEG_STRENGTH
, false));
1946 AgilityBonus
-= CalculateScarAttributePenalty(GetAttribute(AGILITY
, false)) ;
1950 void humanoidtorso::SignalEquipmentAdd(gearslot
* Slot
)
1955 humanoid
* Master
= GetHumanoidMaster();
1956 int EquipmentIndex
= Slot
->GetEquipmentIndex();
1958 if(!Master
->IsInitializing()
1959 && (EquipmentIndex
== CLOAK_INDEX
|| EquipmentIndex
== BODY_ARMOR_INDEX
))
1961 item
* Item
= Slot
->GetItem();
1963 if(Master
->GetRightArm())
1964 Master
->GetRightArm()->ApplyDexterityPenalty(Item
);
1966 if(Master
->GetLeftArm())
1967 Master
->GetLeftArm()->ApplyDexterityPenalty(Item
);
1969 if(Master
->GetRightLeg())
1970 Master
->GetRightLeg()->ApplyAgilityPenalty(Item
);
1972 if(Master
->GetLeftLeg())
1973 Master
->GetLeftLeg()->ApplyAgilityPenalty(Item
);
1976 Master
->SignalEquipmentAdd(EquipmentIndex
);
1979 int arm::GetWieldedHitStrength() const
1981 int HitStrength
= GetAttribute(ARM_STRENGTH
);
1982 int Requirement
= GetWielded()->GetStrengthRequirement();
1984 if(TwoHandWieldIsActive())
1986 HitStrength
+= GetPairArm()->GetAttribute(ARM_STRENGTH
);
1990 return HitStrength
- Requirement
;
1993 void arm::ApplyDexterityPenalty(item
* Item
)
1996 DexterityBonus
-= Item
->GetInElasticityPenalty(GetAttribute(DEXTERITY
, false));
1999 void leg::ApplyAgilityPenalty(item
* Item
)
2002 AgilityBonus
-= Item
->GetInElasticityPenalty(GetAttribute(AGILITY
, false));
2005 int corpse::GetSpoilLevel() const
2009 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
2011 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
2013 if(BodyPart
&& FlyAmount
< BodyPart
->GetSpoilLevel())
2014 FlyAmount
= BodyPart
->GetSpoilLevel();
2020 void bodypart::SignalSpoilLevelChange(material
* Material
)
2023 Master
->SignalSpoilLevelChange();
2025 item::SignalSpoilLevelChange(Material
);
2028 truth
head::DamageArmor(character
* Damager
, int Damage
, int Type
)
2030 sLong AV
[3] = { 0, 0, 0 }, AVSum
= 0;
2033 if((Armor
[0] = GetHelmet()))
2034 AVSum
+= AV
[0] = Max(Armor
[0]->GetStrengthValue(), 1);
2036 if((Armor
[1] = GetExternalBodyArmor()))
2037 AVSum
+= AV
[1] = Max(Armor
[1]->GetStrengthValue() >> 2, 1);
2039 if((Armor
[2] = GetExternalCloak()))
2040 AVSum
+= AV
[2] = Max(Armor
[2]->GetStrengthValue(), 1);
2042 return AVSum
? Armor
[femath::WeightedRand(AV
, AVSum
)]->ReceiveDamage(Damager
, Damage
, Type
) : false;
2045 truth
humanoidtorso::DamageArmor(character
* Damager
, int Damage
, int Type
)
2047 sLong AV
[3] = { 0, 0, 0 }, AVSum
= 0;
2050 if((Armor
[0] = GetBodyArmor()))
2051 AVSum
+= AV
[0] = Max(Armor
[0]->GetStrengthValue(), 1);
2053 if((Armor
[1] = GetBelt()))
2054 AVSum
+= AV
[1] = Max(Armor
[1]->GetStrengthValue(), 1);
2056 if((Armor
[2] = GetCloak()))
2057 AVSum
+= AV
[2] = Max(Armor
[2]->GetStrengthValue(), 1);
2059 return AVSum
? Armor
[femath::WeightedRand(AV
, AVSum
)]->ReceiveDamage(Damager
, Damage
, Type
) : false;
2062 truth
arm::DamageArmor(character
* Damager
, int Damage
, int Type
)
2064 sLong AV
[3] = { 0, 0, 0 }, AVSum
= 0;
2067 if((Armor
[0] = GetGauntlet()))
2068 AVSum
+= AV
[0] = Max(Armor
[0]->GetStrengthValue(), 1);
2070 if((Armor
[1] = GetExternalBodyArmor()))
2071 AVSum
+= AV
[1] = Max(Armor
[1]->GetStrengthValue() >> 1, 1);
2073 if((Armor
[2] = GetExternalCloak()))
2074 AVSum
+= AV
[2] = Max(Armor
[2]->GetStrengthValue(), 1);
2076 return AVSum
? Armor
[femath::WeightedRand(AV
, AVSum
)]->ReceiveDamage(Damager
, Damage
, Type
) : false;
2079 truth
groin::DamageArmor(character
* Damager
, int Damage
, int Type
)
2081 return Master
->GetTorso()->DamageArmor(Damager
, Damage
, Type
);
2084 truth
leg::DamageArmor(character
* Damager
, int Damage
, int Type
)
2086 sLong AV
[3] = { 0, 0, 0 }, AVSum
= 0;
2089 if((Armor
[0] = GetBoot()))
2090 AVSum
+= AV
[0] = Max(Armor
[0]->GetStrengthValue(), 1);
2092 if((Armor
[1] = GetExternalBodyArmor()))
2093 AVSum
+= AV
[1] = Max(Armor
[1]->GetStrengthValue() >> 1, 1);
2095 if((Armor
[2] = GetExternalCloak()))
2096 AVSum
+= AV
[2] = Max(Armor
[2]->GetStrengthValue(), 1);
2098 return AVSum
? Armor
[femath::WeightedRand(AV
, AVSum
)]->ReceiveDamage(Damager
, Damage
, Type
) : false;
2101 truth
bodypart::CanBeEatenByAI(ccharacter
* Who
) const
2103 return item::CanBeEatenByAI(Who
) && !(Who
->IsPet() && PLAYER
->HasHadBodyPart(this));
2106 int bodypart::GetConditionColorIndex() const
2108 if(HP
<= 1 && MaxHP
> 1)
2110 else if((HP
<< 1) + HP
< MaxHP
)
2112 else if((HP
<< 1) + HP
< MaxHP
<< 1)
2120 truth
arm::CheckIfWeaponTooHeavy(cchar
* WeaponDescription
) const
2124 ADD_MESSAGE("%s %s is not usable.", Master
->CHAR_POSSESSIVE_PRONOUN
, GetBodyPartName().CStr());
2125 return !game::TruthQuestion(CONST_S("Continue anyway? [y/N]"));
2128 int HitStrength
= GetAttribute(ARM_STRENGTH
);
2129 int Requirement
= GetWielded()->GetStrengthRequirement();
2131 if(TwoHandWieldIsActive())
2133 HitStrength
+= GetPairArm()->GetAttribute(ARM_STRENGTH
);
2136 if(HitStrength
- Requirement
< 10)
2138 if(HitStrength
<= Requirement
)
2139 ADD_MESSAGE("%s cannot use %s. Wielding it with two hands requires %d strength.", Master
->CHAR_DESCRIPTION(DEFINITE
), WeaponDescription
, (Requirement
>> 1) + 1);
2140 else if(HitStrength
- Requirement
< 4)
2141 ADD_MESSAGE("Using %s even with two hands is extremely difficult for %s.", WeaponDescription
, Master
->CHAR_DESCRIPTION(DEFINITE
));
2142 else if(HitStrength
- Requirement
< 7)
2143 ADD_MESSAGE("%s %s much trouble using %s even with two hands.", Master
->CHAR_DESCRIPTION(DEFINITE
), Master
->IsPlayer() ? "have" : "has", WeaponDescription
);
2145 ADD_MESSAGE("It is somewhat difficult for %s to use %s even with two hands.", Master
->CHAR_DESCRIPTION(DEFINITE
), WeaponDescription
);
2147 return !game::TruthQuestion(CONST_S("Continue anyway? [y/N]"));
2152 if(HitStrength
- Requirement
< 10)
2154 festring OtherHandInfo
;
2155 cchar
* HandInfo
= "";
2157 if(GetWielded()->IsTwoHanded())
2159 if(GetPairArm() && !GetPairArm()->IsUsable())
2160 OtherHandInfo
= Master
->GetPossessivePronoun() + " other arm is unusable. ";
2162 HandInfo
= " with one hand";
2165 if(HitStrength
<= Requirement
)
2166 ADD_MESSAGE("%s%s cannot use %s. Wielding it%s requires %d strength.", OtherHandInfo
.CStr(), Master
->GetDescription(DEFINITE
).CapitalizeCopy().CStr(), WeaponDescription
, HandInfo
, Requirement
+ 1);
2167 else if(HitStrength
- Requirement
< 4)
2168 ADD_MESSAGE("%sUsing %s%s is extremely difficult for %s.", OtherHandInfo
.CStr(), WeaponDescription
, HandInfo
, Master
->CHAR_DESCRIPTION(DEFINITE
));
2169 else if(HitStrength
- Requirement
< 7)
2170 ADD_MESSAGE("%s%s %s much trouble using %s%s.", OtherHandInfo
.CStr(), Master
->GetDescription(DEFINITE
).CapitalizeCopy().CStr(), Master
->IsPlayer() ? "have" : "has", WeaponDescription
, HandInfo
);
2172 ADD_MESSAGE("%sIt is somewhat difficult for %s to use %s%s.", OtherHandInfo
.CStr(), Master
->CHAR_DESCRIPTION(DEFINITE
), WeaponDescription
, HandInfo
);
2174 return !game::TruthQuestion(CONST_S("Continue anyway? [y/N]"));
2181 int corpse::GetArticleMode() const
2183 return Deceased
->LeftOversAreUnique() ? FORCE_THE
: 0;
2186 head
* head::Behead()
2192 truth
arm::EditAllAttributes(int Amount
)
2194 LimitRef(StrengthExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
2195 LimitRef(DexterityExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
2197 && (StrengthExperience
!= MIN_EXP
|| DexterityExperience
!= MIN_EXP
))
2199 && (StrengthExperience
!= MAX_EXP
|| DexterityExperience
!= MAX_EXP
));
2202 truth
leg::EditAllAttributes(int Amount
)
2204 LimitRef(StrengthExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
2205 LimitRef(AgilityExperience
+= Amount
* EXP_MULTIPLIER
, MIN_EXP
, MAX_EXP
);
2207 && (StrengthExperience
!= MIN_EXP
|| AgilityExperience
!= MIN_EXP
))
2209 && (StrengthExperience
!= MAX_EXP
|| AgilityExperience
!= MAX_EXP
));
2214 void arm::AddAttackInfo(felist
& List
) const
2218 festring Entry
= CONST_S(" ");
2222 GetWielded()->AddName(Entry
, UNARTICLED
);
2224 if(TwoHandWieldIsActive())
2228 Entry
<< "melee attack";
2231 Entry
<< GetMinDamage() << '-' << GetMaxDamage();
2233 Entry
<< int(GetToHitValue());
2235 Entry
<< GetAPCost();
2236 List
.AddEntry(Entry
, LIGHT_GRAY
);
2240 void arm::AddDefenceInfo(felist
& List
) const
2244 festring Entry
= CONST_S(" ");
2245 GetWielded()->AddName(Entry
, UNARTICLED
);
2247 Entry
<< int(GetBlockValue());
2249 Entry
<< GetBlockCapability();
2250 List
.AddEntry(Entry
, LIGHT_GRAY
);
2256 void arm::AddAttackInfo(felist
&) const { }
2257 void arm::AddDefenceInfo(felist
&) const { }
2261 void arm::UpdateWieldedPicture()
2263 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2265 truth WasAnimated
= MasterIsAnimated();
2266 item
* Wielded
= GetWielded();
2268 if(Wielded
&& Master
)
2270 int SpecialFlags
= (IsRightArm() ? 0 : MIRROR
)|ST_WIELDED
|(Wielded
->GetSpecialFlags()&~0x3F);
2271 Wielded
->UpdatePictures(WieldedGraphicData
,
2272 Master
->GetWieldedPosition(),
2276 static_cast<bposretriever
>(&item::GetWieldedBitmapPos
));
2279 Wielded
->CheckFluidGearPictures(Wielded
->GetWieldedBitmapPos(0), SpecialFlags
, false);
2282 WieldedGraphicData
.Retire();
2284 if(!WasAnimated
!= !MasterIsAnimated())
2285 SignalAnimationStateChange(WasAnimated
);
2289 void arm::DrawWielded(blitdata
& BlitData
) const
2291 DrawEquipment(WieldedGraphicData
, BlitData
);
2293 if(ShowFluids() && GetWielded())
2294 GetWielded()->DrawFluidGearPictures(BlitData
, IsRightArm() ? 0 : MIRROR
);
2297 void arm::UpdatePictures()
2299 bodypart::UpdatePictures();
2300 UpdateWieldedPicture();
2303 void bodypart::Draw(blitdata
& BlitData
) const
2305 cint AF
= GraphicData
.AnimationFrames
;
2306 cint F
= !(BlitData
.CustomData
& ALLOW_ANIMATE
) || AF
== 1 ? 0 : GET_TICK() & (AF
- 1);
2307 cbitmap
* P
= GraphicData
.Picture
[F
];
2309 if(BlitData
.CustomData
& ALLOW_ALPHA
)
2310 P
->AlphaPriorityBlit(BlitData
);
2312 P
->MaskedPriorityBlit(BlitData
);
2314 if(Fluid
&& ShowFluids())
2315 DrawFluids(BlitData
);
2317 DrawArmor(BlitData
);
2320 void leg::AddAttackInfo(felist
& List
) const
2322 festring Entry
= CONST_S(" kick attack");
2324 Entry
<< GetKickMinDamage() << '-' << GetKickMaxDamage();
2326 Entry
<< int(GetKickToHitValue());
2328 Entry
<< GetKickAPCost();
2329 List
.AddEntry(Entry
, LIGHT_GRAY
);
2332 void corpse::PreProcessForBone()
2334 item::PreProcessForBone();
2336 if(!Deceased
->PreProcessForBone())
2343 void corpse::PostProcessForBone()
2345 item::PostProcessForBone();
2347 if(!Deceased
->PostProcessForBone())
2354 void corpse::FinalProcessForBone()
2356 item::FinalProcessForBone();
2357 Deceased
->FinalProcessForBone();
2360 truth
bodypart::IsRepairable(ccharacter
*) const
2362 return !CanRegenerate() && (GetHP() < GetMaxHP() || IsRusted());
2365 truth
corpse::SuckSoul(character
* Soul
, character
* Summoner
)
2367 v2 Pos
= Soul
->GetPos();
2369 if(Deceased
->SuckSoul(Soul
))
2372 character
* Deceased
= GetDeceased();
2374 if(RaiseTheDead(Summoner
))
2381 Deceased
->SetSoulID(Soul
->GetID());
2390 double arm::GetTypeDamage(ccharacter
* Enemy
) const
2392 if(!GetWielded() || !GetWielded()->IsGoodWithPlants() || !Enemy
->IsPlant())
2395 return Damage
* 1.5;
2398 void largetorso::Draw(blitdata
& BlitData
) const
2400 LargeDraw(BlitData
);
2403 void largecorpse::Draw(blitdata
& BlitData
) const
2405 LargeDraw(BlitData
);
2408 void largetorso::SignalStackAdd(stackslot
* StackSlot
, void (stack::*AddHandler
)(item
*, truth
))
2412 Slot
[0] = StackSlot
;
2414 level
* Level
= GetLevel();
2416 for(int c
= 1; c
< 4; ++c
)
2417 (Level
->GetLSquare(Pos
+ game::GetLargeMoveVector(12 + c
))->GetStack()->*AddHandler
)(this, false);
2420 for(int c
= 1; c
< 4; ++c
)
2423 Slot
[c
] = StackSlot
;
2428 int largetorso::GetSquareIndex(v2 Pos
) const
2430 v2 RelativePos
= Pos
- GetPos();
2431 return RelativePos
.X
+ (RelativePos
.Y
<< 1);
2434 void largecorpse::SignalStackAdd(stackslot
* StackSlot
, void (stack::*AddHandler
)(item
*, truth
))
2438 Slot
[0] = StackSlot
;
2440 level
* Level
= GetLevel();
2442 for(int c
= 1; c
< 4; ++c
)
2443 (Level
->GetLSquare(Pos
+ game::GetLargeMoveVector(12 + c
))->GetStack()->*AddHandler
)(this, false);
2446 for(int c
= 1; c
< 4; ++c
)
2449 Slot
[c
] = StackSlot
;
2454 int largecorpse::GetSquareIndex(v2 Pos
) const
2456 v2 RelativePos
= Pos
- GetPos();
2457 return RelativePos
.X
+ (RelativePos
.Y
<< 1);
2460 character
* corpse::TryNecromancy(character
* Summoner
)
2462 if(Summoner
&& Summoner
->IsPlayer())
2463 game::DoEvilDeed(50);
2465 character
* Zombie
= GetDeceased()->CreateZombie();
2471 Zombie
->ChangeTeam(Summoner
? Summoner
->GetTeam() : game::GetTeam(MONSTER_TEAM
));
2472 Zombie
->PutToOrNear(Pos
);
2473 Zombie
->SignalStepFrom(0);
2481 item
* head::GetArmorToReceiveFluid(truth
) const
2483 item
* Helmet
= GetHelmet();
2485 if(Helmet
&& Helmet
->GetCoverPercentile() > RAND() % 100)
2491 item
* humanoidtorso::GetArmorToReceiveFluid(truth
) const
2493 item
* Cloak
= GetCloak();
2495 if(Cloak
&& !(RAND() % 3))
2498 item
* Belt
= GetBelt();
2500 if(Belt
&& !(RAND() % 10))
2503 item
* BodyArmor
= GetBodyArmor();
2504 return BodyArmor
? BodyArmor
: 0;
2507 item
* arm::GetArmorToReceiveFluid(truth
) const
2509 item
* Cloak
= GetExternalCloak();
2511 if(Cloak
&& !(RAND() % 3))
2514 item
* Wielded
= GetWielded();
2516 if(Wielded
&& !(RAND() % 3))
2519 item
* Gauntlet
= GetGauntlet();
2521 if(Gauntlet
&& RAND() & 1)
2524 item
* BodyArmor
= GetExternalBodyArmor();
2525 return BodyArmor
? BodyArmor
: 0;
2528 item
* groin::GetArmorToReceiveFluid(truth
) const
2530 item
* Cloak
= GetExternalCloak();
2532 if(Cloak
&& !(RAND() % 3))
2535 item
* BodyArmor
= GetExternalBodyArmor();
2536 return BodyArmor
? BodyArmor
: 0;
2539 item
* leg::GetArmorToReceiveFluid(truth SteppedOn
) const
2543 item
* Boot
= GetBoot();
2544 return Boot
? Boot
: 0;
2548 item
* Cloak
= GetExternalCloak();
2550 if(Cloak
&& !(RAND() % 3))
2553 item
* Boot
= GetBoot();
2555 if(Boot
&& RAND() & 1)
2558 item
* BodyArmor
= GetExternalBodyArmor();
2559 return BodyArmor
? BodyArmor
: 0;
2563 void bodypart::SpillFluid(character
* Spiller
, liquid
* Liquid
, int SquareIndex
)
2567 item
* Armor
= GetArmorToReceiveFluid(false);
2570 Armor
->SpillFluid(Spiller
, Liquid
);
2571 else if(GetMaster())
2573 if(Liquid
->GetVolume())
2574 AddFluid(Liquid
, "", SquareIndex
, false);
2580 item::SpillFluid(Spiller
, Liquid
, SquareIndex
);
2583 void bodypart::StayOn(liquid
* Liquid
)
2585 item
* Armor
= GetArmorToReceiveFluid(true);
2588 Liquid
->TouchEffect(Armor
, CONST_S(""));
2589 else if(GetMaster())
2590 Liquid
->TouchEffect(GetMaster(), GetBodyPartIndex());
2593 liquid
* bodypart::CreateBlood(sLong Volume
) const
2595 return liquid::Spawn(GetBloodMaterial(), Volume
);
2598 int corpse::GetRustDataA() const
2600 return Deceased
->GetTorso()->GetMainMaterial()->GetRustData();
2603 void bodypart::UpdateArmorPicture(graphicdata
& GData
, item
* Armor
, int SpecialFlags
, v2 (item::*Retriever
)(int) const, truth BodyArmor
) const
2607 Armor
->UpdatePictures(GData
,
2609 SpecialFlags
|Armor
->GetSpecialFlags(),
2612 static_cast<bposretriever
>(Retriever
));
2613 Armor
->CheckFluidGearPictures((Armor
->*Retriever
)(0), SpecialFlags
, BodyArmor
);
2619 truth
playerkindhead::UpdateArmorPictures()
2621 UpdateHeadArmorPictures(HelmetGraphicData
);
2625 truth
playerkindtorso::UpdateArmorPictures()
2627 UpdateTorsoArmorPictures(TorsoArmorGraphicData
,
2633 truth
playerkindrightarm::UpdateArmorPictures()
2635 UpdateArmArmorPictures(ArmArmorGraphicData
,
2636 GauntletGraphicData
,
2641 truth
playerkindleftarm::UpdateArmorPictures()
2643 UpdateArmArmorPictures(ArmArmorGraphicData
,
2644 GauntletGraphicData
,
2649 truth
playerkindgroin::UpdateArmorPictures()
2651 UpdateGroinArmorPictures(GroinArmorGraphicData
);
2655 truth
playerkindrightleg::UpdateArmorPictures()
2657 UpdateLegArmorPictures(LegArmorGraphicData
,
2663 truth
playerkindleftleg::UpdateArmorPictures()
2665 UpdateLegArmorPictures(LegArmorGraphicData
,
2671 void head::UpdateHeadArmorPictures(graphicdata
& HelmetGraphicData
) const
2673 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2675 UpdateArmorPicture(HelmetGraphicData
,
2678 &item::GetHelmetBitmapPos
);
2682 void humanoidtorso::UpdateTorsoArmorPictures(graphicdata
& TorsoArmorGraphicData
, graphicdata
& CloakGraphicData
, graphicdata
& BeltGraphicData
) const
2684 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2686 UpdateArmorPicture(TorsoArmorGraphicData
,
2689 &item::GetTorsoArmorBitmapPos
,
2691 UpdateArmorPicture(CloakGraphicData
,
2694 &item::GetCloakBitmapPos
);
2695 UpdateArmorPicture(BeltGraphicData
,
2698 &item::GetBeltBitmapPos
);
2702 void arm::UpdateArmArmorPictures(graphicdata
& ArmArmorGraphicData
, graphicdata
& GauntletGraphicData
, int SpecialFlags
) const
2704 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2706 UpdateArmorPicture(ArmArmorGraphicData
,
2707 Master
? GetExternalBodyArmor() : 0,
2709 GetAttribute(ARM_STRENGTH
, false) >= 20 ? &item::GetAthleteArmArmorBitmapPos
: &item::GetArmArmorBitmapPos
,
2711 UpdateArmorPicture(GauntletGraphicData
,
2714 &item::GetGauntletBitmapPos
);
2718 void groin::UpdateGroinArmorPictures(graphicdata
& GroinArmorGraphicData
) const
2720 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2722 UpdateArmorPicture(GroinArmorGraphicData
,
2723 Master
? GetExternalBodyArmor() : 0,
2725 &item::GetLegArmorBitmapPos
,
2730 void leg::UpdateLegArmorPictures(graphicdata
& LegArmorGraphicData
, graphicdata
& BootGraphicData
, int SpecialFlags
) const
2732 if(!Master
|| !Master
->PictureUpdatesAreForbidden())
2734 UpdateArmorPicture(LegArmorGraphicData
,
2735 Master
? GetExternalBodyArmor() : 0,
2737 &item::GetLegArmorBitmapPos
,
2739 UpdateArmorPicture(BootGraphicData
,
2742 &item::GetBootBitmapPos
);
2746 void bodypart::DrawEquipment(const graphicdata
& GraphicData
, blitdata
& BlitData
) const
2748 int EAF
= GraphicData
.AnimationFrames
;
2752 int F
= !(BlitData
.CustomData
& ALLOW_ANIMATE
) || EAF
== 1 ? 0 : GET_TICK() & (EAF
- 1);
2753 GraphicData
.Picture
[F
]->AlphaPriorityBlit(BlitData
);
2757 void playerkindhead::DrawArmor(blitdata
& BlitData
) const
2759 DrawEquipment(HelmetGraphicData
, BlitData
);
2762 GetHelmet()->DrawFluidGearPictures(BlitData
);
2765 void playerkindtorso::DrawArmor(blitdata
& BlitData
) const
2767 DrawEquipment(TorsoArmorGraphicData
, BlitData
);
2770 GetBodyArmor()->DrawFluidGearPictures(BlitData
);
2772 DrawEquipment(CloakGraphicData
, BlitData
);
2775 GetCloak()->DrawFluidGearPictures(BlitData
);
2777 DrawEquipment(BeltGraphicData
, BlitData
);
2780 GetBelt()->DrawFluidGearPictures(BlitData
);
2783 void playerkindrightarm::DrawArmor(blitdata
& BlitData
) const
2785 DrawEquipment(ArmArmorGraphicData
, BlitData
);
2787 if(Master
&& GetExternalBodyArmor())
2788 GetExternalBodyArmor()->DrawFluidBodyArmorPictures(BlitData
, ST_RIGHT_ARM
);
2790 DrawEquipment(GauntletGraphicData
, BlitData
);
2793 GetGauntlet()->DrawFluidGearPictures(BlitData
);
2796 void playerkindleftarm::DrawArmor(blitdata
& BlitData
) const
2798 DrawEquipment(ArmArmorGraphicData
, BlitData
);
2800 if(Master
&& GetExternalBodyArmor())
2801 GetExternalBodyArmor()->DrawFluidBodyArmorPictures(BlitData
, ST_LEFT_ARM
);
2803 DrawEquipment(GauntletGraphicData
, BlitData
);
2806 GetGauntlet()->DrawFluidGearPictures(BlitData
);
2809 void playerkindgroin::DrawArmor(blitdata
& BlitData
) const
2811 DrawEquipment(GroinArmorGraphicData
, BlitData
);
2813 if(Master
&& GetExternalBodyArmor())
2814 GetExternalBodyArmor()->DrawFluidBodyArmorPictures(BlitData
, ST_GROIN
);
2817 void playerkindrightleg::DrawArmor(blitdata
& BlitData
) const
2819 DrawEquipment(LegArmorGraphicData
, BlitData
);
2821 if(Master
&& GetExternalBodyArmor())
2822 GetExternalBodyArmor()->DrawFluidBodyArmorPictures(BlitData
, ST_RIGHT_LEG
);
2824 DrawEquipment(BootGraphicData
, BlitData
);
2827 GetBoot()->DrawFluidGearPictures(BlitData
);
2830 void playerkindleftleg::DrawArmor(blitdata
& BlitData
) const
2832 DrawEquipment(LegArmorGraphicData
, BlitData
);
2834 if(Master
&& GetExternalBodyArmor())
2835 GetExternalBodyArmor()->DrawFluidBodyArmorPictures(BlitData
, ST_LEFT_LEG
);
2837 DrawEquipment(BootGraphicData
, BlitData
);
2840 GetBoot()->DrawFluidGearPictures(BlitData
);
2843 void playerkindhead::Save(outputfile
& SaveFile
) const
2845 head::Save(SaveFile
);
2846 SaveFile
<< HelmetGraphicData
;
2849 void playerkindhead::Load(inputfile
& SaveFile
)
2851 head::Load(SaveFile
);
2852 SaveFile
>> HelmetGraphicData
;
2855 void playerkindtorso::Save(outputfile
& SaveFile
) const
2857 humanoidtorso::Save(SaveFile
);
2858 SaveFile
<< TorsoArmorGraphicData
<< CloakGraphicData
<< BeltGraphicData
;
2861 void playerkindtorso::Load(inputfile
& SaveFile
)
2863 humanoidtorso::Load(SaveFile
);
2864 SaveFile
>> TorsoArmorGraphicData
>> CloakGraphicData
>> BeltGraphicData
;
2867 void playerkindrightarm::Save(outputfile
& SaveFile
) const
2869 rightarm::Save(SaveFile
);
2870 SaveFile
<< ArmArmorGraphicData
<< GauntletGraphicData
;
2873 void playerkindrightarm::Load(inputfile
& SaveFile
)
2875 rightarm::Load(SaveFile
);
2876 SaveFile
>> ArmArmorGraphicData
>> GauntletGraphicData
;
2879 void playerkindleftarm::Save(outputfile
& SaveFile
) const
2881 leftarm::Save(SaveFile
);
2882 SaveFile
<< ArmArmorGraphicData
<< GauntletGraphicData
;
2885 void playerkindleftarm::Load(inputfile
& SaveFile
)
2887 leftarm::Load(SaveFile
);
2888 SaveFile
>> ArmArmorGraphicData
>> GauntletGraphicData
;
2891 void playerkindgroin::Save(outputfile
& SaveFile
) const
2893 groin::Save(SaveFile
);
2894 SaveFile
<< GroinArmorGraphicData
;
2897 void playerkindgroin::Load(inputfile
& SaveFile
)
2899 groin::Load(SaveFile
);
2900 SaveFile
>> GroinArmorGraphicData
;
2903 void playerkindrightleg::Save(outputfile
& SaveFile
) const
2905 rightleg::Save(SaveFile
);
2906 SaveFile
<< LegArmorGraphicData
<< BootGraphicData
;
2909 void playerkindrightleg::Load(inputfile
& SaveFile
)
2911 rightleg::Load(SaveFile
);
2912 SaveFile
>> LegArmorGraphicData
>> BootGraphicData
;
2915 void playerkindleftleg::Save(outputfile
& SaveFile
) const
2917 leftleg::Save(SaveFile
);
2918 SaveFile
<< LegArmorGraphicData
<< BootGraphicData
;
2921 void playerkindleftleg::Load(inputfile
& SaveFile
)
2923 leftleg::Load(SaveFile
);
2924 SaveFile
>> LegArmorGraphicData
>> BootGraphicData
;
2927 truth
bodypart::MasterIsAnimated() const
2929 return Master
&& !Master
->IsInitializing() && Master
->IsAnimated();
2932 void bodypart::UpdatePictures()
2934 truth WasAnimated
= MasterIsAnimated();
2936 item::UpdatePictures();
2937 UpdateArmorPictures();
2939 if(!WasAnimated
!= !MasterIsAnimated())
2940 SignalAnimationStateChange(WasAnimated
);
2943 void playerkindtorso::SignalVolumeAndWeightChange()
2945 humanoidtorso::SignalVolumeAndWeightChange();
2947 if(Master
&& !Master
->IsInitializing())
2948 Master
->UpdatePictures();
2952 void bodypart::ReceiveAcid (material
*Material
, cfestring
&LocationName
, sLong Modifier
) {
2953 if (Master
&& MainMaterial
->GetInteractionFlags() & CAN_DISSOLVE
) {
2954 sLong Tries
= Modifier
/1000;
2955 Modifier
-= Tries
*1000; //opt%?
2957 for (sLong c
= 0; c
< Tries
; ++c
) if (!(RAND() % 100)) ++Damage
;
2958 if (Modifier
&& !(RAND()%100000/Modifier
)) ++Damage
;
2960 feuLong Minute
= game::GetTotalMinutes();
2961 character
*Master
= this->Master
;
2962 if (Master
->GetLastAcidMsgMin() != Minute
&& (Master
->CanBeSeenByPlayer() || Master
->IsPlayer())) {
2963 Master
->SetLastAcidMsgMin(Minute
);
2964 cchar
*MName
= Material
->GetName(false, false).CStr();
2965 if (Master
->IsPlayer()) {
2966 cchar
*TName
= LocationName
.IsEmpty() ? GetBodyPartName().CStr() : LocationName
.CStr();
2967 ADD_MESSAGE("Acidous %s dissolves your %s.", MName
, TName
);
2969 ADD_MESSAGE("Acidous %s dissolves %s.", MName
, Master
->CHAR_NAME(DEFINITE
));
2972 Master
->ReceiveBodyPartDamage(0, Damage
, ACID
, GetBodyPartIndex(), YOURSELF
, false, false, false);
2973 feuLong DeathFlags
= Material
->IsStuckTo(Master
) ? IGNORE_TRAPS
: 0;
2974 Master
->CheckDeath(CONST_S("dissolved by ")+Material
->GetName(), 0, DeathFlags
);
2979 void bodypart::TryToRust(sLong LiquidModifier
)
2981 if(MainMaterial
->TryToRust(LiquidModifier
<< 4))
2983 cchar
* MoreMsg
= MainMaterial
->GetRustLevel() == NOT_RUSTED
? "" : " more";
2987 if(Master
->IsPlayer())
2988 ADD_MESSAGE("Your %s rusts%s.", CHAR_NAME(UNARTICLED
), MoreMsg
);
2989 else if(CanBeSeenByPlayer())
2990 ADD_MESSAGE("The %s of %s rusts%s.", CHAR_NAME(UNARTICLED
), Master
->CHAR_NAME(DEFINITE
), MoreMsg
);
2992 else if(CanBeSeenByPlayer())
2993 ADD_MESSAGE("%s rusts%s.", CHAR_NAME(DEFINITE
), MoreMsg
);
2995 MainMaterial
->SetRustLevel(MainMaterial
->GetRustLevel() + 1);
2999 material
* corpse::GetConsumeMaterial(ccharacter
* Consumer
, materialpredicate Predicate
) const
3001 for(int c
= GetDeceased()->GetBodyParts() - 1; c
; --c
)
3003 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
3007 material
* CM
= BodyPart
->GetConsumeMaterial(Consumer
, Predicate
);
3014 return GetDeceased()->GetTorso()->GetConsumeMaterial(Consumer
, Predicate
);
3017 void corpse::Cannibalize()
3019 item::Cannibalize();
3021 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
3023 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
3026 BodyPart
->Cannibalize();
3030 material
* bodypart::RemoveMaterial(material
* Material
)
3032 if(Master
&& GetBodyPartIndex() == TORSO_INDEX
)
3033 return Master
->GetMotherEntity()->RemoveMaterial(Material
); // gum
3035 return item::RemoveMaterial(Material
);
3038 void arm::CopyAttributes(const bodypart
* BodyPart
)
3040 const arm
* Arm
= static_cast<const arm
*>(BodyPart
);
3041 StrengthExperience
= Arm
->StrengthExperience
;
3042 DexterityExperience
= Arm
->DexterityExperience
;
3045 void leg::CopyAttributes(const bodypart
* BodyPart
)
3047 const leg
* Leg
= static_cast<const leg
*>(BodyPart
);
3048 StrengthExperience
= Leg
->StrengthExperience
;
3049 AgilityExperience
= Leg
->AgilityExperience
;
3052 truth
corpse::DetectMaterial(const material
* Material
) const
3054 return GetDeceased()->DetectMaterial(Material
);
3057 void bodypart::DestroyBodyPart(stack
* Stack
)
3059 int Lumps
= 1 + RAND() % 3;
3060 sLong LumpVolume
= Volume
/ Lumps
>> 2;
3062 if(LumpVolume
>= 10)
3063 for(int c
= 0; c
< Lumps
; ++c
)
3065 item
* Lump
= GetMainMaterial()->CreateNaturalForm(LumpVolume
+ RAND() % LumpVolume
);
3066 Stack
->AddItem(Lump
);
3072 v2
magicmushroomtorso::GetBitmapPos(int Frame
) const
3074 v2 BasePos
= torso::GetBitmapPos(Frame
);
3080 return v2(BasePos
.X
+ 64 - (abs(Frame
- 4) << 4), BasePos
.Y
);
3082 return v2(BasePos
.X
+ 64 - (abs(Frame
- 12) << 4), BasePos
.Y
+ 16);
3088 v2
dogtorso::GetBitmapPos(int Frame
) const
3090 v2 BasePos
= torso::GetBitmapPos(Frame
);
3092 if(Frame
>= GraphicData
.AnimationFrames
>> 1)
3095 return v2(BasePos
.X
+ ((Frame
& 4) << 2), BasePos
.Y
);
3098 void dogtorso::Draw(blitdata
& BlitData
) const
3100 cint AF
= GraphicData
.AnimationFrames
>> 1;
3101 int Index
= !(BlitData
.CustomData
& ALLOW_ANIMATE
) || AF
== 1 ? 0 : GET_TICK() & (AF
- 1);
3103 if(GetHP() << 1 <= GetMaxHP())
3106 cbitmap
* P
= GraphicData
.Picture
[Index
];
3108 if(BlitData
.CustomData
& ALLOW_ALPHA
)
3109 P
->AlphaPriorityBlit(BlitData
);
3111 P
->MaskedPriorityBlit(BlitData
);
3114 void corpse::SetLifeExpectancy(int Base
, int RandPlus
)
3116 Deceased
->SetLifeExpectancy(Base
, RandPlus
);
3121 for(int c
= 0; c
< Deceased
->GetBodyParts(); ++c
)
3123 bodypart
* BodyPart
= Deceased
->GetBodyPart(c
);
3130 void bodypart::SetLifeExpectancy(int Base
, int RandPlus
)
3132 LifeExpectancy
= RandPlus
> 1 ? Base
+ RAND_N(RandPlus
) : Base
;
3138 void bodypart::SpecialEatEffect(character
* Eater
, int Amount
)
3142 if(Amount
&& (!Master
|| Master
->SpillsBlood()) && (IsAlive() || MainMaterial
->IsLiquid()) && !game::IsInWilderness())
3144 if(Eater
->GetVirtualHead())
3145 Eater
->GetVirtualHead()->SpillFluid(Eater
, CreateBlood(Amount
));
3147 Eater
->GetTorso()->SpillFluid(Eater
, CreateBlood(Amount
));
3151 truth
corpse::IsValuable() const
3153 for(int c
= 0; c
< Deceased
->GetBodyParts(); ++c
)
3155 bodypart
* BodyPart
= Deceased
->GetBodyPart(c
);
3157 if(BodyPart
&& BodyPart
->IsValuable())
3164 truth
corpse::Necromancy(character
* Necromancer
)
3166 if(Necromancer
&& Necromancer
->IsPlayer())
3167 game::DoEvilDeed(50);
3169 character
* Zombie
= GetDeceased()->CreateZombie();
3173 Zombie
->ChangeTeam(Necromancer
? Necromancer
->GetTeam() : game::GetTeam(MONSTER_TEAM
));
3174 Zombie
->PutToOrNear(GetPos());
3178 if(Zombie
->CanBeSeenByPlayer())
3179 ADD_MESSAGE("%s rises back to cursed undead life.", Zombie
->CHAR_DESCRIPTION(INDEFINITE
));
3181 Zombie
->SignalStepFrom(0);
3186 if(CanBeSeenByPlayer())
3187 ADD_MESSAGE("%s vibrates for some time.", CHAR_NAME(DEFINITE
));
3193 alpha
mysticfrogtorso::GetOutlineAlpha(int Frame
) const
3196 return Frame
* (31 - Frame
) >> 1;
3199 col16
mysticfrogtorso::GetOutlineColor(int Frame
) const
3201 switch((Frame
&127) >> 5)
3203 case 0: return BLUE
;
3204 case 1: return GREEN
;
3206 case 3: return YELLOW
;
3209 return TRANSPARENT_COLOR
;
3212 void bodypart::UpdateFlags()
3214 if((HP
<< 1) + HP
< MaxHP
|| (HP
== 1 && MaxHP
!= 1))
3215 Flags
|= BADLY_HURT
;
3217 Flags
&= ~BADLY_HURT
;
3219 if(Master
->BodyPartIsStuck(GetBodyPartIndex()))
3225 void head::SignalPossibleUsabilityChange()
3227 feuLong OldFlags
= Flags
;
3230 if(!Master
->IsInitializing() && HP
> 0
3231 && Flags
& BADLY_HURT
&& !(OldFlags
& BADLY_HURT
))
3236 case 2: Master
->LoseConsciousness(50 + RAND_N(50)); break;
3239 case 5: Master
->BeginTemporaryState(CONFUSED
, 500 + RAND_N(500)); break;
3241 if(Master
->IsPlayer() && !RAND_N(3))
3245 ADD_MESSAGE("Your memory becomes blurred.");
3246 GetLevel()->Amnesia(25 + RAND_N(50));
3247 Master
->EditExperience(INTELLIGENCE
, -80, 1 << 13);
3248 game::SendLOSUpdateRequest();
3252 ADD_MESSAGE("A terrible concussion garbles your consciousness.");
3253 Master
->BeginTemporaryState(CONFUSED
, 5000 + RAND_N(5000));
3254 Master
->EditExperience(INTELLIGENCE
, -100, 1 << 14);
3255 GetLevel()->BlurMemory();
3256 game::SendLOSUpdateRequest();
3260 Master
->EditExperience(INTELLIGENCE
, -60, 1 << 12);
3264 Master
->ForgetRandomThing();
3268 void arm::SignalPossibleUsabilityChange()
3270 feuLong OldFlags
= Flags
;
3273 if(Flags
!= OldFlags
&& !Master
->IsInitializing())
3274 Master
->CalculateBattleInfo();
3277 void leg::SignalPossibleUsabilityChange()
3279 feuLong OldFlags
= Flags
;
3282 if(Flags
!= OldFlags
&& !Master
->IsInitializing())
3283 Master
->CalculateBattleInfo();
3286 void bodypart::IncreaseHP()
3290 SignalPossibleUsabilityChange();
3293 void bodypart::FastRestoreHP()
3297 SignalPossibleUsabilityChange();
3300 void bodypart::RestoreHP()
3304 SignalPossibleUsabilityChange();
3305 Master
->CalculateHP();
3308 void bodypart::SetIsUnique(truth What
)
3316 void bodypart::SetIsInfectedByLeprosy(truth What
)
3318 MainMaterial
->SetIsInfectedByLeprosy(What
);
3321 void bodypart::SetSparkleFlags(int What
)
3323 cint S
= SPARKLING_B
|SPARKLING_C
|SPARKLING_D
;
3324 Flags
= (Flags
& ~(S
<< BODYPART_SPARKLE_SHIFT
)) | ((What
& S
) << BODYPART_SPARKLE_SHIFT
);
3327 truth
arm::IsAnimated() const
3329 return WieldedGraphicData
.AnimationFrames
> 1;
3332 void bodypart::SignalAnimationStateChange(truth WasAnimated
)
3336 for(int c
= 0; c
< GetSquaresUnder(); ++c
)
3338 square
* Square
= GetSquareUnder(c
);
3341 Square
->DecAnimatedEntities();
3346 for(int c
= 0; c
< GetSquaresUnder(); ++c
)
3348 square
* Square
= GetSquareUnder(c
);
3351 Square
->IncAnimatedEntities();
3356 truth
bodypart::MaterialIsChangeable(ccharacter
*) const
3358 return !Master
|| !Master
->BodyPartIsVital(GetBodyPartIndex()) || UseMaterialAttributes();
3361 truth
bodypart::AddAdjective(festring
& String
, truth Articled
) const
3368 String
<< "severed ";
3375 void bodypart::RemoveRust()
3381 sLong
bodypart::GetFixPrice() const
3383 return GetMaxHP() - GetHP() + GetMainMaterial()->GetRustLevel() * 25;
3386 truth
bodypart::IsFixableBySmith(ccharacter
*) const
3388 return (GetMainMaterial()->GetCategoryFlags() & IS_METAL
3389 && (GetHP() < GetMaxHP() || IsRusted()));
3392 truth
bodypart::IsFixableByTailor(ccharacter
*) const
3394 return (GetMainMaterial()->GetCategoryFlags() & CAN_BE_TAILORED
3395 && GetHP() < GetMaxHP());
3398 item
* bodypart::Fix()
3404 void bodypart::SignalMaterialChange()
3410 truth
bodypart::ShowMaterial() const
3412 return MainMaterial
->GetConfig() != NormalMaterial
;
3415 col16
lobhsetorso::GetMaterialColorD(int Frame
) const
3418 int Modifier
= Frame
* (31 - Frame
);
3419 return MakeRGB16(220 - (Modifier
>> 2), 220 - (Modifier
>> 1), 0);
3422 truth
bodypart::IsDestroyable(ccharacter
*) const
3424 return !Master
|| !Master
->BodyPartIsVital(GetBodyPartIndex());
3427 truth
bodypart::DamageTypeCanScar(int Type
)
3429 return !(Type
== POISON
|| Type
== DRAIN
);
3432 void bodypart::GenerateScar(int Damage
, int Type
)
3434 Scar
.push_back(scar());
3435 scar
& NewScar
= Scar
.back();
3436 NewScar
.Severity
= 1 + RAND_N(1 + 5 * Damage
/ GetMaxHP());
3438 if(GetMaster()->IsPlayer())
3440 int ScarColor
= MakeShadeColor(GetMainMaterial()->GetColor());
3441 NewScar
.PanelBitmap
= igraph::GenerateScarBitmap(GetBodyPartIndex(),
3444 ADD_MESSAGE("Your %s is scarred.", CHAR_NAME(UNARTICLED
));
3447 NewScar
.PanelBitmap
= 0;
3450 GetMaster()->CalculateMaxHP();
3451 GetMaster()->CalculateAttributeBonuses();
3452 CalculateAttackInfo();
3455 void bodypart::DrawScars(cblitdata
& B
) const
3457 for(unsigned int c
= 0; c
< Scar
.size(); ++c
)
3459 if(!Scar
[c
].PanelBitmap
)
3461 int ScarColor
= MakeShadeColor(GetMainMaterial()->GetColor());
3462 Scar
[c
].PanelBitmap
= igraph::GenerateScarBitmap(GetBodyPartIndex(),
3467 Scar
[c
].PanelBitmap
->NormalMaskedBlit(B
);
3471 outputfile
& operator<<(outputfile
& SaveFile
, const scar
& Scar
)
3473 SaveFile
<< Scar
.Severity
<< Scar
.PanelBitmap
;
3477 inputfile
& operator>>(inputfile
& SaveFile
, scar
& Scar
)
3479 SaveFile
>> Scar
.Severity
>> Scar
.PanelBitmap
;
3483 int bodypart::CalculateScarAttributePenalty(int Attribute
) const
3485 double DoubleAttribute
= Attribute
;
3487 for(unsigned int c
= 0; c
< Scar
.size(); ++c
)
3488 DoubleAttribute
*= (100. - Scar
[c
].Severity
* 4) / 100;
3490 return Min(Attribute
- int(DoubleAttribute
), Attribute
- 1);
3493 bodypart::~bodypart()
3495 for(unsigned int c
= 0; c
< Scar
.size(); ++c
)
3496 delete Scar
[c
].PanelBitmap
;
3499 bodypart::bodypart(const bodypart
& B
) : mybase(B
), OwnerDescription(B
.OwnerDescription
), Master(B
.Master
), CarriedWeight(B
.CarriedWeight
), BodyPartVolume(B
.BodyPartVolume
), BitmapPos(B
.BitmapPos
), ColorB(B
.ColorB
), ColorC(B
.ColorC
), ColorD(B
.ColorD
), SpecialFlags(B
.SpecialFlags
), HP(B
.HP
), MaxHP(B
.MaxHP
), BloodMaterial(B
.BloodMaterial
), NormalMaterial(B
.NormalMaterial
), SpillBloodCounter(B
.SpillBloodCounter
), WobbleData(B
.WobbleData
), Scar(B
.Scar
)
3501 for(unsigned int c
= 0; c
< Scar
.size(); ++c
)
3502 if(Scar
[c
].PanelBitmap
)
3503 Scar
[c
].PanelBitmap
= new bitmap(Scar
[c
].PanelBitmap
);
3506 /* Amount should be > 0 */
3508 void bodypart::RemoveDamageIDs(int Amount
)
3512 damageid& D = DamageID.front();
3513 int CurrentAmount = D.Amount;
3515 if(Amount < CurrentAmount)
3522 DamageID.pop_front();
3523 Amount -= CurrentAmount;
3528 /* Amount should be > 0 */
3530 void bodypart::AddDamageID(int SrcID
, int Amount
)
3532 /*damageid D = { SrcID, Amount };
3533 DamageID.push_back(D);*/
3536 int arm::GetCurrentSWeaponSkillBonus() const
3538 return (*GetCurrentSWeaponSkill()
3539 ? (*GetCurrentSWeaponSkill())->GetBonus() : 1);
3542 v2
battorso::GetBitmapPos(int Frame
) const
3544 v2 BasePos
= torso::GetBitmapPos(Frame
);
3546 return v2(BasePos
.X
+ ((Frame
&~ 3) << 2), BasePos
.Y
);
3549 v2
spidertorso::GetBitmapPos(int Frame
) const
3551 v2 BasePos
= torso::GetBitmapPos(Frame
);
3553 return v2(BasePos
.X
+ ((Frame
&~ 7) << 1), BasePos
.Y
);
3556 truth
arm::HasSadistWeapon() const
3558 item
* Wielded
= GetWielded();
3559 return Wielded
&& Wielded
->IsSadistWeapon();
3562 truth
corpse::AddStateDescription(festring
& Name
, truth Articled
) const
3567 truth Hasted
= true, Slowed
= true;
3569 for(int c
= 0; c
< GetDeceased()->GetBodyParts(); ++c
)
3571 bodypart
* BodyPart
= GetDeceased()->GetBodyPart(c
);
3575 if(!(BodyPart
->ItemFlags
& HASTE
))
3578 if(!(BodyPart
->ItemFlags
& SLOW
))
3583 if((Hasted
| Slowed
) && Articled
)
3596 void arm::ApplyStrengthBonus (item
*Item
) {
3597 if (Item
&& Item
->AffectsArmStrength()) StrengthBonus
+= Item
->GetEnchantment()/2;
3600 void arm::ApplyDexterityBonus (item
*Item
) {
3601 if (Item
&& Item
->AffectsDexterity()) DexterityBonus
+= Item
->GetEnchantment()/2;
3604 void leg::ApplyStrengthBonus (item
*Item
) {
3605 if (Item
&& Item
->AffectsLegStrength()) StrengthBonus
+= Item
->GetEnchantment()/2;
3608 void leg::ApplyAgilityBonus (item
*Item
) {
3609 if (Item
&& Item
->AffectsAgility()) AgilityBonus
+= Item
->GetEnchantment()/2;