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
23 v2 RightArmSparkleValidityArray
[128];
24 v2 LeftArmSparkleValidityArray
[128];
25 v2 GroinSparkleValidityArray
[169];
26 v2 RightLegSparkleValidityArray
[42];
27 v2 LeftLegSparkleValidityArray
[45];
28 v2 NormalSparkleValidityArray
[256];
29 v2 PossibleSparkleBuffer
[256];
31 object::object() : entity(0), MainMaterial(0) {}
32 int object::GetSpecialFlags() const { return ST_NORMAL
; }
33 col16
object::GetOutlineColor(int) const { return TRANSPARENT_COLOR
; }
34 cbitmap
*const* object::GetPicture() const { return GraphicData
.Picture
; }
36 object::object(const object
& Object
) : entity(Object
), id(Object
), VisualEffects(Object
.VisualEffects
)
38 CopyMaterial(Object
.MainMaterial
, MainMaterial
);
39 mOnEvents
= Object
.mOnEvents
;
47 void object::CopyMaterial(material
* const& Source
, material
*& Dest
)
51 Dest
= Source
->Duplicate();
52 Dest
->SetMotherEntity(this);
58 void object::Save(outputfile
& SaveFile
) const
60 SaveFile
<< GraphicData
<< (int)VisualEffects
;
61 SaveFile
<< MainMaterial
;
64 void object::Load(inputfile
& SaveFile
)
66 SaveFile
>> GraphicData
>> (int&)VisualEffects
;
67 LoadMaterial(SaveFile
, MainMaterial
);
70 void object::ObjectInitMaterials(material
*& FirstMaterial
, material
* FirstNewMaterial
, sLong FirstDefaultVolume
, material
*& SecondMaterial
, material
* SecondNewMaterial
, sLong SecondDefaultVolume
, truth CallUpdatePictures
)
72 InitMaterial(FirstMaterial
, FirstNewMaterial
, FirstDefaultVolume
);
73 InitMaterial(SecondMaterial
, SecondNewMaterial
, SecondDefaultVolume
);
74 SignalVolumeAndWeightChange();
76 if(CallUpdatePictures
)
80 void object::InitMaterial(material
*& Material
, material
* NewMaterial
, sLong DefaultVolume
)
82 Material
= NewMaterial
;
89 if(DefaultVolume
&& !Material
->GetVolume())
90 Material
->SetVolume(DefaultVolume
);
92 Material
->SetMotherEntity(this);
93 SignalEmitationIncrease(Material
->GetEmitation());
97 void object::ChangeMaterial(material
*& Material
, material
* NewMaterial
, sLong DefaultVolume
, int SpecialFlags
)
99 delete SetMaterial(Material
, NewMaterial
, DefaultVolume
, SpecialFlags
);
102 material
*object::SetMaterial (material
*&Material
, material
*NewMaterial
, sLong DefaultVolume
, int SpecialFlags
) {
103 material
*OldMaterial
= Material
;
104 Material
= NewMaterial
;
106 if ((!OldMaterial
|| !OldMaterial
->HasBe()) && NewMaterial
&& NewMaterial
->HasBe()) {
108 } else if (OldMaterial
&& OldMaterial
->HasBe() && (!NewMaterial
|| !NewMaterial
->HasBe()) && !CalculateHasBe()) {
112 if (!NewMaterial
->GetVolume()) {
113 if (OldMaterial
) NewMaterial
->SetVolume(OldMaterial
->GetVolume());
114 else if (DefaultVolume
) NewMaterial
->SetVolume(DefaultVolume
);
115 else ABORT("Singularity spawn detected!");
117 NewMaterial
->SetMotherEntity(this);
118 if (!(SpecialFlags
& NO_SIGNALS
)) SignalEmitationIncrease(NewMaterial
->GetEmitation());
120 if (!(SpecialFlags
& NO_SIGNALS
)) {
121 if (OldMaterial
) SignalEmitationDecrease(OldMaterial
->GetEmitation());
122 SignalVolumeAndWeightChange();
123 SignalMaterialChange();
125 if (!(SpecialFlags
& NO_PIC_UPDATE
)) UpdatePictures();
130 void object::UpdatePictures()
132 static cv2
ZeroPos(0, 0);
133 UpdatePictures(GraphicData
, ZeroPos
, VisualEffects
|GetSpecialFlags(), GetMaxAlpha(), GetGraphicsContainerIndex(), &object::GetBitmapPos
);
136 truth
object::RandomizeSparklePos(v2
& SparklePos
, v2 BPos
, int& SparkleTime
, uLong SeedBase
, int SpecialFlags
, int GraphicsContainerIndex
) const
138 static int SeedModifier
= 1;
140 femath::SetSeed(SeedBase
+ SeedModifier
);
142 if(++SeedModifier
> 0x10)
146 int ValidityArraySize
;
148 if((SpecialFlags
& 0x38) == ST_RIGHT_ARM
)
150 ValidityArray
= RightArmSparkleValidityArray
;
151 ValidityArraySize
= 128;
153 else if((SpecialFlags
& 0x38) == ST_LEFT_ARM
)
155 ValidityArray
= LeftArmSparkleValidityArray
;
156 ValidityArraySize
= 128;
158 else if((SpecialFlags
& 0x38) == ST_GROIN
)
160 ValidityArray
= GroinSparkleValidityArray
;
161 ValidityArraySize
= 169;
163 else if((SpecialFlags
& 0x38) == ST_RIGHT_LEG
)
165 ValidityArray
= RightLegSparkleValidityArray
;
166 ValidityArraySize
= 42;
168 else if((SpecialFlags
& 0x38) == ST_LEFT_LEG
)
170 ValidityArray
= LeftLegSparkleValidityArray
;
171 ValidityArraySize
= 45;
175 ValidityArray
= NormalSparkleValidityArray
;
176 ValidityArraySize
= 256;
179 SparklePos
= igraph::GetRawGraphic(GraphicsContainerIndex
)->RandomizeSparklePos(ValidityArray
, PossibleSparkleBuffer
, BPos
, TILE_V2
, ValidityArraySize
, GetSparkleFlags());
181 if(SparklePos
!= ERROR_V2
)
183 SparkleTime
= RAND() % 241;
194 void object::UpdatePictures(graphicdata
& GraphicData
, v2 Position
, int SpecialFlags
, alpha MaxAlpha
, int GraphicsContainerIndex
, bposretriever BitmapPosRetriever
) const
196 int AnimationFrames
= GetClassAnimationFrames();
200 int FlyAmount
= GetSpoilLevel();
201 truth Sparkling
= false, FrameNeeded
= false, SeedNeeded
= false;
202 v2 BPos
= (this->*BitmapPosRetriever
)(0);
205 if(!(SpecialFlags
& (ST_FLAMES
|ST_LIGHTNING
)))
209 int SparkleFlags
= GetSparkleFlags();
212 && RandomizeSparklePos(SparklePos
, BPos
, SparkleTime
,
213 BPos
.X
+ BPos
.Y
+ GetMaterialColorA(0),
214 SpecialFlags
, GraphicsContainerIndex
))
218 if(AnimationFrames
<= 256)
219 AnimationFrames
= 256;
228 if(AnimationFrames
<= 32)
229 AnimationFrames
= 32;
232 else if(SpecialFlags
& ST_FLAMES
)
237 if(AnimationFrames
<= 16)
238 AnimationFrames
= 16;
240 else if(SpecialFlags
& ST_LIGHTNING
)
244 if(AnimationFrames
<= 128)
245 AnimationFrames
= 128;
250 static int SeedModifier
= 1;
251 Seed
= BPos
.X
+ BPos
.Y
+ GetMaterialColorA(0) + SeedModifier
+ 0x42;
253 if(++SeedModifier
> 0x10)
257 int WobbleMask
= 0, WobbleData
= GetWobbleData();
259 if(WobbleData
& WOBBLE
)
261 int Speed
= (WobbleData
& WOBBLE_SPEED_RANGE
) >> WOBBLE_SPEED_SHIFT
;
262 int Freq
= (WobbleData
& WOBBLE_FREQ_RANGE
) >> WOBBLE_FREQ_SHIFT
;
263 int WobbleFrames
= 512 >> (Freq
+ Speed
);
264 WobbleMask
= 7 >> Freq
<< (6 - Speed
);
266 if(AnimationFrames
<= WobbleFrames
)
267 AnimationFrames
= WobbleFrames
;
270 ModifyAnimationFrames(AnimationFrames
);
272 int OldAnimationFrames
= GraphicData
.AnimationFrames
;
274 for(c
= 0; c
< OldAnimationFrames
; ++c
)
275 igraph::RemoveUser(GraphicData
.GraphicIterator
[c
]);
277 if(OldAnimationFrames
!= AnimationFrames
)
279 if(OldAnimationFrames
)
281 delete [] GraphicData
.Picture
;
282 delete [] GraphicData
.GraphicIterator
;
285 GraphicData
.Picture
= new bitmap
*[AnimationFrames
];
286 GraphicData
.GraphicIterator
= new tilemap::iterator
[AnimationFrames
];
289 GraphicData
.AnimationFrames
= AnimationFrames
;
291 if(!AllowRegularColors())
292 SpecialFlags
|= ST_DISALLOW_R_COLORS
;
295 GI
.BaseAlpha
= MaxAlpha
;
296 GI
.FileIndex
= GraphicsContainerIndex
;
297 GI
.SpecialFlags
= SpecialFlags
;
299 GI
.FlyAmount
= FlyAmount
;
300 GI
.Position
= Position
;
301 GI
.RustData
[0] = GetRustDataA();
302 GI
.RustData
[1] = GetRustDataB();
303 GI
.RustData
[2] = GetRustDataC();
304 GI
.RustData
[3] = GetRustDataD();
305 GI
.WobbleData
= WobbleData
;
307 for(c
= 0; c
< AnimationFrames
; ++c
)
309 GI
.Color
[0] = GetMaterialColorA(c
);
310 GI
.Color
[1] = GetMaterialColorB(c
);
311 GI
.Color
[2] = GetMaterialColorC(c
);
312 GI
.Color
[3] = GetMaterialColorD(c
);
313 Alpha
= GetAlphaA(c
);
314 GI
.Alpha
[0] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
315 Alpha
= GetAlphaB(c
);
316 GI
.Alpha
[1] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
317 Alpha
= GetAlphaC(c
);
318 GI
.Alpha
[2] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
319 Alpha
= GetAlphaD(c
);
320 GI
.Alpha
[3] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
321 v2 BPos
= (this->*BitmapPosRetriever
)(c
);
322 GI
.BitmapPosX
= BPos
.X
;
323 GI
.BitmapPosY
= BPos
.Y
;
325 if(Sparkling
&& c
> SparkleTime
&& c
< SparkleTime
+ 16)
327 GI
.SparklePosX
= SparklePos
.X
;
328 GI
.SparklePosY
= SparklePos
.Y
;
329 GI
.SparkleFrame
= c
- SparkleTime
;
333 GI
.SparklePosX
= SPARKLE_POS_X_ERROR
;
341 ((SpecialFlags
& ST_LIGHTNING
) && !((c
+ 1) & 7)) ||
342 ((WobbleData
& WOBBLE
) && !(c
& WobbleMask
))
345 GI
.OutlineColor
= GetOutlineColor(c
);
346 GI
.OutlineAlpha
= GetOutlineAlpha(c
);
347 tilemap::iterator Iterator
= igraph::AddUser(GI
);
348 GraphicData
.GraphicIterator
[c
] = Iterator
;
349 GraphicData
.Picture
[c
] = Iterator
->second
.Bitmap
;
353 col16
object::GetMaterialColorA(int) const
355 return MainMaterial
->GetColor();
358 truth
object::AddRustLevelDescription(festring
& String
, truth Articled
) const
360 return MainMaterial
->AddRustLevelDescription(String
, Articled
);
364 truth
object::AddMaterialDescription(festring
& String
, truth Articled
) const {
365 //FIXME: gum solution
367 festring
s(MainMaterial
->GetName(Articled
));
368 festring::sizetype pos
= s
.FindLast("bone");
369 if (pos
!= festring::NPos
&& pos
== s
.GetSize()-4) {
370 while (pos
> 0 && s
[pos
-1] == ' ') pos
--;
371 s
.Erase(pos
, s
.GetSize()-pos
);
372 if (s
.GetSize() == 0) return true; // no name left
376 MainMaterial
->AddName(String
, Articled
);
383 void object::AddContainerPostFix(festring
& String
) const
385 if(GetSecondaryMaterial())
386 GetSecondaryMaterial()->AddName(String
<< " full of ", false, false);
389 void object::AddLumpyPostFix(festring
& String
) const
391 MainMaterial
->AddName(String
<< " of ", false, false);
394 alpha
object::GetAlphaA(int) const
396 return MainMaterial
->GetAlpha();
399 void object::RandomizeVisualEffects()
401 int AcceptedFlags
= GetOKVisualEffects();
404 SetVisualEffects((RAND() & 0x7 & AcceptedFlags
) | GetForcedVisualEffects());
406 SetVisualEffects(GetForcedVisualEffects());
409 void object::LoadMaterial(inputfile
& SaveFile
, material
*& Material
)
411 SaveFile
>> Material
;
415 if(Material
->HasBe())
418 Material
->SetMotherEntity(this);
419 game::CombineLights(Emitation
, Material
->GetEmitation());
423 int object::RandomizeMaterialConfiguration()
425 const fearray
<sLong
>& MCC
= GetMaterialConfigChances();
427 ? femath::WeightedRand(MCC
.Data
, GetMaterialConfigChanceSum())
431 truth
object::AddEmptyAdjective(festring
& String
, truth Articled
) const
433 if(GetSecondaryMaterial())
437 String
<< (Articled
? "an empty " : "empty ");
442 void object::CalculateEmitation()
444 Emitation
= GetBaseEmitation();
447 game::CombineLights(Emitation
, MainMaterial
->GetEmitation());
450 truth
object::CalculateHasBe() const
452 return MainMaterial
&& MainMaterial
->HasBe();
455 int object::GetSparkleFlags() const
457 return MainMaterial
->IsSparkling() ? SPARKLING_A
: 0;
460 void object::InitSparkleValidityArrays()
464 for(y
= 0; y
< 16; ++y
)
465 for(x
= 0; x
< 8; ++x
)
466 RightArmSparkleValidityArray
[Index
++] = v2(x
, y
);
470 for(y
= 0; y
< 16; ++y
)
471 for(x
= 8; x
< 16; ++x
)
472 LeftArmSparkleValidityArray
[Index
++] = v2(x
, y
);
476 for(y
= 0; y
< 10; ++y
)
477 for(x
= 0; x
< 16; ++x
)
478 GroinSparkleValidityArray
[Index
++] = v2(x
, y
);
480 for(y
= 10; y
< 13; ++y
)
481 for(x
= y
- 5; x
< 20 - y
; ++x
)
482 GroinSparkleValidityArray
[Index
++] = v2(x
, y
);
486 for(y
= 10; y
< 16; ++y
)
487 for(x
= 0; x
< 8; ++x
)
488 if((y
!= 10 || x
< 5) && (y
!= 11 || x
< 6) && (y
!= 12 || x
< 7))
489 RightLegSparkleValidityArray
[Index
++] = v2(x
, y
);
493 for(y
= 10; y
< 16; ++y
)
494 for(x
= 8; x
< 16; ++x
)
495 if((y
!= 10 || x
> 9) && (y
!= 11 || x
> 8))
496 LeftLegSparkleValidityArray
[Index
++] = v2(x
, y
);
500 for(y
= 0; y
< 16; ++y
)
501 for(x
= 0; x
< 16; ++x
)
502 NormalSparkleValidityArray
[Index
++] = v2(x
, y
);
505 int object::GetRustDataA() const
507 return MainMaterial
->GetRustData();
510 truth
object::DetectMaterial(cmaterial
* Material
) const
512 for(int c
= 0; c
< GetMaterials(); ++c
)
513 if(GetMaterial(c
) && GetMaterial(c
)->IsSameAs(Material
))