CLIVAN: copied muntuo (not all critters yet)
[k8-i-v-a-n.git] / src / game / gear.cpp
bloba111725bf1072600d2f3df28f51de3158132625f
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
13 /* Compiled through itemset.cpp */
15 void meleeweapon::SetSecondaryMaterial(material* What, int SpecialFlags) { SetMaterial(SecondaryMaterial, What, GetDefaultSecondaryVolume(), SpecialFlags); }
16 void meleeweapon::ChangeSecondaryMaterial(material* What, int SpecialFlags) { ChangeMaterial(SecondaryMaterial, What, GetDefaultSecondaryVolume(), SpecialFlags); }
17 void meleeweapon::InitMaterials(material* M1, material* M2, truth CUP) { ObjectInitMaterials(MainMaterial, M1, GetDefaultMainVolume(), SecondaryMaterial, M2, GetDefaultSecondaryVolume(), CUP); }
18 double meleeweapon::GetTHVBonus() const { return Enchantment * .5; }
19 double meleeweapon::GetDamageBonus() const { return Enchantment; }
20 col16 meleeweapon::GetDripColor() const { return Fluid[0]->GetLiquid()->GetColor(); }
21 truth meleeweapon::IsDippable(ccharacter*) const { return !Fluid; }
22 truth meleeweapon::AllowRegularColors() const { return SecondaryMaterial->GetVolume(); }
23 v2 meleeweapon::GetWieldedBitmapPos(int I) const { return SecondaryMaterial->GetVolume() ? item::GetWieldedBitmapPos(I) : v2(160, 128); }
24 void meleeweapon::InitMaterials(const materialscript* M, const materialscript* S, truth CUP) { InitMaterials(M->Instantiate(), S->Instantiate(), CUP); }
26 col16 justifier::GetOutlineColor(int) const { return MakeRGB16(0, 255, 0); }
28 col16 neercseulb::GetOutlineColor(int) const { return MakeRGB16(255, 0, 0); }
30 int flamingsword::GetSpecialFlags() const { return meleeweapon::GetSpecialFlags()|ST_FLAME_1; }
32 col16 gorovitsweapon::GetOutlineColor(int) const { return MakeRGB16(255, 0, 0); }
34 int thunderhammer::GetSpecialFlags() const { return !IsBroken() ? meleeweapon::GetSpecialFlags()|ST_LIGHTNING : meleeweapon::GetSpecialFlags(); }
36 int armor::GetCarryingBonus() const { return Enchantment << 1; }
37 double armor::GetTHVBonus() const { return Enchantment * .5; }
38 double armor::GetDamageBonus() const { return Enchantment; }
40 sLong bodyarmor::GetPrice() const { return (armor::GetPrice() << 3) + GetEnchantedPrice(Enchantment); }
41 truth bodyarmor::IsInCorrectSlot(int I) const { return I == BODY_ARMOR_INDEX; }
42 cfestring& bodyarmor::GetNameSingular() const { return GetMainMaterial()->GetFlexibility() >= 5 ? item::GetFlexibleNameSingular() : item::GetNameSingular(); }
43 cchar* bodyarmor::GetBreakVerb() const { return GetMainMaterial()->GetFlexibility() >= 5 ? "is torn apart" : "breaks"; }
45 col16 goldeneagleshirt::GetOutlineColor(int) const { return MakeRGB16(0, 255, 255); }
47 sLong cloak::GetPrice() const { return armor::GetPrice() * 10 + GetEnchantedPrice(Enchantment); }
48 truth cloak::IsInCorrectSlot(int I) const { return I == CLOAK_INDEX; }
49 col16 cloak::GetMaterialColorB(int) const { return MakeRGB16(111, 64, 37); }
50 cchar* cloak::GetBreakVerb() const { return GetMainMaterial()->GetFlexibility() >= 5 ? "is torn apart" : "breaks"; }
51 truth cloak::ReceiveDamage(character* Damager, int Damage, int Type, int Dir) { return armor::ReceiveDamage(Damager, Damage >> 1, Type, Dir); }
52 int cloak::GetSpecialFlags() const { return ST_CLOAK; }
54 sLong boot::GetPrice() const { return armor::GetPrice() / 5 + GetEnchantedPrice(Enchantment); }
55 truth boot::IsInCorrectSlot(int I) const { return I == RIGHT_BOOT_INDEX || I == LEFT_BOOT_INDEX; }
57 sLong gauntlet::GetPrice() const { return armor::GetPrice() / 3 + GetEnchantedPrice(Enchantment); }
58 truth gauntlet::IsInCorrectSlot(int I) const { return I == RIGHT_GAUNTLET_INDEX || I == LEFT_GAUNTLET_INDEX; }
60 sLong belt::GetPrice() const { return armor::GetPrice() * 5 + GetEnchantedPrice(Enchantment); }
61 truth belt::IsInCorrectSlot(int I) const { return I == BELT_INDEX; }
63 truth ring::IsInCorrectSlot(int I) const { return I == RIGHT_RING_INDEX || I == LEFT_RING_INDEX; }
64 col16 ring::GetMaterialColorB(int) const { return MakeRGB16(200, 200, 200); }
66 truth amulet::IsInCorrectSlot(int I) const { return I == AMULET_INDEX; }
67 col16 amulet::GetMaterialColorB(int) const { return MakeRGB16(111, 64, 37); }
69 truth helmet::IsGorovitsFamilyRelic() const { return GetConfig() == GOROVITS_FAMILY_GAS_MASK; }
70 sLong helmet::GetPrice() const { return armor::GetPrice() + GetEnchantedPrice(Enchantment); }
71 truth helmet::IsInCorrectSlot(int I) const { return I == HELMET_INDEX; }
72 col16 helmet::GetMaterialColorB(int) const { return GetConfig() != GOROVITS_FAMILY_GAS_MASK ? (GetConfig() & ~BROKEN) ? MakeRGB16(140, 70, 70) : MakeRGB16(111, 64, 37) : MakeRGB16(0, 40, 0); }
73 col16 helmet::GetMaterialColorC(int) const { return MakeRGB16(180, 200, 180); }
75 int wondersmellstaff::GetClassAnimationFrames() const { return !IsBroken() ? 128 : 1; }
77 truth meleeweapon::HitEffect(character* Enemy, character*, v2, int BodyPartIndex, int, truth BlockedByArmour)
79 if(!BlockedByArmour && Fluid)
81 truth Success = false;
82 fluidvector FluidVector;
83 FillFluidVector(FluidVector);
85 for(uInt c = 0; c < FluidVector.size(); ++c)
86 if(FluidVector[c]->Exists()
87 && FluidVector[c]->GetLiquid()->HitEffect(Enemy, Enemy->GetBodyPart(BodyPartIndex)))
88 Success = true;
90 return Success;
92 else
93 return false;
96 void meleeweapon::DipInto(liquid* Liquid, character* Dipper)
98 if(Dipper->IsPlayer())
99 ADD_MESSAGE("%s is now covered with %s.", CHAR_NAME(DEFINITE), Liquid->GetName(false, false).CStr());
101 SpillFluid(Dipper, Liquid);
102 Dipper->DexterityAction(10);
105 truth pickaxe::Apply(character* User)
107 if(IsBroken())
109 ADD_MESSAGE("%s is totally broken.",CHAR_NAME(DEFINITE));
110 return false;
113 int Dir = game::DirectionQuestion(CONST_S("What direction do you want to dig? [press a direction key]"), false);
115 v2 Temp = game::GetMoveVector(Dir);
116 v2 ToBeDug = User->GetPos() + Temp;
117 if(Dir == DIR_ERROR || !GetArea()->IsValidPos(ToBeDug))
118 return false;
120 lsquare* Square = GetNearLSquare(ToBeDug);
121 olterrain* Terrain = Square->GetOLTerrain();
123 if(!Terrain)
125 ADD_MESSAGE("Nothing to dig there!");
126 return false;
129 if(Square->CanBeDug())
131 if(Terrain->CanBeDestroyed())
132 if(Terrain->GetMainMaterial()->CanBeDug(GetMainMaterial()))
134 int RoomNumber = Square->GetRoomIndex();
136 if(!RoomNumber || Square->GetLevel()->GetRoom(RoomNumber)->CheckDestroyTerrain(User))
138 User->SwitchToDig(this, ToBeDug);
139 User->DexterityAction(5);
140 return true;
142 else
143 return false;
145 else
146 ADD_MESSAGE("%s is too hard to dig with %s.", Square->GetOLTerrain()->CHAR_NAME(DEFINITE), CHAR_NAME(INDEFINITE));
147 else
148 ADD_MESSAGE(Terrain->GetDigMessage().CStr());
151 return false;
154 sLong meleeweapon::GetPrice() const
156 double WeaponStrengthModifier = GetFormModifier() * GetMainMaterial()->GetStrengthValue();
157 WeaponStrengthModifier *= WeaponStrengthModifier;
158 WeaponStrengthModifier *= GetMainMaterial()->GetWeight();
159 WeaponStrengthModifier *= Max((10 + Enchantment) * 0.1, 0.1);
160 return sLong(WeaponStrengthModifier / (20000000.0 * sqrt(GetWeight())))
161 + GetEnchantedPrice(Enchantment);
164 int whip::GetFormModifier() const
166 return item::GetFormModifier() * GetMainMaterial()->GetFlexibility();
169 truth pickaxe::IsAppliable(ccharacter* Who) const
171 return Who->CanWield();
174 void meleeweapon::Save(outputfile& SaveFile) const
176 item::Save(SaveFile);
177 SaveFile << Enchantment;
178 SaveFile << SecondaryMaterial;
181 void meleeweapon::Load(inputfile& SaveFile)
183 item::Load(SaveFile);
184 SaveFile >> Enchantment;
185 LoadMaterial(SaveFile, SecondaryMaterial);
188 material* meleeweapon::GetMaterial(int I) const
190 return !I ? MainMaterial : SecondaryMaterial;
193 col16 meleeweapon::GetMaterialColorB(int) const
195 return SecondaryMaterial->GetVolume() ? SecondaryMaterial->GetColor() : TRANSPARENT_COLOR;
198 alpha meleeweapon::GetAlphaB(int) const
200 return SecondaryMaterial->GetAlpha();
203 truth flamingsword::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
205 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
207 if(Enemy->IsEnabled() && RAND() & 1)
209 if(Hitter)
211 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
212 ADD_MESSAGE("%s sword burns %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
214 else
216 if(Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
217 ADD_MESSAGE("The sword burns %s.", Enemy->CHAR_DESCRIPTION(DEFINITE));
220 return Enemy->ReceiveBodyPartDamage(Hitter, 3 + (RAND() & 3), FIRE, BodyPartIndex, Direction) || BaseSuccess;
222 else
223 return BaseSuccess;
226 truth mjolak::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
228 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
230 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 3))
232 if(Hitter)
234 if(Hitter->IsPlayer())
235 game::DoEvilDeed(10);
237 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
238 ADD_MESSAGE("A burst of %s Mjolak's unholy energy fries %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
240 else
242 if(Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
243 ADD_MESSAGE("A burst of Mjolak's unholy energy fries %s.", Enemy->CHAR_DESCRIPTION(DEFINITE));
246 return Enemy->ReceiveBodyPartDamage(Hitter, 5 + (RAND() % 6), ENERGY, BodyPartIndex, Direction) || BaseSuccess;
248 else
249 return BaseSuccess;
252 truth vermis::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
254 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
256 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5))
258 if(Hitter)
260 if(Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
261 ADD_MESSAGE("%s Vermis sends %s on a sudden journey.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
263 else
265 if(Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
266 ADD_MESSAGE("Vermis sends %s on a sudden journey.", Enemy->CHAR_DESCRIPTION(DEFINITE));
269 Enemy->TeleportRandomly();
270 return true;
272 else
273 return BaseSuccess;
276 truth turox::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
278 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
280 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5))
282 if(Hitter)
284 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
285 ADD_MESSAGE("%s smash%s %s with the full force of Turox.", Hitter->CHAR_PERSONAL_PRONOUN, Hitter->IsPlayer() ? "" : "es", Enemy->CHAR_DESCRIPTION(DEFINITE));
287 else
289 if(Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
290 ADD_MESSAGE("Turox is smashed against %s with full force.", Enemy->CHAR_DESCRIPTION(DEFINITE));
293 if(GetSquareUnder()->CanBeSeenByPlayer(true))
294 ADD_MESSAGE("A magical explosion is triggered!");
296 Enemy->GetLevel()->Explosion(Hitter, CONST_S("burned @bkp Turox's explosion"), HitPos, 10 + RAND() % 100);
297 return true;
299 else
300 return BaseSuccess;
303 truth whipofthievery::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
305 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
307 if(Enemy->IsEnabled() && Hitter && CleptiaHelps(Enemy, Hitter))
309 if(Hitter->IsPlayer())
311 game::DoEvilDeed(10);
312 game::GetGod(CLEPTIA)->AdjustRelation(10);
315 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
316 ADD_MESSAGE("%s whip asks for the help of Cleptia as it steals %s %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_POSSESSIVE_PRONOUN, Enemy->GetMainWielded()->CHAR_NAME(UNARTICLED));
318 Enemy->GetMainWielded()->MoveTo(GetLSquareUnder()->GetStack());
319 return true;
321 else
322 return BaseSuccess;
325 meleeweapon::~meleeweapon()
327 delete SecondaryMaterial;
330 meleeweapon::meleeweapon(const meleeweapon& MW) : mybase(MW), Enchantment(MW.Enchantment)
332 CopyMaterial(MW.SecondaryMaterial, SecondaryMaterial);
335 truth whipofthievery::CleptiaHelps(ccharacter* Enemy, ccharacter* Hitter) const
337 if(Enemy->IsImmuneToWhipOfThievery() || !Enemy->GetMainWielded() || GetMainMaterial()->GetFlexibility() <= 5)
338 return false;
340 if(Hitter->IsPlayer())
342 if(game::GetGod(CLEPTIA)->GetRelation() < 0)
343 return false;
344 else
345 return !RAND_N(10 - game::GetGod(CLEPTIA)->GetRelation() / 200);
347 else
348 return !RAND_N(10);
351 void meleeweapon::AddInventoryEntry(ccharacter* Viewer, festring& Entry, int, truth ShowSpecialInfo) const // never piled
353 AddName(Entry, INDEFINITE);
355 if(ShowSpecialInfo)
357 Entry << " [" << GetWeight() << "g, DAM " << GetBaseMinDamage() << '-' << GetBaseMaxDamage();
358 Entry << ", " << GetBaseToHitValueDescription();
360 if(!IsBroken() && !IsWhip())
361 Entry << ", " << GetStrengthValueDescription();
363 int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this);
364 int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this);
366 if(CWeaponSkillLevel || SWeaponSkillLevel)
367 Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel;
369 Entry << ']';
373 void meleeweapon::SignalSpoil (material *Material) {
374 if (!Exists()) return;
375 if (Material == MainMaterial) {
376 if (CanBeSeenByPlayer()) {
377 if (SecondaryMaterial->GetVolume()) ADD_MESSAGE("The edge of %s spoils.", GetExtendedDescription().CStr());
378 else ADD_MESSAGE("%s spoils.", GetExtendedDescription().CStr());
380 RemoveMainMaterial();
381 } else {
382 if (CanBeSeenByPlayer()) ADD_MESSAGE("The handle of %s spoils", GetExtendedDescription().CStr());
383 delete RemoveSecondaryMaterial();
387 void meleeweapon::AddPostFix(festring& String, int Case) const
389 item::AddPostFix(String, Case);
391 if(Fluid)
393 String << " covered with ";
394 fluid::AddFluidInfo(Fluid[0], String);
397 if(Enchantment > 0)
398 String << " +" << Enchantment;
399 else if(Enchantment < 0)
400 String << ' ' << Enchantment;
403 void meleeweapon::Be()
405 item::Be();
407 if(Exists() && SecondaryMaterial->GetVolume())
408 SecondaryMaterial->Be(ItemFlags);
411 sLong whipofthievery::GetPrice() const
413 /* If intact but not flexible enough to work, special thievery bonus must be removed */
415 return GetMainMaterial()->GetFlexibility() > 5 || IsBroken() ? whip::GetPrice() : whip::GetPrice() - item::GetPrice();
418 int meleeweapon::GetSparkleFlags() const
420 return (MainMaterial->IsSparkling() ? SPARKLING_A|(SecondaryMaterial->GetVolume() ? SPARKLING_C : 0) : 0)
421 | (SecondaryMaterial->IsSparkling() ? SPARKLING_B : 0);
424 void meleeweapon::SetEnchantment(int Amount)
426 Enchantment = Amount;
427 SignalEnchantmentChange();
430 void meleeweapon::EditEnchantment(int Amount)
432 Enchantment += Amount;
433 SignalEnchantmentChange();
436 int meleeweapon::GetStrengthValue() const
438 return Max<int>(sLong(GetStrengthModifier()) * GetMainMaterial()->GetStrengthValue() / 2000 + Enchantment, 0);
441 void meleeweapon::PostConstruct()
443 Enchantment = GetBaseEnchantment();
446 int meleeweapon::GetSpoilLevel() const
448 int MainSpoilLevel = MainMaterial->GetSpoilLevel();
450 if(SecondaryMaterial->GetVolume())
451 return Max(MainSpoilLevel, SecondaryMaterial->GetSpoilLevel());
452 else
453 return MainSpoilLevel;
456 truth neercseulb::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
458 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
460 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5))
462 if(Hitter->IsPlayer())
463 game::DoEvilDeed(10);
465 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
466 ADD_MESSAGE("%s Neerc Se-ulb's life-draining energies swallow %s!", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
468 return Enemy->ReceiveBodyPartDamage(Hitter, 10 + (RAND() % 11), DRAIN, BodyPartIndex, Direction) || BaseSuccess;
470 else
471 return BaseSuccess;
474 truth thunderhammer::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
476 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
478 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5))
480 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
481 ADD_MESSAGE("%s hammer shoots a lightning bolt at %s!", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
483 beamdata Beam
485 Hitter,
486 CONST_S("electrocuted @bkp thunder hammer"),
487 Hitter->GetPos(),
488 WHITE,
489 BEAM_LIGHTNING,
490 Direction,
495 GetLevel()->LightningBeam(Beam);
496 return true;
498 else
499 return BaseSuccess;
502 truth thunderhammer::ReceiveDamage(character* Damager, int Damage, int Type, int Dir)
504 return Type & ELECTRICITY ? false : meleeweapon::ReceiveDamage(Damager, Damage, Type, Dir);
507 sLong armor::GetPrice() const
509 double StrengthValue = GetStrengthValue();
510 return sLong(StrengthValue * StrengthValue * StrengthValue * 20 / sqrt(GetWeight()));
513 int belt::GetFormModifier() const
515 return item::GetFormModifier() * GetMainMaterial()->GetFlexibility();
518 void armor::AddInventoryEntry(ccharacter*, festring& Entry, int Amount, truth ShowSpecialInfo) const
520 if(Amount == 1)
521 AddName(Entry, INDEFINITE);
522 else
524 Entry << Amount << ' ';
525 AddName(Entry, PLURAL);
528 if(ShowSpecialInfo)
529 Entry << " [" << GetWeight() * Amount << "g, AV " << GetStrengthValue() << ']';
532 void shield::AddInventoryEntry(ccharacter* Viewer, festring& Entry, int, truth ShowSpecialInfo) const // never piled
534 AddName(Entry, INDEFINITE);
536 if(ShowSpecialInfo)
538 Entry << " [" << GetWeight() << "g, " << GetBaseBlockValueDescription();
540 if(!IsBroken())
541 Entry << ", " << GetStrengthValueDescription();
543 int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this);
544 int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this);
546 if(CWeaponSkillLevel || SWeaponSkillLevel)
547 Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel;
549 Entry << ']';
553 truth armor::CanBePiledWith(citem* Item, ccharacter* Viewer) const
555 return item::CanBePiledWith(Item, Viewer) && Enchantment == static_cast<const armor*>(Item)->Enchantment;
558 sLong shield::GetPrice() const /* temporary... */
560 double StrengthValue = GetStrengthValue();
561 return sLong(sqrt(GetBaseBlockValue()) * StrengthValue * StrengthValue) + item::GetPrice();
564 void armor::Save(outputfile& SaveFile) const
566 item::Save(SaveFile);
567 SaveFile << Enchantment;
570 void armor::Load(inputfile& SaveFile)
572 item::Load(SaveFile);
573 SaveFile >> Enchantment;
576 void armor::AddPostFix(festring& String, int Case) const
578 item::AddPostFix(String, Case);
580 if(Fluid)
582 String << " covered with ";
583 fluid::AddFluidInfo(Fluid[0], String);
586 if(Enchantment > 0)
587 String << " +" << Enchantment;
588 else if(Enchantment < 0)
589 String << ' ' << Enchantment;
592 void armor::SetEnchantment(int Amount)
594 Enchantment = Amount;
595 SignalEnchantmentChange();
598 void armor::EditEnchantment(int Amount)
600 Enchantment += Amount;
601 SignalEnchantmentChange();
604 int armor::GetStrengthValue() const
606 return Max<sLong>(sLong(GetStrengthModifier()) * GetMainMaterial()->GetStrengthValue() / 2000 + Enchantment, 0);
609 void armor::PostConstruct()
611 Enchantment = GetBaseEnchantment();
614 int armor::GetInElasticityPenalty(int Attribute) const
616 return Attribute * GetInElasticityPenaltyModifier() / (GetMainMaterial()->GetFlexibility() * 100);
619 void meleeweapon::GenerateMaterials()
621 int Chosen = RandomizeMaterialConfiguration();
622 const fearray<sLong>& MMC = GetMainMaterialConfig();
623 InitMaterial(MainMaterial,
624 MAKE_MATERIAL(MMC.Data[MMC.Size == 1 ? 0 : Chosen]),
625 GetDefaultMainVolume());
626 const fearray<sLong>& SMC = GetSecondaryMaterialConfig();
627 InitMaterial(SecondaryMaterial,
628 MAKE_MATERIAL(SMC.Data[SMC.Size == 1 ? 0 : Chosen]),
629 GetDefaultSecondaryVolume());
632 truth chameleonwhip::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
634 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
636 if(!IsBroken() && Enemy->IsEnabled() && ScabiesHelps(Enemy, Hitter))
638 if(Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
639 ADD_MESSAGE("%s whip asks for the help of Scabies as it polymorphs %s.", Hitter->CHAR_PERSONAL_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
641 if(Hitter->IsPlayer())
643 game::DoEvilDeed(20);
644 game::GetGod(SCABIES)->AdjustRelation(10);
647 int CurrentDanger = int(Enemy->GetRelativeDanger(PLAYER) * 1000);
648 Enemy->PolymorphRandomly(CurrentDanger / 4, Min(CurrentDanger, 999999), 100 + RAND() % 400);
649 return true;
651 else
652 return BaseSuccess;
655 truth chameleonwhip::ScabiesHelps(ccharacter* Enemy, ccharacter* Hitter) const
657 if(!Enemy->IsPolymorphable())
658 return false;
660 if(Hitter->IsPlayer())
662 if(game::GetGod(SCABIES)->GetRelation() < 0)
663 return false;
664 else
665 return !(RAND() % (20 - game::GetGod(SCABIES)->GetRelation() / 150));
667 else
668 return !(RAND() % 20);
671 alpha justifier::GetOutlineAlpha(int Frame) const
673 Frame &= 31;
674 return 50 + (Frame * (31 - Frame) >> 1);
677 alpha neercseulb::GetOutlineAlpha(int Frame) const
679 Frame &= 31;
680 return 50 + (Frame * (31 - Frame) >> 1);
683 alpha gorovitsweapon::GetOutlineAlpha(int Frame) const
685 Frame &= 31;
686 return 50 + (Frame * (31 - Frame) >> 1);
689 alpha goldeneagleshirt::GetOutlineAlpha(int Frame) const
691 Frame &= 31;
692 return 50 + (Frame * (31 - Frame) >> 1);
695 alpha wondersmellstaff::GetOutlineAlpha(int Frame) const
697 if(!IsBroken())
699 Frame &= 31;
700 return Frame * (31 - Frame) >> 1;
702 else
703 return 255;
706 col16 wondersmellstaff::GetOutlineColor(int Frame) const
708 if(!IsBroken())
709 switch((Frame&127) >> 5)
711 case 0: return BLUE;
712 case 1: return GREEN;
713 case 2: return RED;
714 case 3: return YELLOW;
717 return TRANSPARENT_COLOR;
720 truth wondersmellstaff::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
722 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
724 if(!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5))
726 if(RAND() & 3)
728 truth Seen = false;
729 int Amount = 250 / Enemy->GetSquaresUnder();
731 for(int c = 0; c < Enemy->GetSquaresUnder(); ++c)
733 lsquare* Square = Enemy->GetLSquareUnder(c);
735 if(Square->IsFlyable())
737 Square->AddSmoke(gas::Spawn(EVIL_WONDER_STAFF_VAPOUR, Amount));
739 if(!Seen && Square->CanBeSeenByPlayer())
740 Seen = true;
744 if(Seen)
745 ADD_MESSAGE("Strange red smoke billows out of %s staff.", Hitter->CHAR_POSSESSIVE_PRONOUN);
747 else
749 /* Can a multitiled creature ever be the hitter? */
751 lsquare* Square = Hitter->GetLSquareUnder();
753 if(Square->IsFlyable())
755 if(Square->CanBeSeenByPlayer())
756 ADD_MESSAGE("Strange blue smoke billows out of %s staff.", Hitter->CHAR_POSSESSIVE_PRONOUN);
758 Square->AddSmoke(gas::Spawn(GOOD_WONDER_STAFF_VAPOUR, 100));
762 return true;
764 else
765 return BaseSuccess;
768 truth bodyarmor::AddAdjective(festring& String, truth Articled) const
770 if(IsBroken())
772 if(Articled)
773 String << "a ";
775 if(GetMainMaterial()->GetFlexibility() >= 5)
776 String << "torn";
777 else
778 String << "broken";
780 String << ' ';
781 return true;
783 else
784 return false;
787 truth cloak::AddAdjective(festring& String, truth Articled) const
789 if(IsBroken())
791 if(Articled)
792 String << "a ";
794 if(GetMainMaterial()->GetFlexibility() >= 5)
795 String << "torn";
796 else
797 String << "broken";
799 String << ' ';
800 return true;
802 else
803 return false;
806 int meleeweapon::GetRustDataB() const
808 return SecondaryMaterial->GetRustData();
811 void meleeweapon::TryToRust(sLong LiquidModifier)
813 item::TryToRust(LiquidModifier);
815 if(SecondaryMaterial->GetVolume() && SecondaryMaterial->TryToRust(LiquidModifier))
816 SecondaryMaterial->SetRustLevel(SecondaryMaterial->GetRustLevel() + 1);
819 material* meleeweapon::GetConsumeMaterial(ccharacter* Consumer, materialpredicate Predicate) const
821 if((SecondaryMaterial->*Predicate)()
822 && SecondaryMaterial->GetVolume()
823 && Consumer->CanConsume(SecondaryMaterial))
824 return SecondaryMaterial;
825 else
826 return item::GetConsumeMaterial(Consumer, Predicate);
829 material* meleeweapon::RemoveMaterial(material* Material)
831 if(Material == MainMaterial)
832 return RemoveMainMaterial();
833 else
834 return RemoveSecondaryMaterial();
837 material* meleeweapon::RemoveMainMaterial()
839 truth Equipped = PLAYER->Equips(this);
841 if(SecondaryMaterial->GetVolume())
843 item* Lump = SecondaryMaterial->CreateNaturalForm(SecondaryMaterial->GetVolume());
844 DonateFluidsTo(Lump);
845 DonateIDTo(Lump);
846 DonateSlotTo(Lump);
848 else
849 RemoveFromSlot();
851 if(Equipped)
852 game::AskForEscPress(CONST_S("Equipment destroyed!"));
854 SendToHell();
855 return 0;
858 material* meleeweapon::RemoveSecondaryMaterial()
860 SecondaryMaterial->SetVolume(0);
862 if(!IsBroken())
863 Break(0);
864 else
866 RedistributeFluids();
867 UpdatePictures();
868 SendNewDrawAndMemorizedUpdateRequest();
871 return 0;
874 pixelpredicate meleeweapon::GetFluidPixelAllowedPredicate() const
876 if(SecondaryMaterial->GetVolume())
877 return &rawbitmap::IsTransparent;
878 else
879 return &rawbitmap::IsMaterialColor1;
882 void meleeweapon::CalculateEmitation()
884 Emitation = GetBaseEmitation();
886 if(MainMaterial)
887 game::CombineLights(Emitation, MainMaterial->GetEmitation());
889 if(SecondaryMaterial->GetVolume())
890 game::CombineLights(Emitation, SecondaryMaterial->GetEmitation());
893 truth meleeweapon::CalculateHasBe() const
895 return LifeExpectancy
896 || (MainMaterial && MainMaterial->HasBe())
897 || (SecondaryMaterial
898 && SecondaryMaterial->GetVolume()
899 && SecondaryMaterial->HasBe());
902 void decosadshirt::Be()
904 if(PLAYER->Equips(this))
905 ++EquippedTicks;
907 bodyarmor::Be();
910 decosadshirt::decosadshirt() : EquippedTicks(0)
912 Enable();
915 void decosadshirt::Save(outputfile& SaveFile) const
917 bodyarmor::Save(SaveFile);
918 SaveFile << EquippedTicks;
921 void decosadshirt::Load(inputfile& SaveFile)
923 bodyarmor::Load(SaveFile);
924 SaveFile >> EquippedTicks;
925 Enable();
928 item* meleeweapon::Fix()
930 SecondaryMaterial->SetVolumeNoSignals(GetDefaultSecondaryVolume());
931 return item::Fix();
934 sLong meleeweapon::GetMaterialPrice() const
936 return MainMaterial->GetRawPrice() + SecondaryMaterial->GetRawPrice();
939 void meleeweapon::CalculateEnchantment()
941 Enchantment -= femath::LoopRoll(game::GetCurrentLevel()->GetEnchantmentMinusChance(), 5);
942 Enchantment += femath::LoopRoll(game::GetCurrentLevel()->GetEnchantmentPlusChance(), 5);
943 Enchantment -= femath::LoopRoll(GetEnchantmentMinusChance(), 5);
944 Enchantment += femath::LoopRoll(GetEnchantmentPlusChance(), 5);
947 void armor::CalculateEnchantment()
949 Enchantment -= femath::LoopRoll(game::GetCurrentLevel()->GetEnchantmentMinusChance(), 5);
950 Enchantment += femath::LoopRoll(game::GetCurrentLevel()->GetEnchantmentPlusChance(), 5);
951 Enchantment -= femath::LoopRoll(GetEnchantmentMinusChance(), 5);
952 Enchantment += femath::LoopRoll(GetEnchantmentPlusChance(), 5);
955 col16 meleeweapon::GetMaterialColorC(int Frame) const
957 return SecondaryMaterial->GetVolume() ? GetMaterialColorA(Frame) : TRANSPARENT_COLOR;
960 void daggerofvenom::Be()
962 meleeweapon::Be();
964 if(Exists() && !IsBroken() && (*Slot)->IsGearSlot() && !RAND_N(10))
966 fluidvector FluidVector;
967 FillFluidVector(FluidVector);
968 uInt Volume = 0;
970 for(uInt c = 0; c < FluidVector.size(); ++c)
972 liquid* L = FluidVector[c]->GetLiquid();
973 Volume += L->GetVolume(); //I imagine that there is a function I don't know to do this...
976 if(Volume < 90)
977 SpillFluid(0, liquid::Spawn(POISON_LIQUID, 10));
981 truth weepblade::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
983 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
985 if(Enemy->IsEnabled() && !(RAND_N(3)))
987 if(Enemy->IsPlayer() || Hitter->IsPlayer()
988 || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
989 ADD_MESSAGE("%s weeping blade spills acid on %s.",
990 Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
991 Enemy->SpillFluid(PLAYER, liquid::Spawn(SULPHURIC_ACID, 25+RAND()%25));
992 return BaseSuccess;
994 else
995 return BaseSuccess;
998 void acidshield::BlockEffect(character* Blocker, character* Attacker, item* Weapon, int Type)
1000 /*k8 int CheckAttackType = 0;*/
1001 if(!IsBroken())
1003 if(!RAND_N(400))
1005 if(Weapon)
1007 Weapon->SpillFluid(Blocker, liquid::Spawn(SULPHURIC_ACID, 200 + RAND() % 51));
1008 ADD_MESSAGE("%s is completely doused in sulpheric acid!", Attacker->CHAR_DESCRIPTION(DEFINITE));
1009 return;
1013 if(RAND_2 && Weapon)
1015 Weapon->SpillFluid(Blocker, liquid::Spawn(SULPHURIC_ACID, 20 + RAND() % 41));
1016 ADD_MESSAGE("%s weapon is splashed with acid from the shield!", Attacker->CHAR_POSSESSIVE_PRONOUN);
1019 if(!RAND_N(5))
1021 Attacker->SpillFluid(Blocker, liquid::Spawn(SULPHURIC_ACID, 5 + RAND() % 11));
1022 ADD_MESSAGE("%s is splashed with acid!", Attacker->CHAR_DESCRIPTION(DEFINITE));
1023 return;
1026 if(RAND_2)
1028 Attacker->SpillFluid(Blocker, liquid::Spawn(SULPHURIC_ACID, 25 + RAND() % 26));
1029 ADD_MESSAGE("%s is splashed with acid from the shield!", Attacker->CHAR_DESCRIPTION(DEFINITE));
1035 void wondersmellstaff::Break(character* Who, int Much)
1037 /*k8: material* GasMaterial = GetSecondaryMaterial(); */
1038 GetLevel()->GasExplosion(gas::Spawn(GOOD_WONDER_STAFF_VAPOUR, 100), GetLSquareUnder());
1040 if(CanBeSeenByPlayer())
1042 ADD_MESSAGE("%s unleashes a puff of a wonderous gas.", CHAR_NAME(DEFINITE));
1045 meleeweapon::Break(Who,Much);
1049 truth vacuumblade::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1050 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1051 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 2)) {
1052 if (Hitter) {
1053 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1054 ADD_MESSAGE("%s blade creates a wind vortex cutting %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1055 } else {
1056 if (Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer())
1057 ADD_MESSAGE("The blade creates a wind vortex cutting %s.", Enemy->CHAR_DESCRIPTION(DEFINITE));
1059 return Enemy->ReceiveBodyPartDamage(Hitter, 6 + (RAND() % 6), ENERGY, BodyPartIndex, Direction) || BaseSuccess;
1061 return BaseSuccess;
1065 col16 masamune::GetOutlineColor (int) const { return MakeRGB16(0, 0, 255); }
1067 alpha masamune::GetOutlineAlpha (int Frame) const {
1068 Frame &= 31;
1069 return 50+(Frame*(31-Frame)>>1);
1072 truth masamune::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1073 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1074 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 4)) {
1075 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1076 ADD_MESSAGE("%s Masamune's slash cuts %s so deep you thought it was cut in half for a moment.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1077 return Enemy->ReceiveBodyPartDamage(Hitter, 4 + (RAND() % 4), PHYSICAL_DAMAGE, BodyPartIndex, Direction) || BaseSuccess;
1079 return BaseSuccess;
1082 truth zulfiqar::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1083 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1084 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 3)) {
1085 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1086 ADD_MESSAGE("%s Zulfiqar's slash deeply cuts %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1087 return Enemy->ReceiveBodyPartDamage(Hitter, 4 + (RAND() % 5), PHYSICAL_DAMAGE, BodyPartIndex, Direction) || BaseSuccess;
1089 return BaseSuccess;
1092 truth tipswordofpenetration::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1093 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1094 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 3)) {
1095 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1096 ADD_MESSAGE("%s tip sword's slash penetrates %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1097 return Enemy->ReceiveBodyPartDamage(Hitter, 2 + (RAND() % 5), PHYSICAL_DAMAGE, BodyPartIndex, Direction) || BaseSuccess;
1099 return BaseSuccess;
1103 col16 loricatushammer::GetOutlineColor (int) const { return MakeRGB16(0, 0, 255); }
1105 alpha loricatushammer::GetOutlineAlpha (int Frame) const {
1106 Frame &= 31;
1107 return 50 + (Frame * (31 - Frame) >> 1);
1111 col16 belderiver::GetOutlineColor (int) const { return MakeRGB16(180, 50, 50); }
1113 alpha belderiver::GetOutlineAlpha (int Frame) const {
1114 Frame &= 31;
1115 return 50 + (Frame * (31 - Frame) >> 1);
1119 col16 demonhead::GetOutlineColor (int) const { return MakeRGB16(255, 0, 0); }
1121 alpha demonhead::GetOutlineAlpha (int Frame) const {
1122 Frame &= 31;
1123 return 50 + (Frame * (31 - Frame) >> 1);
1127 col16 muramasa::GetOutlineColor (int) const { return MakeRGB16(255, 0, 0); }
1129 alpha muramasa::GetOutlineAlpha (int Frame) const {
1130 Frame &= 31;
1131 return 50 + (Frame * (31 - Frame) >> 1);
1134 truth muramasa::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1135 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1136 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5)) {
1137 if (Hitter->IsPlayer()) game::DoEvilDeed(10);
1138 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1139 ADD_MESSAGE("%s Muramasa's life-draining energies swallow %s!", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1140 return Enemy->ReceiveBodyPartDamage(Hitter, 10 + (RAND() % 11), DRAIN, BodyPartIndex, Direction) || BaseSuccess;
1142 return BaseSuccess;
1146 int smite::GetSpecialFlags() const {
1147 return !IsBroken() ? meleeweapon::GetSpecialFlags()|ST_LIGHTNING : meleeweapon::GetSpecialFlags();
1150 truth smite::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1151 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1152 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5)) {
1153 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1154 ADD_MESSAGE("%s mace named Smite shoots a lightning bolt at %s!", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1155 beamdata Beam (
1156 Hitter,
1157 CONST_S("electrocuted @bkp mace named Smite"),
1158 Hitter->GetPos(),
1159 WHITE,
1160 BEAM_LIGHTNING,
1161 Direction,
1165 GetLevel()->LightningBeam(Beam);
1166 return true;
1168 return BaseSuccess;
1171 truth smite::ReceiveDamage (character *Damager, int Damage, int Type, int Dir) {
1172 return Type & ELECTRICITY ? false : meleeweapon::ReceiveDamage(Damager, Damage, Type, Dir);
1176 col16 goldenjaguarshirt::GetOutlineColor (int) const { return MakeRGB16(255, 255, 128); }
1178 alpha goldenjaguarshirt::GetOutlineAlpha (int Frame) const {
1179 Frame &= 31;
1180 return 50 + (Frame * (31 - Frame) >> 1);
1184 col16 kawai::GetOutlineColor (int) const { return MakeRGB16(255, 0, 0); }
1186 alpha kawai::GetOutlineAlpha (int Frame) const {
1187 Frame &= 31;
1188 return 50 + (Frame * (31 - Frame) >> 1);
1191 truth kawai::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) {
1192 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1193 if (!IsBroken() && Enemy->IsEnabled() && !(RAND() % 5)) {
1194 if (Hitter->IsPlayer()) game::DoEvilDeed(10);
1195 if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer())
1196 ADD_MESSAGE("%s Kawai's life-draining energies swallow %s!", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE));
1197 return Enemy->ReceiveBodyPartDamage(Hitter, 10 + (RAND() % 11), DRAIN, BodyPartIndex, Direction) || BaseSuccess;
1199 return BaseSuccess;
1203 int eptyron::GetClassAnimationFrames() const { return !IsBroken() ? 128 : 1; }
1205 //Entropyaxe code begins
1207 /** Whatever is not commented below, is stuff that works */
1209 truth eptyron::HitEffect(character* Enemy, character* Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour)
1211 truth BaseSuccess = meleeweapon::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour);
1212 int Index = 0;
1215 if(!IsBroken() && Enemy->IsEnabled() && Enemy->IsHumanoid() /*&& !(RAND() % 2)*/)
1217 //bodypart* BodyPartThatWasHit = Enemy -> GetBodyPart(BodyPartIndex);
1218 item* MainArmor = 0;
1220 switch(BodyPartIndex)
1222 case TORSO_INDEX:
1223 MainArmor = Enemy->GetEquipment(BODY_ARMOR_INDEX);
1224 break;
1225 case HEAD_INDEX:
1226 MainArmor = Enemy->GetEquipment(HELMET_INDEX);
1227 break;
1228 case RIGHT_ARM_INDEX:
1229 MainArmor = Enemy->GetEquipment(RIGHT_GAUNTLET_INDEX);
1230 //BodyPartThatWasHit = Enemy -> GetBodyPart(BodyPartIndex);
1231 break;
1232 case LEFT_ARM_INDEX:
1233 MainArmor = Enemy->GetEquipment(LEFT_GAUNTLET_INDEX);
1234 //BodyPartThatWasHit = Enemy -> GetBodyPart(BodyPartIndex);
1235 break;
1236 case GROIN_INDEX:
1237 MainArmor = Enemy->GetEquipment(BELT_INDEX);
1238 break;
1239 case RIGHT_LEG_INDEX:
1240 MainArmor = Enemy->GetEquipment(RIGHT_BOOT_INDEX);
1241 //BodyPartThatWasHit = Enemy -> GetBodyPart(BodyPartIndex);
1242 break;
1243 case LEFT_LEG_INDEX:
1244 MainArmor = Enemy->GetEquipment(LEFT_BOOT_INDEX);
1245 //BodyPartThatWasHit = Enemy -> GetBodyPart(BodyPartIndex);
1246 break;
1249 if(MainArmor)
1251 material* OldMaterial = MainArmor->GetMainMaterial();
1252 int OldModifier = OldMaterial->GetHardenModifier(MainArmor);
1253 materialvector MaterialVector;
1254 protosystem::CreateEveryMaterial(MaterialVector);
1255 truth Changed = false;
1256 int * CandidateMaterialIndex;
1257 CandidateMaterialIndex = new int[MaterialVector.size()];
1259 festring Desc;
1260 MainArmor->AddName(Desc, UNARTICLED);
1262 for(unsigned int c = 0; c < MaterialVector.size(); ++c)
1264 if((MaterialVector[c]->GetCommonFlags() & CAN_BE_WISHED)
1265 && (MaterialVector[c]->GetConsumeType() & OldMaterial->GetConsumeType()) )
1267 material* Material = MaterialVector[c];
1269 if(Material->GetHardenModifier(MainArmor) < OldModifier
1270 /*&& Material->GetRawPrice() < OldMaterial->GetRawPrice()*/
1271 && ((Material->GetCommonFlags() & IS_VALUABLE) == (OldMaterial->GetCommonFlags() & IS_VALUABLE)) //Hint: ie only valuable can entropy to valuable, and non-valuable to non-valuable
1272 && ( 10*(1 + OldMaterial->GetIntelligenceRequirement() - Material->GetIntelligenceRequirement()) < (Hitter->GetAttribute(INTELLIGENCE))*(Hitter->GetSWeaponSkillLevel(this)) ) )
1274 CandidateMaterialIndex[Index++] = c;
1278 if(Index)
1280 int Chosen = CandidateMaterialIndex[(RAND() % Index)];
1281 material* ChosenMaterial = MaterialVector[Chosen];
1282 MainArmor->ChangeMainMaterial(ChosenMaterial->SpawnMore());
1283 if(ChosenMaterial != NONE)
1285 if(Hitter->IsPlayer())
1287 ADD_MESSAGE("%s's %s softens into %s!", Enemy->CHAR_DESCRIPTION(DEFINITE), Desc.CStr() , ChosenMaterial->GetName(false, false).CStr());
1289 else
1290 ADD_MESSAGE("Your %s softens into %s!", Desc.CStr(), ChosenMaterial->GetName(false, false).CStr());
1291 Changed = true;
1293 else
1295 Changed = false;
1298 delete[] CandidateMaterialIndex;
1300 for(unsigned int c = 0; c < MaterialVector.size(); ++c) delete MaterialVector[c];
1301 if(!Changed) {
1302 if(Hitter->IsPlayer())
1304 ADD_MESSAGE("%s's %s vibrates slightly but remains unchanged.", Enemy->CHAR_DESCRIPTION(DEFINITE), MainArmor->CHAR_NAME(UNARTICLED) );
1306 else
1307 ADD_MESSAGE("Your %s vibrates slightly but remains unchanged.", MainArmor->CHAR_NAME(UNARTICLED) );
1309 return Changed;
1312 /*this bit softens enemy limbs!!! but pictures do not update :( */
1313 //if(BodyPartThatWasHit && !(Enemy -> BodyPartIsVital(BodyPartIndex)) )
1315 // material* OldMaterial = BodyPartThatWasHit->GetMainMaterial();
1316 // int OldModifier = OldMaterial->GetHardenModifier(BodyPartThatWasHit);
1317 // materialvector MaterialVector;
1318 // protosystem::CreateEveryMaterial(MaterialVector);
1319 // truth Changed = false;
1321 //// for(c = 0; c < MaterialVector.size(); ++c)
1322 // {
1323 // if(MaterialVector[c]->GetCommonFlags() & CAN_BE_WISHED)
1324 // {
1325 // material* Material = MaterialVector[c];
1327 //// if(Material->GetHardenModifier(BodyPartThatWasHit) < OldModifier
1328 // /*&& !RAND_N(Max(Material->GetIntelligenceRequirement() - 15, 1))*/)
1329 // {
1330 // BodyPartThatWasHit->ChangeMainMaterial(Material->SpawnMore());
1331 // if(Hitter->IsPlayer())
1332 // {
1333 // ADD_MESSAGE("%s %s softens into %s!", Enemy->CHAR_POSSESSIVE_PRONOUN, BodyPartThatWasHit->GetBodyPartName().CStr() , Material->GetName(false, false).CStr());
1334 // }
1335 // else
1336 // ADD_MESSAGE("Your %s softens into %s!", BodyPartThatWasHit->GetBodyPartName().CStr(), Material->GetName(false, false).CStr());
1337 // Changed = true;
1338 // break;
1339 // }
1340 // }
1341 // }
1342 // for(c = 0; c < MaterialVector.size(); ++c)
1343 // delete MaterialVector[c];
1344 // if(!Changed)
1345 // if(Hitter->IsPlayer())
1346 // {
1347 // ADD_MESSAGE("%s %s vibrates slightly but remains unchanged.", Enemy->CHAR_POSSESSIVE_PRONOUN, BodyPartThatWasHit->GetBodyPartName().CStr() );
1348 // }
1349 // else
1350 // ADD_MESSAGE("Your %s vibrates slightly but remains unchanged.", BodyPartThatWasHit->GetBodyPartName().CStr() );
1352 // return Changed;
1356 ////if(BlockedByArmour)
1357 ////{
1358 // if(MainArmor)
1359 // {
1360 // if(MainArmor->IsMaterialChangeable())
1361 // {
1362 // festring Desc;
1363 // MainArmor->AddName(Desc, UNARTICLED);
1364 // Desc << " is transformed";
1366 // switch(RAND() % 3)
1367 // {
1368 // case 0:
1369 // MainArmor->ChangeMainMaterial(MAKE_MATERIAL(CLOTH));
1370 // break;
1371 // case 1:
1372 // MainArmor->ChangeMainMaterial(MAKE_MATERIAL(PLANT_FIBER));
1373 // break;
1374 // case 2:
1375 // MainArmor->ChangeMainMaterial(MAKE_MATERIAL(PARCHMENT));
1376 // break;
1377 // }
1378 // if(Hitter->IsPlayer())
1379 // {
1380 // ADD_MESSAGE("%s's %s", Enemy->CHAR_DESCRIPTION(DEFINITE), Desc.CStr());
1381 // }
1382 // else
1383 // ADD_MESSAGE("Your %s", Desc.CStr());
1384 // }
1385 // else
1386 // ADD_MESSAGE("%s's %s emits a strange light but remain unchanged.", Enemy->CHAR_DESCRIPTION(DEFINITE), MainArmor->CHAR_NAME(DEFINITE));
1387 // }
1388 // return true;
1389 ////}
1391 //if(BodyPartThatWasHit && !(Enemy -> BodyPartIsVital(BodyPartIndex)) )
1393 // if(BodyPartThatWasHit->IsMaterialChangeable())
1394 // {
1395 // if(Hitter->IsPlayer())
1396 // {
1397 // ADD_MESSAGE("%s's %s softens into banana flesh.", Enemy->CHAR_DESCRIPTION(DEFINITE), BodyPartThatWasHit->GetBodyPartName().CStr() );
1398 // }
1399 // else
1400 // ADD_MESSAGE("Your %s softens into banana flesh.", BodyPartThatWasHit->GetBodyPartName().CStr() );
1402 // BodyPartThatWasHit->ChangeMainMaterial(MAKE_MATERIAL(BANANA_FLESH));
1403 // }
1404 // else
1405 // ADD_MESSAGE("%s's %s emits a strange light but remains unchanged.", Enemy->CHAR_DESCRIPTION(DEFINITE), BodyPartThatWasHit->GetBodyPartName().CStr() );
1406 // }
1407 //return true;
1409 return BaseSuccess;
1412 void eptyron::BlockEffect(character* Blocker, character* Attacker, item* Weapon, int Type)
1414 int Index = 0;
1416 if(!IsBroken())
1418 if(Weapon && !(Weapon->IsWhip()))
1420 material* OldMaterial = Weapon->GetMainMaterial();
1421 int OldModifier = OldMaterial->GetHardenModifier(Weapon);
1422 materialvector MaterialVector;
1423 protosystem::CreateEveryMaterial(MaterialVector);
1424 truth Changed = false;
1425 int * CandidateMaterialIndex;
1426 CandidateMaterialIndex = new int[MaterialVector.size()];
1428 festring Desc;
1429 Weapon->AddName(Desc, UNARTICLED);
1431 for(unsigned int c = 0; c < MaterialVector.size(); ++c)
1433 if((MaterialVector[c]->GetCommonFlags() & CAN_BE_WISHED)
1434 && (MaterialVector[c]->GetConsumeType() & OldMaterial->GetConsumeType()) )
1436 material* Material = MaterialVector[c];
1438 if(Material->GetHardenModifier(Weapon) < OldModifier
1439 && Material->GetRawPrice() < OldMaterial->GetRawPrice()
1440 && ((Material->GetCommonFlags() & IS_VALUABLE) == (OldMaterial->GetCommonFlags() & IS_VALUABLE)) //ie only valuable can entropy to valuable, and non-valuable to non-valuable
1441 && ( 10*(1 + OldMaterial->GetIntelligenceRequirement() - Material->GetIntelligenceRequirement()) < (Blocker->GetAttribute(INTELLIGENCE))*(Blocker->GetSWeaponSkillLevel(this)) ) )
1443 CandidateMaterialIndex[Index++] = c;
1447 if(Index)
1449 int Chosen = CandidateMaterialIndex[(RAND() % Index)];
1450 material* ChosenMaterial = MaterialVector[Chosen];
1451 Weapon->ChangeMainMaterial(ChosenMaterial->SpawnMore());
1452 if(ChosenMaterial != NONE)
1454 if(Blocker->IsPlayer())
1456 ADD_MESSAGE("%s's %s softens into %s!", Attacker->CHAR_DESCRIPTION(DEFINITE), Desc.CStr() , ChosenMaterial->GetName(false, false).CStr());
1458 else
1459 ADD_MESSAGE("Your %s softens into %s!", Desc.CStr(), ChosenMaterial->GetName(false, false).CStr());
1460 Changed = true;
1462 else
1464 Changed = false;
1467 delete[] CandidateMaterialIndex;
1469 for(unsigned int c = 0; c < MaterialVector.size(); ++c) delete MaterialVector[c];
1470 if(!Changed) {
1471 if(Blocker->IsPlayer())
1473 ADD_MESSAGE("%s's %s vibrates slightly but remains unchanged.", Attacker->CHAR_DESCRIPTION(DEFINITE), Weapon->CHAR_NAME(UNARTICLED) );
1475 else
1476 ADD_MESSAGE("Your %s vibrates slightly but remains unchanged.", Weapon->CHAR_NAME(UNARTICLED) );
1478 return;
1481 return;
1484 //Entropyaxe code ends
1486 alpha eptyron::GetOutlineAlpha(int Frame) const
1488 if(!IsBroken())
1490 Frame &= 31;
1491 return Frame * (31 - Frame) >> 1;
1493 else
1494 return 255;
1497 col16 eptyron::GetOutlineColor(int Frame) const
1499 if(!IsBroken())
1500 switch((Frame&127) >> 5)
1502 case 0: return BLUE;
1503 case 1: return GREEN;
1504 case 2: return RED;
1505 case 3: return YELLOW;
1508 return TRANSPARENT_COLOR;
1512 int taiaha::GetClassAnimationFrames() const { return !IsBroken() ? 128 : 1; }
1514 //begin taiaha
1516 truth taiaha::Zap(character* Zapper, v2, int Direction)
1518 if(Charges <= TimesUsed)
1520 ADD_MESSAGE("Nothing happens.");
1521 return true;
1524 Zapper->EditExperience(PERCEPTION, 150, 1 << 10);
1525 int TaiahaBeamEffect = RAND() & 3;
1527 beamdata Beam // Just hard-code this
1529 Zapper,
1530 CONST_S("killed by ") + GetName(INDEFINITE) + " zapped @bk",
1531 Zapper->GetPos(),
1532 GREEN, //was GetBeamColor()
1533 TaiahaBeamEffect ? ((RAND() & 2) ? BEAM_FIRE_BALL : BEAM_STRIKE ) : BEAM_LIGHTNING, //was GetBeamEffect()
1534 Direction,
1535 15, // 10 is the lowest beamrange out of the three
1536 0 //was GetSpecialParameters()
1539 (GetLevel()->*level::GetBeam(!TaiahaBeamEffect))(Beam); // BeamStyle = !TaiahaBeamEffect;
1540 ++TimesUsed;
1541 return true;
1544 void taiaha::AddInventoryEntry(ccharacter* Viewer, festring& Entry, int, truth ShowSpecialInfo) const // never piled
1546 AddName(Entry, INDEFINITE);
1548 if(ShowSpecialInfo)
1550 Entry << " [" << GetWeight() << "g, DAM " << GetBaseMinDamage() << '-' << GetBaseMaxDamage();
1551 Entry << ", " << GetBaseToHitValueDescription();
1553 if(!IsBroken() && !IsWhip())
1554 Entry << ", " << GetStrengthValueDescription();
1556 int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this);
1557 int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this);
1559 if(CWeaponSkillLevel || SWeaponSkillLevel)
1560 Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel;
1562 if(TimesUsed == 1)
1563 Entry << ", zapped 1 time]";
1564 else if(TimesUsed)
1565 Entry << ", zapped " << TimesUsed << " times]";
1566 else
1567 Entry << "]";
1571 void taiaha::BreakEffect(character* Terrorist, cfestring& DeathMsg)
1573 v2 Pos = GetPos();
1574 level* Level = GetLevel();
1575 RemoveFromSlot();
1576 ulong StackSize = Level->AddRadiusToSquareStack(Pos, 2); //hardcode, default is 2 for most wands, but zero for fireballs
1577 lsquare** SquareStack = Level->GetSquareStack();
1578 ulong c;
1580 for(c = 0; c < StackSize; ++c)
1581 SquareStack[c]->RemoveFlags(IN_SQUARE_STACK);
1583 fearray<lsquare*> Stack(SquareStack, StackSize);
1584 (Level->*level::GetBeamEffectVisualizer(PARTICLE_BEAM))(Stack, YELLOW); //beamstyle
1586 beamdata Beam
1588 Terrorist,
1589 DeathMsg,
1590 YOURSELF,
1591 0 //was GetSpecialParameters()
1594 for(c = 0; c < Stack.Size; ++c)
1595 (Stack[c]->*lsquare::GetBeamEffect(BEAM_FIRE_BALL))(Beam); // beam effect
1597 SendToHell(); //removes the taiaha from existence
1600 void taiaha::Save(outputfile& SaveFile) const
1602 item::Save(SaveFile);
1603 SaveFile << TimesUsed << Charges;
1604 SaveFile << Enchantment;
1605 SaveFile << SecondaryMaterial;
1606 //meleeweapon::Save(SaveFile);
1609 void taiaha::Load(inputfile& SaveFile)
1611 item::Load(SaveFile);
1612 SaveFile >> TimesUsed >> Charges;
1613 SaveFile >> Enchantment;
1614 LoadMaterial(SaveFile, SecondaryMaterial);
1615 //meleeweapon::Load(SaveFile);
1618 truth taiaha::ReceiveDamage(character* Damager, int Damage, int Type, int)
1620 if(Type & (FIRE|ENERGY|PHYSICAL_DAMAGE) && Damage && (Damage > 125 || !(RAND() % (250 / Damage))))
1622 festring DeathMsg = CONST_S("killed by an explosion of ");
1623 AddName(DeathMsg, INDEFINITE);
1625 if(Damager)
1626 DeathMsg << " caused @bk";
1628 if(CanBeSeenByPlayer())
1629 ADD_MESSAGE("%s %s.", GetExtendedDescription().CStr(), GetBreakMsg().CStr());
1631 BreakEffect(Damager, DeathMsg);
1632 return true;
1635 return false;
1638 void taiaha::PostConstruct()
1640 Charges = GetMinCharges() + RAND() % (GetMaxCharges() - GetMinCharges() + 1);
1641 TimesUsed = 0;
1642 meleeweapon::PostConstruct();
1645 alpha taiaha::GetOutlineAlpha(int Frame) const
1647 if(!IsBroken())
1649 Frame &= 31;
1650 return Frame * (31 - Frame) >> 1;
1652 else
1653 return 255;
1656 col16 taiaha::GetOutlineColor(int Frame) const
1658 if(!IsBroken())
1659 switch((Frame&127) >> 5)
1661 case 0: return BLUE;
1662 case 1: return GREEN;
1663 case 2: return RED;
1664 case 3: return YELLOW;
1667 return TRANSPARENT_COLOR;
1670 //end taiaha