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
24 v2 RightArmSparkleValidityArray
[128];
25 v2 LeftArmSparkleValidityArray
[128];
26 v2 GroinSparkleValidityArray
[169];
27 v2 RightLegSparkleValidityArray
[42];
28 v2 LeftLegSparkleValidityArray
[45];
29 v2 NormalSparkleValidityArray
[256];
30 v2 PossibleSparkleBuffer
[256];
33 object::object () : entity(0), MainMaterial(0) {}
34 int object::GetSpecialFlags () const { return ST_NORMAL
; }
35 col16
object::GetOutlineColor (int) const { return TRANSPARENT_COLOR
; }
36 cbitmap
*const *object::GetPicture () const { return GraphicData
.Picture
; }
39 object::object (const object
& Object
) : entity(Object
), id(Object
), VisualEffects(Object
.VisualEffects
) {
40 CopyMaterial(Object
.MainMaterial
, MainMaterial
);
41 mOnEvents
= Object
.mOnEvents
;
50 void object::CopyMaterial (material
*const &Source
, material
*&Dest
) {
52 Dest
= Source
->Duplicate();
53 Dest
->SetMotherEntity(this);
60 void object::Save (outputfile
&SaveFile
) const {
61 SaveFile
<< GraphicData
<< (int)VisualEffects
;
62 SaveFile
<< MainMaterial
;
66 void object::Load (inputfile
&SaveFile
) {
67 SaveFile
>> GraphicData
>> (int&)VisualEffects
;
68 LoadMaterial(SaveFile
, MainMaterial
);
72 void object::ObjectInitMaterials (material
*&FirstMaterial
, material
*FirstNewMaterial
, sLong FirstDefaultVolume
,
73 material
*&SecondMaterial
, material
*SecondNewMaterial
, sLong SecondDefaultVolume
, truth CallUpdatePictures
)
75 InitMaterial(FirstMaterial
, FirstNewMaterial
, FirstDefaultVolume
);
76 InitMaterial(SecondMaterial
, SecondNewMaterial
, SecondDefaultVolume
);
77 SignalVolumeAndWeightChange();
78 if (CallUpdatePictures
) UpdatePictures();
82 void object::InitMaterial (material
*&Material
, material
*NewMaterial
, sLong DefaultVolume
) {
83 Material
= NewMaterial
;
85 if (Material
->HasBe()) Enable();
86 if (DefaultVolume
&& !Material
->GetVolume()) Material
->SetVolume(DefaultVolume
);
87 Material
->SetMotherEntity(this);
88 SignalEmitationIncrease(Material
->GetEmitation());
93 void object::ChangeMaterial (material
*&Material
, material
*NewMaterial
, sLong DefaultVolume
, int SpecialFlags
) {
94 delete SetMaterial(Material
, NewMaterial
, DefaultVolume
, SpecialFlags
);
98 material
*object::SetMaterial (material
*&Material
, material
*NewMaterial
, sLong DefaultVolume
, int SpecialFlags
) {
99 material
*OldMaterial
= Material
;
101 Material
= NewMaterial
;
102 if ((!OldMaterial
|| !OldMaterial
->HasBe()) && NewMaterial
&& NewMaterial
->HasBe()) {
104 } else if (OldMaterial
&& OldMaterial
->HasBe() && (!NewMaterial
|| !NewMaterial
->HasBe()) && !CalculateHasBe()) {
108 if (!NewMaterial
->GetVolume()) {
109 if (OldMaterial
) NewMaterial
->SetVolume(OldMaterial
->GetVolume());
110 else if (DefaultVolume
) NewMaterial
->SetVolume(DefaultVolume
);
111 else ABORT("Singularity spawn detected!");
113 NewMaterial
->SetMotherEntity(this);
114 if (!(SpecialFlags
&NO_SIGNALS
)) SignalEmitationIncrease(NewMaterial
->GetEmitation());
116 if (!(SpecialFlags
&NO_SIGNALS
)) {
117 if (OldMaterial
) SignalEmitationDecrease(OldMaterial
->GetEmitation());
118 SignalVolumeAndWeightChange();
119 SignalMaterialChange();
121 if (!(SpecialFlags
&NO_PIC_UPDATE
)) UpdatePictures();
126 void object::UpdatePictures () {
127 static cv2
ZeroPos(0, 0);
129 UpdatePictures(GraphicData
, ZeroPos
, VisualEffects
|GetSpecialFlags(), GetMaxAlpha(), GetGraphicsContainerIndex(), &object::GetBitmapPos
);
133 truth
object::RandomizeSparklePos (v2
&SparklePos
, v2 BPos
, int &SparkleTime
, feuLong SeedBase
, int SpecialFlags
, int GraphicsContainerIndex
) const {
134 static int SeedModifier
= 1;
136 int ValidityArraySize
;
139 femath::SetSeed(SeedBase
+SeedModifier
);
140 if (++SeedModifier
> 0x10) SeedModifier
= 1;
142 if ((SpecialFlags
&0x38) == ST_RIGHT_ARM
) {
143 ValidityArray
= RightArmSparkleValidityArray
;
144 ValidityArraySize
= 128;
145 } else if ((SpecialFlags
&0x38) == ST_LEFT_ARM
) {
146 ValidityArray
= LeftArmSparkleValidityArray
;
147 ValidityArraySize
= 128;
148 } else if ((SpecialFlags
&0x38) == ST_GROIN
) {
149 ValidityArray
= GroinSparkleValidityArray
;
150 ValidityArraySize
= 169;
151 } else if ((SpecialFlags
&0x38) == ST_RIGHT_LEG
) {
152 ValidityArray
= RightLegSparkleValidityArray
;
153 ValidityArraySize
= 42;
154 } else if ((SpecialFlags
&0x38) == ST_LEFT_LEG
) {
155 ValidityArray
= LeftLegSparkleValidityArray
;
156 ValidityArraySize
= 45;
158 ValidityArray
= NormalSparkleValidityArray
;
159 ValidityArraySize
= 256;
162 SparklePos
= igraph::GetRawGraphic(GraphicsContainerIndex
)->RandomizeSparklePos(ValidityArray
, PossibleSparkleBuffer
, BPos
, TILE_V2
, ValidityArraySize
, GetSparkleFlags());
164 if (SparklePos
!= ERROR_V2
) {
165 SparkleTime
= RAND() % 241;
174 void object::UpdatePictures (graphicdata
&GraphicData
, v2 Position
, int SpecialFlags
, alpha MaxAlpha
,
175 int GraphicsContainerIndex
, bposretriever BitmapPosRetriever
) const
177 int AnimationFrames
= GetClassAnimationFrames();
181 int FlyAmount
= GetSpoilLevel();
182 truth Sparkling
= false, FrameNeeded
= false, SeedNeeded
= false;
183 v2 BPos
= (this->*BitmapPosRetriever
)(0);
186 if (!(SpecialFlags
&(ST_FLAMES
|ST_LIGHTNING
))) {
187 if (AllowSparkling()) {
188 int SparkleFlags
= GetSparkleFlags();
190 if (SparkleFlags
&& RandomizeSparklePos(SparklePos
, BPos
, SparkleTime
, BPos
.X
+BPos
.Y
+GetMaterialColorA(0), SpecialFlags
, GraphicsContainerIndex
)) {
192 if (AnimationFrames
<= 256) AnimationFrames
= 256;
198 if (AnimationFrames
<= 32) AnimationFrames
= 32;
200 } else if (SpecialFlags
&ST_FLAMES
) {
203 if (AnimationFrames
<= 16) AnimationFrames
= 16;
204 } else if (SpecialFlags
&ST_LIGHTNING
) {
206 if (AnimationFrames
<= 128) AnimationFrames
= 128;
209 static int SeedModifier
= 1;
210 Seed
= BPos
.X
+BPos
.Y
+GetMaterialColorA(0)+SeedModifier
+0x42;
211 if (++SeedModifier
> 0x10) SeedModifier
= 1;
214 int WobbleMask
= 0, WobbleData
= GetWobbleData();
216 if (WobbleData
&WOBBLE
) {
217 int Speed
= (WobbleData
&WOBBLE_SPEED_RANGE
)>>WOBBLE_SPEED_SHIFT
;
218 int Freq
= (WobbleData
&WOBBLE_FREQ_RANGE
)>>WOBBLE_FREQ_SHIFT
;
219 int WobbleFrames
= 512>>(Freq
+Speed
);
221 WobbleMask
= 7>>Freq
<<(6-Speed
);
222 if (AnimationFrames
<= WobbleFrames
) AnimationFrames
= WobbleFrames
;
225 ModifyAnimationFrames(AnimationFrames
);
227 int OldAnimationFrames
= GraphicData
.AnimationFrames
;
229 for (int c
= 0; c
< OldAnimationFrames
; ++c
) igraph::RemoveUser(GraphicData
.GraphicIterator
[c
]);
230 if (OldAnimationFrames
!= AnimationFrames
) {
231 if (OldAnimationFrames
) {
232 delete [] GraphicData
.Picture
;
233 delete [] GraphicData
.GraphicIterator
;
235 GraphicData
.Picture
= new bitmap
* [AnimationFrames
];
236 GraphicData
.GraphicIterator
= new tilemap::iterator
[AnimationFrames
];
238 GraphicData
.AnimationFrames
= AnimationFrames
;
240 if (!AllowRegularColors()) SpecialFlags
|= ST_DISALLOW_R_COLORS
;
243 GI
.BaseAlpha
= MaxAlpha
;
244 GI
.FileIndex
= GraphicsContainerIndex
;
245 GI
.SpecialFlags
= SpecialFlags
;
247 GI
.FlyAmount
= FlyAmount
;
248 GI
.Position
= Position
;
249 GI
.RustData
[0] = GetRustDataA();
250 GI
.RustData
[1] = GetRustDataB();
251 GI
.RustData
[2] = GetRustDataC();
252 GI
.RustData
[3] = GetRustDataD();
253 GI
.WobbleData
= WobbleData
;
255 for (int c
= 0; c
< AnimationFrames
; ++c
) {
256 GI
.Color
[0] = GetMaterialColorA(c
);
257 GI
.Color
[1] = GetMaterialColorB(c
);
258 GI
.Color
[2] = GetMaterialColorC(c
);
259 GI
.Color
[3] = GetMaterialColorD(c
);
260 Alpha
= GetAlphaA(c
);
261 GI
.Alpha
[0] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
262 Alpha
= GetAlphaB(c
);
263 GI
.Alpha
[1] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
264 Alpha
= GetAlphaC(c
);
265 GI
.Alpha
[2] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
266 Alpha
= GetAlphaD(c
);
267 GI
.Alpha
[3] = Alpha
< MaxAlpha
? Alpha
: MaxAlpha
;
268 v2 BPos
= (this->*BitmapPosRetriever
)(c
);
269 GI
.BitmapPosX
= BPos
.X
;
270 GI
.BitmapPosY
= BPos
.Y
;
271 if (Sparkling
&& c
> SparkleTime
&& c
< SparkleTime
+16) {
272 GI
.SparklePosX
= SparklePos
.X
;
273 GI
.SparklePosY
= SparklePos
.Y
;
274 GI
.SparkleFrame
= c
-SparkleTime
;
276 GI
.SparklePosX
= SPARKLE_POS_X_ERROR
;
282 ((SpecialFlags
&ST_LIGHTNING
) && !((c
+1)&7)) ||
283 ((WobbleData
&WOBBLE
) && !(c
&WobbleMask
)) ? c
: 0;
284 GI
.OutlineColor
= GetOutlineColor(c
);
285 GI
.OutlineAlpha
= GetOutlineAlpha(c
);
286 tilemap::iterator Iterator
= igraph::AddUser(GI
);
287 GraphicData
.GraphicIterator
[c
] = Iterator
;
288 GraphicData
.Picture
[c
] = Iterator
->second
.Bitmap
;
293 col16
object::GetMaterialColorA (int) const {
294 return MainMaterial
->GetColor();
298 truth
object::AddRustLevelDescription (festring
&String
, truth Articled
) const {
299 return MainMaterial
->AddRustLevelDescription(String
, Articled
);
303 truth
object::AddMaterialDescription (festring
&String
, truth Articled
) const {
304 //FIXME: gum solution
305 if (IsBoneNameSingular()) {
306 //FIXME: 'bone bone' removing
307 festring
s(MainMaterial
->GetName(Articled
));
308 festring::sizetype pos
= s
.FindLast("bone");
309 if (pos
!= festring::NPos
&& pos
== s
.GetSize()-4) {
310 while (pos
> 0 && s
[pos
-1] == ' ') --pos
;
311 s
.Erase(pos
, s
.GetSize()-pos
);
312 if (s
.GetSize() == 0) return true; // no name left
316 MainMaterial
->AddName(String
, Articled
);
323 void object::AddContainerPostFix (festring
&String
) const {
324 if (GetSecondaryMaterial()) GetSecondaryMaterial()->AddName(String
<< " full of ", false, false);
328 void object::AddLumpyPostFix (festring
&String
) const {
329 MainMaterial
->AddName(String
<< " of ", false, false);
333 alpha
object::GetAlphaA (int) const {
334 return MainMaterial
->GetAlpha();
338 void object::RandomizeVisualEffects () {
339 int AcceptedFlags
= GetOKVisualEffects();
342 SetVisualEffects((RAND()&0x7&AcceptedFlags
)|GetForcedVisualEffects());
344 SetVisualEffects(GetForcedVisualEffects());
349 void object::LoadMaterial (inputfile
&SaveFile
, material
*&Material
) {
350 SaveFile
>> Material
;
352 if (Material
->HasBe()) Enable();
353 Material
->SetMotherEntity(this);
354 game::CombineLights(Emitation
, Material
->GetEmitation());
359 int object::RandomizeMaterialConfiguration () {
360 const fearray
<sLong
>& MCC
= GetMaterialConfigChances();
362 return MCC
.Size
> 1 ? femath::WeightedRand(MCC
.Data
, GetMaterialConfigChanceSum()) : 0;
366 truth
object::AddEmptyAdjective (festring
&String
, truth Articled
) const {
367 if (GetSecondaryMaterial()) return false;
368 String
<< (Articled
? "an empty " : "empty ");
373 void object::CalculateEmitation () {
374 Emitation
= GetBaseEmitation();
375 if (MainMaterial
) game::CombineLights(Emitation
, MainMaterial
->GetEmitation());
379 truth
object::CalculateHasBe () const {
380 return MainMaterial
&& MainMaterial
->HasBe();
384 int object::GetSparkleFlags () const {
385 return MainMaterial
->IsSparkling() ? SPARKLING_A
: 0;
389 void object::InitSparkleValidityArrays () {
392 for (int y
= 0; y
< 16; ++y
)
393 for (int x
= 0; x
< 8; ++x
)
394 RightArmSparkleValidityArray
[Index
++] = v2(x
, y
);
397 for (int y
= 0; y
< 16; ++y
)
398 for (int x
= 8; x
< 16; ++x
)
399 LeftArmSparkleValidityArray
[Index
++] = v2(x
, y
);
402 for (int y
= 0; y
< 10; ++y
)
403 for (int x
= 0; x
< 16; ++x
)
404 GroinSparkleValidityArray
[Index
++] = v2(x
, y
);
405 for (int y
= 10; y
< 13; ++y
)
406 for (int x
= y
-5; x
< 20-y
; ++x
)
407 GroinSparkleValidityArray
[Index
++] = v2(x
, y
);
410 for (int y
= 10; y
< 16; ++y
)
411 for (int x
= 0; x
< 8; ++x
)
412 if ((y
!= 10 || x
< 5) && (y
!= 11 || x
< 6) && (y
!= 12 || x
< 7))
413 RightLegSparkleValidityArray
[Index
++] = v2(x
, y
);
416 for (int y
= 10; y
< 16; ++y
)
417 for (int x
= 8; x
< 16; ++x
)
418 if ((y
!= 10 || x
> 9) && (y
!= 11 || x
> 8))
419 LeftLegSparkleValidityArray
[Index
++] = v2(x
, y
);
422 for (int y
= 0; y
< 16; ++y
)
423 for (int x
= 0; x
< 16; ++x
)
424 NormalSparkleValidityArray
[Index
++] = v2(x
, y
);
428 int object::GetRustDataA () const {
429 return MainMaterial
->GetRustData();
433 truth
object::DetectMaterial (cmaterial
*Material
) const {
434 for (int c
= 0; c
< GetMaterials(); ++c
) if (GetMaterial(c
) && GetMaterial(c
)->IsSameAs(Material
)) return true;