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 levelset.cpp */
15 glterrainprototype::glterrainprototype(const glterrainprototype
* Base
, glterrainspawner Spawner
, cchar
* ClassID
) : Base(Base
), Spawner(Spawner
), ClassID(ClassID
) { Index
= protocontainer
<glterrain
>::Add(this); }
16 olterrainprototype::olterrainprototype(const olterrainprototype
* Base
, olterrainspawner Spawner
, cchar
* ClassID
) : Base(Base
), Spawner(Spawner
), ClassID(ClassID
) { Index
= protocontainer
<olterrain
>::Add(this); }
18 square
* lterrain::GetSquareUnderEntity(int) const { return LSquareUnder
; }
19 level
* lterrain::GetLevel() const { return LSquareUnder
->GetLevel(); }
20 lsquare
* lterrain::GetNearLSquare(v2 Pos
) const { return LSquareUnder
->GetLevel()->GetLSquare(Pos
); }
21 lsquare
* lterrain::GetNearLSquare(int x
, int y
) const { return LSquareUnder
->GetLevel()->GetLSquare(x
, y
); }
22 room
* lterrain::GetRoom() const { return GetLSquareUnder()->GetRoom(); }
23 void lterrain::SetMainMaterial(material
* NewMaterial
, int SpecialFlags
) { SetMaterial(MainMaterial
, NewMaterial
, 0, SpecialFlags
); }
24 void lterrain::ChangeMainMaterial(material
* NewMaterial
, int SpecialFlags
) { ChangeMaterial(MainMaterial
, NewMaterial
, 0, SpecialFlags
); }
25 void lterrain::InitMaterials(const materialscript
* M
, const materialscript
*, truth CUP
) { InitMaterials(M
->Instantiate(), CUP
); }
27 void glterrain::InstallDataBase(int NewConfig
) { databasecreator
<glterrain
>::InstallDataBase(this, NewConfig
); }
28 void olterrain::InstallDataBase(int NewConfig
) { databasecreator
<olterrain
>::InstallDataBase(this, NewConfig
); }
29 int glterrain::GetGraphicsContainerIndex() const { return GR_GLTERRAIN
; }
30 int olterrain::GetGraphicsContainerIndex() const { return GR_OLTERRAIN
; }
32 truth
olterraindatabase::AllowRandomInstantiation() const { return !(Config
& S_LOCK_ID
); }
34 festring
olterrain::GetText() const { return ""; }
36 void lterrain::Load(inputfile
& SaveFile
)
38 LSquareUnder
= static_cast<lsquare
*>(game::GetSquareInLoad());
39 object::Load(SaveFile
);
42 void glterrain::Save(outputfile
& SaveFile
) const
44 SaveFile
<< (uShort
)GetType();
45 lterrain::Save(SaveFile
);
46 SaveFile
<< (uShort
)GetConfig();
49 void glterrain::Load(inputfile
& SaveFile
)
51 lterrain::Load(SaveFile
);
52 databasecreator
<glterrain
>::InstallDataBase(this, ReadType(uShort
, SaveFile
));
55 void olterrain::Save(outputfile
& SaveFile
) const
57 SaveFile
<< (uShort
)GetType();
58 lterrain::Save(SaveFile
);
59 SaveFile
<< (uShort
)GetConfig();
63 void olterrain::Load(inputfile
& SaveFile
)
65 lterrain::Load(SaveFile
);
66 databasecreator
<olterrain
>::InstallDataBase(this, ReadType(uShort
, SaveFile
));
70 v2
lterrain::GetPos() const
72 return LSquareUnder
->GetPos();
75 truth
lterrain::SitOn(character
* Sitter
)
77 if(GetSitMessage().GetSize())
79 ADD_MESSAGE("%s", GetSitMessage().CStr());
80 Sitter
->EditAP(-1000);
87 void olterrain::Break()
89 lsquare
* Square
= GetLSquareUnder();
90 const fearray
<contentscript
<item
> >& ItemArray
= GetLeftOverItems();
92 for(uInt c1
= 0; c1
< ItemArray
.Size
; ++c1
)
93 if(ItemArray
[c1
].IsValid())
95 const interval
* TimesPtr
= ItemArray
[c1
].GetTimes();
96 int Times
= TimesPtr
? TimesPtr
->Randomize() : 1;
98 for(int c2
= 0; c2
< Times
; ++c2
)
100 item
* Item
= ItemArray
[c1
].InstantiateBasedOnMaterial(GetMainMaterial()->GetDigProductMaterial());
104 Square
->AddItem(Item
);
105 Item
->SpecialGenerationHandler();
110 Square
->ChangeOLTerrainAndUpdateLights(0);
113 glterrain
* glterrainprototype::SpawnAndLoad(inputfile
& SaveFile
) const
115 glterrain
* Terrain
= Spawner(0, LOAD
);
116 Terrain
->Load(SaveFile
);
117 Terrain
->CalculateAll();
121 olterrain
* olterrainprototype::SpawnAndLoad(inputfile
& SaveFile
) const
123 olterrain
* Terrain
= Spawner(0, LOAD
);
124 Terrain
->Load(SaveFile
);
125 Terrain
->CalculateAll();
129 void lterrain::Initialize(int NewConfig
, int SpecialFlags
)
131 if(!(SpecialFlags
& LOAD
))
133 InstallDataBase(NewConfig
);
134 RandomizeVisualEffects();
136 if(!(SpecialFlags
& NO_MATERIALS
))
140 if(!(SpecialFlags
& LOAD
))
146 if(!(SpecialFlags
& LOAD
))
148 if(!(SpecialFlags
& NO_MATERIALS
))
152 if(!(SpecialFlags
& NO_PIC_UPDATE
))
158 truth
lterrain::CanBeSeenByPlayer() const
160 return LSquareUnder
->CanBeSeenByPlayer();
163 truth
lterrain::CanBeSeenBy(character
* Who
) const
166 return CanBeSeenByPlayer();
168 return LSquareUnder
->CanBeSeenFrom(Who
->GetPos(), Who
->GetLOSRangeSquare());
171 void olterrain::ShowRestMessage(character
*) const
173 if(GetRestMessage().GetSize())
174 ADD_MESSAGE("%s", GetRestMessage().CStr());
177 void lterrain::SignalEmitationIncrease(col24 EmitationUpdate
)
179 if(game::CompareLights(EmitationUpdate
, Emitation
) > 0)
181 game::CombineLights(Emitation
, EmitationUpdate
);
184 LSquareUnder
->SignalEmitationIncrease(EmitationUpdate
);
188 void lterrain::SignalEmitationDecrease(col24 EmitationUpdate
)
190 if(game::CompareLights(EmitationUpdate
, Emitation
) >= 0 && Emitation
)
192 col24 Backup
= Emitation
;
193 CalculateEmitation();
195 if(Backup
!= Emitation
&& LSquareUnder
)
196 LSquareUnder
->SignalEmitationDecrease(EmitationUpdate
);
200 truth
olterrain::Enter(truth DirectionUp
) const
203 ADD_MESSAGE("You can't go up.");
205 ADD_MESSAGE("You can't go down.");
210 int olterrain::GetStrengthValue() const
212 return GetMainMaterial()->GetStrengthValue() / 20;
215 void olterrain::ReceiveDamage(character
* Villain
, int Damage
, int)
217 if(CanBeDestroyed() && Damage
> GetStrengthValue())
219 EditHP(GetStrengthValue() - Damage
);
223 room
* Room
= GetRoom();
227 Room
->DestroyTerrain(Villain
);
232 void olterrain::BeKicked(character
* Kicker
, int Damage
, int)
234 if(CanBeDestroyed() && Damage
> GetMainMaterial()->GetStrengthValue() >> 1)
236 EditHP((GetMainMaterial()->GetStrengthValue() >> 1) - Damage
);
240 room
* Room
= GetRoom();
242 if(CanBeSeenByPlayer())
243 ADD_MESSAGE("%s is shattered.", CHAR_NAME(DEFINITE
));
248 Room
->DestroyTerrain(Kicker
);
251 else if(Kicker
->IsPlayer())
252 ADD_MESSAGE("Your kick has no effect on %s.", CHAR_NAME(DEFINITE
));
255 int olterrain::CalculateMaxHP()
257 if(GetMainMaterial())
259 sLong SV
= GetMainMaterial()->GetStrengthValue();
260 return SV
* SV
* GetHPModifier() / 6000;
266 int glterrain::GetAttachedGod() const
268 return DataBase
->AttachedGod
? DataBase
->AttachedGod
: MainMaterial
->GetAttachedGod();
271 int olterrain::GetAttachedGod() const
273 return DataBase
->AttachedGod
? DataBase
->AttachedGod
: MainMaterial
->GetAttachedGod();
276 void olterrain::SetConfig(int NewConfig
, int SpecialFlags
)
278 databasecreator
<olterrain
>::InstallDataBase(this, NewConfig
);
280 if(!(SpecialFlags
& NO_PIC_UPDATE
))
284 god
* olterrain::GetMasterGod() const
286 return game::GetGod(GetConfig());
289 truth
olterrain::CanBeDestroyed() const
291 return DataBase
->CanBeDestroyed
&& ((GetPos().X
&& GetPos().Y
&& GetPos().X
!= GetLevel()->GetXSize() - 1 && GetPos().Y
!= GetLevel()->GetYSize() - 1) || GetLevel()->IsOnGround());
294 //extern itemprototype key_ProtoType;
296 int olterrainprototype::CreateSpecialConfigurations (olterraindatabase
**TempConfig
, int Configs
, int Level
) {
297 if (Level
) return Configs
;
299 if (TempConfig
[0]->CreateDivineConfigurations
) {
300 Configs
= databasecreator
<olterrain
>::CreateDivineConfigurations(this, TempConfig
, Configs
);
304 if (TempConfig
[0]->CreateLockConfigurations
) {
305 const item::database
*const* KeyConfigData
= key::ProtoType
.GetConfigData();
306 int KeyConfigSize
= key::ProtoType
.GetConfigSize();
307 int OldConfigs
= Configs
;
308 for (int c1
= 0; c1
< OldConfigs
; ++c1
) {
309 if (!TempConfig
[c1
]->IsAbstract
) {
311 lcfgname
<< TempConfig
[c1
]->CfgStrName
;
312 lcfgname
<< "|locked-broken";
313 int BaseConfig
= TempConfig
[c1
]->Config
;
314 int NewConfig
= BaseConfig
|BROKEN_LOCK
;
315 olterraindatabase
* ConfigDataBase
= new olterraindatabase(*TempConfig
[c1
]);
316 ConfigDataBase
->InitDefaults(this, NewConfig
, lcfgname
);
317 ConfigDataBase
->PostFix
<< "with a broken lock";
318 TempConfig
[Configs
++] = ConfigDataBase
;
319 for (int c2
= 0; c2
< KeyConfigSize
; ++c2
) {
321 xcfgname
<< TempConfig
[c1
]->CfgStrName
;
322 xcfgname
<< "|locked";
323 NewConfig
= BaseConfig
|KeyConfigData
[c2
]->Config
;
324 ConfigDataBase
= new olterraindatabase(*TempConfig
[c1
]);
325 ConfigDataBase
->InitDefaults(this, NewConfig
, xcfgname
);
326 ConfigDataBase
->PostFix
<< "with ";
327 if (KeyConfigData
[c2
]->UsesLongAdjectiveArticle
) ConfigDataBase
->PostFix
<< "an "; else ConfigDataBase
->PostFix
<< "a ";
328 ConfigDataBase
->PostFix
<< KeyConfigData
[c2
]->Adjective
<< " lock";
329 TempConfig
[Configs
++] = ConfigDataBase
;
335 if (TempConfig
[0]->CreateWindowConfigurations
) {
336 int OldConfigs
= Configs
;
337 for (int c1
= 0; c1
< OldConfigs
; ++c1
) {
338 if (!TempConfig
[c1
]->IsAbstract
) {
340 xcfgname
<< TempConfig
[c1
]->CfgStrName
;
341 xcfgname
<< "|window";
342 int NewConfig
= TempConfig
[c1
]->Config
|WINDOW
;
343 olterraindatabase
* ConfigDataBase
= new olterraindatabase(*TempConfig
[c1
]);
344 ConfigDataBase
->InitDefaults(this, NewConfig
, xcfgname
);
345 ConfigDataBase
->PostFix
<< "with a window";
346 ConfigDataBase
->IsAlwaysTransparent
= true;
347 ConfigDataBase
->BitmapPos
= ConfigDataBase
->WindowBitmapPos
;
348 TempConfig
[Configs
++] = ConfigDataBase
;
356 truth
olterrain::IsTransparent() const
358 return IsAlwaysTransparent() || MainMaterial
->IsTransparent();
361 void glterrain::ModifyAnimationFrames(int& AF
) const
367 v2
glterrain::GetBorderBitmapPos(v2 BasePos
, int I
) const
371 int Index
= I
? 8 - (I
+ (I
<< 3)) / GraphicData
.AnimationFrames
: 8;
372 v2 MV
= game::GetMoveVector(Index
);
374 if(VisualEffects
& MIRROR
)
377 if(VisualEffects
& FLIP
)
380 if(VisualEffects
& ROTATE
)
387 return BasePos
+ (MV
<< 4);
393 void glterrain::Draw(blitdata
& BlitData
) const
397 cint TrueAF
= GraphicData
.AnimationFrames
/ 9;
398 int PictureIndex
= (BlitData
.CustomData
& SQUARE_INDEX_MASK
) * TrueAF
;
400 if(BlitData
.CustomData
& ALLOW_ANIMATE
&& TrueAF
!= 1)
401 PictureIndex
+= GET_TICK() & (TrueAF
- 1);
403 GraphicData
.Picture
[PictureIndex
]->LuminanceMaskedBlit(BlitData
);
407 cint AF
= GraphicData
.AnimationFrames
;
408 cint F
= !(BlitData
.CustomData
& ALLOW_ANIMATE
) || AF
== 1 ? 0 : GET_TICK() & (AF
- 1);
409 GraphicData
.Picture
[F
]->LuminanceBlit(BlitData
);
413 void olterrain::ModifyAnimationFrames(int& AF
) const
419 v2
olterrain::GetBorderBitmapPos(v2 BasePos
, int I
) const
423 int Index
= I
? 8 - (I
+ (I
<< 3)) / GraphicData
.AnimationFrames
: 8;
424 v2 MV
= game::GetMoveVector(Index
);
426 if(VisualEffects
& MIRROR
)
429 if(VisualEffects
& FLIP
)
432 if(VisualEffects
& ROTATE
)
439 return BasePos
+ (MV
<< 4);
445 void olterrain::Draw(blitdata
& BlitData
) const
449 cint TrueAF
= GraphicData
.AnimationFrames
/ 9;
450 int PictureIndex
= (BlitData
.CustomData
& SQUARE_INDEX_MASK
) * TrueAF
;
452 if(BlitData
.CustomData
& ALLOW_ANIMATE
&& TrueAF
!= 1)
453 PictureIndex
+= GET_TICK() & (TrueAF
- 1);
455 GraphicData
.Picture
[PictureIndex
]->AlphaLuminanceBlit(BlitData
);
459 cint AF
= GraphicData
.AnimationFrames
;
460 cint F
= !(BlitData
.CustomData
& ALLOW_ANIMATE
) || AF
== 1 ? 0 : GET_TICK() & (AF
- 1);
461 GraphicData
.Picture
[F
]->AlphaLuminanceBlit(BlitData
);
465 void lterrain::SignalRustLevelChange()
468 GetLSquareUnder()->SendMemorizedUpdateRequest();
469 GetLSquareUnder()->SendNewDrawRequest();
472 void olterrain::SignalRustLevelChange()
474 lterrain::SignalRustLevelChange();
475 HP
= Min(HP
, CalculateMaxHP());
478 void lterrain::TryToRust (sLong LiquidModifier
) {
479 if (MainMaterial
->TryToRust(LiquidModifier
*10, 10000)) {
480 if (CanBeSeenByPlayer()) {
481 if (MainMaterial
->GetRustLevel() == NOT_RUSTED
) ADD_MESSAGE("%s rusts.", CHAR_NAME(DEFINITE
));
482 else ADD_MESSAGE("%s rusts more.", CHAR_NAME(DEFINITE
));
484 MainMaterial
->SetRustLevel(MainMaterial
->GetRustLevel()+1);
488 void olterrain::ReceiveAcid(material
*, sLong Modifier
)
490 if(GetMainMaterial()->GetInteractionFlags() & CAN_DISSOLVE
)
492 int Damage
= Modifier
/ 10000;
496 Damage
+= RAND() % Damage
;
497 ReceiveDamage(0, Damage
, ACID
);
502 void lterrain::InitMaterials(material
* FirstMaterial
, truth CallUpdatePictures
)
504 InitMaterial(MainMaterial
, FirstMaterial
, 0);
505 SignalVolumeAndWeightChange();
507 if(CallUpdatePictures
)
511 void lterrain::GenerateMaterials()
513 int Chosen
= RandomizeMaterialConfiguration();
514 const fearray
<sLong
>& MMC
= GetMainMaterialConfig();
515 InitMaterial(MainMaterial
,
516 MAKE_MATERIAL(MMC
.Data
[MMC
.Size
== 1 ? 0 : Chosen
]),
520 void glterraindatabase::InitDefaults (const glterrainprototype
*NewProtoType
, int NewConfig
, cfestring
&acfgstrname
)
523 ProtoType
= NewProtoType
;
525 CfgStrName
= acfgstrname
;
528 void olterraindatabase::InitDefaults (const olterrainprototype
*NewProtoType
, int NewConfig
, cfestring
&acfgstrname
)
531 ProtoType
= NewProtoType
;
533 CfgStrName
= acfgstrname
;
536 truth
olterrain::ShowThingsUnder() const
538 return DataBase
->ShowThingsUnder
|| IsTransparent();
541 truth
olterrain::WillBeDestroyedBy(ccharacter
* Char
) const
543 return IsWall() && CanBeDestroyed() && MainMaterial
->GetStrengthValue() <= (Char
->GetAttribute(ARM_STRENGTH
) * 3);
546 v2
glterrain::GetBitmapPos(int I
) const
548 return GetBorderBitmapPos(DataBase
->BitmapPos
, I
);
551 v2
olterrain::GetBitmapPos(int I
) const
553 return GetBorderBitmapPos(DataBase
->BitmapPos
, I
);
556 truth
glterrain::IsAnimated() const
558 return GraphicData
.AnimationFrames
> (UseBorderTiles() ? 9 : 1);
561 truth
olterrain::IsAnimated() const
563 return GraphicData
.AnimationFrames
> (UseBorderTiles() ? 9 : 1);
566 void lterrain::AddLocationDescription(festring
& String
) const
568 String
<< " on the " << GetNameSingular();